PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

1115 lines
27KB

  1. #include "TFT_ILI9163C.h"
  2. #include <limits.h>
  3. #include "pins_arduino.h"
  4. #include "wiring_private.h"
  5. #include <SPI.h>
  6. #if defined(SPI_HAS_TRANSACTION)
  7. static SPISettings ILI9163C_SPI;
  8. #endif
  9. //constructors
  10. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  11. TFT_ILI9163C::TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin,uint8_t mosi,uint8_t sclk) : Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT)
  12. {
  13. _cs = cspin;
  14. _rs = dcpin;
  15. _rst = rstpin;
  16. _mosi = mosi;
  17. _sclk = sclk;
  18. }
  19. #elif defined(__MKL26Z64__)
  20. TFT_ILI9163C::TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin,uint8_t mosi,uint8_t sclk) : Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT)
  21. {
  22. _cs = cspin;
  23. _rs = dcpin;
  24. _rst = rstpin;
  25. _mosi = mosi;
  26. _sclk = sclk;
  27. _useSPI1 = false;
  28. if ((_mosi == 0 || _mosi == 21) && (_sclk == 20)) _useSPI1 = true;
  29. }
  30. #else
  31. TFT_ILI9163C::TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin) : Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT)
  32. {
  33. _cs = cspin;
  34. _rs = dcpin;
  35. _rst = rstpin;
  36. }
  37. #endif
  38. //Arduino Uno, Leonardo, Mega, Teensy 2.0, etc
  39. #if defined(__AVR__)
  40. inline void TFT_ILI9163C::spiwrite(uint8_t c)
  41. {
  42. SPDR = c;
  43. while(!(SPSR & _BV(SPIF)));
  44. }
  45. void TFT_ILI9163C::writecommand(uint8_t c)
  46. {
  47. #if defined(SPI_HAS_TRANSACTION)
  48. SPI.beginTransaction(ILI9163C_SPI);
  49. #endif
  50. *rsport &= ~rspinmask;//low
  51. *csport &= ~cspinmask;//low
  52. spiwrite(c);
  53. *csport |= cspinmask;//hi
  54. #if defined(SPI_HAS_TRANSACTION)
  55. SPI.endTransaction();
  56. #endif
  57. }
  58. void TFT_ILI9163C::writedata(uint8_t c)
  59. {
  60. #if defined(SPI_HAS_TRANSACTION)
  61. SPI.beginTransaction(ILI9163C_SPI);
  62. #endif
  63. *rsport |= rspinmask;//hi
  64. *csport &= ~cspinmask;//low
  65. spiwrite(c);
  66. *csport |= cspinmask;//hi
  67. #if defined(SPI_HAS_TRANSACTION)
  68. SPI.endTransaction();
  69. #endif
  70. }
  71. void TFT_ILI9163C::writedata16(uint16_t d)
  72. {
  73. #if defined(SPI_HAS_TRANSACTION)
  74. SPI.beginTransaction(ILI9163C_SPI);
  75. #endif
  76. *rsport |= rspinmask;//hi
  77. *csport &= ~cspinmask;//low
  78. spiwrite(d >> 8);
  79. spiwrite(d);
  80. *csport |= cspinmask;//hi
  81. #if defined(SPI_HAS_TRANSACTION)
  82. SPI.endTransaction();
  83. #endif
  84. }
  85. void TFT_ILI9163C::setBitrate(uint32_t n)
  86. {
  87. #if !defined (SPI_HAS_TRANSACTION)
  88. if (n >= 8000000) {
  89. SPI.setClockDivider(SPI_CLOCK_DIV2);
  90. } else if (n >= 4000000) {
  91. SPI.setClockDivider(SPI_CLOCK_DIV4);
  92. } else if (n >= 2000000) {
  93. SPI.setClockDivider(SPI_CLOCK_DIV8);
  94. } else {
  95. SPI.setClockDivider(SPI_CLOCK_DIV16);
  96. }
  97. #endif
  98. }
  99. #elif defined(__SAM3X8E__)// Arduino Due
  100. inline void TFT_ILI9163C::spiwrite(uint8_t c)
  101. {
  102. SPI.transfer(c);
  103. }
  104. void TFT_ILI9163C::writecommand(uint8_t c)
  105. {
  106. #if defined(SPI_HAS_TRANSACTION)
  107. SPI.beginTransaction(ILI9163C_SPI);
  108. #endif
  109. rsport->PIO_CODR |= rspinmask;//LO
  110. csport->PIO_CODR |= cspinmask;//LO
  111. spiwrite(c);
  112. csport->PIO_SODR |= cspinmask;//HI
  113. #if defined(SPI_HAS_TRANSACTION)
  114. SPI.endTransaction();
  115. #endif
  116. }
  117. void TFT_ILI9163C::writedata(uint8_t c)
  118. {
  119. #if defined(SPI_HAS_TRANSACTION)
  120. SPI.beginTransaction(ILI9163C_SPI);
  121. #endif
  122. rsport->PIO_SODR |= rspinmask;//HI
  123. csport->PIO_CODR |= cspinmask;//LO
  124. spiwrite(c);
  125. csport->PIO_SODR |= cspinmask;//HI
  126. #if defined(SPI_HAS_TRANSACTION)
  127. SPI.endTransaction();
  128. #endif
  129. }
  130. void TFT_ILI9163C::writedata16(uint16_t d)
  131. {
  132. #if defined(SPI_HAS_TRANSACTION)
  133. SPI.beginTransaction(ILI9163C_SPI);
  134. #endif
  135. rsport->PIO_SODR |= rspinmask;//HI
  136. csport->PIO_CODR |= cspinmask;//LO
  137. spiwrite(d >> 8);
  138. spiwrite(d);
  139. csport->PIO_SODR |= cspinmask;//HI
  140. #if defined(SPI_HAS_TRANSACTION)
  141. SPI.endTransaction();
  142. #endif
  143. }
  144. void TFT_ILI9163C::setBitrate(uint32_t n)
  145. {
  146. #if !defined(SPI_HAS_TRANSACTION)
  147. uint32_t divider = 1;
  148. while (divider < 255) {
  149. if (n >= 84000000 / divider) break;
  150. divider = divider - 1;
  151. }
  152. SPI.setClockDivider(divider);
  153. #endif
  154. }
  155. #elif defined(__MKL26Z64__)//Teensy LC (preliminary
  156. void TFT_ILI9163C::writecommand(uint8_t c)
  157. {
  158. if (_useSPI1){
  159. SPI1.beginTransaction(ILI9163C_SPI);
  160. digitalWriteFast(_rs,LOW);
  161. digitalWriteFast(_cs,LOW);
  162. SPI1.transfer(c);
  163. digitalWriteFast(_cs,HIGH);
  164. SPI1.endTransaction();
  165. } else {
  166. SPI.beginTransaction(ILI9163C_SPI);
  167. digitalWriteFast(_rs,LOW);
  168. digitalWriteFast(_cs,LOW);
  169. SPI.transfer(c);
  170. digitalWriteFast(_cs,HIGH);
  171. SPI.endTransaction();
  172. }
  173. }
  174. void TFT_ILI9163C::writedata(uint8_t c)
  175. {
  176. if (_useSPI1){
  177. SPI1.beginTransaction(ILI9163C_SPI);
  178. digitalWriteFast(_rs,HIGH);
  179. digitalWriteFast(_cs,LOW);
  180. SPI1.transfer(c);
  181. digitalWriteFast(_cs,HIGH);
  182. SPI1.endTransaction();
  183. } else {
  184. SPI.beginTransaction(ILI9163C_SPI);
  185. digitalWriteFast(_rs,HIGH);
  186. digitalWriteFast(_cs,LOW);
  187. SPI.transfer(c);
  188. digitalWriteFast(_cs,HIGH);
  189. SPI.endTransaction();
  190. }
  191. }
  192. void TFT_ILI9163C::writedata16(uint16_t d)
  193. {
  194. if (_useSPI1){
  195. SPI1.beginTransaction(ILI9163C_SPI);
  196. digitalWriteFast(_rs,HIGH);
  197. digitalWriteFast(_cs,LOW);
  198. SPI1.transfer16(d);
  199. digitalWriteFast(_cs,HIGH);
  200. SPI1.endTransaction();
  201. } else {
  202. SPI.beginTransaction(ILI9163C_SPI);
  203. digitalWriteFast(_rs,HIGH);
  204. digitalWriteFast(_cs,LOW);
  205. SPI.transfer16(d);
  206. digitalWriteFast(_cs,HIGH);
  207. SPI.endTransaction();
  208. }
  209. }
  210. void TFT_ILI9163C::setBitrate(uint32_t n)
  211. {
  212. //nop
  213. }
  214. #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) //Teensy 3.0 & 3.1 & 3.2 & 3.5 & 3.6
  215. void TFT_ILI9163C::setBitrate(uint32_t n)
  216. {
  217. //nop
  218. }
  219. #else
  220. void TFT_ILI9163C::writecommand(uint8_t c)
  221. {
  222. #if defined(SPI_HAS_TRANSACTION)
  223. SPI.beginTransaction(ILI9163C_SPI);
  224. #endif
  225. digitalWrite(_rs,LOW);
  226. digitalWrite(_cs,LOW);
  227. SPI.transfer(c);
  228. digitalWrite(_cs,HIGH);
  229. #if defined(SPI_HAS_TRANSACTION)
  230. SPI.endTransaction();
  231. #endif
  232. }
  233. void TFT_ILI9163C::writedata(uint8_t c)
  234. {
  235. #if defined(SPI_HAS_TRANSACTION)
  236. SPI.beginTransaction(ILI9163C_SPI);
  237. #endif
  238. digitalWrite(_rs,HIGH);
  239. digitalWrite(_cs,LOW);
  240. SPI.transfer(c);
  241. digitalWrite(_cs,HIGH);
  242. #if defined(SPI_HAS_TRANSACTION)
  243. SPI.endTransaction();
  244. #endif
  245. }
  246. void TFT_ILI9163C::writedata16(uint16_t d)
  247. {
  248. #if defined(SPI_HAS_TRANSACTION)
  249. SPI.beginTransaction(ILI9163C_SPI);
  250. #endif
  251. digitalWrite(_rs,HIGH);
  252. digitalWrite(_cs,LOW);
  253. SPI.transfer(d >> 8);
  254. SPI.transfer(d);
  255. digitalWrite(_cs,HIGH);
  256. #if defined(SPI_HAS_TRANSACTION)
  257. SPI.endTransaction();
  258. #endif
  259. }
  260. void TFT_ILI9163C::setBitrate(uint32_t n)
  261. {
  262. //nop
  263. }
  264. #endif //#if defined(TEENSY3.x)
  265. void TFT_ILI9163C::begin(void)
  266. {
  267. sleep = 0;
  268. _initError = 0b00000000;
  269. #if defined(__AVR__)
  270. pinMode(_rs, OUTPUT);
  271. pinMode(_cs, OUTPUT);
  272. csport = portOutputRegister(digitalPinToPort(_cs));
  273. rsport = portOutputRegister(digitalPinToPort(_rs));
  274. cspinmask = digitalPinToBitMask(_cs);
  275. rspinmask = digitalPinToBitMask(_rs);
  276. SPI.begin();
  277. #if !defined(SPI_HAS_TRANSACTION)
  278. SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz
  279. SPI.setBitOrder(MSBFIRST);
  280. SPI.setDataMode(SPI_MODE0);
  281. #else
  282. ILI9163C_SPI = SPISettings(8000000, MSBFIRST, SPI_MODE0);
  283. #endif
  284. *csport &= ~cspinmask;// toggle CS low so it'll listen to us
  285. #elif defined(__SAM3X8E__)
  286. pinMode(_rs, OUTPUT);
  287. pinMode(_cs, OUTPUT);
  288. csport = digitalPinToPort(_cs);
  289. rsport = digitalPinToPort(_rs);
  290. cspinmask = digitalPinToBitMask(_cs);
  291. rspinmask = digitalPinToBitMask(_rs);
  292. SPI.begin();
  293. #if !defined(SPI_HAS_TRANSACTION)
  294. SPI.setClockDivider(5); // 8 MHz
  295. SPI.setBitOrder(MSBFIRST);
  296. SPI.setDataMode(SPI_MODE0);
  297. #else
  298. ILI9163C_SPI = SPISettings(24000000, MSBFIRST, SPI_MODE0);
  299. #endif
  300. csport ->PIO_CODR |= cspinmask; // toggle CS low so it'll listen to us
  301. #elif defined(__MKL26Z64__)//Teensy LC (preliminary)
  302. pinMode(_rs, OUTPUT);
  303. pinMode(_cs, OUTPUT);
  304. if (_useSPI1){
  305. if ((_mosi == 0 || _mosi == 21) && (_sclk == 20)) {//identify alternate SPI channel 1 (24Mhz)
  306. ILI9163C_SPI = SPISettings(24000000, MSBFIRST, SPI_MODE0);
  307. SPI1.setMOSI(_mosi);
  308. SPI1.setSCK(_sclk);
  309. SPI1.begin();
  310. _useSPI1 = true; //confirm
  311. } else {
  312. bitSet(_initError,0);
  313. return;
  314. }
  315. if (!SPI.pinIsChipSelect(_cs)) {//ERROR
  316. bitSet(_initError,1);
  317. return;
  318. }
  319. } else {
  320. if ((_mosi == 11 || _mosi == 7) && (_sclk == 13 || _sclk == 14)) {//valid SPI pins?
  321. ILI9163C_SPI = SPISettings(12000000, MSBFIRST, SPI_MODE0);
  322. SPI.setMOSI(_mosi);
  323. SPI.setSCK(_sclk);
  324. SPI.begin();
  325. _useSPI1 = false; //confirm
  326. } else {
  327. bitSet(_initError,0);
  328. return;
  329. }
  330. if (!SPI.pinIsChipSelect(_cs)) {//ERROR
  331. bitSet(_initError,1);
  332. return;
  333. }
  334. }
  335. digitalWriteFast(_cs, LOW);
  336. #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  337. ILI9163C_SPI = SPISettings(30000000, MSBFIRST, SPI_MODE0);
  338. if ((_mosi == 11 || _mosi == 7) && (_sclk == 13 || _sclk == 14)) {
  339. SPI.setMOSI(_mosi);
  340. SPI.setSCK(_sclk);
  341. } else {
  342. bitSet(_initError,0);
  343. return;
  344. }
  345. SPI.begin();
  346. if (SPI.pinIsChipSelect(_cs, _rs)) {
  347. pcs_data = SPI.setCS(_cs);
  348. pcs_command = pcs_data | SPI.setCS(_rs);
  349. } else {
  350. pcs_data = 0;
  351. pcs_command = 0;
  352. bitSet(_initError,1);
  353. return;
  354. }
  355. #else//all the rest of possible boards
  356. pinMode(_rs, OUTPUT);
  357. pinMode(_cs, OUTPUT);
  358. SPI.begin();
  359. #if !defined(SPI_HAS_TRANSACTION)
  360. SPI.setClockDivider(4);
  361. SPI.setBitOrder(MSBFIRST);
  362. SPI.setDataMode(SPI_MODE0);
  363. #else
  364. ILI9163C_SPI = SPISettings(8000000, MSBFIRST, SPI_MODE0);
  365. #endif
  366. digitalWrite(_cs, LOW);
  367. #endif
  368. if (_rst != 255) {
  369. pinMode(_rst, OUTPUT);
  370. digitalWrite(_rst, HIGH);
  371. delay(500);
  372. digitalWrite(_rst, LOW);
  373. delay(500);
  374. digitalWrite(_rst, HIGH);
  375. delay(500);
  376. }
  377. /*
  378. 7) MY: 1(bottom to top), 0(top to bottom) Row Address Order
  379. 6) MX: 1(R to L), 0(L to R) Column Address Order
  380. 5) MV: 1(Exchanged), 0(normal) Row/Column exchange
  381. 4) ML: 1(bottom to top), 0(top to bottom) Vertical Refresh Order
  382. 3) RGB: 1(BGR), 0(RGB) Color Space
  383. 2) MH: 1(R to L), 0(L to R) Horizontal Refresh Order
  384. 1)
  385. 0)
  386. MY, MX, MV, ML,RGB, MH, D1, D0
  387. 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //normal
  388. 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //Y-Mirror
  389. 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Mirror
  390. 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Y-Mirror
  391. 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange
  392. 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange, Y-Mirror
  393. 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 //XY exchange
  394. 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0
  395. */
  396. _Mactrl_Data = 0b00000000;
  397. _colorspaceData = __COLORSPC;//start with default data;
  398. chipInit();
  399. }
  400. uint8_t TFT_ILI9163C::errorCode(void)
  401. {
  402. return _initError;
  403. }
  404. void TFT_ILI9163C::chipInit() {
  405. uint8_t i;
  406. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  407. SPI.beginTransaction(ILI9163C_SPI);
  408. writecommand_cont(CMD_SWRESET);//software reset
  409. delay(500);
  410. writecommand_cont(CMD_SLPOUT);//exit sleep
  411. delay(5);
  412. writecommand_cont(CMD_PIXFMT);//Set Color Format 16bit
  413. writedata8_cont(0x05);
  414. delay(5);
  415. writecommand_cont(CMD_GAMMASET);//default gamma curve 3
  416. writedata8_cont(0x08);//0x04
  417. delay(1);
  418. writecommand_cont(CMD_GAMRSEL);//Enable Gamma adj
  419. writedata8_cont(0x01);
  420. delay(1);
  421. writecommand_cont(CMD_NORML);
  422. writecommand_cont(CMD_DFUNCTR);
  423. writedata8_cont(0b11111111);//
  424. writedata8_cont(0b00000110);//
  425. writecommand_cont(CMD_PGAMMAC);//Positive Gamma Correction Setting
  426. for (i=0;i<15;i++){
  427. writedata8_cont(pGammaSet[i]);
  428. }
  429. writecommand_cont(CMD_NGAMMAC);//Negative Gamma Correction Setting
  430. for (i=0;i<15;i++){
  431. writedata8_cont(nGammaSet[i]);
  432. }
  433. writecommand_cont(CMD_FRMCTR1);//Frame Rate Control (In normal mode/Full colors)
  434. writedata8_cont(0x08);//0x0C//0x08
  435. writedata8_cont(0x02);//0x14//0x08
  436. delay(1);
  437. writecommand_cont(CMD_DINVCTR);//display inversion
  438. writedata8_cont(0x07);
  439. delay(1);
  440. writecommand_cont(CMD_PWCTR1);//Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD
  441. writedata8_cont(0x0A);//4.30 - 0x0A
  442. writedata8_cont(0x02);//0x05
  443. delay(1);
  444. writecommand_cont(CMD_PWCTR2);//Set BT[2:0] for AVDD & VCL & VGH & VGL
  445. writedata8_cont(0x02);
  446. delay(1);
  447. writecommand_cont(CMD_VCOMCTR1);//Set VMH[6:0] & VML[6:0] for VOMH & VCOML
  448. writedata8_cont(0x50);//0x50
  449. writedata8_cont(99);//0x5b
  450. delay(1);
  451. writecommand_cont(CMD_VCOMOFFS);
  452. writedata8_cont(0);//0x40
  453. delay(1);
  454. writecommand_cont(CMD_CLMADRS);//Set Column Address
  455. writedata16_cont(0x00);
  456. writedata16_cont(_GRAMWIDTH);
  457. writecommand_cont(CMD_PGEADRS);//Set Page Address
  458. writedata16_cont(0x00);
  459. writedata16_cont(_GRAMHEIGH);
  460. // set scroll area (thanks Masuda)
  461. writecommand_cont(CMD_VSCLLDEF);
  462. writedata16_cont(__OFFSET);
  463. writedata16_cont(_GRAMHEIGH - __OFFSET);
  464. writedata16_last(0);
  465. SPI.endTransaction();
  466. colorSpace(_colorspaceData);
  467. setRotation(0);
  468. SPI.beginTransaction(ILI9163C_SPI);
  469. writecommand_cont(CMD_DISPON);//display ON
  470. delay(1);
  471. writecommand_last(CMD_RAMWR);//Memory Write
  472. SPI.endTransaction();
  473. delay(1);
  474. #else
  475. writecommand(CMD_SWRESET);//software reset
  476. delay(500);
  477. writecommand(CMD_SLPOUT);//exit sleep
  478. delay(5);
  479. writecommand(CMD_PIXFMT);//Set Color Format 16bit
  480. writedata(0x05);
  481. delay(5);
  482. writecommand(CMD_GAMMASET);//default gamma curve 3
  483. writedata(0x04);//0x04
  484. delay(1);
  485. writecommand(CMD_GAMRSEL);//Enable Gamma adj
  486. writedata(0x01);
  487. delay(1);
  488. writecommand(CMD_NORML);
  489. writecommand(CMD_DFUNCTR);
  490. writedata(0b11111111);//
  491. writedata(0b00000110);//
  492. writecommand(CMD_PGAMMAC);//Positive Gamma Correction Setting
  493. for (i=0;i<15;i++){
  494. writedata(pGammaSet[i]);
  495. }
  496. writecommand(CMD_NGAMMAC);//Negative Gamma Correction Setting
  497. for (i=0;i<15;i++){
  498. writedata(nGammaSet[i]);
  499. }
  500. writecommand(CMD_FRMCTR1);//Frame Rate Control (In normal mode/Full colors)
  501. writedata(0x08);//0x0C//0x08
  502. writedata(0x02);//0x14//0x08
  503. delay(1);
  504. writecommand(CMD_DINVCTR);//display inversion
  505. writedata(0x07);
  506. delay(1);
  507. writecommand(CMD_PWCTR1);//Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD
  508. writedata(0x0A);//4.30 - 0x0A
  509. writedata(0x02);//0x05
  510. delay(1);
  511. writecommand(CMD_PWCTR2);//Set BT[2:0] for AVDD & VCL & VGH & VGL
  512. writedata(0x02);
  513. delay(1);
  514. writecommand(CMD_VCOMCTR1);//Set VMH[6:0] & VML[6:0] for VOMH & VCOML
  515. writedata(0x50);//0x50
  516. writedata(99);//0x5b
  517. delay(1);
  518. writecommand(CMD_VCOMOFFS);
  519. writedata(0);//0x40
  520. delay(1);
  521. writecommand(CMD_CLMADRS);//Set Column Address
  522. writedata16(0x00);
  523. writedata16(_GRAMWIDTH);
  524. writecommand(CMD_PGEADRS);//Set Page Address
  525. writedata16(0X00);
  526. writedata16(_GRAMHEIGH);
  527. // set scroll area (thanks Masuda)
  528. writecommand(CMD_VSCLLDEF);
  529. writedata16(__OFFSET);
  530. writedata16(_GRAMHEIGH - __OFFSET);
  531. writedata16(0);
  532. colorSpace(_colorspaceData);
  533. setRotation(0);
  534. writecommand(CMD_DISPON);//display ON
  535. delay(1);
  536. writecommand(CMD_RAMWR);//Memory Write
  537. delay(1);
  538. #endif
  539. fillScreen(BLACK);
  540. }
  541. /*
  542. Colorspace selection:
  543. 0: RGB
  544. 1: GBR
  545. */
  546. void TFT_ILI9163C::colorSpace(uint8_t cspace) {
  547. if (cspace < 1){
  548. bitClear(_Mactrl_Data,3);
  549. } else {
  550. bitSet(_Mactrl_Data,3);
  551. }
  552. }
  553. void TFT_ILI9163C::invertDisplay(boolean i) {
  554. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  555. SPI.beginTransaction(ILI9163C_SPI);
  556. writecommand_last(i ? CMD_DINVON : CMD_DINVOF);
  557. SPI.endTransaction();
  558. #else
  559. writecommand(i ? CMD_DINVON : CMD_DINVOF);
  560. #endif
  561. }
  562. void TFT_ILI9163C::display(boolean onOff) {
  563. if (onOff){
  564. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  565. SPI.beginTransaction(ILI9163C_SPI);
  566. writecommand_last(CMD_DISPON);
  567. SPI.endTransaction();
  568. #else
  569. writecommand(CMD_DISPON);
  570. #endif
  571. } else {
  572. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  573. SPI.beginTransaction(ILI9163C_SPI);
  574. writecommand_last(CMD_DISPOFF);
  575. SPI.endTransaction();
  576. #else
  577. writecommand(CMD_DISPOFF);
  578. #endif
  579. }
  580. }
  581. void TFT_ILI9163C::idleMode(boolean onOff) {
  582. if (onOff){
  583. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  584. SPI.beginTransaction(ILI9163C_SPI);
  585. writecommand_last(CMD_IDLEON);
  586. SPI.endTransaction();
  587. #else
  588. writecommand(CMD_IDLEON);
  589. #endif
  590. } else {
  591. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  592. SPI.beginTransaction(ILI9163C_SPI);
  593. writecommand_last(CMD_IDLEOF);
  594. SPI.endTransaction();
  595. #else
  596. writecommand(CMD_IDLEOF);
  597. #endif
  598. }
  599. }
  600. void TFT_ILI9163C::sleepMode(boolean mode) {
  601. if (mode){
  602. if (sleep == 1) return;//already sleeping
  603. sleep = 1;
  604. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  605. SPI.beginTransaction(ILI9163C_SPI);
  606. writecommand_last(CMD_SLPIN);
  607. SPI.endTransaction();
  608. #else
  609. writecommand(CMD_SLPIN);
  610. #endif
  611. delay(5);//needed
  612. } else {
  613. if (sleep == 0) return; //Already awake
  614. sleep = 0;
  615. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  616. SPI.beginTransaction(ILI9163C_SPI);
  617. writecommand_last(CMD_SLPOUT);
  618. SPI.endTransaction();
  619. #else
  620. writecommand(CMD_SLPOUT);
  621. #endif
  622. delay(120);//needed
  623. }
  624. }
  625. void TFT_ILI9163C::defineScrollArea(uint16_t tfa, uint16_t bfa){
  626. tfa += __OFFSET;
  627. int16_t vsa = _GRAMHEIGH - tfa - bfa;
  628. if (vsa >= 0) {
  629. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  630. SPI.beginTransaction(ILI9163C_SPI);
  631. writecommand_cont(CMD_VSCLLDEF);
  632. writedata16_cont(tfa);
  633. writedata16_cont(vsa);
  634. writedata16_last(bfa);
  635. SPI.endTransaction();
  636. #else
  637. writecommand(CMD_VSCLLDEF);
  638. writedata16(tfa);
  639. writedata16(vsa);
  640. writedata16(bfa);
  641. #endif
  642. }
  643. }
  644. void TFT_ILI9163C::scroll(uint16_t adrs) {
  645. if (adrs <= _GRAMHEIGH) {
  646. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  647. SPI.beginTransaction(ILI9163C_SPI);
  648. writecommand_cont(CMD_VSSTADRS);
  649. writedata16_last(adrs + __OFFSET);
  650. SPI.endTransaction();
  651. #else
  652. writecommand(CMD_VSSTADRS);
  653. writedata16(adrs + __OFFSET);
  654. #endif
  655. }
  656. }
  657. //corrected! v3
  658. void TFT_ILI9163C::clearScreen(uint16_t color) {
  659. int px;
  660. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  661. SPI.beginTransaction(ILI9163C_SPI);
  662. _setAddrWindow(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH);
  663. for (px = 0;px < _GRAMSIZE; px++){
  664. writedata16_cont(color);
  665. }
  666. writecommand_last(CMD_NOP);
  667. SPI.endTransaction();
  668. #else
  669. setAddr(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH);//go home
  670. for (px = 0;px < _GRAMSIZE; px++){
  671. writedata16(color);
  672. }
  673. #endif
  674. }
  675. void TFT_ILI9163C::startPushData(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
  676. setAddr(x0,y0,x1,y1);
  677. }
  678. void TFT_ILI9163C::pushData(uint16_t color) {
  679. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  680. writedata16_cont(color);
  681. #else
  682. writedata16(color);
  683. #endif
  684. }
  685. void TFT_ILI9163C::endPushData() {
  686. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  687. writecommand_last(CMD_NOP);
  688. SPI.endTransaction();
  689. #endif
  690. }
  691. void TFT_ILI9163C::pushColor(uint16_t color) {
  692. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  693. SPI.beginTransaction(ILI9163C_SPI);
  694. writedata16_last(color);
  695. SPI.endTransaction();
  696. #else
  697. writedata16(color);
  698. #endif
  699. }
  700. void TFT_ILI9163C::writeScreen24(const uint32_t *bitmap,uint16_t size) {
  701. uint16_t color;
  702. uint16_t px;
  703. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  704. writecommand_cont(CMD_RAMWR);
  705. for (px = 0;px < size; px++){//16384
  706. color = Color24To565(bitmap[px]);
  707. writedata16_cont(color);
  708. }
  709. _setAddrWindow(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH);//home
  710. SPI.endTransaction();
  711. #else
  712. writecommand(CMD_RAMWR);
  713. for (px = 0;px < size; px++){
  714. color = Color24To565(bitmap[px]);
  715. writedata16(color);
  716. }
  717. homeAddress();
  718. #endif
  719. }
  720. void TFT_ILI9163C::homeAddress() {
  721. setAddrWindow(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH);
  722. }
  723. void TFT_ILI9163C::setCursor(int16_t x, int16_t y) {
  724. if (boundaryCheck(x,y)) return;
  725. setAddrWindow(0x00,0x00,x,y);
  726. cursor_x = x;
  727. cursor_y = y;
  728. }
  729. void TFT_ILI9163C::drawPixel(int16_t x, int16_t y, uint16_t color) {
  730. if (boundaryCheck(x,y)) return;
  731. if ((x < 0) || (y < 0)) return;
  732. setAddr(x,y,x+1,y+1);
  733. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  734. writedata16_last(color);
  735. SPI.endTransaction();
  736. #else
  737. writedata16(color);
  738. #endif
  739. }
  740. void TFT_ILI9163C::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
  741. // Rudimentary clipping
  742. if (boundaryCheck(x,y)) return;
  743. if (((y + h) - 1) >= _height) h = _height-y;
  744. setAddr(x,y,x,(y+h)-1);
  745. while (h-- > 0) {
  746. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  747. if (h == 0){
  748. writedata16_last(color);
  749. } else {
  750. writedata16_cont(color);
  751. }
  752. #else
  753. writedata16(color);
  754. #endif
  755. }
  756. #if defined(SPI_HAS_TRANSACTION)
  757. SPI.endTransaction();
  758. #endif
  759. }
  760. bool TFT_ILI9163C::boundaryCheck(int16_t x,int16_t y){
  761. if ((x >= _width) || (y >= _height)) return true;
  762. return false;
  763. }
  764. void TFT_ILI9163C::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
  765. // Rudimentary clipping
  766. if (boundaryCheck(x,y)) return;
  767. if (((x+w) - 1) >= _width) w = _width-x;
  768. setAddr(x,y,(x+w)-1,y);
  769. while (w-- > 0) {
  770. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  771. if (w == 0){
  772. writedata16_last(color);
  773. } else {
  774. writedata16_cont(color);
  775. }
  776. #else
  777. writedata16(color);
  778. #endif
  779. }
  780. #if defined(SPI_HAS_TRANSACTION)
  781. SPI.endTransaction();
  782. #endif
  783. }
  784. void TFT_ILI9163C::fillScreen(uint16_t color) {
  785. clearScreen(color);
  786. }
  787. // fill a rectangle
  788. void TFT_ILI9163C::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
  789. if (boundaryCheck(x,y)) return;
  790. if (((x + w) - 1) >= _width) w = _width - x;
  791. if (((y + h) - 1) >= _height) h = _height - y;
  792. setAddr(x,y,(x+w)-1,(y+h)-1);
  793. for (y = h;y > 0;y--) {
  794. for (x = w;x > 1;x--) {
  795. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  796. writedata16_cont(color);
  797. #else
  798. writedata16(color);
  799. #endif
  800. }
  801. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  802. writedata16_last(color);
  803. #else
  804. writedata16(color);
  805. #endif
  806. }
  807. #if defined(SPI_HAS_TRANSACTION)
  808. SPI.endTransaction();
  809. #endif
  810. }
  811. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  812. void TFT_ILI9163C::drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y1, uint16_t color){
  813. if (y0 == y1) {
  814. if (x1 > x0) {
  815. drawFastHLine(x0, y0, x1 - x0 + 1, color);
  816. } else if (x1 < x0) {
  817. drawFastHLine(x1, y0, x0 - x1 + 1, color);
  818. } else {
  819. drawPixel(x0, y0, color);
  820. }
  821. return;
  822. } else if (x0 == x1) {
  823. if (y1 > y0) {
  824. drawFastVLine(x0, y0, y1 - y0 + 1, color);
  825. } else {
  826. drawFastVLine(x0, y1, y0 - y1 + 1, color);
  827. }
  828. return;
  829. }
  830. bool steep = abs(y1 - y0) > abs(x1 - x0);
  831. if (steep) {
  832. std::swap(x0, y0);
  833. std::swap(x1, y1);
  834. }
  835. if (x0 > x1) {
  836. std::swap(x0, x1);
  837. std::swap(y0, y1);
  838. }
  839. int16_t dx, dy;
  840. dx = x1 - x0;
  841. dy = abs(y1 - y0);
  842. int16_t err = dx / 2;
  843. int16_t ystep;
  844. if (y0 < y1) {
  845. ystep = 1;
  846. } else {
  847. ystep = -1;
  848. }
  849. SPI.beginTransaction(ILI9163C_SPI);
  850. int16_t xbegin = x0;
  851. if (steep) {
  852. for (; x0<=x1; x0++) {
  853. err -= dy;
  854. if (err < 0) {
  855. int16_t len = x0 - xbegin;
  856. if (len) {
  857. VLine(y0, xbegin, len + 1, color);
  858. } else {
  859. Pixel(y0, x0, color);
  860. }
  861. xbegin = x0 + 1;
  862. y0 += ystep;
  863. err += dx;
  864. }
  865. }
  866. if (x0 > xbegin + 1) {
  867. VLine(y0, xbegin, x0 - xbegin, color);
  868. }
  869. } else {
  870. for (; x0<=x1; x0++) {
  871. err -= dy;
  872. if (err < 0) {
  873. int16_t len = x0 - xbegin;
  874. if (len) {
  875. HLine(xbegin, y0, len + 1, color);
  876. } else {
  877. Pixel(x0, y0, color);
  878. }
  879. xbegin = x0 + 1;
  880. y0 += ystep;
  881. err += dx;
  882. }
  883. }
  884. if (x0 > xbegin + 1) {
  885. HLine(xbegin, y0, x0 - xbegin, color);
  886. }
  887. }
  888. writecommand_last(CMD_NOP);
  889. SPI.endTransaction();
  890. }
  891. void TFT_ILI9163C::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
  892. SPI.beginTransaction(ILI9163C_SPI);
  893. HLine(x, y, w, color);
  894. HLine(x, y+h-1, w, color);
  895. VLine(x, y, h, color);
  896. VLine(x+w-1, y, h, color);
  897. writecommand_last(CMD_NOP);
  898. SPI.endTransaction();
  899. }
  900. #endif
  901. void TFT_ILI9163C::setAddr(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1){
  902. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  903. SPI.beginTransaction(ILI9163C_SPI);
  904. _setAddrWindow(x0,y0,x1,y1);
  905. #else
  906. setAddrWindow(x0,y0,x1,y1);
  907. #endif
  908. }
  909. void TFT_ILI9163C::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
  910. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  911. SPI.beginTransaction(ILI9163C_SPI);
  912. _setAddrWindow(x0,y0,x1,y1);
  913. SPI.endTransaction();
  914. #else
  915. writecommand(CMD_CLMADRS); // Column
  916. if (rotation == 0 || rotation > 1){
  917. writedata16(x0);
  918. writedata16(x1);
  919. } else {
  920. writedata16(x0 + __OFFSET);
  921. writedata16(x1 + __OFFSET);
  922. }
  923. writecommand(CMD_PGEADRS); // Page
  924. if (rotation == 0){
  925. writedata16(y0 + __OFFSET);
  926. writedata16(y1 + __OFFSET);
  927. } else {
  928. writedata16(y0);
  929. writedata16(y1);
  930. }
  931. writecommand(CMD_RAMWR); //Into RAM
  932. #endif
  933. }
  934. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  935. void TFT_ILI9163C::_setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
  936. writecommand_cont(CMD_CLMADRS); // Column
  937. if (rotation == 0 || rotation > 1){
  938. writedata16_cont(x0);
  939. writedata16_cont(x1);
  940. } else {
  941. writedata16_cont(x0 + __OFFSET);
  942. writedata16_cont(x1 + __OFFSET);
  943. }
  944. writecommand_cont(CMD_PGEADRS); // Page
  945. if (rotation == 0){
  946. writedata16_cont(y0 + __OFFSET);
  947. writedata16_cont(y1 + __OFFSET);
  948. } else {
  949. writedata16_cont(y0);
  950. writedata16_cont(y1);
  951. }
  952. writecommand_cont(CMD_RAMWR); //Into RAM
  953. }
  954. #endif
  955. void TFT_ILI9163C::setRotation(uint8_t m) {
  956. rotation = m % 4; // can't be higher than 3
  957. switch (rotation) {
  958. case 0:
  959. _Mactrl_Data = 0b00001000;
  960. _width = _TFTWIDTH;
  961. _height = _TFTHEIGHT;//-__OFFSET;
  962. break;
  963. case 1:
  964. _Mactrl_Data = 0b01101000;
  965. _width = _TFTHEIGHT;//-__OFFSET;
  966. _height = _TFTWIDTH;
  967. break;
  968. case 2:
  969. _Mactrl_Data = 0b11001000;
  970. _width = _TFTWIDTH;
  971. _height = _TFTHEIGHT;//-__OFFSET;
  972. break;
  973. case 3:
  974. _Mactrl_Data = 0b10101000;
  975. _width = _TFTWIDTH;
  976. _height = _TFTHEIGHT;//-__OFFSET;
  977. break;
  978. }
  979. colorSpace(_colorspaceData);
  980. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  981. SPI.beginTransaction(ILI9163C_SPI);
  982. writecommand_cont(CMD_MADCTL);
  983. writedata8_last(_Mactrl_Data);
  984. SPI.endTransaction();
  985. #else
  986. writecommand(CMD_MADCTL);
  987. writedata(_Mactrl_Data);
  988. #endif
  989. }