Advertisement
jadenquinn

34ggy4rgyrg435642ytre3474356734yettyreyyrwuyr3756474574567435348453761234567890.txt

Nov 5th, 2017
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 92.99 KB | None | 0 0
  1. /*
  2. ILI9341_due_.cpp - Arduino Due library for interfacing with ILI9341-based TFTs
  3.  
  4. Copyright (c) 2014 Marek Buriak
  5.  
  6. This library is based on ILI9341_t3 library from Paul Stoffregen
  7. (https://github.com/PaulStoffregen/ILI9341_t3), Adafruit_ILI9341
  8. and Adafruit_GFX libraries from Limor Fried/Ladyada
  9. (https://github.com/adafruit/Adafruit_ILI9341).
  10.  
  11. This file is part of the Arduino ILI9341_due library.
  12. Sources for this library can be found at https://github.com/marekburiak/ILI9341_Due.
  13.  
  14. ILI9341_due is free software: you can redistribute it and/or modify
  15. it under the terms of the GNU Lesser General Public License as published by
  16. the Free Software Foundation, either version 2.1 of the License, or
  17. (at your option) any later version.
  18.  
  19. ILI9341_due is distributed in the hope that it will be useful,
  20. but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. GNU Lesser General Public License for more details.
  23.  
  24. You should have received a copy of the GNU Lesser General Public License
  25. along with ILI9341_due. If not, see <http://www.gnu.org/licenses/>.
  26. */
  27.  
  28. /***************************************************
  29. This is our library for the Adafruit ILI9341 Breakout and Shield
  30. ----> http://www.adafruit.com/products/1651
  31.  
  32. Check out the links above for our tutorials and wiring diagrams
  33. These displays use SPI to communicate, 4 or 5 pins are required to
  34. interface (RST is optional)
  35. Adafruit invests time and resources providing this open source code,
  36. please support Adafruit and open-source hardware by purchasing
  37. products from Adafruit!
  38.  
  39. Written by Limor Fried/Ladyada for Adafruit Industries.
  40. MIT license, all text above must be included in any redistribution.
  41. ****************************************************/
  42.  
  43. #include "ILI9341_due.h"
  44. #if SPI_MODE_NORMAL | SPI_MODE_EXTENDED | defined(ILI_USE_SPI_TRANSACTION)
  45. #include <SPI.h>
  46. #endif
  47.  
  48. //#include "..\Streaming\Streaming.h"
  49.  
  50. #pragma GCC diagnostic push
  51. #pragma GCC diagnostic ignored "-Wattributes"
  52. #pragma GCC diagnostic ignored "-Wswitch"
  53.  
  54.  
  55. static const uint8_t init_commands[] PROGMEM = {
  56. 4, 0xEF, 0x03, 0x80, 0x02,
  57. 4, 0xCF, 0x00, 0XC1, 0X30,
  58. 5, 0xED, 0x64, 0x03, 0X12, 0X81,
  59. 4, 0xE8, 0x85, 0x00, 0x78,
  60. 6, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02,
  61. 2, 0xF7, 0x20,
  62. 3, 0xEA, 0x00, 0x00,
  63. 2, ILI9341_PWCTR1, 0x23, // Power control
  64. 2, ILI9341_PWCTR2, 0x10, // Power control
  65. 3, ILI9341_VMCTR1, 0x3e, 0x28, // VCM control
  66. 2, ILI9341_VMCTR2, 0x86, // VCM control2
  67. 2, ILI9341_MADCTL, 0x48, // Memory Access Control
  68. 2, ILI9341_PIXFMT, 0x55,
  69. 3, ILI9341_FRMCTR1, 0x00, 0x18,
  70. 4, ILI9341_DFUNCTR, 0x08, 0x82, 0x27, // Display Function Control
  71. 2, 0xF2, 0x00, // Gamma Function Disable
  72. 2, ILI9341_GAMMASET, 0x01, // Gamma curve selected
  73. 16, ILI9341_GMCTRP1, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08,
  74. 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, // Set Gamma
  75. 16, ILI9341_GMCTRN1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07,
  76. 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, // Set Gamma
  77. 0
  78. };
  79.  
  80.  
  81. ILI9341_due::ILI9341_due(uint8_t cs, uint8_t dc, uint8_t rst)
  82. {
  83. _cs = cs;
  84. _dc = dc;
  85. _rst = rst;
  86. _spiClkDivider = ILI9341_SPI_CLKDIVIDER;
  87. _width = ILI9341_TFTWIDTH;
  88. _height = ILI9341_TFTHEIGHT;
  89. _area.x = 0;
  90. _area.y = 0;
  91. _area.w = ILI9341_TFTWIDTH;
  92. _area.h = ILI9341_TFTHEIGHT;
  93. _rotation = iliRotation0;
  94.  
  95. _arcAngleMax = DEFAULT_ARC_ANGLE_MAX;
  96. _angleOffset = DEFAULT_ANGLE_OFFSET;
  97.  
  98. #ifdef ILI_USE_SPI_TRANSACTION
  99. _isInTransaction = false;
  100. #endif
  101.  
  102. _fontMode = gTextFontModeSolid;
  103. _fontBgColor = ILI9341_BLACK;
  104. _fontColor = ILI9341_WHITE;
  105. _letterSpacing = DEFAULT_LETTER_SPACING;
  106. _lineSpacing = DEFAULT_LINE_SPACING;
  107. #ifdef TEXT_SCALING_ENABLED
  108. _textScale = 1;
  109. #endif
  110. _isFirstChar = true;
  111. setTextArea(0, 0, _width - 1, _height - 1);
  112.  
  113. }
  114.  
  115.  
  116. bool ILI9341_due::begin(void)
  117. {
  118. if (pinIsChipSelect(_cs)) {
  119. pinMode(_dc, OUTPUT);
  120. _dcport = portOutputRegister(digitalPinToPort(_dc));
  121. _dcpinmask = digitalPinToBitMask(_dc);
  122.  
  123. #if SPI_MODE_NORMAL | SPI_MODE_DMA
  124. pinMode(_cs, OUTPUT);
  125. _csport = portOutputRegister(digitalPinToPort(_cs));
  126. _cspinmask = digitalPinToBitMask(_cs);
  127. #endif
  128.  
  129. #if SPI_MODE_NORMAL
  130. SPI.begin();
  131. #elif SPI_MODE_EXTENDED
  132. SPI.begin(_cs);
  133. #elif SPI_MODE_DMA
  134. dmaBegin();
  135. #endif
  136. setSPIClockDivider(ILI9341_SPI_CLKDIVIDER);
  137.  
  138. // toggle RST low to reset
  139. if (_rst < 255) {
  140. pinMode(_rst, OUTPUT);
  141. digitalWrite(_rst, HIGH);
  142. delay(5);
  143. digitalWrite(_rst, LOW);
  144. delay(20);
  145. digitalWrite(_rst, HIGH);
  146. delay(150);
  147. }
  148.  
  149. const uint8_t *addr = init_commands;
  150. while (1) {
  151. uint8_t count = pgm_read_byte(addr++);
  152. if (count-- == 0) break;
  153. writecommand_cont(pgm_read_byte(addr++));
  154. while (count-- > 0) {
  155. writedata8_cont(pgm_read_byte(addr++));
  156. }
  157. }
  158.  
  159. writecommand_last(ILI9341_SLPOUT); // Exit Sleep
  160. delay(120);
  161. writecommand_last(ILI9341_DISPON); // Display on
  162. delay(120);
  163. _isInSleep = _isIdle = false;
  164.  
  165.  
  166.  
  167. //#ifdef ILI_USE_SPI_TRANSACTION
  168. //#if SPI_MODE_NORMAL | SPI_MODE_EXTENDED
  169. endTransaction();
  170. //#endif
  171. //#endif
  172. return true;
  173. }
  174. else {
  175. return false;
  176. }
  177. }
  178.  
  179. bool ILI9341_due::pinIsChipSelect(uint8_t cs)
  180. {
  181. #if SPI_MODE_EXTENDED
  182. if(cs == 4 || cs == 10 || cs == 52) // in Extended SPI mode only these pins are valid
  183. {
  184. return true;
  185. }
  186. else
  187. {
  188. Serial.print("Pin ");
  189. Serial.print(_cs);
  190. Serial.println(" is not a valid Chip Select pin for SPI Extended Mode. Valid pins are 4, 10, 52");
  191. return false;
  192. }
  193. #elif SPI_MODE_NORMAL | SPI_MODE_DMA
  194. return true;
  195. #endif
  196. }
  197.  
  198. void ILI9341_due::getDisplayStatus(void)
  199. {
  200. beginTransaction();
  201. uint8_t x = readcommand8(ILI9341_RDMODE);
  202. Serial.print(F("\nDisplay Power Mode: 0x")); Serial.println(x, HEX);
  203. Serial.print(F(" Booster: ")); Serial.println(x & 0x80 ? F("On and working OK") : F("Off or has a fault"));
  204. Serial.print(F(" Idle Mode: ")); Serial.println(x & 0x40 ? F("On") : F("Off"));
  205. Serial.print(F(" Partial Mode: ")); Serial.println(x & 0x20 ? F("On") : F("Off"));
  206. Serial.print(F(" Sleep Mode: ")); Serial.println(x & 0x10 ? F("Off") : F("On"));
  207. Serial.print(F(" Display Normal Mode: ")); Serial.println(x & 0x08 ? F("On") : F("Off"));
  208. Serial.print(F(" Display: ")); Serial.println(x & 0x04 ? F("On") : F("Off"));
  209.  
  210. x = readcommand8(ILI9341_RDMADCTL);
  211. Serial.print(F("MADCTL Mode: 0x")); Serial.println(x, HEX);
  212. Serial.println(x & 0x80 ? F(" Bottom to Top") : F(" Top to Bottom"));
  213. Serial.println(x & 0x40 ? F(" Right to Left") : F(" Left to Right"));
  214. Serial.println(x & 0x20 ? F(" Normal Mode") : F(" Reverse Mode"));
  215. Serial.println(x & 0x10 ? F(" LCD Refresh Bottom to Top") : F(" LCD Refresh Top to Bottom"));
  216. Serial.println(x & 0x08 ? F(" BGR") : F("RGB"));
  217. Serial.println(x & 0x04 ? F(" LCD Refresh Right to Left") : F(" LCD Refresh Left to Right"));
  218.  
  219. x = readcommand8(ILI9341_RDPIXFMT);
  220. Serial.print(F("Pixel Format: 0x")); Serial.println(x, HEX);
  221. if ((x & 0x07) == 0x05)
  222. Serial.println(F(" 16 bits/pixel"));
  223. if ((x & 0x07) == 0x06)
  224. Serial.println(F(" 18 bits/pixel"));
  225.  
  226. x = readcommand8(ILI9341_RDIMGFMT);
  227. Serial.print(F("Image Format: 0x")); Serial.println(x, HEX);
  228. if ((x & 0x07) == 0x00)
  229. Serial.println(F(" Gamma curve 1"));
  230.  
  231. x = readcommand8(ILI9341_RDDSPSGNMODE);
  232. Serial.print(F("Display Signal Mode: 0x")); Serial.println(x, HEX);
  233. Serial.print(F(" Tearing effect line: ")); Serial.println(x & 0x80 ? F("On") : F("Off"));
  234. Serial.print(F(" Tearing effect line: mode ")); Serial.println(x & 0x40 ? F("2") : F("1"));
  235. Serial.print(F(" Horizontal sync: ")); Serial.println(x & 0x20 ? F("On") : F("Off"));
  236. Serial.print(F(" Vertical sync: ")); Serial.println(x & 0x10 ? F("On") : F("Off"));
  237. Serial.print(F(" Pixel clock: ")); Serial.println(x & 0x08 ? F("On") : F("Off"));
  238. Serial.print(F(" Data enable: ")); Serial.println(x & 0x04 ? F("On") : F("Off"));
  239.  
  240. x = readcommand8(ILI9341_RDSELFDIAG);
  241. Serial.print(F("Self Diagnostic: 0x")); Serial.println(x, HEX);
  242. Serial.print(F(" Register Loading: ")); Serial.println(x & 0x80 ? F("working") : F("not working"));
  243. Serial.print(F(" Functionality: ")); Serial.println(x & 0x40 ? F("working") : F("not working"));
  244.  
  245. endTransaction();
  246. }
  247.  
  248. void ILI9341_due::setSPIClockDivider(uint8_t divider)
  249. {
  250. _spiClkDivider = divider;
  251. #ifdef ILI_USE_SPI_TRANSACTION
  252. #if defined (ARDUINO_SAM_DUE)
  253. _spiSettings = SPISettings(F_CPU / divider, MSBFIRST, SPI_MODE0);
  254. #elif defined (ARDUINO_ARCH_AVR)
  255. #if divider == SPI_CLOCK_DIV2
  256. _spiSettings = SPISettings(F_CPU / 2, MSBFIRST, SPI_MODE0);
  257. #elif divider == SPI_CLOCK_DIV4
  258. _spiSettings = SPISettings(F_CPU / 4, MSBFIRST, SPI_MODE0);
  259. #elif divider == SPI_CLOCK_DIV8
  260. _spiSettings = SPISettings(F_CPU / 8, MSBFIRST, SPI_MODE0);
  261. #elif divider == SPI_CLOCK_DIV16
  262. _spiSettings = SPISettings(F_CPU / 16, MSBFIRST, SPI_MODE0);
  263. #elif divider == SPI_CLOCK_DIV32
  264. _spiSettings = SPISettings(F_CPU / 32, MSBFIRST, SPI_MODE0);
  265. #elif divider == SPI_CLOCK_DIV64
  266. _spiSettings = SPISettings(F_CPU / 64, MSBFIRST, SPI_MODE0);
  267. #elif divider == SPI_CLOCK_DIV128
  268. _spiSettings = SPISettings(F_CPU / 128, MSBFIRST, SPI_MODE0);
  269. #endif
  270. #endif
  271. #endif
  272.  
  273. #ifdef ILI_USE_SPI_TRANSACTION
  274. beginTransaction();
  275. #else
  276. #if SPI_MODE_NORMAL
  277. SPI.setClockDivider(divider);
  278. SPI.setBitOrder(MSBFIRST);
  279. SPI.setDataMode(SPI_MODE0);
  280. #elif SPI_MODE_EXTENDED
  281. SPI.setClockDivider(_cs, divider);
  282. SPI.setBitOrder(_cs, MSBFIRST);
  283. SPI.setDataMode(_cs, SPI_MODE0);
  284. #endif
  285. #endif
  286.  
  287. #if SPI_MODE_DMA
  288. dmaInit(divider);
  289. #endif
  290. }
  291.  
  292. void ILI9341_due::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
  293. {
  294. beginTransaction();
  295. enableCS();
  296. setAddrAndRW_cont(x0, y0, x1 - x0 + 1, y1 - y0 + 1);
  297. disableCS();
  298. endTransaction();
  299. }
  300.  
  301. void ILI9341_due::setAddrWindowRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
  302. {
  303. beginTransaction();
  304. enableCS();
  305. setAddrAndRW_cont(x, y, w, h);
  306. disableCS();
  307. endTransaction();
  308. }
  309.  
  310. void ILI9341_due::pushColor(uint16_t color)
  311. {
  312. beginTransaction();
  313. enableCS();
  314. setDCForData();
  315. write16_last(color);
  316. endTransaction();
  317. }
  318.  
  319. //void ILI9341_due::pushColors(uint16_t *colors, uint16_t offset, uint16_t len) {
  320. // beginTransaction();
  321. // enableCS();
  322. // setDCForData();
  323. // colors = colors + offset * 2;
  324. //#if SPI_MODE_EXTENDED
  325. // uint16_t i;
  326. // for (i = 0; i < len-1; i++) {
  327. // write16_cont(colors[i]);
  328. // }
  329. // write16_last(colors[i]);
  330. //#else
  331. // for (uint16_t i = 0; i < (len << 1); i += 2) {
  332. // uint16_t color = *colors;
  333. // _scanline[i] = highByte(color);
  334. // _scanline[i + 1] = lowByte(color);
  335. // colors++;
  336. // }
  337. // writeScanline(len);
  338. // disableCS();
  339. //#endif
  340. //
  341. // endTransaction();
  342. //}
  343.  
  344. // pushes pixels stored in the colors array (one color is 2 bytes)
  345. // in big endian (high byte first)
  346. // len should be the length of the array (so to push 320 pixels,
  347. // you have to have a 640-byte array and len should be 640)
  348. //void ILI9341_due::pushColors565(uint8_t *colors, uint16_t offset, uint32_t len) {
  349. // beginTransaction();
  350. // enableCS();
  351. // setDCForData();
  352. // colors = colors + offset;
  353. //
  354. // //#if SPI_MODE_NORMAL | SPI_MODE_EXTENDED
  355. // // for (uint16_t i = 0; i < len; i++) {
  356. // // write8_cont(colors[i]);
  357. // // }
  358. // //#elif SPI_MODE_DMA
  359. // write_cont(colors, len);
  360. // //#endif
  361. // disableCS();
  362. // endTransaction();
  363. //}
  364.  
  365. void ILI9341_due::pushColors(const uint16_t *colors, uint16_t offset, uint32_t len) {
  366. beginTransaction();
  367. enableCS();
  368. pushColors_noTrans_noCS(colors, offset, len);
  369. disableCS();
  370. endTransaction();
  371. }
  372.  
  373. void ILI9341_due::pushColors(uint16_t *colors, uint16_t offset, uint32_t len) {
  374. beginTransaction();
  375. enableCS();
  376. setDCForData();
  377. colors = colors + offset;
  378. write_cont(colors, len);
  379. disableCS();
  380. endTransaction();
  381. }
  382.  
  383. void ILI9341_due::pushColors_noTrans_noCS(const uint16_t *colors, uint16_t offset, uint32_t len) {
  384. setDCForData();
  385. colors = colors + offset;
  386.  
  387. #if SPI_MODE_DMA
  388. const uint32_t numLoops = len / (uint32_t)SCANLINE_PIXEL_COUNT;
  389. for (uint32_t l = 0; l < numLoops; l++)
  390. {
  391. for (uint32_t i = 0; i < SCANLINE_PIXEL_COUNT; i++)
  392. {
  393. _scanline16[i] = colors[l*SCANLINE_PIXEL_COUNT + i];
  394. }
  395. writeScanline16(SCANLINE_PIXEL_COUNT);
  396. }
  397. uint16_t remainingPixels = len % SCANLINE_PIXEL_COUNT;
  398. if (remainingPixels > 0){
  399. for (uint32_t i = 0; i < remainingPixels; i++)
  400. {
  401. _scanline16[i] = colors[numLoops*SCANLINE_PIXEL_COUNT + i];
  402. }
  403. writeScanline16(remainingPixels);
  404. }
  405. #else
  406. write_cont(colors, len);
  407. #endif
  408. }
  409.  
  410.  
  411. void ILI9341_due::drawPixel(int16_t x, int16_t y, uint16_t color) {
  412. beginTransaction();
  413. enableCS();
  414. drawPixel_last(x, y, color);
  415. disableCS();
  416. endTransaction();
  417. }
  418.  
  419. void ILI9341_due::drawImage(const uint16_t *colors, uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
  420. const uint32_t totalPixels = (uint32_t)w*(uint32_t)h;
  421. beginTransaction();
  422. enableCS();
  423. setAddrAndRW_cont(x, y, w, h);
  424. pushColors_noTrans_noCS(colors, 0, totalPixels);
  425. disableCS();
  426. endTransaction();
  427. }
  428.  
  429. void ILI9341_due::drawFastVLine(int16_t x, int16_t y, uint16_t h, uint16_t color)
  430. {
  431. beginTransaction();
  432. drawFastVLine_noTrans(x, y, h, color);
  433. endTransaction();
  434. }
  435.  
  436. void ILI9341_due::drawFastVLine_noTrans(int16_t x, int16_t y, uint16_t h, uint16_t color)
  437. {
  438. // Rudimentary clipping
  439. if ((x >= _width) || (y >= _height)) return;
  440. if ((y + (int16_t)h - 1) >= _height) h = _height - y;
  441.  
  442. fillScanline16(color, min(h, SCANLINE_PIXEL_COUNT));
  443.  
  444. enableCS();
  445. setAddrAndRW_cont(x, y, 1, h);
  446. setDCForData();
  447. #ifdef ARDUINO_SAM_DUE
  448. writeScanline16(h);
  449. #elif defined ARDUINO_ARCH_AVR
  450. writeScanlineLooped(h);
  451. #endif
  452. disableCS();
  453. }
  454.  
  455. void ILI9341_due::drawFastVLine_cont_noFill(int16_t x, int16_t y, int16_t h, uint16_t color)
  456. {
  457. // Rudimentary clipping
  458. // if ((x >= _width) || (y >= _height)) return;
  459. // if ((y + h - 1) >= _height) h = _height - y;
  460. //
  461. // setAddrAndRW_cont(x, y, 1, h);
  462. // setDCForData();
  463. //#if SPI_MODE_NORMAL | SPI_MODE_EXTENDED
  464. // while (h-- > 0) {
  465. // write16_cont(color);
  466. // }
  467. //#elif SPI_MODE_DMA
  468. // writeScanline(h);
  469. //#endif
  470.  
  471. if ((x >= _width) || (y >= _height)) return;
  472. if ((y + h - 1) >= _height) h = _height - y;
  473.  
  474. setAddrAndRW_cont(x, y, 1, h);
  475. setDCForData();
  476. #ifdef ARDUINO_SAM_DUE
  477. writeScanline16(h);
  478. #elif defined ARDUINO_ARCH_AVR
  479. writeScanlineLooped(h);
  480. #endif
  481.  
  482. }
  483.  
  484. void ILI9341_due::drawFastHLine(int16_t x, int16_t y, uint16_t w, uint16_t color)
  485. {
  486. beginTransaction();
  487. drawFastHLine_noTrans(x, y, w, color);
  488. endTransaction();
  489. }
  490.  
  491. void ILI9341_due::drawFastHLine_noTrans(int16_t x, int16_t y, uint16_t w, uint16_t color)
  492. {
  493. // Rudimentary clipping
  494. if ((x >= _width) || (y >= _height)) return;
  495. if ((x + (int16_t)w - 1) >= _width) w = _width - x;
  496.  
  497.  
  498. fillScanline16(color, min(w, SCANLINE_PIXEL_COUNT));
  499. enableCS();
  500. setAddrAndRW_cont(x, y, w, 1);
  501. setDCForData();
  502. #ifdef ARDUINO_SAM_DUE
  503. writeScanline16(w);
  504. #elif defined ARDUINO_ARCH_AVR
  505. writeScanlineLooped(w);
  506. #endif
  507. disableCS();
  508. }
  509.  
  510. void ILI9341_due::fillScreen(uint16_t color)
  511. {
  512. const uint32_t numLoops = (uint32_t)76800 / (uint32_t)SCANLINE_PIXEL_COUNT;
  513. fillScanline16(color);
  514.  
  515. beginTransaction();
  516. enableCS();
  517. setAddrAndRW_cont(0, 0, _width, _height);
  518. setDCForData();
  519. for (uint32_t l = 0; l < numLoops; l++)
  520. {
  521. writeScanline16(SCANLINE_PIXEL_COUNT);
  522. }
  523. disableCS();
  524. endTransaction();
  525. //#endif
  526. }
  527.  
  528. // fill a rectangle
  529. void ILI9341_due::fillRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color)
  530. {
  531. beginTransaction();
  532. fillRect_noTrans(x, y, w, h, color);
  533. endTransaction();
  534. }
  535.  
  536. // fill a rectangle
  537. void ILI9341_due::fillRect_noTrans(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color)
  538. {
  539. //Serial << "x:" << x << " y:" << y << " w:" << x << " h:" << h << " width:" << _width << " height:" << _height <<endl;
  540. // rudimentary clipping (drawChar w/big text requires this)
  541. if ((x >= _width) || (y >= _height) || (x + w - 1 < 0) || (y + h - 1 < 0)) return;
  542. if ((x + (int16_t)w - 1) >= _width) w = _width - x;
  543. if ((y + (int16_t)h - 1) >= _height) h = _height - y;
  544.  
  545. const uint32_t totalPixels = (uint32_t)w*(uint32_t)h;
  546. fillScanline16(color, min(totalPixels, SCANLINE_PIXEL_COUNT));
  547. enableCS();
  548. setAddrAndRW_cont(x, y, w, h);
  549. setDCForData();
  550. writeScanlineLooped(totalPixels);
  551. disableCS();
  552. }
  553.  
  554. #define MADCTL_MY 0x80
  555. #define MADCTL_MX 0x40
  556. #define MADCTL_MV 0x20
  557. #define MADCTL_ML 0x10
  558. #define MADCTL_RGB 0x00
  559. #define MADCTL_BGR 0x08
  560. #define MADCTL_MH 0x04
  561.  
  562. void ILI9341_due::setRotation(iliRotation r)
  563. {
  564. beginTransaction();
  565. writecommand_cont(ILI9341_MADCTL);
  566. _rotation = r;
  567. switch (r) {
  568. case iliRotation0:
  569. writedata8_last(MADCTL_MX | MADCTL_BGR);
  570. _width = ILI9341_TFTWIDTH;
  571. _height = ILI9341_TFTHEIGHT;
  572. break;
  573. case iliRotation90:
  574. writedata8_last(MADCTL_MV | MADCTL_BGR);
  575. _width = ILI9341_TFTHEIGHT;
  576. _height = ILI9341_TFTWIDTH;
  577. break;
  578. case iliRotation180:
  579. writedata8_last(MADCTL_MY | MADCTL_BGR);
  580. _width = ILI9341_TFTWIDTH;
  581. _height = ILI9341_TFTHEIGHT;
  582. break;
  583. case iliRotation270:
  584. writedata8_last(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR);
  585. _width = ILI9341_TFTHEIGHT;
  586. _height = ILI9341_TFTWIDTH;
  587. break;
  588. }
  589. //_area.x = 0;
  590. //_area.y = 0;
  591. _area.w = _width;
  592. _area.h = _height;
  593. endTransaction();
  594. }
  595.  
  596.  
  597. void ILI9341_due::invertDisplay(boolean i)
  598. {
  599. beginTransaction();
  600. writecommand_last(i ? ILI9341_INVON : ILI9341_INVOFF);
  601. endTransaction();
  602. }
  603.  
  604.  
  605. // Reads one pixel/color from the TFT's GRAM
  606. uint16_t ILI9341_due::readPixel(int16_t x, int16_t y)
  607. {
  608. beginTransaction();
  609. //setAddr_cont(x, y, x + 1, y + 1); ? should it not be x,y,x,y?
  610. setAddr_cont(x, y, 1, 1);
  611. writecommand_cont(ILI9341_RAMRD); // read from RAM
  612. readdata8_cont(); // dummy read
  613. uint8_t red = read8_cont();
  614. uint8_t green = read8_cont();
  615. uint8_t blue = read8_last();
  616. uint16_t color = color565(red, green, blue);
  617. endTransaction();
  618. return color;
  619.  
  620. }
  621.  
  622. //void ILI9341_due::drawArc(uint16_t cx, uint16_t cy, uint16_t radius, uint16_t thickness, uint16_t start, uint16_t end, uint16_t color) {
  623. // //void graphics_draw_arc(GContext *ctx, GPoint p, int radius, int thickness, int start, int end) {
  624. // start = start % 360;
  625. // end = end % 360;
  626. //
  627. // while (start < 0) start += 360;
  628. // while (end < 0) end += 360;
  629. //
  630. // if (end == 0) end = 360;
  631. //
  632. // //Serial << "start: " << start << " end:" << end << endl;
  633. //
  634. // // Serial << (float)cos_lookup(start * ARC_MAX_STEPS / 360) << " x " << (float)sin_lookup(start * ARC_MAX_STEPS / 360) << endl;
  635. //
  636. // float sslope = (float)cos_lookup(start * ARC_MAX_STEPS / 360) / (float)sin_lookup(start * ARC_MAX_STEPS / 360);
  637. // float eslope = (float)cos_lookup(end * ARC_MAX_STEPS / 360) / (float)sin_lookup(end * ARC_MAX_STEPS / 360);
  638. //
  639. // //Serial << "sslope: " << sslope << " eslope:" << eslope << endl;
  640. //
  641. // if (end == 360) eslope = -1000000;
  642. //
  643. // int ir2 = (radius - thickness) * (radius - thickness);
  644. // int or2 = radius * radius;
  645. //
  646. // for (int x = -radius; x <= radius; x++)
  647. // for (int y = -radius; y <= radius; y++)
  648. // {
  649. // int x2 = x * x;
  650. // int y2 = y * y;
  651. //
  652. // if (
  653. // (x2 + y2 < or2 && x2 + y2 >= ir2) &&
  654. // (
  655. // (y > 0 && start < 180 && x <= y * sslope) ||
  656. // (y < 0 && start > 180 && x >= y * sslope) ||
  657. // (y < 0 && start <= 180) ||
  658. // (y == 0 && start <= 180 && x < 0) ||
  659. // (y == 0 && start == 0 && x > 0)
  660. // ) &&
  661. // (
  662. // (y > 0 && end < 180 && x >= y * eslope) ||
  663. // (y < 0 && end > 180 && x <= y * eslope) ||
  664. // (y > 0 && end >= 180) ||
  665. // (y == 0 && end >= 180 && x < 0) ||
  666. // (y == 0 && start == 0 && x > 0)
  667. // )
  668. // )
  669. // drawPixel_cont(cx+x, cy+y, color);
  670. // }
  671. //}
  672.  
  673.  
  674. // DrawArc function thanks to Jnmattern and his Arc_2.0 (https://github.com/Jnmattern)
  675. void ILI9341_due::fillArcOffsetted(uint16_t cx, uint16_t cy, uint16_t radius, uint16_t thickness, float start, float end, uint16_t color) {
  676. int16_t xmin = 65535, xmax = -32767, ymin = 32767, ymax = -32767;
  677. float cosStart, sinStart, cosEnd, sinEnd;
  678. float r, t;
  679. float startAngle, endAngle;
  680.  
  681. //Serial << "start: " << start << " end: " << end << endl;
  682. startAngle = (start / _arcAngleMax) * 360; // 252
  683. endAngle = (end / _arcAngleMax) * 360; // 807
  684. //Serial << "startAngle: " << startAngle << " endAngle: " << endAngle << endl;
  685.  
  686. while (startAngle < 0) startAngle += 360;
  687. while (endAngle < 0) endAngle += 360;
  688. while (startAngle > 360) startAngle -= 360;
  689. while (endAngle > 360) endAngle -= 360;
  690. //Serial << "startAngleAdj: " << startAngle << " endAngleAdj: " << endAngle << endl;
  691. //if (endAngle == 0) endAngle = 360;
  692.  
  693. if (startAngle > endAngle) {
  694. fillArcOffsetted(cx, cy, radius, thickness, ((startAngle) / (float)360) * _arcAngleMax, _arcAngleMax, color);
  695. fillArcOffsetted(cx, cy, radius, thickness, 0, ((endAngle) / (float)360) * _arcAngleMax, color);
  696. }
  697. else {
  698. // Calculate bounding box for the arc to be drawn
  699. cosStart = cosDegrees(startAngle);
  700. sinStart = sinDegrees(startAngle);
  701. cosEnd = cosDegrees(endAngle);
  702. sinEnd = sinDegrees(endAngle);
  703.  
  704. //Serial << cosStart << " " << sinStart << " " << cosEnd << " " << sinEnd << endl;
  705.  
  706. r = radius;
  707. // Point 1: radius & startAngle
  708. t = r * cosStart;
  709. if (t < xmin) xmin = t;
  710. if (t > xmax) xmax = t;
  711. t = r * sinStart;
  712. if (t < ymin) ymin = t;
  713. if (t > ymax) ymax = t;
  714.  
  715. // Point 2: radius & endAngle
  716. t = r * cosEnd;
  717. if (t < xmin) xmin = t;
  718. if (t > xmax) xmax = t;
  719. t = r * sinEnd;
  720. if (t < ymin) ymin = t;
  721. if (t > ymax) ymax = t;
  722.  
  723. r = radius - thickness;
  724. // Point 3: radius-thickness & startAngle
  725. t = r * cosStart;
  726. if (t < xmin) xmin = t;
  727. if (t > xmax) xmax = t;
  728. t = r * sinStart;
  729. if (t < ymin) ymin = t;
  730. if (t > ymax) ymax = t;
  731.  
  732. // Point 4: radius-thickness & endAngle
  733. t = r * cosEnd;
  734. if (t < xmin) xmin = t;
  735. if (t > xmax) xmax = t;
  736. t = r * sinEnd;
  737. if (t < ymin) ymin = t;
  738. if (t > ymax) ymax = t;
  739.  
  740.  
  741. //Serial << xmin << " " << xmax << " " << ymin << " " << ymax << endl;
  742. // Corrections if arc crosses X or Y axis
  743. if ((startAngle < 90) && (endAngle > 90)) {
  744. ymax = radius;
  745. }
  746.  
  747. if ((startAngle < 180) && (endAngle > 180)) {
  748. xmin = -radius;
  749. }
  750.  
  751. if ((startAngle < 270) && (endAngle > 270)) {
  752. ymin = -radius;
  753. }
  754.  
  755. // Slopes for the two sides of the arc
  756. float sslope = (float)cosStart / (float)sinStart;
  757. float eslope = (float)cosEnd / (float)sinEnd;
  758.  
  759. //Serial << "sslope2: " << sslope << " eslope2:" << eslope << endl;
  760.  
  761. if (endAngle == 360) eslope = -1000000;
  762.  
  763. int ir2 = (radius - thickness) * (radius - thickness);
  764. int or2 = radius * radius;
  765. //Serial << "ymin: " << ymin << " ymax: " << ymax << endl;
  766.  
  767. fillScanline16(color);
  768.  
  769. enableCS();
  770. for (int x = xmin; x <= xmax; x++) {
  771. bool y1StartFound = false, y2StartFound = false;
  772. bool y1EndFound = false, y2EndSearching = false;
  773. int y1s = 0, y1e = 0, y2s = 0;
  774. for (int y = ymin; y <= ymax; y++)
  775. {
  776. int x2 = x * x;
  777. int y2 = y * y;
  778.  
  779. if (
  780. (x2 + y2 < or2 && x2 + y2 >= ir2) && (
  781. (y > 0 && startAngle < 180 && x <= y * sslope) ||
  782. (y < 0 && startAngle > 180 && x >= y * sslope) ||
  783. (y < 0 && startAngle <= 180) ||
  784. (y == 0 && startAngle <= 180 && x < 0) ||
  785. (y == 0 && startAngle == 0 && x > 0)
  786. ) && (
  787. (y > 0 && endAngle < 180 && x >= y * eslope) ||
  788. (y < 0 && endAngle > 180 && x <= y * eslope) ||
  789. (y > 0 && endAngle >= 180) ||
  790. (y == 0 && endAngle >= 180 && x < 0) ||
  791. (y == 0 && startAngle == 0 && x > 0)))
  792. {
  793. if (!y1StartFound) //start of the higher line found
  794. {
  795. y1StartFound = true;
  796. y1s = y;
  797. }
  798. else if (y1EndFound && !y2StartFound) //start of the lower line found
  799. {
  800. //Serial << "Found y2 start x: " << x << " y:" << y << endl;
  801. y2StartFound = true;
  802. //drawPixel_cont(cx+x, cy+y, ILI9341_BLUE);
  803. y2s = y;
  804. y += y1e - y1s - 1; // calculate the most probable end of the lower line (in most cases the length of lower line is equal to length of upper line), in the next loop we will validate if the end of line is really there
  805. if (y > ymax - 1) // the most probable end of line 2 is beyond ymax so line 2 must be shorter, thus continue with pixel by pixel search
  806. {
  807. y = y2s; // reset y and continue with pixel by pixel search
  808. y2EndSearching = true;
  809. }
  810.  
  811. //Serial << "Upper line length: " << (y1e - y1s) << " Setting y to " << y << endl;
  812. }
  813. else if (y2StartFound && !y2EndSearching)
  814. {
  815. // we validated that the probable end of the lower line has a pixel, continue with pixel by pixel search, in most cases next loop with confirm the end of lower line as it will not find a valid pixel
  816. y2EndSearching = true;
  817. }
  818. //Serial << "x:" << x << " y:" << y << endl;
  819. //drawPixel_cont(cx+x, cy+y, ILI9341_BLUE);
  820. }
  821. else
  822. {
  823. if (y1StartFound && !y1EndFound) //higher line end found
  824. {
  825. y1EndFound = true;
  826. y1e = y - 1;
  827. //Serial << "line: " << y1s << " - " << y1e << endl;
  828. drawFastVLine_cont_noFill(cx + x, cy + y1s, y - y1s, color);
  829. if (y < 0)
  830. {
  831. //Serial << x << " " << y << endl;
  832. y = abs(y); // skip the empty middle
  833. }
  834. else
  835. break;
  836. }
  837. else if (y2StartFound)
  838. {
  839. if (y2EndSearching)
  840. {
  841. //Serial << "Found final end at y: " << y << endl;
  842. // we found the end of the lower line after pixel by pixel search
  843. drawFastVLine_cont_noFill(cx + x, cy + y2s, y - y2s, color);
  844. y2EndSearching = false;
  845. break;
  846. }
  847. else
  848. {
  849. //Serial << "Expected end not found" << endl;
  850. // the expected end of the lower line is not there so the lower line must be shorter
  851. y = y2s; // put the y back to the lower line start and go pixel by pixel to find the end
  852. y2EndSearching = true;
  853. }
  854. }
  855. //else
  856. //drawPixel_cont(cx+x, cy+y, ILI9341_RED);
  857. }
  858. //
  859.  
  860. //delay(75);
  861. }
  862. if (y1StartFound && !y1EndFound)
  863. {
  864. y1e = ymax;
  865. //Serial << "line: " << y1s << " - " << y1e << endl;
  866. drawFastVLine_cont_noFill(cx + x, cy + y1s, y1e - y1s + 1, color);
  867. }
  868. else if (y2StartFound && y2EndSearching) // we found start of lower line but we are still searching for the end
  869. { // which we haven't found in the loop so the last pixel in a column must be the end
  870. drawFastVLine_cont_noFill(cx + x, cy + y2s, ymax - y2s + 1, color);
  871. }
  872. }
  873. disableCS();
  874. }
  875. }
  876.  
  877. void ILI9341_due::screenshotToConsole()
  878. {
  879. uint8_t lastColor[3];
  880. uint8_t color[3];
  881. uint32_t sameColorPixelCount = 0;
  882. uint16_t sameColorPixelCount16 = 0;
  883. uint32_t sameColorStartIndex = 0;
  884. uint32_t totalImageDataLength = 0;
  885. Serial.println();
  886. Serial.println(F("==== PIXEL DATA START ===="));
  887. //uint16_t x=0;
  888. //uint16_t y=0;
  889. beginTransaction();
  890. setAddr_cont(0, 0, _width, _height);
  891. writecommand_cont(ILI9341_RAMRD); // read from RAM
  892. readdata8_cont(); // dummy read, also sets DC high
  893.  
  894. #if SPI_MODE_DMA
  895. read_cont(color, 3);
  896. lastColor[0] = color[0];
  897. lastColor[1] = color[1];
  898. lastColor[2] = color[2];
  899. #elif SPI_MODE_NORMAL | SPI_MODE_EXTENDED
  900. lastColor[0] = color[0] = read8_cont();
  901. lastColor[1] = color[1] = read8_cont();
  902. lastColor[2] = color[2] = read8_cont();
  903. #endif
  904. printHex8(color, 3); //write color of the first pixel
  905. totalImageDataLength += 6;
  906. sameColorStartIndex = 0;
  907.  
  908. for (uint32_t i = 1; i < (uint32_t)_width*(uint32_t)_height; i++)
  909. {
  910. #if SPI_MODE_DMA
  911. read_cont(color, 3);
  912. #elif SPI_MODE_NORMAL | SPI_MODE_EXTENDED
  913. color[0] = read8_cont();
  914. color[1] = read8_cont();
  915. color[2] = read8_cont();
  916. #endif
  917.  
  918. if (color[0] != lastColor[0] ||
  919. color[1] != lastColor[1] ||
  920. color[2] != lastColor[2])
  921. {
  922. sameColorPixelCount = i - sameColorStartIndex;
  923. if (sameColorPixelCount > 65535)
  924. {
  925. sameColorPixelCount16 = 65535;
  926. printHex16(&sameColorPixelCount16, 1);
  927. printHex8(lastColor, 3);
  928. totalImageDataLength += 10;
  929. sameColorPixelCount16 = sameColorPixelCount - 65535;
  930. }
  931. else
  932. sameColorPixelCount16 = sameColorPixelCount;
  933. printHex16(&sameColorPixelCount16, 1);
  934. printHex8(color, 3);
  935. totalImageDataLength += 10;
  936.  
  937. sameColorStartIndex = i;
  938. lastColor[0] = color[0];
  939. lastColor[1] = color[1];
  940. lastColor[2] = color[2];
  941. }
  942. }
  943. disableCS();
  944. endTransaction();
  945. sameColorPixelCount = (uint32_t)_width*(uint32_t)_height - sameColorStartIndex;
  946. if (sameColorPixelCount > 65535)
  947. {
  948. sameColorPixelCount16 = 65535;
  949. printHex16(&sameColorPixelCount16, 1);
  950. printHex8(lastColor, 3);
  951. totalImageDataLength += 10;
  952. sameColorPixelCount16 = sameColorPixelCount - 65535;
  953. }
  954. else
  955. sameColorPixelCount16 = sameColorPixelCount;
  956. printHex16(&sameColorPixelCount16, 1);
  957. totalImageDataLength += 4;
  958. printHex32(&totalImageDataLength, 1);
  959.  
  960. Serial.println();
  961. Serial.println(F("==== PIXEL DATA END ===="));
  962. Serial.print(F("Total Image Data Length: "));
  963. Serial.println(totalImageDataLength);
  964. }
  965.  
  966. /*
  967. This is the core graphics library for all our displays, providing a common
  968. set of graphics primitives (points, lines, circles, etc.). It needs to bex
  969. paired with a hardware-specific library for each display device we carry
  970. (to handle the lower-level functions).
  971.  
  972. Adafruit invests time and resources providing this open source code, please
  973. support Adafruit & open-source hardware by purchasing products from Adafruit!
  974.  
  975. Copyright (c) 2013 Adafruit Industries. All rights reserved.
  976.  
  977. Redistribution and use in source and binary forms, with or without
  978. modification, are permitted provided that the following conditions are met:
  979.  
  980. - Redistributions of source code must retain the above copyright notice,
  981. this list of conditions and the following disclaimer.
  982. - Redistributions in binary form must reproduce the above copyright notice,
  983. this list of conditions and the following disclaimer in the documentation
  984. and/or other materials provided with the distribution.
  985.  
  986. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  987. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  988. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  989. ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  990. LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  991. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  992. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  993. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  994. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  995. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  996. POSSIBILITY OF SUCH DAMAGE.
  997. */
  998.  
  999. // Draw a circle outline
  1000. void ILI9341_due::drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)
  1001. {
  1002.  
  1003. int16_t f = 1 - r;
  1004. int16_t ddF_x = 1;
  1005. int16_t ddF_y = -2 * r;
  1006. int16_t x = 0;
  1007. int16_t y = r;
  1008. beginTransaction();
  1009. enableCS();
  1010.  
  1011. drawPixel_cont(x0, y0 + r, color);
  1012. drawPixel_cont(x0, y0 - r, color);
  1013. drawPixel_cont(x0 + r, y0, color);
  1014. drawPixel_cont(x0 - r, y0, color);
  1015.  
  1016. while (x < y) {
  1017. if (f >= 0) {
  1018. y--;
  1019. ddF_y += 2;
  1020. f += ddF_y;
  1021. }
  1022. x++;
  1023. ddF_x += 2;
  1024. f += ddF_x;
  1025.  
  1026. drawPixel_cont(x0 + x, y0 + y, color);
  1027. drawPixel_cont(x0 - x, y0 + y, color);
  1028. drawPixel_cont(x0 + x, y0 - y, color);
  1029. drawPixel_cont(x0 - x, y0 - y, color);
  1030. drawPixel_cont(x0 + y, y0 + x, color);
  1031. drawPixel_cont(x0 - y, y0 + x, color);
  1032. drawPixel_cont(x0 + y, y0 - x, color);
  1033. drawPixel_cont(x0 - y, y0 - x, color);
  1034. }
  1035. disableCS();
  1036. endTransaction();
  1037. }
  1038.  
  1039.  
  1040. void ILI9341_due::drawCircleHelper(int16_t x0, int16_t y0,
  1041. int16_t r, uint8_t cornername, uint16_t color)
  1042. {
  1043. int16_t f = 1 - r;
  1044. int16_t ddF_x = 1;
  1045. int16_t ddF_y = -2 * r;
  1046. int16_t x = 0;
  1047. int16_t y = r;
  1048. enableCS();
  1049. while (x < y) {
  1050. if (f >= 0) {
  1051. y--;
  1052. ddF_y += 2;
  1053. f += ddF_y;
  1054. }
  1055. x++;
  1056. ddF_x += 2;
  1057. f += ddF_x;
  1058. if (cornername & 0x4) {
  1059. drawPixel_cont(x0 + x, y0 + y, color);
  1060. drawPixel_cont(x0 + y, y0 + x, color);
  1061. }
  1062. if (cornername & 0x2) {
  1063. drawPixel_cont(x0 + x, y0 - y, color);
  1064. drawPixel_cont(x0 + y, y0 - x, color);
  1065. }
  1066. if (cornername & 0x8) {
  1067. drawPixel_cont(x0 - y, y0 + x, color);
  1068. drawPixel_cont(x0 - x, y0 + y, color);
  1069. }
  1070. if (cornername & 0x1) {
  1071. drawPixel_cont(x0 - y, y0 - x, color);
  1072. drawPixel_cont(x0 - x, y0 - y, color);
  1073. }
  1074. }
  1075. disableCS();
  1076. }
  1077.  
  1078. void ILI9341_due::fillCircle(int16_t x0, int16_t y0, int16_t r,
  1079. uint16_t color)
  1080. {
  1081. beginTransaction();
  1082. drawFastVLine_noTrans(x0, y0 - r, 2 * r + 1, color);
  1083. fillCircleHelper(x0, y0, r, 3, 0, color);
  1084. endTransaction();
  1085. }
  1086.  
  1087. // Used to do circles and roundrects
  1088. // Further optimizations by Chris_CT
  1089. void ILI9341_due::fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
  1090. uint8_t cornername, int16_t delta, uint16_t color)
  1091. {
  1092. int16_t f = 1 - r;
  1093. int16_t ddF_x = 1;
  1094. int16_t ddF_y = -2 * r;
  1095. int16_t x = 0;
  1096. int16_t y = r;
  1097. int16_t ylm = x0 - r; // **added**
  1098.  
  1099. #ifdef ARDUINO_SAM_DUE
  1100. fillScanline16(color, 2 * max(x, y) + 1 + delta);
  1101. #else
  1102. fillScanline16(color);
  1103. #endif
  1104.  
  1105. enableCS();
  1106. while (x < y) {
  1107. if (f >= 0) {
  1108. if (cornername & 0x1) drawFastVLine_cont_noFill(x0 + y, y0 - x, 2 * x + 1 + delta, color); // **moved**
  1109. if (cornername & 0x2) drawFastVLine_cont_noFill(x0 - y, y0 - x, 2 * x + 1 + delta, color); // **moved**
  1110. ylm = x0 - y; // **added**
  1111. y--;
  1112. ddF_y += 2;
  1113. f += ddF_y;
  1114. }
  1115. x++;
  1116. ddF_x += 2;
  1117. f += ddF_x;
  1118.  
  1119. if ((x0 - x) > ylm) { // **added**
  1120. if (cornername & 0x1) drawFastVLine_cont_noFill(x0 + x, y0 - y, 2 * y + 1 + delta, color);
  1121. if (cornername & 0x2) drawFastVLine_cont_noFill(x0 - x, y0 - y, 2 * y + 1 + delta, color);
  1122. } // **added**
  1123. }
  1124. disableCS();
  1125. }
  1126.  
  1127. void ILI9341_due::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)
  1128. {
  1129. beginTransaction();
  1130. drawLine_noTrans(x0, y0, x1, y1, color);
  1131. endTransaction();
  1132. }
  1133.  
  1134. void ILI9341_due::drawLineByAngle(int16_t x, int16_t y, int16_t angle, uint16_t length, uint16_t color)
  1135. {
  1136. beginTransaction();
  1137. drawLine_noTrans(
  1138. x,
  1139. y,
  1140. x + length*cosDegrees(angle + _angleOffset),
  1141. y + length*sinDegrees(angle + _angleOffset), color);
  1142. endTransaction();
  1143. }
  1144.  
  1145.  
  1146. void ILI9341_due::drawLineByAngle(int16_t x, int16_t y, int16_t angle, uint16_t start, uint16_t length, uint16_t color)
  1147. {
  1148. beginTransaction();
  1149. drawLine_noTrans(
  1150. x + start*cosDegrees(angle + _angleOffset),
  1151. y + start*sinDegrees(angle + _angleOffset),
  1152. x + (start + length)*cosDegrees(angle + _angleOffset),
  1153. y + (start + length)*sinDegrees(angle + _angleOffset), color);
  1154. endTransaction();
  1155. }
  1156.  
  1157. // Bresenham's algorithm - thx wikpedia
  1158. void ILI9341_due::drawLine_noTrans(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)
  1159. {
  1160. beginTransaction();
  1161. if (y0 == y1) {
  1162. if (x1 > x0) {
  1163. drawFastHLine_noTrans(x0, y0, x1 - x0 + 1, color);
  1164. }
  1165. else if (x1 < x0) {
  1166. drawFastHLine_noTrans(x1, y0, x0 - x1 + 1, color);
  1167. }
  1168. else {
  1169. drawPixel_last(x0, y0, color);
  1170. }
  1171. return;
  1172. }
  1173. else if (x0 == x1) {
  1174. if (y1 > y0) {
  1175. drawFastVLine_noTrans(x0, y0, y1 - y0 + 1, color);
  1176. }
  1177. else {
  1178. drawFastVLine_noTrans(x0, y1, y0 - y1 + 1, color);
  1179. }
  1180. return;
  1181. }
  1182.  
  1183. bool steep = abs(y1 - y0) > abs(x1 - x0);
  1184. if (steep) {
  1185. swap(x0, y0);
  1186. swap(x1, y1);
  1187. }
  1188. if (x0 > x1) {
  1189. swap(x0, x1);
  1190. swap(y0, y1);
  1191. }
  1192.  
  1193. int16_t dx, dy;
  1194. dx = x1 - x0;
  1195. dy = abs(y1 - y0);
  1196.  
  1197. int16_t err = dx >> 1;
  1198. int16_t ystep;
  1199.  
  1200. if (y0 < y1) {
  1201. ystep = 1;
  1202. }
  1203. else {
  1204. ystep = -1;
  1205. }
  1206.  
  1207. int16_t xbegin = x0;
  1208.  
  1209. fillScanline16(color);
  1210.  
  1211. enableCS();
  1212. if (steep) {
  1213. for (; x0 <= x1; x0++) {
  1214. err -= dy;
  1215. if (err < 0) {
  1216. int16_t len = x0 - xbegin;
  1217. if (len) {
  1218. #ifdef ARDUINO_SAM_DUE
  1219. writeVLine_cont_noCS_noFill(y0, xbegin, len + 1);
  1220. #elif defined ARDUINO_ARCH_AVR
  1221. writeVLine_cont_noCS_noScanline(y0, xbegin, len + 1, color);
  1222. #endif
  1223. }
  1224. else {
  1225. writePixel_cont(y0, x0, color);
  1226. }
  1227. xbegin = x0 + 1;
  1228. y0 += ystep;
  1229. err += dx;
  1230. }
  1231. }
  1232. if (x0 > xbegin + 1) {
  1233. #ifdef ARDUINO_SAM_DUE
  1234. writeVLine_cont_noCS_noFill(y0, xbegin, x0 - xbegin);
  1235. #elif defined ARDUINO_ARCH_AVR
  1236. writeVLine_cont_noCS_noScanline(y0, xbegin, x0 - xbegin, color);
  1237. #endif
  1238. }
  1239.  
  1240. }
  1241. else {
  1242. for (; x0 <= x1; x0++) {
  1243. err -= dy;
  1244. if (err < 0) {
  1245. int16_t len = x0 - xbegin;
  1246. if (len) {
  1247. #ifdef ARDUINO_SAM_DUE
  1248. writeHLine_cont_noCS_noFill(xbegin, y0, len + 1);
  1249. #elif defined ARDUINO_ARCH_AVR
  1250. writeHLine_cont_noCS_noScanline(xbegin, y0, len + 1, color);
  1251. #endif
  1252. }
  1253. else {
  1254. writePixel_cont(x0, y0, color);
  1255. }
  1256. xbegin = x0 + 1;
  1257. y0 += ystep;
  1258. err += dx;
  1259. }
  1260. }
  1261. if (x0 > xbegin + 1) {
  1262. #ifdef ARDUINO_SAM_DUE
  1263. writeHLine_cont_noCS_noFill(xbegin, y0, x0 - xbegin);
  1264. #elif defined ARDUINO_ARCH_AVR
  1265. writeHLine_cont_noCS_noScanline(xbegin, y0, x0 - xbegin, color);
  1266. #endif
  1267. }
  1268. }
  1269. disableCS();
  1270. endTransaction();
  1271. }
  1272.  
  1273.  
  1274. // Draw a rectangle
  1275. //void ILI9341_due::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
  1276. //{
  1277. // writeHLine_cont(x, y, w, color);
  1278. // writeHLine_cont(x, y+h-1, w, color);
  1279. // writeVLine_cont(x, y, h, color);
  1280. // writeVLine_last(x+w-1, y, h, color);
  1281. //}
  1282.  
  1283. void ILI9341_due::drawRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color)
  1284. {
  1285. beginTransaction();
  1286.  
  1287. fillScanline16(color, min(SCANLINE_PIXEL_COUNT, max(w, h)));
  1288.  
  1289. enableCS();
  1290. writeHLine_cont_noCS_noFill(x, y, w);
  1291. writeHLine_cont_noCS_noFill(x, y + h - 1, w);
  1292. writeVLine_cont_noCS_noFill(x, y, h);
  1293. writeVLine_cont_noCS_noFill(x + w - 1, y, h);
  1294. disableCS();
  1295. endTransaction();
  1296. }
  1297.  
  1298. // Draw a rounded rectangle
  1299. void ILI9341_due::drawRoundRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t r, uint16_t color)
  1300. {
  1301. beginTransaction();
  1302.  
  1303. fillScanline16(color, min(SCANLINE_PIXEL_COUNT, max(w, h)));
  1304.  
  1305. enableCS();
  1306. // smarter version
  1307. writeHLine_cont_noCS_noFill(x + r, y, w - 2 * r); // Top
  1308. writeHLine_cont_noCS_noFill(x + r, y + h - 1, w - 2 * r); // Bottom
  1309. writeVLine_cont_noCS_noFill(x, y + r, h - 2 * r); // Left
  1310. writeVLine_cont_noCS_noFill(x + w - 1, y + r, h - 2 * r); // Right
  1311. disableCS();
  1312. // draw four corners
  1313. drawCircleHelper(x + r, y + r, r, 1, color);
  1314. drawCircleHelper(x + w - r - 1, y + r, r, 2, color);
  1315. drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4, color);
  1316. drawCircleHelper(x + r, y + h - r - 1, r, 8, color);
  1317. endTransaction();
  1318. }
  1319.  
  1320. // Fill a rounded rectangle
  1321. void ILI9341_due::fillRoundRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t r, uint16_t color)
  1322. {
  1323. beginTransaction();
  1324. // smarter version
  1325. fillRect_noTrans(x + r, y, w - 2 * r, h, color);
  1326.  
  1327. // draw four corners
  1328. fillCircleHelper(x + w - r - 1, y + r, r, 1, h - 2 * r - 1, color);
  1329. fillCircleHelper(x + r, y + r, r, 2, h - 2 * r - 1, color);
  1330. endTransaction();
  1331. }
  1332.  
  1333. // Draw a triangle
  1334. void ILI9341_due::drawTriangle(int16_t x0, int16_t y0,
  1335. int16_t x1, int16_t y1,
  1336. int16_t x2, int16_t y2, uint16_t color)
  1337. {
  1338. beginTransaction();
  1339. drawLine_noTrans(x0, y0, x1, y1, color);
  1340. drawLine_noTrans(x1, y1, x2, y2, color);
  1341. drawLine_noTrans(x2, y2, x0, y0, color);
  1342. endTransaction();
  1343. }
  1344.  
  1345. // Fill a triangle
  1346. void ILI9341_due::fillTriangle(int16_t x0, int16_t y0,
  1347. int16_t x1, int16_t y1,
  1348. int16_t x2, int16_t y2, uint16_t color)
  1349. {
  1350. beginTransaction();
  1351. int16_t a, b, y, last;
  1352.  
  1353. // Sort coordinates by Y order (y2 >= y1 >= y0)
  1354. if (y0 > y1) {
  1355. swap(y0, y1); swap(x0, x1);
  1356. }
  1357. if (y1 > y2) {
  1358. swap(y2, y1); swap(x2, x1);
  1359. }
  1360. if (y0 > y1) {
  1361. swap(y0, y1); swap(x0, x1);
  1362. }
  1363.  
  1364. if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
  1365. a = b = x0;
  1366. if (x1 < a) a = x1;
  1367. else if (x1 > b) b = x1;
  1368. if (x2 < a) a = x2;
  1369. else if (x2 > b) b = x2;
  1370. drawFastHLine_noTrans(a, y0, b - a + 1, color);
  1371. endTransaction();
  1372. return;
  1373. }
  1374.  
  1375. int16_t
  1376. dx01 = x1 - x0,
  1377. dy01 = y1 - y0,
  1378. dx02 = x2 - x0,
  1379. dy02 = y2 - y0,
  1380. dx12 = x2 - x1,
  1381. dy12 = y2 - y1,
  1382. sa = 0,
  1383. sb = 0;
  1384.  
  1385. // For upper part of triangle, find scanline crossings for segments
  1386. // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
  1387. // is included here (and second loop will be skipped, avoiding a /0
  1388. // error there), otherwise scanline y1 is skipped here and handled
  1389. // in the second loop...which also avoids a /0 error here if y0=y1
  1390. // (flat-topped triangle).
  1391. if (y1 == y2) last = y1; // Include y1 scanline
  1392. else last = y1 - 1; // Skip it
  1393.  
  1394. fillScanline16(color, min(SCANLINE_PIXEL_COUNT, max(x0, max(x1, x2)) - min(x0, min(x1, x2)))); // fill scanline with the widest scanline that'll be used
  1395.  
  1396. enableCS();
  1397. for (y = y0; y <= last; y++) {
  1398. a = x0 + sa / dy01;
  1399. b = x0 + sb / dy02;
  1400. sa += dx01;
  1401. sb += dx02;
  1402. /* longhand:
  1403. a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
  1404. b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
  1405. */
  1406. if (a > b) swap(a, b);
  1407. writeHLine_cont_noCS_noFill(a, y, b - a + 1);
  1408. }
  1409.  
  1410. // For lower part of triangle, find scanline crossings for segments
  1411. // 0-2 and 1-2. This loop is skipped if y1=y2.
  1412. sa = dx12 * (y - y1);
  1413. sb = dx02 * (y - y0);
  1414. for (; y <= y2; y++) {
  1415. a = x1 + sa / dy12;
  1416. b = x0 + sb / dy02;
  1417. sa += dx12;
  1418. sb += dx02;
  1419. /* longhand:
  1420. a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
  1421. b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
  1422. */
  1423. if (a > b) swap(a, b);
  1424. writeHLine_cont_noCS_noFill(a, y, b - a + 1);
  1425. }
  1426. disableCS();
  1427. endTransaction();
  1428. }
  1429.  
  1430. // draws monochrome (single color) bitmaps
  1431. void ILI9341_due::drawBitmap(const uint8_t *bitmap, int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color)
  1432. {
  1433. uint16_t i, j, byteWidth = (w + 7) / 8;
  1434.  
  1435. beginTransaction();
  1436. enableCS();
  1437. for (j = 0; j < h; j++)
  1438. {
  1439. for (i = 0; i < w; i++)
  1440. {
  1441. if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
  1442. drawPixel_cont(x + i, y + j, color);
  1443. }
  1444. }
  1445. }
  1446. disableCS();
  1447. endTransaction();
  1448. }
  1449.  
  1450. // draws monochrome (single color) bitmaps
  1451. void ILI9341_due::drawBitmap(const uint8_t *bitmap, int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color, uint16_t bgcolor)
  1452. {
  1453. uint16_t i, j, byteWidth = (w + 7) / 8;
  1454.  
  1455. beginTransaction();
  1456. enableCS();
  1457. for (j = 0; j < h; j++)
  1458. {
  1459. for (i = 0; i < w; i++)
  1460. {
  1461. if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
  1462. #if defined ARDUINO_ARCH_AVR
  1463. drawPixel_cont(x + i, y + j, color);
  1464. #elif defined ARDUINO_SAM_DUE
  1465. _scanline16[i] = color;
  1466. #endif
  1467. }
  1468. else
  1469. {
  1470. #if defined ARDUINO_ARCH_AVR
  1471. drawPixel_cont(x + i, y + j, bgcolor);
  1472. #elif defined ARDUINO_SAM_DUE
  1473. _scanline16[i] = bgcolor;
  1474. #endif
  1475. }
  1476. }
  1477. #ifdef ARDUINO_SAM_DUE
  1478. setAddrAndRW_cont(x, y + j, w, 1);
  1479. setDCForData();
  1480. writeScanline16(w);
  1481. #endif
  1482. }
  1483. disableCS();
  1484. endTransaction();
  1485. }
  1486.  
  1487. uint8_t ILI9341_due::getRotation(void) {
  1488. return _rotation;
  1489. }
  1490.  
  1491. // if true, tft will be blank (white),
  1492. // display's frame buffer is unaffected
  1493. // (you can write to it without showing content on the screen)
  1494. void ILI9341_due::display(boolean d){
  1495. beginTransaction();
  1496. writecommand_last(d ? ILI9341_DISPON : ILI9341_DISPOFF);
  1497. endTransaction();
  1498. }
  1499.  
  1500. // puts display in/out of sleep mode
  1501. void ILI9341_due::sleep(boolean s)
  1502. {
  1503. beginTransaction();
  1504. writecommand_last(s ? ILI9341_SLPIN : ILI9341_SLPOUT);
  1505. endTransaction();
  1506. delay(120);
  1507. }
  1508.  
  1509. void ILI9341_due::idle(boolean i){
  1510. beginTransaction();
  1511. writecommand_last(i ? ILI9341_IDMON : ILI9341_IDMOFF);
  1512. endTransaction();
  1513. }
  1514.  
  1515.  
  1516. void ILI9341_due::setPowerLevel(pwrLevel p)
  1517. {
  1518. switch (p)
  1519. {
  1520. case pwrLevelNormal:
  1521. if (_isIdle) { idle(false); _isIdle = false; }
  1522. if (_isInSleep) { sleep(false); _isInSleep = false; }
  1523. break;
  1524. case pwrLevelIdle:
  1525. if (!_isIdle) { idle(true); _isIdle = true; }
  1526. if (_isInSleep) { sleep(false); _isInSleep = false; }
  1527. break;
  1528. case pwrLevelSleep:
  1529. if (!_isInSleep) { sleep(true); _isInSleep = true; }
  1530. if (_isIdle) { idle(false); _isIdle = false; }
  1531. break;
  1532. }
  1533. }
  1534.  
  1535.  
  1536. void ILI9341_due::setArcParams(float arcAngleMax)
  1537. {
  1538. _arcAngleMax = arcAngleMax;
  1539. }
  1540.  
  1541. void ILI9341_due::setAngleOffset(int16_t angleOffset)
  1542. {
  1543. _angleOffset = DEFAULT_ANGLE_OFFSET + angleOffset;
  1544. }
  1545.  
  1546. //uint8_t ILI9341_due::spiread(void) {
  1547. // uint8_t r = 0;
  1548. //
  1549. // //SPI.setClockDivider(_cs, 12); // 8-ish MHz (full! speed!)
  1550. // //SPI.setBitOrder(_cs, MSBFIRST);
  1551. // //SPI.setDataMode(_cs, SPI_MODE0);
  1552. // r = SPI.transfer(_cs, 0x00);
  1553. // Serial.print("read: 0x"); Serial.print(r, HEX);
  1554. //
  1555. // return r;
  1556. //}
  1557. //
  1558. //void ILI9341_due::spiwrite(uint8_t c) {
  1559. //
  1560. // //Serial.print("0x"); Serial.print(c, HEX); Serial.print(", ");
  1561. //
  1562. //
  1563. // //SPI.setClockDivider(_cs, 12); // 8-ish MHz (full! speed!)
  1564. // //SPI.setBitOrder(_cs, MSBFIRST);
  1565. // //SPI.setDataMode(_cs, SPI_MODE0);
  1566. // SPI.transfer(_cs, c);
  1567. //
  1568. //}
  1569.  
  1570. //void ILI9341_due::writecommand(uint8_t c) {
  1571. // //*dcport &= ~dcpinmask;
  1572. // digitalWrite(_dc, LOW);
  1573. // //*clkport &= ~clkpinmask; // clkport is a NULL pointer when hwSPI==true
  1574. // //digitalWrite(_sclk, LOW);
  1575. // //*csport &= ~cspinmask;
  1576. // //digitalWrite(_cs, LOW);
  1577. //
  1578. // spiwrite(c);
  1579. //
  1580. // //*csport |= cspinmask;
  1581. // //digitalWrite(_cs, HIGH);
  1582. //}
  1583. //
  1584. //
  1585. //void ILI9341_due::writedata(uint8_t c) {
  1586. // //*dcport |= dcpinmask;
  1587. // digitalWrite(_dc, HIGH);
  1588. // //*clkport &= ~clkpinmask; // clkport is a NULL pointer when hwSPI==true
  1589. // //digitalWrite(_sclk, LOW);
  1590. // //*csport &= ~cspinmask;
  1591. // //digitalWrite(_cs, LOW);
  1592. //
  1593. // spiwrite(c);
  1594. //
  1595. // //digitalWrite(_cs, HIGH);
  1596. // //*csport |= cspinmask;
  1597. //}
  1598.  
  1599. void ILI9341_due::printHex8(uint8_t *data, uint8_t length) // prints 8-bit data in hex
  1600. {
  1601. char tmp[length * 2 + 1];
  1602. byte first;
  1603. byte second;
  1604. for (int i = 0; i < length; i++) {
  1605. first = (data[i] >> 4) & 0x0f;
  1606. second = data[i] & 0x0f;
  1607. // base for converting single digit numbers to ASCII is 48
  1608. // base for 10-16 to become upper-case characters A-F is 55
  1609. // note: difference is 7
  1610. tmp[i * 2] = first + 48;
  1611. tmp[i * 2 + 1] = second + 48;
  1612. if (first > 9) tmp[i * 2] += 7;
  1613. if (second > 9) tmp[i * 2 + 1] += 7;
  1614. }
  1615. tmp[length * 2] = 0;
  1616. Serial.print(tmp);
  1617. }
  1618.  
  1619.  
  1620. void ILI9341_due::printHex16(uint16_t *data, uint8_t length) // prints 8-bit data in hex
  1621. {
  1622. char tmp[length * 4 + 1];
  1623. byte first;
  1624. byte second;
  1625. byte third;
  1626. byte fourth;
  1627. for (int i = 0; i < length; i++) {
  1628. first = (data[i] >> 12) & 0x0f;
  1629. second = (data[i] >> 8) & 0x0f;
  1630. third = (data[i] >> 4) & 0x0f;
  1631. fourth = data[i] & 0x0f;
  1632. //Serial << first << " " << second << " " << third << " " << fourth << endl;
  1633. // base for converting single digit numbers to ASCII is 48
  1634. // base for 10-16 to become upper-case characters A-F is 55
  1635. // note: difference is 7
  1636. tmp[i * 4] = first + 48;
  1637. tmp[i * 4 + 1] = second + 48;
  1638. tmp[i * 4 + 2] = third + 48;
  1639. tmp[i * 4 + 3] = fourth + 48;
  1640. //tmp[i*5+4] = 32; // add trailing space
  1641. if (first > 9) tmp[i * 4] += 7;
  1642. if (second > 9) tmp[i * 4 + 1] += 7;
  1643. if (third > 9) tmp[i * 4 + 2] += 7;
  1644. if (fourth > 9) tmp[i * 4 + 3] += 7;
  1645. }
  1646. tmp[length * 4] = 0;
  1647. Serial.print(tmp);
  1648. }
  1649.  
  1650. void ILI9341_due::printHex32(uint32_t *data, uint8_t length) // prints 8-bit data in hex
  1651. {
  1652. char tmp[length * 8 + 1];
  1653. byte dataByte[8];
  1654. for (int i = 0; i < length; i++) {
  1655. dataByte[0] = (data[i] >> 28) & 0x0f;
  1656. dataByte[1] = (data[i] >> 24) & 0x0f;
  1657. dataByte[2] = (data[i] >> 20) & 0x0f;
  1658. dataByte[3] = (data[i] >> 16) & 0x0f;
  1659. dataByte[4] = (data[i] >> 12) & 0x0f;
  1660. dataByte[5] = (data[i] >> 8) & 0x0f;
  1661. dataByte[6] = (data[i] >> 4) & 0x0f;
  1662. dataByte[7] = data[i] & 0x0f;
  1663. //Serial << first << " " << second << " " << third << " " << fourth << endl;
  1664. // base for converting single digit numbers to ASCII is 48
  1665. // base for 10-16 to become upper-case characters A-F is 55
  1666. // note: difference is 7
  1667. tmp[i * 4] = dataByte[0] + 48;
  1668. tmp[i * 4 + 1] = dataByte[1] + 48;
  1669. tmp[i * 4 + 2] = dataByte[2] + 48;
  1670. tmp[i * 4 + 3] = dataByte[3] + 48;
  1671. tmp[i * 4 + 4] = dataByte[4] + 48;
  1672. tmp[i * 4 + 5] = dataByte[5] + 48;
  1673. tmp[i * 4 + 6] = dataByte[6] + 48;
  1674. tmp[i * 4 + 7] = dataByte[7] + 48;
  1675. //tmp[i*5+4] = 32; // add trailing space
  1676. if (dataByte[0] > 9) tmp[i * 4] += 7;
  1677. if (dataByte[1] > 9) tmp[i * 4 + 1] += 7;
  1678. if (dataByte[2] > 9) tmp[i * 4 + 2] += 7;
  1679. if (dataByte[3] > 9) tmp[i * 4 + 3] += 7;
  1680. if (dataByte[4] > 9) tmp[i * 4 + 4] += 7;
  1681. if (dataByte[5] > 9) tmp[i * 4 + 5] += 7;
  1682. if (dataByte[6] > 9) tmp[i * 4 + 6] += 7;
  1683. if (dataByte[7] > 9) tmp[i * 4 + 7] += 7;
  1684. }
  1685. tmp[length * 8] = 0;
  1686. Serial.print(tmp);
  1687. }
  1688.  
  1689.  
  1690.  
  1691. void ILI9341_due::clearTextArea()
  1692. {
  1693. fillRect(_area.x, _area.y, _area.w, _area.h, _fontBgColor);
  1694. }
  1695.  
  1696. void ILI9341_due::clearTextArea(uint16_t color)
  1697. {
  1698. fillRect(_area.x, _area.y, _area.w, _area.h, color);
  1699. }
  1700.  
  1701. void ILI9341_due::clearTextArea(gTextArea area)
  1702. {
  1703. fillRect(area.x, area.y, area.w, area.h, _fontBgColor);
  1704. }
  1705.  
  1706. void ILI9341_due::clearTextArea(gTextArea area, uint16_t color)
  1707. {
  1708. fillRect(area.x, area.y, area.w, area.h, color);
  1709. }
  1710.  
  1711. void ILI9341_due::setTextArea(gTextArea area) //, textMode mode)
  1712. {
  1713. _area.x = area.x;
  1714. _area.y = area.y;
  1715. _area.w = area.w;
  1716. _area.h = area.h;
  1717. _x = _xStart = area.x;
  1718. _y = _yStart = area.y;
  1719. }
  1720.  
  1721. //void ILI9341_due::setTextArea(int16_t x0, int16_t y0, int16_t x1, int16_t y1) //, textMode mode)
  1722. //{
  1723. // _area.x = x0;
  1724. // _area.y = y0;
  1725. // _area.x1 = x1;
  1726. // _area.y1 = y1;
  1727. // _x = x0;
  1728. // _y = y0;
  1729. //}
  1730.  
  1731. void ILI9341_due::setTextArea(int16_t x, int16_t y, int16_t columns, int16_t rows, gTextFont font) //, textMode mode)
  1732. {
  1733. //textMode mode = DEFAULT_SCROLLDIR;
  1734. uint16_t x1, y1;
  1735.  
  1736. setFont(font);
  1737.  
  1738. x1 = x + columns * (pgm_read_byte(_font + GTEXT_FONT_FIXED_WIDTH) + 1) - 1;
  1739. y1 = y + rows * (fontHeight() + 1) - 1;
  1740.  
  1741. setTextArea(x, y, x1, y1); //, mode);
  1742. }
  1743.  
  1744. void ILI9341_due::setTextArea(int16_t x, int16_t y, int16_t w, int16_t h) //, textMode mode)
  1745. {
  1746. _area.x = x;
  1747. _area.y = y;
  1748. _area.w = w;
  1749. _area.h = h;
  1750. _x = _xStart = x;
  1751. _y = _xStart = y;
  1752. }
  1753.  
  1754. __attribute__((always_inline))
  1755. void ILI9341_due::specialChar(uint8_t c)
  1756. {
  1757.  
  1758.  
  1759. if (c == '\n')
  1760. {
  1761. uint8_t height = fontHeight();
  1762.  
  1763. /*
  1764. * Erase all pixels remaining to edge of text area.on all wraps
  1765. * It looks better when using inverted (WHITE) text, on proportional fonts, and
  1766. * doing WHITE scroll fills.
  1767. *
  1768. */
  1769.  
  1770.  
  1771. /*if (_fontMode == gTextFontModeSolid && _x < _area.x1)
  1772. fillRect(_x, _y, _area.x1 - _x, height, _fontBgColor);*/
  1773. //glcd_Device::SetPixels(_x, _y, _area.x1, _y+height, _fontColor == BLACK ? WHITE : BLACK);
  1774.  
  1775. // /*
  1776. // * Check for scroll up vs scroll down (scrollup is normal)
  1777. // */
  1778. //#ifndef GLCD_NO_SCROLLDOWN
  1779. // if (_area.mode == SCROLL_UP)
  1780. //#endif
  1781. // {
  1782. //
  1783. // /*
  1784. // * Normal/up scroll
  1785. // */
  1786. //
  1787. // /*
  1788. // * Note this comparison and the pixel calcuation below takes into
  1789. // * consideration that fonts
  1790. // * are atually 1 pixel taller when rendered.
  1791. // * This extra pixel is along the bottom for a "gap" between the character below.
  1792. // */
  1793. // if (_y + 2 * height >= _area.y1)
  1794. // {
  1795. //#ifndef GLCD_NODEFER_SCROLL
  1796. // if (!_needScroll)
  1797. // {
  1798. // _needScroll = 1;
  1799. // return;
  1800. // }
  1801. //#endif
  1802. //
  1803. // /*
  1804. // * forumula for pixels to scroll is:
  1805. // * (assumes "height" is one less than rendered height)
  1806. // *
  1807. // * pixels = height - ((_area.y1 - _y) - height) +1;
  1808. // *
  1809. // * The forumala below is unchanged
  1810. // * But has been re-written/simplified in hopes of better code
  1811. // *
  1812. // */
  1813. //
  1814. // uint8_t pixels = 2 * height + _y - _area.y1 + 1;
  1815. //
  1816. // /*
  1817. // * Scroll everything to make room
  1818. // * * NOTE: (FIXME, slight "bug")
  1819. // * When less than the full character height of pixels is scrolled,
  1820. // * There can be an issue with the newly created empty line.
  1821. // * This is because only the # of pixels scrolled will be colored.
  1822. // * What it means is that if the area starts off as white and the text
  1823. // * color is also white, the newly created empty text line after a scroll
  1824. // * operation will not be colored BLACK for the full height of the character.
  1825. // * The only way to fix this would be alter the code use a "move pixels"
  1826. // * rather than a scroll pixels, and then do a clear to end line immediately
  1827. // * after the move and wrap.
  1828. // *
  1829. // * Currently this only shows up when
  1830. // * there are are less than 2xheight pixels below the current Y coordinate to
  1831. // * the bottom of the text area
  1832. // * and the current background of the pixels below the current text line
  1833. // * matches the text color
  1834. // * and a wrap was just completed.
  1835. // *
  1836. // * After a full row of text is printed, the issue will resolve itself.
  1837. // *
  1838. // *
  1839. // */
  1840. // //ScrollUp(_area.x, _area.y, _area.x1, _area.y1, pixels, _fontBgColor);
  1841. //
  1842. // _x = _area.x;
  1843. // _y = _area.y1 - height;
  1844. // }
  1845. // else
  1846. // {
  1847. /*
  1848. * Room for simple wrap
  1849. */
  1850.  
  1851. _x = _xStart; // _area.x;
  1852. _y = _y + (height + _lineSpacing)*_textScale;
  1853. _isFirstChar = true;
  1854.  
  1855. // }
  1856. // }
  1857. //#ifndef GLCD_NO_SCROLLDOWN
  1858. // else
  1859. // {
  1860. // /*
  1861. // * Reverse/Down scroll
  1862. // */
  1863. //
  1864. // /*
  1865. // * Check for Wrap vs scroll.
  1866. // *
  1867. // * Note this comparison and the pixel calcuation below takes into
  1868. // * consideration that fonts
  1869. // * are atually 1 pixel taller when rendered.
  1870. // *
  1871. // */
  1872. // if (_y > _area.y + height)
  1873. // {
  1874. // /*
  1875. // * There is room so just do a simple wrap
  1876. // */
  1877. // _x = _area.x;
  1878. // _y = _y - (height + 1);
  1879. // }
  1880. // else
  1881. // {
  1882. //#ifndef GLCD_NODEFER_SCROLL
  1883. // if (!_needScroll)
  1884. // {
  1885. // _needScroll = 1;
  1886. // return;
  1887. // }
  1888. //#endif
  1889. //
  1890. // /*
  1891. // * Scroll down everything to make room for new line
  1892. // * (assumes "height" is one less than rendered height)
  1893. // */
  1894. //
  1895. // uint8_t pixels = height + 1 - (_area.y - _y);
  1896. //
  1897. // //ScrollDown(_area.x, _area.y, _area.x1, _area.y1, pixels, _fontBgColor);
  1898. //
  1899. // _x = _area.x;
  1900. // _y = _area.y;
  1901. // }
  1902. // }
  1903. //#endif
  1904. }
  1905. else if (c == '\r'){
  1906. _isFirstChar = true;
  1907. }
  1908.  
  1909. }
  1910.  
  1911. size_t ILI9341_due::write(uint8_t c)
  1912. {
  1913. //Serial << c << endl2;
  1914. if (_font == 0)
  1915. {
  1916. Serial.println(F("No font selected"));
  1917. return 0; // no font selected
  1918. }
  1919.  
  1920. /*
  1921. * check for special character processing
  1922. */
  1923.  
  1924. if (c < 0x20)
  1925. {
  1926. specialChar(c);
  1927. return 1;
  1928. }
  1929. uint16_t charWidth = 0;
  1930. uint16_t charHeight = fontHeight();
  1931. uint8_t charHeightInBytes = (charHeight + 7) / 8; /* calculates height in rounded up bytes */
  1932.  
  1933. uint8_t firstChar = pgm_read_byte(_font + GTEXT_FONT_FIRST_CHAR);
  1934. uint8_t charCount = pgm_read_byte(_font + GTEXT_FONT_CHAR_COUNT);
  1935.  
  1936. uint16_t index = 0;
  1937.  
  1938. if (c < firstChar || c >= (firstChar + charCount)) {
  1939. return 0; // invalid char
  1940. }
  1941. c -= firstChar;
  1942.  
  1943. if (isFixedWidthFont(_font) {
  1944. //thielefont = 0;
  1945. charWidth = pgm_read_byte(_font + GTEXT_FONT_FIXED_WIDTH);
  1946. index = c*charHeightInBytes*charWidth + GTEXT_FONT_WIDTH_TABLE;
  1947. }
  1948. else{
  1949. // variable width font, read width data, to get the index
  1950. //thielefont = 1;
  1951. /*
  1952. * Because there is no table for the offset of where the data
  1953. * for each character glyph starts, run the table and add up all the
  1954. * widths of all the characters prior to the character we
  1955. * need to locate.
  1956. */
  1957. for (uint8_t i = 0; i < c; i++) {
  1958. index += pgm_read_byte(_font + GTEXT_FONT_WIDTH_TABLE + i);
  1959. }
  1960. /*
  1961. * Calculate the offset of where the font data
  1962. * for our character starts.
  1963. * The index value from above has to be adjusted because
  1964. * there is potentialy more than 1 byte per column in the glyph,
  1965. * when the characgter is taller than 8 bits.
  1966. * To account for this, index has to be multiplied
  1967. * by the height in bytes because there is one byte of font
  1968. * data for each vertical 8 pixels.
  1969. * The index is then adjusted to skip over the font width data
  1970. * and the font header information.
  1971. */
  1972.  
  1973. index = index*charHeightInBytes + charCount + GTEXT_FONT_WIDTH_TABLE;
  1974.  
  1975. /*
  1976. * Finally, fetch the width of our character
  1977. */
  1978. charWidth = pgm_read_byte(_font + GTEXT_FONT_WIDTH_TABLE + c);
  1979. }
  1980.  
  1981. //#ifndef GLCD_NODEFER_SCROLL
  1982. // /*
  1983. // * check for a defered scroll
  1984. // * If there is a deferred scroll,
  1985. // * Fake a newline to complete it.
  1986. // */
  1987. //
  1988. // if (_needScroll)
  1989. // {
  1990. // write('\n'); // fake a newline to cause wrap/scroll
  1991. // _needScroll = 0;
  1992. // }
  1993. //#endif
  1994.  
  1995. /*
  1996. * If the character won't fit in the text area,
  1997. * fake a newline to get the text area to wrap and
  1998. * scroll if necessary.
  1999. * NOTE/WARNING: the below calculation assumes a 1 pixel pad.
  2000. * This will need to be changed if/when configurable pixel padding is supported.
  2001. */
  2002. // if (_wrap && _x + charWidth > _area.x1)
  2003. // {
  2004. // write('\n'); // fake a newline to cause wrap/scroll
  2005. //#ifndef GLCD_NODEFER_SCROLL
  2006. // /*
  2007. // * We can't defer a scroll at this point since we need to ouput
  2008. // * a character right now.
  2009. // */
  2010. // if (_needScroll)
  2011. // {
  2012. // write('\n'); // fake a newline to cause wrap/scroll
  2013. // _needScroll = 0;
  2014. // }
  2015. //#endif
  2016. // }
  2017. beginTransaction();
  2018. if (_fontMode == gTextFontModeSolid)
  2019. drawSolidChar(c, index, charWidth, charHeight);
  2020. else if (_fontMode == gTextFontModeTransparent)
  2021. drawTransparentChar(c, index, charWidth, charHeight);
  2022. endTransaction();
  2023.  
  2024. return 1; // valid char
  2025. }
  2026.  
  2027. void ILI9341_due::drawSolidChar(char c, uint16_t index, uint16_t charWidth, uint16_t charHeight)
  2028. {
  2029. uint8_t bitId = 0;
  2030. uint16_t py;
  2031. #ifdef ARDUINO_SAM_DUE
  2032. uint16_t lineId = 0;
  2033. #endif
  2034. uint16_t charHeightInBytes = (charHeight + 7) / 8; /* calculates height in rounded up bytes */
  2035.  
  2036. uint8_t numRenderBits = 8;
  2037. const uint8_t numRemainingBits = charHeight % 8;
  2038. uint16_t numPixelsInOnePoint = 1;
  2039. if (_textScale > 1)
  2040. numPixelsInOnePoint = (uint16_t)_textScale *(uint16_t)_textScale;
  2041. #ifdef ARDUINO_ARCH_AVR
  2042. uint16_t pixelsInOnePointToDraw;
  2043. #endif
  2044.  
  2045. if (_letterSpacing > 0 && !_isFirstChar)
  2046. {
  2047. #ifdef LINE_SPACING_AS_PART_OF_LETTERS
  2048. fillRect(_x, _y, _letterSpacing * _textScale, (charHeight + _lineSpacing)*_textScale, _fontBgColor);
  2049. #else
  2050. fillRect(_x, _y, _letterSpacing * _textScale, charHeight *_textScale, _fontBgColor);
  2051. #endif
  2052. _x += _letterSpacing * _textScale;
  2053. }
  2054. _isFirstChar = false;
  2055.  
  2056. #ifdef LINE_SPACING_AS_PART_OF_LETTERS
  2057. if (_lineSpacing > 0){
  2058. fillRect(_x, _y + charHeight*_textScale, charWidth * _textScale, _lineSpacing *_textScale, _fontBgColor);
  2059. }
  2060. #endif
  2061.  
  2062. //#if SPI_MODE_DMA
  2063. // if (_textScale > 1)
  2064. // fillScanline16(_fontColor, numPixelsInOnePoint); //pre-fill the scanline, we will be drawing different lenghts of it
  2065. //#endif
  2066.  
  2067. enableCS();
  2068. if (_textScale == 1)
  2069. setRowAddr(_y, charHeight);
  2070.  
  2071. for (uint16_t j = 0; j < charWidth; j++) /* each column */
  2072. {
  2073. //Serial << "Printing row" << endl;
  2074. #ifdef ARDUINO_SAM_DUE
  2075. lineId = 0;
  2076. #endif
  2077. numRenderBits = 8;
  2078. if (_x >= 0 && _x < _width)
  2079. {
  2080. setColumnAddr(_x, _textScale);
  2081.  
  2082. if (_textScale == 1)
  2083. {
  2084. //setAddrAndRW_cont(_x, _y, 1, charHeight);
  2085. setRW();
  2086. setDCForData();
  2087. }
  2088.  
  2089. for (uint16_t i = 0; i < charHeightInBytes; i++) /* each vertical byte */
  2090. {
  2091. uint16_t page = i*charWidth; // page must be 16 bit to prevent overflow
  2092. uint8_t data = pgm_read_byte(_font + index + page + j);
  2093.  
  2094. /*
  2095. * This funkyness is because when the character glyph is not a
  2096. * multiple of 8 in height, the residual bits in the font data
  2097. * were aligned to the incorrect end of the byte with respect
  2098. * to the GLCD. I believe that this was an initial oversight (bug)
  2099. * in Thieles font creator program. It is easily fixed
  2100. * in the font program but then creates a potential backward
  2101. * compatiblity problem.
  2102. * --- bperrybap
  2103. */
  2104. if (charHeight > 8 && charHeight < (i + 1) * 8) /* is it last byte of multibyte tall font? */
  2105. {
  2106. data >>= ((i + 1) << 3) - charHeight; // (i+1)*8
  2107. }
  2108. //Serial << "data:" <<data << " x:" << cx << " y:" << cy << endl;
  2109.  
  2110.  
  2111. if (i == charHeightInBytes - 1) // last byte in column
  2112. numRenderBits = numRemainingBits;
  2113.  
  2114. for (bitId = 0; bitId < numRenderBits; bitId++)
  2115. {
  2116. py = _y + (i * 8 + bitId)*_textScale;
  2117. if ((data & 0x01) == 0)
  2118. {
  2119. if (_textScale == 1)
  2120. {
  2121. #ifdef ARDUINO_ARCH_AVR
  2122. write16_cont(_fontBgColor);
  2123. #elif defined ARDUINO_SAM_DUE
  2124. _scanline16[lineId++] = _fontBgColor;
  2125. #endif
  2126. }
  2127. else
  2128. {
  2129. // set a rectangle area
  2130. //setAddrAndRW_cont(_x, py, _textScale, _textScale);
  2131. setRowAddr(py, _textScale);
  2132. setRW();
  2133. //Serial << cx << " " << cy + (i * 8 + bitId)*_textScale << " " << _textScale <<endl2;
  2134. setDCForData();
  2135. #ifdef ARDUINO_ARCH_AVR
  2136. pixelsInOnePointToDraw = numPixelsInOnePoint;
  2137. while (pixelsInOnePointToDraw--){
  2138. write16_cont(_fontBgColor);
  2139. }
  2140. #elif defined ARDUINO_SAM_DUE
  2141. fillScanline16(_fontBgColor, numPixelsInOnePoint);
  2142. writeScanlineLooped(numPixelsInOnePoint);
  2143. #endif
  2144. }
  2145. }
  2146. else
  2147. {
  2148. if (_textScale == 1)
  2149. {
  2150. #ifdef ARDUINO_ARCH_AVR
  2151. write16_cont(_fontColor);
  2152. #elif defined ARDUINO_SAM_DUE
  2153. _scanline16[lineId++] = _fontColor;
  2154. #endif
  2155. }
  2156. else
  2157. {
  2158. // set a rectangle area
  2159. //setAddrAndRW_cont(_x, py, _textScale, _textScale);
  2160. setRowAddr(py, _textScale);
  2161. setRW();
  2162. setDCForData();
  2163. #ifdef ARDUINO_ARCH_AVR
  2164. pixelsInOnePointToDraw = numPixelsInOnePoint;
  2165. while (pixelsInOnePointToDraw--){
  2166. write16_cont(_fontColor);
  2167. }
  2168. #elif defined ARDUINO_SAM_DUE
  2169. fillScanline16(_fontColor, numPixelsInOnePoint);
  2170. writeScanlineLooped(numPixelsInOnePoint);
  2171. #endif
  2172. }
  2173. }
  2174. data >>= 1;
  2175. }
  2176.  
  2177. //#ifdef ARDUINO_ARCH_AVR
  2178. //if (_textScale == 1 && (lineId == SCANLINE_PIXEL_COUNT - 1 || i == charHeightInBytes - 1)) // we have either filled the buffer or are rendering the bottom portion of the char
  2179. //{
  2180. // writeScanline16(numRenderBits); // max 8
  2181. // lineId = 0;
  2182. //}
  2183. //#endif
  2184.  
  2185. //delay(50);
  2186. }
  2187. }
  2188. //Serial << endl;
  2189. #ifdef ARDUINO_SAM_DUE
  2190. if (_textScale == 1)
  2191. {
  2192. writeScanline16(charHeight);
  2193. }
  2194. #endif
  2195. _x += _textScale;
  2196.  
  2197. }
  2198. disableCS(); // to put CS line back up
  2199.  
  2200. //_x = cx;
  2201.  
  2202. //Serial << " ending at " << _x << " lastChar " << _lastChar <<endl;
  2203.  
  2204.  
  2205. //Serial << "letterSpacing " << _letterSpacing <<" x: " << _x <<endl;
  2206. }
  2207.  
  2208. void ILI9341_due::drawTransparentChar(char c, uint16_t index, uint16_t charWidth, uint16_t charHeight)
  2209. {
  2210. uint8_t bitId = 0;
  2211. uint8_t bit = 0, lastBit = 0;
  2212. uint16_t lineStart = 0;
  2213. uint16_t lineEnd = 0;
  2214. if (_letterSpacing > 0 && !_isFirstChar)
  2215. {
  2216. _x += _letterSpacing * _textScale;
  2217. }
  2218. _isFirstChar = false;
  2219.  
  2220.  
  2221. fillScanline16(_fontColor); //pre-fill the scanline, we will be drawing different lenghts of it
  2222.  
  2223.  
  2224. uint16_t charHeightInBytes = (charHeight + 7) / 8; /* calculates height in rounded up bytes */
  2225.  
  2226. uint8_t numRenderBits = 8;
  2227. const uint8_t numRemainingBits = charHeight % 8;
  2228.  
  2229. enableCS();
  2230.  
  2231. for (uint8_t j = 0; j < charWidth; j++) /* each column */
  2232. {
  2233. //Serial << "Printing row" << endl;
  2234. numRenderBits = 8;
  2235.  
  2236. if (_x >= 0 && _x < _width)
  2237. {
  2238. setColumnAddr(_x, _textScale);
  2239.  
  2240. for (uint16_t i = 0; i < charHeightInBytes; i++) /* each vertical byte */
  2241. {
  2242. uint16_t page = i*charWidth; // page must be 16 bit to prevent overflow
  2243. uint8_t data = pgm_read_byte(_font + index + page + j);
  2244.  
  2245. /*
  2246. * This funkyness is because when the character glyph is not a
  2247. * multiple of 8 in height, the residual bits in the font data
  2248. * were aligned to the incorrect end of the byte with respect
  2249. * to the GLCD. I believe that this was an initial oversight (bug)
  2250. * in Thieles font creator program. It is easily fixed
  2251. * in the font program but then creates a potential backward
  2252. * compatiblity problem.
  2253. * --- bperrybap
  2254. */
  2255. if (charHeight > 8 && charHeight < (i + 1) * 8) /* is it last byte of multibyte tall font? */
  2256. {
  2257. data >>= ((i + 1) << 3) - charHeight; // (i+1)*8
  2258. }
  2259. //Serial << "data:" <<data << " x:" << cx << " y:" << cy << endl;
  2260.  
  2261. if (i == 0)
  2262. bit = lastBit = lineStart = 0;
  2263. else if (i == charHeightInBytes - 1) // last byte in column
  2264. numRenderBits = numRemainingBits;
  2265.  
  2266. for (bitId = 0; bitId < numRenderBits; bitId++)
  2267. {
  2268. bit = data & 0x01;
  2269. if (bit ^ lastBit) // same as bit != lastBit
  2270. {
  2271. if (bit ^ 0x00) // if bit != 0 (so it's 1)
  2272. {
  2273. lineStart = lineEnd = (i * 8 + bitId) * _textScale;
  2274. }
  2275. else
  2276. {
  2277. const uint32_t totalPixels = (lineEnd - lineStart + _textScale) * _textScale;
  2278. //setRowAddr(_y + lineStart, _y + lineEnd + _textScale - 1);
  2279. setRowAddr(_y + lineStart, lineEnd - lineStart + _textScale);
  2280. setRW();
  2281. setDCForData();
  2282. writeScanlineLooped(totalPixels);
  2283.  
  2284. //setAddrAndRW_cont(_x, _y + lineStart, _textScale, lineEnd - lineStart + _textScale);
  2285. ////fillRect(cx, cy + lineStart, _textScale, lineEnd - lineStart + _textScale, ILI9341_BLUEVIOLET);
  2286.  
  2287. //setDCForData();
  2288.  
  2289. //for (uint8_t s = 0; s < _textScale; s++)
  2290. //{
  2291. // writeScanline16(lineEnd - lineStart + _textScale);
  2292. //}
  2293. }
  2294. lastBit = bit;
  2295. }
  2296. else if (bit ^ 0x00) // increment only if bit is 1
  2297. {
  2298. lineEnd += _textScale;
  2299. }
  2300.  
  2301. data >>= 1;
  2302. }
  2303.  
  2304. if (lineEnd == (charHeight - 1) * _textScale) // we have a line that goes all the way to the bottom
  2305. {
  2306. const uint32_t totalPixels = uint32_t(lineEnd - lineStart + _textScale)*(uint32_t)_textScale;
  2307. //setRowAddr(_y + lineStart, _y + lineEnd + _textScale - 1);
  2308. setRowAddr(_y + lineStart, lineEnd - lineStart + _textScale);
  2309. setRW();
  2310. setDCForData();
  2311. writeScanlineLooped(totalPixels);
  2312.  
  2313. ////fillRect(cx, cy + lineStart, _textScale, lineEnd - lineStart + _textScale, ILI9341_BLUEVIOLET);
  2314. //setAddrAndRW_cont(_x, _y + lineStart, _textScale, lineEnd - lineStart + _textScale);
  2315. //setDCForData();
  2316.  
  2317. //for (uint8_t s = 0; s < _textScale; s++)
  2318. //{
  2319. // writeScanline16(lineEnd - lineStart + _textScale);
  2320. // //delay(25);
  2321. //}
  2322. }
  2323. }
  2324. }
  2325. //Serial << endl;
  2326. _x += _textScale;
  2327. }
  2328. disableCS(); // to put CS line back up
  2329.  
  2330. //_x = cx;
  2331. }
  2332.  
  2333. size_t ILI9341_due::print(char c){
  2334. _isFirstChar = true;
  2335. beginTransaction();
  2336. write(c);
  2337. endTransaction();
  2338. return 0;
  2339. }
  2340. size_t ILI9341_due::print(unsigned char c, int b){
  2341. _isFirstChar = true;
  2342. beginTransaction();
  2343. Print::print(c,b);
  2344. endTransaction();
  2345. return 0;
  2346. }
  2347. size_t ILI9341_due::print(int d, int b){
  2348. _isFirstChar = true;
  2349. beginTransaction();
  2350. Print::print(d,b);
  2351. endTransaction();
  2352. return 0;
  2353. }
  2354. size_t ILI9341_due::print(unsigned int u, int b){
  2355. _isFirstChar = true;
  2356. beginTransaction();
  2357. Print::print(u,b);
  2358. endTransaction();
  2359. return 0;
  2360. }
  2361. size_t ILI9341_due::print(long l, int b){
  2362. _isFirstChar = true;
  2363. beginTransaction();
  2364. Print::print(l,b);
  2365. endTransaction();
  2366. return 0;
  2367. }
  2368. size_t ILI9341_due::print(unsigned long ul, int b){
  2369. _isFirstChar = true;
  2370. beginTransaction();
  2371. Print::print(ul,b);
  2372. endTransaction();
  2373. return 0;
  2374. }
  2375. size_t ILI9341_due::print(double d, int b){
  2376. _isFirstChar = true;
  2377. beginTransaction();
  2378. Print::print(d,b);
  2379. endTransaction();
  2380. return 0;
  2381. }
  2382. size_t ILI9341_due::print(const Printable& str){
  2383. _isFirstChar = true;
  2384. beginTransaction();
  2385. Print::print(str);
  2386. endTransaction();
  2387. return 0;
  2388. }
  2389.  
  2390. size_t ILI9341_due::println(const __FlashStringHelper *str){
  2391. _isFirstChar = true;
  2392. beginTransaction();
  2393. Print::println(str);
  2394. endTransaction();
  2395. return 0;
  2396. }
  2397. size_t ILI9341_due::println(const String &str){
  2398. _isFirstChar = true;
  2399. beginTransaction();
  2400. Print::println(str);
  2401. endTransaction();
  2402. return 0;
  2403. }
  2404. size_t ILI9341_due::println(const char* str){
  2405. _isFirstChar = true;
  2406. beginTransaction();
  2407. Print::println(str);
  2408. endTransaction();
  2409. return 0;
  2410. }
  2411. size_t ILI9341_due::println(char c){
  2412. _isFirstChar = true;
  2413. beginTransaction();
  2414. Print::println(c);
  2415. endTransaction();
  2416. return 0;
  2417. }
  2418. size_t ILI9341_due::println(unsigned char c, int b){
  2419. _isFirstChar = true;
  2420. beginTransaction();
  2421. Print::println(c,b);
  2422. endTransaction();
  2423. return 0;
  2424. }
  2425. size_t ILI9341_due::println(int d, int b){
  2426. _isFirstChar = true;
  2427. beginTransaction();
  2428. Print::println(d,b);
  2429. endTransaction();
  2430. return 0;
  2431. }
  2432. size_t ILI9341_due::println(unsigned int u, int b){
  2433. _isFirstChar = true;
  2434. beginTransaction();
  2435. Print::println(u,b);
  2436. endTransaction();
  2437. return 0;
  2438. }
  2439. size_t ILI9341_due::println(long l, int b){
  2440. _isFirstChar = true;
  2441. beginTransaction();
  2442. Print::println(l,b);
  2443. endTransaction();
  2444. return 0;
  2445. }
  2446. size_t ILI9341_due::println(unsigned long ul, int b){
  2447. _isFirstChar = true;
  2448. beginTransaction();
  2449. Print::println(ul,b);
  2450. endTransaction();
  2451. return 0;
  2452. }
  2453. size_t ILI9341_due::println(double d, int b){
  2454. _isFirstChar = true;
  2455. beginTransaction();
  2456. Print::println(d,b);
  2457. endTransaction();
  2458. return 0;
  2459. }
  2460. size_t ILI9341_due::println(const Printable& str){
  2461. _isFirstChar = true;
  2462. beginTransaction();
  2463. Print::println(str);
  2464. endTransaction();
  2465. return 0;
  2466. }
  2467. size_t ILI9341_due::println(void){
  2468. _isFirstChar = true;
  2469. beginTransaction();
  2470. Print::println();
  2471. endTransaction();
  2472. return 0;
  2473. }
  2474.  
  2475. size_t ILI9341_due::print(const char *str)
  2476. {
  2477. beginTransaction();
  2478. _isFirstChar = true;
  2479. while (*str)
  2480. {
  2481. write((uint8_t)*str);
  2482. //_isFirstChar = false;
  2483. str++;
  2484. }
  2485. endTransaction();
  2486. return 0;
  2487. }
  2488.  
  2489. size_t ILI9341_due::print(const String &str)
  2490. {
  2491. beginTransaction();
  2492. _isFirstChar = true;
  2493. for (uint16_t i = 0; i < str.length(); i++)
  2494. {
  2495. write(str[i]);
  2496. //_isFirstChar = false;
  2497. }
  2498. endTransaction();
  2499. return 0;
  2500. }
  2501.  
  2502. size_t ILI9341_due::print(const __FlashStringHelper *str)
  2503. {
  2504. beginTransaction();
  2505. _isFirstChar = true;
  2506. PGM_P p = reinterpret_cast<PGM_P>(str);
  2507. uint8_t c;
  2508. while ((c = pgm_read_byte(p)) != 0) {
  2509. write(c);
  2510. //_isFirstChar = false;
  2511. p++;
  2512. }
  2513. endTransaction();
  2514. return 0;
  2515. }
  2516.  
  2517. void ILI9341_due::printAt(const char *str, int16_t x, int16_t y)
  2518. {
  2519. cursorToXY(x, y);
  2520. print(str);
  2521. }
  2522.  
  2523. void ILI9341_due::printAt(const String &str, int16_t x, int16_t y)
  2524. {
  2525. cursorToXY(x, y);
  2526. print(str);
  2527. }
  2528.  
  2529. void ILI9341_due::printAt(const __FlashStringHelper *str, int16_t x, int16_t y)
  2530. {
  2531. cursorToXY(x, y);
  2532. print(str);
  2533. }
  2534.  
  2535. void ILI9341_due::printAt(const char *str, int16_t x, int16_t y, gTextEraseLine eraseLine)
  2536. {
  2537. cursorToXY(x, y);
  2538. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2539. clearPixelsOnLeft(1024);
  2540. print(str);
  2541. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2542. clearPixelsOnRight(1024);
  2543. }
  2544.  
  2545. void ILI9341_due::printAt(const String &str, int16_t x, int16_t y, gTextEraseLine eraseLine)
  2546. {
  2547. cursorToXY(x, y);
  2548. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2549. clearPixelsOnLeft(1024);
  2550. print(str);
  2551. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2552. clearPixelsOnRight(1024);
  2553. }
  2554.  
  2555. void ILI9341_due::printAt(const __FlashStringHelper *str, int16_t x, int16_t y, gTextEraseLine eraseLine)
  2556. {
  2557. cursorToXY(x, y);
  2558. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2559. clearPixelsOnLeft(1024);
  2560. print(str);
  2561. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2562. clearPixelsOnRight(1024);
  2563. }
  2564.  
  2565. void ILI9341_due::printAt(const char *str, int16_t x, int16_t y, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2566. {
  2567. cursorToXY(x, y);
  2568.  
  2569. // CLEAR PIXELS ON THE LEFT
  2570. if (pixelsClearedOnLeft > 0)
  2571. clearPixelsOnLeft(pixelsClearedOnLeft);
  2572.  
  2573. print(str);
  2574.  
  2575. // CLEAR PIXELS ON THE RIGHT
  2576. if (pixelsClearedOnRight > 0)
  2577. clearPixelsOnRight(pixelsClearedOnRight);
  2578. }
  2579.  
  2580. void ILI9341_due::printAt(const String &str, int16_t x, int16_t y, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2581. {
  2582. cursorToXY(x, y);
  2583.  
  2584. // CLEAR PIXELS ON THE LEFT
  2585. if (pixelsClearedOnLeft > 0)
  2586. clearPixelsOnLeft(pixelsClearedOnLeft);
  2587.  
  2588. print(str);
  2589.  
  2590. // CLEAR PIXELS ON THE RIGHT
  2591. if (pixelsClearedOnRight > 0)
  2592. clearPixelsOnRight(pixelsClearedOnRight);
  2593. }
  2594.  
  2595. void ILI9341_due::printAt(const __FlashStringHelper *str, int16_t x, int16_t y, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2596. {
  2597. cursorToXY(x, y);
  2598.  
  2599. // CLEAR PIXELS ON THE LEFT
  2600. if (pixelsClearedOnLeft > 0)
  2601. clearPixelsOnLeft(pixelsClearedOnLeft);
  2602.  
  2603. print(str);
  2604.  
  2605. // CLEAR PIXELS ON THE RIGHT
  2606. if (pixelsClearedOnRight > 0)
  2607. clearPixelsOnRight(pixelsClearedOnRight);
  2608. }
  2609.  
  2610. __attribute__((always_inline))
  2611. void ILI9341_due::printAligned(const char *str, gTextAlign align)
  2612. {
  2613. printAlignedPivotedOffseted(str, align, gTextPivotDefault, 0, 0, 0, 0);
  2614. }
  2615.  
  2616. __attribute__((always_inline))
  2617. void ILI9341_due::printAligned(const String &str, gTextAlign align)
  2618. {
  2619. printAlignedPivotedOffseted(str, align, gTextPivotDefault, 0, 0, 0, 0);
  2620. }
  2621.  
  2622. __attribute__((always_inline))
  2623. void ILI9341_due::printAligned(const __FlashStringHelper *str, gTextAlign align)
  2624. {
  2625. printAlignedPivotedOffseted(str, align, gTextPivotDefault, 0, 0, 0, 0);
  2626. }
  2627.  
  2628. void ILI9341_due::printAligned(const char *str, gTextAlign align, gTextEraseLine eraseLine)
  2629. {
  2630. uint16_t pixelsClearedOnLeft = 0;
  2631. uint16_t pixelsClearedOnRight = 0;
  2632. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2633. pixelsClearedOnLeft = 1024;
  2634. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2635. pixelsClearedOnRight = 1024;
  2636. printAlignedPivotedOffseted(str, align, gTextPivotDefault, 0, 0, pixelsClearedOnLeft, pixelsClearedOnRight);
  2637. }
  2638.  
  2639. void ILI9341_due::printAligned(const String &str, gTextAlign align, gTextEraseLine eraseLine)
  2640. {
  2641. uint16_t pixelsClearedOnLeft = 0;
  2642. uint16_t pixelsClearedOnRight = 0;
  2643. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2644. pixelsClearedOnLeft = 1024;
  2645. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2646. pixelsClearedOnRight = 1024;
  2647. printAlignedPivotedOffseted(str, align, gTextPivotDefault, 0, 0, pixelsClearedOnLeft, pixelsClearedOnRight);
  2648. }
  2649.  
  2650. void ILI9341_due::printAligned(const __FlashStringHelper *str, gTextAlign align, gTextEraseLine eraseLine)
  2651. {
  2652. uint16_t pixelsClearedOnLeft = 0;
  2653. uint16_t pixelsClearedOnRight = 0;
  2654. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2655. pixelsClearedOnLeft = 1024;
  2656. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2657. pixelsClearedOnRight = 1024;
  2658. printAlignedPivotedOffseted(str, align, gTextPivotDefault, 0, 0, pixelsClearedOnLeft, pixelsClearedOnRight);
  2659. }
  2660.  
  2661. __attribute__((always_inline))
  2662. void ILI9341_due::printAligned(const char *str, gTextAlign align, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2663. {
  2664. printAlignedPivotedOffseted(str, align, gTextPivotDefault, 0, 0, pixelsClearedOnLeft, pixelsClearedOnRight);
  2665. }
  2666.  
  2667. __attribute__((always_inline))
  2668. void ILI9341_due::printAligned(const String &str, gTextAlign align, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2669. {
  2670. printAlignedPivotedOffseted(str, align, gTextPivotDefault, 0, 0, pixelsClearedOnLeft, pixelsClearedOnRight);
  2671. }
  2672.  
  2673. __attribute__((always_inline))
  2674. void ILI9341_due::printAligned(const __FlashStringHelper *str, gTextAlign align, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2675. {
  2676. printAlignedPivotedOffseted(str, align, gTextPivotDefault, 0, 0, pixelsClearedOnLeft, pixelsClearedOnRight);
  2677. }
  2678.  
  2679. __attribute__((always_inline))
  2680. void ILI9341_due::printAlignedOffseted(const char *str, gTextAlign align, int16_t offsetX, int16_t offsetY)
  2681. {
  2682. printAlignedPivotedOffseted(str, align, gTextPivotDefault, offsetX, offsetY, 0, 0);
  2683. }
  2684.  
  2685. __attribute__((always_inline))
  2686. void ILI9341_due::printAlignedOffseted(const String &str, gTextAlign align, int16_t offsetX, int16_t offsetY)
  2687. {
  2688. printAlignedPivotedOffseted(str, align, gTextPivotDefault, offsetX, offsetY, 0, 0);
  2689. }
  2690.  
  2691. __attribute__((always_inline))
  2692. void ILI9341_due::printAlignedOffseted(const __FlashStringHelper *str, gTextAlign align, int16_t offsetX, int16_t offsetY)
  2693. {
  2694. printAlignedPivotedOffseted(str, align, gTextPivotDefault, offsetX, offsetY, 0, 0);
  2695. }
  2696.  
  2697. void ILI9341_due::printAlignedOffseted(const char *str, gTextAlign align, int16_t offsetX, int16_t offsetY, gTextEraseLine eraseLine)
  2698. {
  2699. uint16_t pixelsClearedOnLeft = 0;
  2700. uint16_t pixelsClearedOnRight = 0;
  2701. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2702. pixelsClearedOnLeft = 1024;
  2703. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2704. pixelsClearedOnRight = 1024;
  2705. printAlignedPivotedOffseted(str, align, gTextPivotDefault, offsetX, offsetY, pixelsClearedOnLeft, pixelsClearedOnRight);
  2706. }
  2707.  
  2708. void ILI9341_due::printAlignedOffseted(const String &str, gTextAlign align, int16_t offsetX, int16_t offsetY, gTextEraseLine eraseLine)
  2709. {
  2710. uint16_t pixelsClearedOnLeft = 0;
  2711. uint16_t pixelsClearedOnRight = 0;
  2712. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2713. pixelsClearedOnLeft = 1024;
  2714. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2715. pixelsClearedOnRight = 1024;
  2716. printAlignedPivotedOffseted(str, align, gTextPivotDefault, offsetX, offsetY, pixelsClearedOnLeft, pixelsClearedOnRight);
  2717. }
  2718.  
  2719. void ILI9341_due::printAlignedOffseted(const __FlashStringHelper *str, gTextAlign align, int16_t offsetX, int16_t offsetY, gTextEraseLine eraseLine)
  2720. {
  2721. uint16_t pixelsClearedOnLeft = 0;
  2722. uint16_t pixelsClearedOnRight = 0;
  2723. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2724. pixelsClearedOnLeft = 1024;
  2725. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2726. pixelsClearedOnRight = 1024;
  2727. printAlignedPivotedOffseted(str, align, gTextPivotDefault, offsetX, offsetY, pixelsClearedOnLeft, pixelsClearedOnRight);
  2728. }
  2729.  
  2730. __attribute__((always_inline))
  2731. void ILI9341_due::printAlignedOffseted(const char *str, gTextAlign align, int16_t offsetX, int16_t offsetY, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2732. {
  2733. printAlignedPivotedOffseted(str, align, gTextPivotDefault, offsetX, offsetY, pixelsClearedOnLeft, pixelsClearedOnRight);
  2734. }
  2735.  
  2736. __attribute__((always_inline))
  2737. void ILI9341_due::printAlignedOffseted(const String &str, gTextAlign align, int16_t offsetX, int16_t offsetY, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2738. {
  2739. printAlignedPivotedOffseted(str, align, gTextPivotDefault, offsetX, offsetY, pixelsClearedOnLeft, pixelsClearedOnRight);
  2740. }
  2741.  
  2742. __attribute__((always_inline))
  2743. void ILI9341_due::printAlignedOffseted(const __FlashStringHelper *str, gTextAlign align, int16_t offsetX, int16_t offsetY, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2744. {
  2745. printAlignedPivotedOffseted(str, align, gTextPivotDefault, offsetX, offsetY, pixelsClearedOnLeft, pixelsClearedOnRight);
  2746. }
  2747.  
  2748. void ILI9341_due::printAtPivoted(const char *str, int16_t x, int16_t y, gTextPivot pivot)
  2749. {
  2750. cursorToXY(x, y);
  2751.  
  2752. if (pivot != gTextPivotTopLeft && pivot != gTextPivotDefault)
  2753. applyPivot(str, pivot, gTextAlignTopLeft);
  2754.  
  2755. print(str);
  2756. }
  2757.  
  2758. void ILI9341_due::printAtPivoted(const String &str, int16_t x, int16_t y, gTextPivot pivot)
  2759. {
  2760. cursorToXY(x, y);
  2761.  
  2762. if (pivot != gTextPivotTopLeft && pivot != gTextPivotDefault)
  2763. applyPivot(str, pivot, gTextAlignTopLeft);
  2764.  
  2765. print(str);
  2766. }
  2767.  
  2768. void ILI9341_due::printAtPivoted(const __FlashStringHelper *str, int16_t x, int16_t y, gTextPivot pivot)
  2769. {
  2770. cursorToXY(x, y);
  2771.  
  2772. if (pivot != gTextPivotTopLeft && pivot != gTextPivotDefault)
  2773. applyPivot(str, pivot, gTextAlignTopLeft);
  2774.  
  2775. print(str);
  2776. }
  2777.  
  2778. void ILI9341_due::printAlignedPivoted(const char *str, gTextAlign align, gTextPivot pivot)
  2779. {
  2780. printAlignedPivotedOffseted(str, align, pivot, 0, 0, 0, 0);
  2781. }
  2782.  
  2783. void ILI9341_due::printAlignedPivoted(const String &str, gTextAlign align, gTextPivot pivot)
  2784. {
  2785. printAlignedPivotedOffseted(str, align, pivot, 0, 0, 0, 0);
  2786. }
  2787.  
  2788. void ILI9341_due::printAlignedPivoted(const __FlashStringHelper *str, gTextAlign align, gTextPivot pivot)
  2789. {
  2790. printAlignedPivotedOffseted(str, align, pivot, 0, 0, 0, 0);
  2791. }
  2792.  
  2793. void ILI9341_due::printAlignedPivoted(const char *str, gTextAlign align, gTextPivot pivot, gTextEraseLine eraseLine)
  2794. {
  2795. uint16_t pixelsClearedOnLeft = 0;
  2796. uint16_t pixelsClearedOnRight = 0;
  2797. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2798. pixelsClearedOnLeft = 1024;
  2799. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2800. pixelsClearedOnRight = 1024;
  2801. printAlignedPivotedOffseted(str, align, pivot, 0, 0, pixelsClearedOnLeft, pixelsClearedOnRight);
  2802. }
  2803.  
  2804. void ILI9341_due::printAlignedPivoted(const String &str, gTextAlign align, gTextPivot pivot, gTextEraseLine eraseLine)
  2805. {
  2806. uint16_t pixelsClearedOnLeft = 0;
  2807. uint16_t pixelsClearedOnRight = 0;
  2808. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2809. pixelsClearedOnLeft = 1024;
  2810. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2811. pixelsClearedOnRight = 1024;
  2812. printAlignedPivotedOffseted(str, align, pivot, 0, 0, pixelsClearedOnLeft, pixelsClearedOnRight);
  2813. }
  2814.  
  2815. void ILI9341_due::printAlignedPivoted(const __FlashStringHelper *str, gTextAlign align, gTextPivot pivot, gTextEraseLine eraseLine)
  2816. {
  2817. uint16_t pixelsClearedOnLeft = 0;
  2818. uint16_t pixelsClearedOnRight = 0;
  2819. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2820. pixelsClearedOnLeft = 1024;
  2821. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2822. pixelsClearedOnRight = 1024;
  2823. printAlignedPivotedOffseted(str, align, pivot, 0, 0, pixelsClearedOnLeft, pixelsClearedOnRight);
  2824. }
  2825.  
  2826. void ILI9341_due::printAlignedPivoted(const char *str, gTextAlign align, gTextPivot pivot, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2827. {
  2828. printAlignedPivotedOffseted(str, align, pivot, 0, 0, pixelsClearedOnLeft, pixelsClearedOnRight);
  2829. }
  2830.  
  2831. void ILI9341_due::printAlignedPivoted(const String &str, gTextAlign align, gTextPivot pivot, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2832. {
  2833. printAlignedPivotedOffseted(str, align, pivot, 0, 0, pixelsClearedOnLeft, pixelsClearedOnRight);
  2834. }
  2835.  
  2836. void ILI9341_due::printAlignedPivoted(const __FlashStringHelper *str, gTextAlign align, gTextPivot pivot, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2837. {
  2838. printAlignedPivotedOffseted(str, align, pivot, 0, 0, pixelsClearedOnLeft, pixelsClearedOnRight);
  2839. }
  2840.  
  2841. void ILI9341_due::printAlignedPivotedOffseted(const char *str, gTextAlign align, gTextPivot pivot, int16_t offsetX, int16_t offsetY)
  2842. {
  2843. printAlignedPivotedOffseted(str, align, pivot, offsetX, offsetY, 0, 0);
  2844. }
  2845.  
  2846. void ILI9341_due::printAlignedPivotedOffseted(const String &str, gTextAlign align, gTextPivot pivot, int16_t offsetX, int16_t offsetY)
  2847. {
  2848. printAlignedPivotedOffseted(str, align, pivot, offsetX, offsetY, 0, 0);
  2849. }
  2850.  
  2851. void ILI9341_due::printAlignedPivotedOffseted(const __FlashStringHelper *str, gTextAlign align, gTextPivot pivot, int16_t offsetX, int16_t offsetY)
  2852. {
  2853. printAlignedPivotedOffseted(str, align, pivot, offsetX, offsetY, 0, 0);
  2854. }
  2855.  
  2856. void ILI9341_due::printAlignedPivotedOffseted(const char *str, gTextAlign align, gTextPivot pivot, int16_t offsetX, int16_t offsetY, gTextEraseLine eraseLine)
  2857. {
  2858. uint16_t pixelsClearedOnLeft = 0;
  2859. uint16_t pixelsClearedOnRight = 0;
  2860. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2861. pixelsClearedOnLeft = 1024;
  2862. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2863. pixelsClearedOnRight = 1024;
  2864. printAlignedPivotedOffseted(str, align, pivot, offsetX, offsetY, pixelsClearedOnLeft, pixelsClearedOnRight);
  2865. }
  2866.  
  2867. void ILI9341_due::printAlignedPivotedOffseted(const String &str, gTextAlign align, gTextPivot pivot, int16_t offsetX, int16_t offsetY, gTextEraseLine eraseLine)
  2868. {
  2869. uint16_t pixelsClearedOnLeft = 0;
  2870. uint16_t pixelsClearedOnRight = 0;
  2871. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2872. pixelsClearedOnLeft = 1024;
  2873. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2874. pixelsClearedOnRight = 1024;
  2875. printAlignedPivotedOffseted(str, align, pivot, offsetX, offsetY, pixelsClearedOnLeft, pixelsClearedOnRight);
  2876. }
  2877.  
  2878. void ILI9341_due::printAlignedPivotedOffseted(const __FlashStringHelper *str, gTextAlign align, gTextPivot pivot, int16_t offsetX, int16_t offsetY, gTextEraseLine eraseLine)
  2879. {
  2880. uint16_t pixelsClearedOnLeft = 0;
  2881. uint16_t pixelsClearedOnRight = 0;
  2882. if (eraseLine == gTextEraseFromBOL || eraseLine == gTextEraseFullLine)
  2883. pixelsClearedOnLeft = 1024;
  2884. if (eraseLine == gTextEraseToEOL || eraseLine == gTextEraseFullLine)
  2885. pixelsClearedOnRight = 1024;
  2886. printAlignedPivotedOffseted(str, align, pivot, offsetX, offsetY, pixelsClearedOnLeft, pixelsClearedOnRight);
  2887. }
  2888.  
  2889. void ILI9341_due::printAlignedPivotedOffseted(const char *str, gTextAlign align, gTextPivot pivot, int16_t offsetX, int16_t offsetY, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2890. {
  2891. //Serial << pixelsClearedOnLeft << " " << pixelsClearedOnRight << endl;
  2892. _x = _xStart = _area.x;
  2893. _y = _yStart = _area.y;
  2894.  
  2895. applyAlignPivotOffset(str, align, pivot, offsetX, offsetY);
  2896.  
  2897. clearPixelsOnLeft(pixelsClearedOnLeft);
  2898. print(str);
  2899. clearPixelsOnRight(pixelsClearedOnRight);
  2900. }
  2901.  
  2902. void ILI9341_due::printAlignedPivotedOffseted(const String &str, gTextAlign align, gTextPivot pivot, int16_t offsetX, int16_t offsetY, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2903. {
  2904. //Serial << pixelsClearedOnLeft << " " << pixelsClearedOnRight << endl;
  2905. _x = _xStart = _area.x;
  2906. _y = _yStart = _area.y;
  2907.  
  2908. applyAlignPivotOffset(str, align, pivot, offsetX, offsetY);
  2909.  
  2910. clearPixelsOnLeft(pixelsClearedOnLeft);
  2911. print(str);
  2912. clearPixelsOnRight(pixelsClearedOnRight);
  2913. }
  2914.  
  2915. void ILI9341_due::printAlignedPivotedOffseted(const __FlashStringHelper *str, gTextAlign align, gTextPivot pivot, int16_t offsetX, int16_t offsetY, uint16_t pixelsClearedOnLeft, uint16_t pixelsClearedOnRight)
  2916. {
  2917. //Serial << pixelsClearedOnLeft << " " << pixelsClearedOnRight << endl;
  2918. _x = _xStart = _area.x;
  2919. _y = _yStart = _area.y;
  2920.  
  2921. applyAlignPivotOffset(str, align, pivot, offsetX, offsetY);
  2922.  
  2923. clearPixelsOnLeft(pixelsClearedOnLeft);
  2924. print(str);
  2925. clearPixelsOnRight(pixelsClearedOnRight);
  2926. }
  2927.  
  2928. __attribute__((always_inline))
  2929. void ILI9341_due::clearPixelsOnLeft(uint16_t pixelsToClearOnLeft){
  2930. // CLEAR PIXELS ON THE LEFT
  2931. if (pixelsToClearOnLeft > 0)
  2932. {
  2933. int16_t clearX1 = max(min((int16_t)_x, (int16_t)_area.x), (int16_t)_x - (int16_t)pixelsToClearOnLeft);
  2934. //Serial.println(clearX1);
  2935. //Serial << "clearPixelsOnLeft " << _x << " " << _area.x << " " << clearX1 << endl2;
  2936. fillRect(clearX1, _y, _x - clearX1, scaledFontHeight(), _fontBgColor);
  2937. }
  2938. }
  2939.  
  2940. __attribute__((always_inline))
  2941. void ILI9341_due::clearPixelsOnRight(uint16_t pixelsToClearOnRight){
  2942. // CLEAR PIXELS ON THE RIGHT
  2943. if (pixelsToClearOnRight > 0)
  2944. {
  2945. int16_t clearX2 = min(max((int16_t)_x, (int16_t)_area.x + (int16_t)_area.w - 1), (int16_t)_x + (int16_t)pixelsToClearOnRight);
  2946. //Serial << "area from " << _area.x << " to " << _area.x1 << endl;
  2947. //Serial << "clearing on right from " << _x << " to " << clearX2 << endl;
  2948. fillRect(_x, _y, clearX2 - _x + 1, scaledFontHeight(), _fontBgColor);
  2949. //TOTRY
  2950. //fillRect(_x, _y, clearX2 - _x + 1, fontHeight(), _fontBgColor);
  2951. }
  2952. }
  2953.  
  2954. void ILI9341_due::applyAlignPivotOffset(const char *str, gTextAlign align, gTextPivot pivot, int16_t offsetX, int16_t offsetY){
  2955. //PIVOT
  2956. if (pivot != gTextPivotTopLeft)
  2957. applyPivot(str, pivot, align);
  2958.  
  2959. // ALIGN & OFFSET
  2960. applyAlignOffset(align, offsetX, offsetY);
  2961. }
  2962.  
  2963. void ILI9341_due::applyAlignPivotOffset(const String &str, gTextAlign align, gTextPivot pivot, int16_t offsetX, int16_t offsetY){
  2964. //PIVOT
  2965. if (pivot != gTextPivotTopLeft)
  2966. applyPivot(str, pivot, align);
  2967.  
  2968. // ALIGN & OFFSET
  2969. applyAlignOffset(align, offsetX, offsetY);
  2970. }
  2971.  
  2972. void ILI9341_due::applyAlignPivotOffset(const __FlashStringHelper *str, gTextAlign align, gTextPivot pivot, int16_t offsetX, int16_t offsetY){
  2973. //PIVOT
  2974. if (pivot != gTextPivotTopLeft)
  2975. applyPivot(str, pivot, align);
  2976.  
  2977. // ALIGN & OFFSET
  2978. applyAlignOffset(align, offsetX, offsetY);
  2979. }
  2980.  
  2981. void ILI9341_due::applyAlignOffset(gTextAlign align, int16_t offsetX, int16_t offsetY)
  2982. {
  2983. if (align != gTextAlignTopLeft)
  2984. {
  2985. switch (align)
  2986. {
  2987. case gTextAlignTopCenter:
  2988. {
  2989. _x += _area.w / 2;
  2990. break;
  2991. }
  2992. case gTextAlignTopRight:
  2993. {
  2994. _x += _area.w;
  2995. break;
  2996. }
  2997. case gTextAlignMiddleLeft:
  2998. {
  2999. _y += _area.h / 2;
  3000. break;
  3001. }
  3002. case gTextAlignMiddleCenter:
  3003. {
  3004. _x += _area.w / 2;
  3005. _y += _area.h / 2;
  3006. break;
  3007. }
  3008. case gTextAlignMiddleRight:
  3009. {
  3010. _x += _area.w;
  3011. _y += _area.h / 2;
  3012. break;
  3013. }
  3014. case gTextAlignBottomLeft:
  3015. {
  3016. _y += _area.h;
  3017. break;
  3018. }
  3019. case gTextAlignBottomCenter:
  3020. {
  3021. _x += _area.w / 2;
  3022. _y += _area.h;
  3023. break;
  3024. }
  3025. case gTextAlignBottomRight:
  3026. {
  3027. _x += _area.w;
  3028. _y += _area.h;
  3029. break;
  3030. }
  3031. }
  3032. }
  3033. // OFFSET
  3034. _x += offsetX;
  3035. _y += offsetY;
  3036. }
  3037.  
  3038. void ILI9341_due::applyPivot(const String &str, gTextPivot pivot, gTextAlign align)
  3039. {
  3040. applyPivot(str.c_str(), pivot, align);
  3041. }
  3042.  
  3043. void ILI9341_due::applyPivot(const __FlashStringHelper *str, gTextPivot pivot, gTextAlign align)
  3044. {
  3045. //PIVOT
  3046. if (pivot == gTextPivotDefault)
  3047. {
  3048. switch (align)
  3049. {
  3050. case gTextAlignTopLeft: { pivot = gTextPivotTopLeft; break; }
  3051. case gTextAlignTopCenter: { pivot = gTextPivotTopCenter; break; }
  3052. case gTextAlignTopRight: { pivot = gTextPivotTopRight; break; }
  3053. case gTextAlignMiddleLeft: { pivot = gTextPivotMiddleLeft; break; }
  3054. case gTextAlignMiddleCenter: { pivot = gTextPivotMiddleCenter; break; }
  3055. case gTextAlignMiddleRight: { pivot = gTextPivotMiddleRight; break; }
  3056. case gTextAlignBottomLeft: { pivot = gTextPivotBottomLeft; break; }
  3057. case gTextAlignBottomCenter: { pivot = gTextPivotBottomCenter; break; }
  3058. case gTextAlignBottomRight: { pivot = gTextPivotBottomRight; break; }
  3059. }
  3060. }
  3061.  
  3062. if (pivot != gTextPivotTopLeft)
  3063. {
  3064. switch (pivot)
  3065. {
  3066. case gTextPivotTopCenter:
  3067. {
  3068. _x -= stringWidth(str) / 2;
  3069. break;
  3070. }
  3071. case gTextPivotTopRight:
  3072. {
  3073. _x -= stringWidth(str);
  3074. break;
  3075. }
  3076. case gTextPivotMiddleLeft:
  3077. {
  3078. _y -= scaledFontHeight() / 2;
  3079. break;
  3080. }
  3081. case gTextPivotMiddleCenter:
  3082. {
  3083. _x -= stringWidth(str) / 2;
  3084. _y -= scaledFontHeight() / 2;
  3085. break;
  3086. }
  3087. case gTextPivotMiddleRight:
  3088. {
  3089. _x -= stringWidth(str);
  3090. _y -= scaledFontHeight() / 2;
  3091. break;
  3092. }
  3093. case gTextPivotBottomLeft:
  3094. {
  3095. _y -= scaledFontHeight();
  3096. break;
  3097. }
  3098. case gTextPivotBottomCenter:
  3099. {
  3100. _x -= stringWidth(str) / 2;
  3101. _y -= scaledFontHeight();
  3102. break;
  3103. }
  3104. case gTextPivotBottomRight:
  3105. {
  3106. _x -= stringWidth(str);
  3107. _y -= scaledFontHeight();
  3108. break;
  3109. }
  3110. }
  3111. }
  3112. }
  3113.  
  3114. void ILI9341_due::applyPivot(const char *str, gTextPivot pivot, gTextAlign align)
  3115. {
  3116. //PIVOT
  3117. if (pivot == gTextPivotDefault)
  3118. {
  3119. switch (align)
  3120. {
  3121. case gTextAlignTopLeft: { pivot = gTextPivotTopLeft; break; }
  3122. case gTextAlignTopCenter: { pivot = gTextPivotTopCenter; break; }
  3123. case gTextAlignTopRight: { pivot = gTextPivotTopRight; break; }
  3124. case gTextAlignMiddleLeft: { pivot = gTextPivotMiddleLeft; break; }
  3125. case gTextAlignMiddleCenter: { pivot = gTextPivotMiddleCenter; break; }
  3126. case gTextAlignMiddleRight: { pivot = gTextPivotMiddleRight; break; }
  3127. case gTextAlignBottomLeft: { pivot = gTextPivotBottomLeft; break; }
  3128. case gTextAlignBottomCenter: { pivot = gTextPivotBottomCenter; break; }
  3129. case gTextAlignBottomRight: { pivot = gTextPivotBottomRight; break; }
  3130. }
  3131. }
  3132.  
  3133. if (pivot != gTextPivotTopLeft)
  3134. {
  3135. switch (pivot)
  3136. {
  3137. case gTextPivotTopCenter:
  3138. {
  3139. _x -= stringWidth(str) / 2;
  3140. break;
  3141. }
  3142. case gTextPivotTopRight:
  3143. {
  3144. _x -= stringWidth(str);
  3145. break;
  3146. }
  3147. case gTextPivotMiddleLeft:
  3148. {
  3149. _y -= scaledFontHeight() / 2;
  3150. break;
  3151. }
  3152. case gTextPivotMiddleCenter:
  3153. {
  3154. _x -= stringWidth(str) / 2;
  3155. _y -= scaledFontHeight() / 2;
  3156. break;
  3157. }
  3158. case gTextPivotMiddleRight:
  3159. {
  3160. _x -= stringWidth(str);
  3161. _y -= scaledFontHeight() / 2;
  3162. break;
  3163. }
  3164. case gTextPivotBottomLeft:
  3165. {
  3166. _y -= scaledFontHeight();
  3167. break;
  3168. }
  3169. case gTextPivotBottomCenter:
  3170. {
  3171. _x -= stringWidth(str) / 2;
  3172. _y -= scaledFontHeight();
  3173. break;
  3174. }
  3175. case gTextPivotBottomRight:
  3176. {
  3177. _x -= stringWidth(str);
  3178. _y -= scaledFontHeight();
  3179. break;
  3180. }
  3181. }
  3182. }
  3183. }
  3184.  
  3185. void ILI9341_due::cursorTo(uint8_t column, uint8_t row)
  3186. {
  3187. if (_font == 0)
  3188. return; // no font selected
  3189.  
  3190. /*
  3191. * Text position is relative to current text area
  3192. */
  3193.  
  3194. _x = _xStart = _area.x + column * (pgm_read_byte(_font + GTEXT_FONT_FIXED_WIDTH) + 1);
  3195. _y = _yStart = _area.y + row * (fontHeight() + _lineSpacing) * _textScale;
  3196. _isFirstChar = true;
  3197. //#ifndef GLCD_NODEFER_SCROLL
  3198. // /*
  3199. // * Make sure to clear a deferred scroll operation when repositioning
  3200. // */
  3201. // _needScroll = 0;
  3202. //#endif
  3203. }
  3204.  
  3205. void ILI9341_due::cursorTo(int8_t column)
  3206. {
  3207. if (_font == 0)
  3208. return; // no font selected
  3209. /*
  3210. * Text position is relative to current text area
  3211. * negative value moves the cursor backwards
  3212. */
  3213. if (column >= 0)
  3214. _x = _xStart = column * (pgm_read_byte(_font + GTEXT_FONT_FIXED_WIDTH) + 1) + _area.x;
  3215. else
  3216. _x -= column * (pgm_read_byte(_font + GTEXT_FONT_FIXED_WIDTH) + 1);
  3217.  
  3218. _isFirstChar = true;
  3219.  
  3220. //#ifndef GLCD_NODEFER_SCROLL
  3221. // /*
  3222. // * Make sure to clear a deferred scroll operation when repositioning
  3223. // */
  3224. // _needScroll = 0;
  3225. //#endif
  3226. }
  3227.  
  3228. __attribute__((always_inline))
  3229. void ILI9341_due::cursorToXY(int16_t x, int16_t y)
  3230. {
  3231. /*
  3232. * Text position is relative to current text area
  3233. */
  3234.  
  3235. _x = _xStart = _area.x + x;
  3236. _y = _yStart = _area.y + y;
  3237. _isFirstChar = true;
  3238. //Serial << F("cursorToXY x:") << x << F(" y:") << y << endl;
  3239.  
  3240. //#ifndef GLCD_NODEFER_SCROLL
  3241. // /*
  3242. // * Make sure to clear a deferred scroll operation when repositioning
  3243. // */
  3244. // _needScroll = 0;
  3245. //#endif
  3246. }
  3247.  
  3248. void ILI9341_due::setTextScale(uint8_t s) {
  3249. #ifdef TEXT_SCALING_ENABLED
  3250. _textScale = (s > 0) ? s : 1;
  3251. #endif
  3252. }
  3253.  
  3254.  
  3255. void ILI9341_due::eraseTextLine(uint16_t color, gTextEraseLine type)
  3256. {
  3257. /*int16_t x = _x;
  3258. int16_t y = _y;
  3259. int16_t height = fontHeight();*/
  3260. //uint8_t color = (_fontColor == BLACK) ? WHITE : BLACK;
  3261.  
  3262. switch (type)
  3263. {
  3264. case gTextEraseToEOL:
  3265. fillRect(_x, _y, _area.x + _area.w - _x, scaledFontHeight(), color);
  3266. break;
  3267. case gTextEraseFromBOL:
  3268. fillRect(_area.x, _y, _x - _area.x, scaledFontHeight(), color);
  3269. break;
  3270. case gTextEraseFullLine:
  3271. fillRect(_area.x, _y, _area.w, scaledFontHeight(), color);
  3272. break;
  3273. }
  3274.  
  3275. //cursorToXY(x, y);
  3276. }
  3277.  
  3278. void ILI9341_due::eraseTextLine(uint16_t color, uint8_t row)
  3279. {
  3280. cursorTo(0, row);
  3281. eraseTextLine(color, gTextEraseToEOL);
  3282. }
  3283.  
  3284.  
  3285. void ILI9341_due::setFont(gTextFont font)
  3286. {
  3287. _font = font;
  3288. }
  3289.  
  3290. void ILI9341_due::setTextColor(uint16_t color)
  3291. {
  3292. _fontColor = color;
  3293. }
  3294.  
  3295. void ILI9341_due::setTextColor(uint8_t R, uint8_t G, uint8_t B)
  3296. {
  3297. _fontColor = color565(R, G, B);
  3298. }
  3299.  
  3300. void ILI9341_due::setTextColor(uint16_t color, uint16_t backgroundColor)
  3301. {
  3302. _fontColor = color;
  3303. _fontBgColor = backgroundColor;
  3304. }
  3305.  
  3306. void ILI9341_due::setTextColor(uint8_t R, uint8_t G, uint8_t B, uint8_t bgR, uint8_t bgG, uint8_t bgB)
  3307. {
  3308. _fontColor = color565(R, G, B);
  3309. _fontBgColor = color565(bgR, bgG, bgB);
  3310. }
  3311.  
  3312. void ILI9341_due::setTextLineSpacing(uint8_t lineSpacing)
  3313. {
  3314. _lineSpacing = lineSpacing;
  3315. }
  3316.  
  3317. void ILI9341_due::setTextLetterSpacing(uint8_t letterSpacing)
  3318. {
  3319. _letterSpacing = letterSpacing;
  3320. }
  3321.  
  3322. void ILI9341_due::setTextWrap(bool wrap)
  3323. {
  3324. _wrap = wrap;
  3325. }
  3326.  
  3327. void ILI9341_due::setFontMode(gTextFontMode fontMode)
  3328. {
  3329. if (fontMode == gTextFontModeSolid || fontMode == gTextFontModeTransparent)
  3330. _fontMode = fontMode;
  3331. }
  3332.  
  3333. uint16_t ILI9341_due::charWidth(uint8_t c)
  3334. {
  3335. int16_t width = 0;
  3336.  
  3337. if (isFixedWidthFont(_font){
  3338. width = (pgm_read_byte(_font + GTEXT_FONT_FIXED_WIDTH)) * _textScale;
  3339. }
  3340. else{
  3341. // variable width font
  3342. uint8_t firstChar = pgm_read_byte(_font + GTEXT_FONT_FIRST_CHAR);
  3343. uint8_t charCount = pgm_read_byte(_font + GTEXT_FONT_CHAR_COUNT);
  3344.  
  3345. // read width data
  3346. if (c >= firstChar && c < (firstChar + charCount)) {
  3347. c -= firstChar;
  3348. width = (pgm_read_byte(_font + GTEXT_FONT_WIDTH_TABLE + c)) * _textScale;
  3349. //Serial << "strWidth of " << c << " : " << width << endl;
  3350. }
  3351. }
  3352. return width;
  3353. }
  3354.  
  3355. uint16_t ILI9341_due::stringWidth(const char* str)
  3356. {
  3357. uint16_t width = 0;
  3358.  
  3359. while (*str != 0) {
  3360. width += charWidth(*str++) + _letterSpacing * _textScale;
  3361. }
  3362. if (width > 0)
  3363. width -= _letterSpacing * _textScale;
  3364. return width;
  3365. }
  3366.  
  3367. uint16_t ILI9341_due::stringWidth(const __FlashStringHelper *str)
  3368. {
  3369. PGM_P p = reinterpret_cast<PGM_P>(str);
  3370. uint16_t width = 0;
  3371. uint8_t c;
  3372. while ((c = pgm_read_byte(p)) != 0) {
  3373. width += charWidth(c) + _letterSpacing * _textScale;
  3374. p++;
  3375. }
  3376. width -= _letterSpacing;
  3377. return width;
  3378. }
  3379.  
  3380. uint16_t ILI9341_due::stringWidth(const String &str)
  3381. {
  3382. uint16_t width = 0;
  3383.  
  3384. for (uint16_t i = 0; i < str.length(); i++)
  3385. {
  3386. width += charWidth(str[i]) + _letterSpacing * _textScale;
  3387. }
  3388. width -= _letterSpacing;
  3389. return width;
  3390. }
  3391.  
  3392.  
  3393.  
  3394. #pragma GCC diagnostic pop
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement