PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ILI9341_t3.h 22KB

3 yıl önce
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. // https://github.com/PaulStoffregen/ILI9341_t3
  2. // http://forum.pjrc.com/threads/26305-Highly-optimized-ILI9341-(320x240-TFT-color-display)-library
  3. /***************************************************
  4. This is our library for the Adafruit ILI9341 Breakout and Shield
  5. ----> http://www.adafruit.com/products/1651
  6. Check out the links above for our tutorials and wiring diagrams
  7. These displays use SPI to communicate, 4 or 5 pins are required to
  8. interface (RST is optional)
  9. Adafruit invests time and resources providing this open source code,
  10. please support Adafruit and open-source hardware by purchasing
  11. products from Adafruit!
  12. Written by Limor Fried/Ladyada for Adafruit Industries.
  13. MIT license, all text above must be included in any redistribution
  14. ****************************************************/
  15. // <SoftEgg>
  16. //Additional graphics routines by Tim Trzepacz, SoftEgg LLC added December 2015
  17. //(And then accidentally deleted and rewritten March 2016. Oops!)
  18. //Gradient support
  19. //----------------
  20. // fillRectVGradient - fills area with vertical gradient
  21. // fillRectHGradient - fills area with horizontal gradient
  22. // fillScreenVGradient - fills screen with vertical gradient
  23. // fillScreenHGradient - fills screen with horizontal gradient
  24. //Additional Color Support
  25. //------------------------
  26. // color565toRGB - converts 565 format 16 bit color to RGB
  27. // color565toRGB14 - converts 16 bit 565 format color to 14 bit RGB (2 bits clear for math and sign)
  28. // RGB14tocolor565 - converts 14 bit RGB back to 16 bit 565 format color
  29. //Low Memory Bitmap Support
  30. //-------------------------
  31. // writeRect8BPP - write 8 bit per pixel paletted bitmap
  32. // writeRect4BPP - write 4 bit per pixel paletted bitmap
  33. // writeRect2BPP - write 2 bit per pixel paletted bitmap
  34. // writeRect1BPP - write 1 bit per pixel paletted bitmap
  35. //String Pixel Length support
  36. //---------------------------
  37. // strPixelLen - gets pixel length of given ASCII string
  38. // <\SoftEgg>
  39. #ifndef _ILI9341_t3H_
  40. #define _ILI9341_t3H_
  41. #ifdef __cplusplus
  42. #include "Arduino.h"
  43. #endif
  44. #if defined(__MKL26Z64__)
  45. #error "Sorry, ILI9341_t3 does not work with Teensy LC. Use Adafruit_ILI9341."
  46. #elif defined(__AVR__)
  47. #error "Sorry, ILI9341_t3 does not work with Teensy 2.0 or Teensy++ 2.0. Use Adafruit_ILI9341."
  48. #endif
  49. #define ILI9341_TFTWIDTH 240
  50. #define ILI9341_TFTHEIGHT 320
  51. #define ILI9341_NOP 0x00
  52. #define ILI9341_SWRESET 0x01
  53. #define ILI9341_RDDID 0x04
  54. #define ILI9341_RDDST 0x09
  55. #define ILI9341_SLPIN 0x10
  56. #define ILI9341_SLPOUT 0x11
  57. #define ILI9341_PTLON 0x12
  58. #define ILI9341_NORON 0x13
  59. #define ILI9341_RDMODE 0x0A
  60. #define ILI9341_RDMADCTL 0x0B
  61. #define ILI9341_RDPIXFMT 0x0C
  62. #define ILI9341_RDIMGFMT 0x0D
  63. #define ILI9341_RDSELFDIAG 0x0F
  64. #define ILI9341_INVOFF 0x20
  65. #define ILI9341_INVON 0x21
  66. #define ILI9341_GAMMASET 0x26
  67. #define ILI9341_DISPOFF 0x28
  68. #define ILI9341_DISPON 0x29
  69. #define ILI9341_CASET 0x2A
  70. #define ILI9341_PASET 0x2B
  71. #define ILI9341_RAMWR 0x2C
  72. #define ILI9341_RAMRD 0x2E
  73. #define ILI9341_PTLAR 0x30
  74. #define ILI9341_MADCTL 0x36
  75. #define ILI9341_VSCRSADD 0x37
  76. #define ILI9341_PIXFMT 0x3A
  77. #define ILI9341_FRMCTR1 0xB1
  78. #define ILI9341_FRMCTR2 0xB2
  79. #define ILI9341_FRMCTR3 0xB3
  80. #define ILI9341_INVCTR 0xB4
  81. #define ILI9341_DFUNCTR 0xB6
  82. #define ILI9341_PWCTR1 0xC0
  83. #define ILI9341_PWCTR2 0xC1
  84. #define ILI9341_PWCTR3 0xC2
  85. #define ILI9341_PWCTR4 0xC3
  86. #define ILI9341_PWCTR5 0xC4
  87. #define ILI9341_VMCTR1 0xC5
  88. #define ILI9341_VMCTR2 0xC7
  89. #define ILI9341_RDID1 0xDA
  90. #define ILI9341_RDID2 0xDB
  91. #define ILI9341_RDID3 0xDC
  92. #define ILI9341_RDID4 0xDD
  93. #define ILI9341_GMCTRP1 0xE0
  94. #define ILI9341_GMCTRN1 0xE1
  95. /*
  96. #define ILI9341_PWCTR6 0xFC
  97. */
  98. // Color definitions
  99. #define ILI9341_BLACK 0x0000 /* 0, 0, 0 */
  100. #define ILI9341_NAVY 0x000F /* 0, 0, 128 */
  101. #define ILI9341_DARKGREEN 0x03E0 /* 0, 128, 0 */
  102. #define ILI9341_DARKCYAN 0x03EF /* 0, 128, 128 */
  103. #define ILI9341_MAROON 0x7800 /* 128, 0, 0 */
  104. #define ILI9341_PURPLE 0x780F /* 128, 0, 128 */
  105. #define ILI9341_OLIVE 0x7BE0 /* 128, 128, 0 */
  106. #define ILI9341_LIGHTGREY 0xC618 /* 192, 192, 192 */
  107. #define ILI9341_DARKGREY 0x7BEF /* 128, 128, 128 */
  108. #define ILI9341_BLUE 0x001F /* 0, 0, 255 */
  109. #define ILI9341_GREEN 0x07E0 /* 0, 255, 0 */
  110. #define ILI9341_CYAN 0x07FF /* 0, 255, 255 */
  111. #define ILI9341_RED 0xF800 /* 255, 0, 0 */
  112. #define ILI9341_MAGENTA 0xF81F /* 255, 0, 255 */
  113. #define ILI9341_YELLOW 0xFFE0 /* 255, 255, 0 */
  114. #define ILI9341_WHITE 0xFFFF /* 255, 255, 255 */
  115. #define ILI9341_ORANGE 0xFD20 /* 255, 165, 0 */
  116. #define ILI9341_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
  117. #define ILI9341_PINK 0xF81F
  118. #define CL(_r,_g,_b) ((((_r)&0xF8)<<8)|(((_g)&0xFC)<<3)|((_b)>>3))
  119. #define sint16_t int16_t
  120. // Documentation on the ILI9341_t3 font data format:
  121. // https://forum.pjrc.com/threads/54316-ILI9341_t-font-structure-format
  122. typedef struct {
  123. const unsigned char *index;
  124. const unsigned char *unicode;
  125. const unsigned char *data;
  126. unsigned char version;
  127. unsigned char reserved;
  128. unsigned char index1_first;
  129. unsigned char index1_last;
  130. unsigned char index2_first;
  131. unsigned char index2_last;
  132. unsigned char bits_index;
  133. unsigned char bits_width;
  134. unsigned char bits_height;
  135. unsigned char bits_xoffset;
  136. unsigned char bits_yoffset;
  137. unsigned char bits_delta;
  138. unsigned char line_space;
  139. unsigned char cap_height;
  140. } ILI9341_t3_font_t;
  141. #ifdef __cplusplus
  142. // At all other speeds, ILI9241_KINETISK__pspi->beginTransaction() will use the fastest available clock
  143. #include <SPI.h>
  144. #define ILI9341_SPICLOCK 30000000
  145. #define ILI9341_SPICLOCK_READ 6500000
  146. class ILI9341_t3 : public Print
  147. {
  148. public:
  149. ILI9341_t3(uint8_t _CS, uint8_t _DC, uint8_t _RST = 255, uint8_t _MOSI=11, uint8_t _SCLK=13, uint8_t _MISO=12);
  150. void begin(void);
  151. void sleep(bool enable);
  152. void setClock(unsigned long clk) { _clock = clk;}
  153. void pushColor(uint16_t color);
  154. void fillScreen(uint16_t color);
  155. void drawPixel(int16_t x, int16_t y, uint16_t color);
  156. void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
  157. void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
  158. void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
  159. void fillRectHGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color1, uint16_t color2);
  160. void fillRectVGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color1, uint16_t color2);
  161. void fillScreenVGradient(uint16_t color1, uint16_t color2);
  162. void fillScreenHGradient(uint16_t color1, uint16_t color2);
  163. void setRotation(uint8_t r);
  164. void setScroll(uint16_t offset);
  165. void invertDisplay(boolean i);
  166. void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
  167. // Pass 8-bit (each) R,G,B, get back 16-bit packed color
  168. static uint16_t color565(uint8_t r, uint8_t g, uint8_t b) {
  169. return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
  170. }
  171. //color565toRGB - converts 565 format 16 bit color to RGB
  172. static void color565toRGB(uint16_t color, uint8_t &r, uint8_t &g, uint8_t &b) {
  173. r = (color>>8)&0x00F8;
  174. g = (color>>3)&0x00FC;
  175. b = (color<<3)&0x00F8;
  176. }
  177. //color565toRGB14 - converts 16 bit 565 format color to 14 bit RGB (2 bits clear for math and sign)
  178. //returns 00rrrrr000000000,00gggggg00000000,00bbbbb000000000
  179. //thus not overloading sign, and allowing up to double for additions for fixed point delta
  180. static void color565toRGB14(uint16_t color, int16_t &r, int16_t &g, int16_t &b) {
  181. r = (color>>2)&0x3E00;
  182. g = (color<<3)&0x3F00;
  183. b = (color<<9)&0x3E00;
  184. }
  185. //RGB14tocolor565 - converts 14 bit RGB back to 16 bit 565 format color
  186. static uint16_t RGB14tocolor565(int16_t r, int16_t g, int16_t b)
  187. {
  188. return (((r & 0x3E00) << 2) | ((g & 0x3F00) >>3) | ((b & 0x3E00) >> 9));
  189. }
  190. //uint8_t readdata(void);
  191. uint8_t readcommand8(uint8_t reg, uint8_t index = 0);
  192. uint16_t readScanLine();
  193. // Added functions to read pixel data...
  194. uint16_t readPixel(int16_t x, int16_t y);
  195. void readRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t *pcolors);
  196. void writeRect(int16_t x, int16_t y, int16_t w, int16_t h, const uint16_t *pcolors);
  197. // writeRect8BPP - write 8 bit per pixel paletted bitmap
  198. // bitmap data in array at pixels, one byte per pixel
  199. // color palette data in array at palette
  200. void writeRect8BPP(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t *pixels, const uint16_t * palette );
  201. // writeRect4BPP - write 4 bit per pixel paletted bitmap
  202. // bitmap data in array at pixels, 4 bits per pixel
  203. // color palette data in array at palette
  204. // width must be at least 2 pixels
  205. void writeRect4BPP(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t *pixels, const uint16_t * palette );
  206. // writeRect2BPP - write 2 bit per pixel paletted bitmap
  207. // bitmap data in array at pixels, 4 bits per pixel
  208. // color palette data in array at palette
  209. // width must be at least 4 pixels
  210. void writeRect2BPP(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t *pixels, const uint16_t * palette );
  211. // writeRect1BPP - write 1 bit per pixel paletted bitmap
  212. // bitmap data in array at pixels, 4 bits per pixel
  213. // color palette data in array at palette
  214. // width must be at least 8 pixels
  215. void writeRect1BPP(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t *pixels, const uint16_t * palette );
  216. // from Adafruit_GFX.h
  217. void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
  218. void drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color);
  219. void fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
  220. void fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color);
  221. void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
  222. void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
  223. void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
  224. void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
  225. void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
  226. void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size);
  227. void setCursor(int16_t x, int16_t y);
  228. void getCursor(int16_t *x, int16_t *y);
  229. void setTextColor(uint16_t c);
  230. void setTextColor(uint16_t c, uint16_t bg);
  231. void setTextSize(uint8_t s);
  232. uint8_t getTextSize();
  233. void setTextWrap(boolean w);
  234. boolean getTextWrap();
  235. virtual size_t write(uint8_t);
  236. int16_t width(void) { return _width; }
  237. int16_t height(void) { return _height; }
  238. uint8_t getRotation(void);
  239. void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
  240. void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
  241. int16_t getCursorX(void) const { return cursor_x; }
  242. int16_t getCursorY(void) const { return cursor_y; }
  243. void setFont(const ILI9341_t3_font_t &f) { font = &f; }
  244. void setFontAdafruit(void) { font = NULL; }
  245. void drawFontChar(unsigned int c);
  246. void measureChar(uint8_t c, uint16_t* w, uint16_t* h);
  247. uint16_t fontCapHeight() { return (font) ? font->cap_height : textsize * 8; }
  248. uint16_t fontLineSpace() { return (font) ? font->line_space : textsize * 8; }
  249. uint16_t fontGap() { return (font) ? font->line_space - font->cap_height : 0; };
  250. uint16_t measureTextWidth(const char* text, int chars = 0);
  251. uint16_t measureTextHeight(const char* text, int chars = 0);
  252. int16_t strPixelLen(char * str);
  253. protected:
  254. unsigned long _clock = ILI9341_SPICLOCK;
  255. int16_t _width, _height; // Display w/h as modified by current rotation
  256. int16_t cursor_x, cursor_y;
  257. uint16_t textcolor, textbgcolor;
  258. uint8_t textsize, rotation;
  259. boolean wrap; // If set, 'wrap' text at right edge of display
  260. const ILI9341_t3_font_t *font;
  261. uint8_t _rst;
  262. uint8_t _cs, _dc;
  263. uint8_t pcs_data, pcs_command;
  264. uint8_t _miso, _mosi, _sclk;
  265. // add support to allow only one hardware CS (used for dc)
  266. #if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
  267. uint32_t _cspinmask;
  268. volatile uint32_t *_csport;
  269. uint32_t _spi_tcr_current;
  270. uint32_t _dcpinmask;
  271. uint8_t _pending_rx_count;
  272. volatile uint32_t *_dcport;
  273. uint32_t _tcr_dc_assert;
  274. uint32_t _tcr_dc_not_assert;
  275. #else
  276. uint8_t _cspinmask;
  277. volatile uint8_t *_csport;
  278. #endif
  279. uint16_t old_x0=-1, old_x1, old_y0=-1, old_y1;
  280. void setAddr(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
  281. __attribute__((always_inline)) {
  282. if (x0 != old_x0 || x1 != old_x1) {
  283. writecommand_cont(ILI9341_CASET); // Column addr set
  284. writedata16_cont(x0); // XSTART
  285. writedata16_cont(x1); // XEND
  286. old_x0 = x0; old_x1 = x1;
  287. }
  288. if (y0 != old_y0 || y1 != old_y1) {
  289. writecommand_cont(ILI9341_PASET); // Row addr set
  290. writedata16_cont(y0); // YSTART
  291. writedata16_cont(y1); // YEND
  292. old_y0 = y0; old_y1 = y1;
  293. }
  294. }
  295. //----------------------------------------------------------------------
  296. // Processor Specific stuff
  297. #if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
  298. // T4
  299. void DIRECT_WRITE_LOW(volatile uint32_t * base, uint32_t mask) __attribute__((always_inline)) {
  300. *(base+34) = mask;
  301. }
  302. void DIRECT_WRITE_HIGH(volatile uint32_t * base, uint32_t mask) __attribute__((always_inline)) {
  303. *(base+33) = mask;
  304. }
  305. void waitFifoNotFull(void) {
  306. uint32_t tmp __attribute__((unused));
  307. do {
  308. if ((IMXRT_LPSPI4_S.RSR & LPSPI_RSR_RXEMPTY) == 0) {
  309. tmp = IMXRT_LPSPI4_S.RDR; // Read any pending RX bytes in
  310. if (_pending_rx_count) _pending_rx_count--; //decrement count of bytes still levt
  311. }
  312. } while ((IMXRT_LPSPI4_S.SR & LPSPI_SR_TDF) == 0) ;
  313. }
  314. void waitTransmitComplete(void) {
  315. uint32_t tmp __attribute__((unused));
  316. // digitalWriteFast(2, HIGH);
  317. while (_pending_rx_count) {
  318. if ((IMXRT_LPSPI4_S.RSR & LPSPI_RSR_RXEMPTY) == 0) {
  319. tmp = IMXRT_LPSPI4_S.RDR; // Read any pending RX bytes in
  320. _pending_rx_count--; //decrement count of bytes still levt
  321. }
  322. }
  323. IMXRT_LPSPI4_S.CR = LPSPI_CR_MEN | LPSPI_CR_RRF; // Clear RX FIFO
  324. // digitalWriteFast(2, LOW);
  325. }
  326. #define TCR_MASK (LPSPI_TCR_PCS(3) | LPSPI_TCR_FRAMESZ(31) | LPSPI_TCR_CONT | LPSPI_TCR_RXMSK )
  327. void maybeUpdateTCR(uint32_t requested_tcr_state) /*__attribute__((always_inline)) */ {
  328. if ((_spi_tcr_current & TCR_MASK) != requested_tcr_state) {
  329. bool dc_state_change = (_spi_tcr_current & LPSPI_TCR_PCS(3)) != (requested_tcr_state & LPSPI_TCR_PCS(3));
  330. _spi_tcr_current = (_spi_tcr_current & ~TCR_MASK) | requested_tcr_state ;
  331. // only output when Transfer queue is empty.
  332. if (!dc_state_change || !_dcpinmask) {
  333. while ((IMXRT_LPSPI4_S.FSR & 0x1f) ) ;
  334. IMXRT_LPSPI4_S.TCR = _spi_tcr_current; // update the TCR
  335. } else {
  336. waitTransmitComplete();
  337. if (requested_tcr_state & LPSPI_TCR_PCS(3)) DIRECT_WRITE_HIGH(_dcport, _dcpinmask);
  338. else DIRECT_WRITE_LOW(_dcport, _dcpinmask);
  339. IMXRT_LPSPI4_S.TCR = _spi_tcr_current & ~(LPSPI_TCR_PCS(3) | LPSPI_TCR_CONT); // go ahead and update TCR anyway?
  340. }
  341. }
  342. }
  343. void beginSPITransaction(uint32_t clock = ILI9341_SPICLOCK) __attribute__((always_inline)) {
  344. SPI.beginTransaction(SPISettings(clock, MSBFIRST, SPI_MODE0));
  345. if (!_dcport) _spi_tcr_current = IMXRT_LPSPI4_S.TCR; // Only if DC is on hardware CS
  346. if (_csport)
  347. DIRECT_WRITE_LOW(_csport, _cspinmask);
  348. }
  349. void endSPITransaction() __attribute__((always_inline)) {
  350. if (_csport)
  351. DIRECT_WRITE_HIGH(_csport, _cspinmask);
  352. SPI.endTransaction();
  353. }
  354. // BUGBUG:: currently assumming we only have CS_0 as valid CS
  355. void writecommand_cont(uint8_t c) __attribute__((always_inline)) {
  356. maybeUpdateTCR(_tcr_dc_assert | LPSPI_TCR_FRAMESZ(7) /*| LPSPI_TCR_CONT*/);
  357. IMXRT_LPSPI4_S.TDR = c;
  358. _pending_rx_count++; //
  359. waitFifoNotFull();
  360. }
  361. void writedata8_cont(uint8_t c) __attribute__((always_inline)) {
  362. maybeUpdateTCR(_tcr_dc_not_assert | LPSPI_TCR_FRAMESZ(7) | LPSPI_TCR_CONT);
  363. IMXRT_LPSPI4_S.TDR = c;
  364. _pending_rx_count++; //
  365. waitFifoNotFull();
  366. }
  367. void writedata16_cont(uint16_t d) __attribute__((always_inline)) {
  368. maybeUpdateTCR(_tcr_dc_not_assert | LPSPI_TCR_FRAMESZ(15) | LPSPI_TCR_CONT);
  369. IMXRT_LPSPI4_S.TDR = d;
  370. _pending_rx_count++; //
  371. waitFifoNotFull();
  372. }
  373. void writecommand_last(uint8_t c) __attribute__((always_inline)) {
  374. maybeUpdateTCR(_tcr_dc_assert | LPSPI_TCR_FRAMESZ(7));
  375. IMXRT_LPSPI4_S.TDR = c;
  376. // IMXRT_LPSPI4_S.SR = LPSPI_SR_WCF | LPSPI_SR_FCF | LPSPI_SR_TCF;
  377. _pending_rx_count++; //
  378. waitTransmitComplete();
  379. }
  380. void writedata8_last(uint8_t c) __attribute__((always_inline)) {
  381. maybeUpdateTCR(_tcr_dc_not_assert | LPSPI_TCR_FRAMESZ(7));
  382. IMXRT_LPSPI4_S.TDR = c;
  383. // IMXRT_LPSPI4_S.SR = LPSPI_SR_WCF | LPSPI_SR_FCF | LPSPI_SR_TCF;
  384. _pending_rx_count++; //
  385. waitTransmitComplete();
  386. }
  387. void writedata16_last(uint16_t d) __attribute__((always_inline)) {
  388. maybeUpdateTCR(_tcr_dc_not_assert | LPSPI_TCR_FRAMESZ(15));
  389. IMXRT_LPSPI4_S.TDR = d;
  390. // IMXRT_LPSPI4_S.SR = LPSPI_SR_WCF | LPSPI_SR_FCF | LPSPI_SR_TCF;
  391. _pending_rx_count++; //
  392. waitTransmitComplete();
  393. }
  394. #else
  395. // T3.x
  396. //void waitFifoNotFull(void) __attribute__((always_inline)) {
  397. void waitFifoNotFull(void) {
  398. uint32_t sr;
  399. uint32_t tmp __attribute__((unused));
  400. do {
  401. sr = KINETISK_SPI0.SR;
  402. if (sr & 0xF0) tmp = KINETISK_SPI0.POPR; // drain RX FIFO
  403. } while ((sr & (15 << 12)) > (3 << 12));
  404. }
  405. void waitFifoEmpty(void) {
  406. uint32_t sr;
  407. uint32_t tmp __attribute__((unused));
  408. do {
  409. sr = KINETISK_SPI0.SR;
  410. if (sr & 0xF0) tmp = KINETISK_SPI0.POPR; // drain RX FIFO
  411. } while ((sr & 0xF0F0) > 0); // wait both RX & TX empty
  412. }
  413. void waitTransmitComplete(void) __attribute__((always_inline)) {
  414. uint32_t tmp __attribute__((unused));
  415. while (!(KINETISK_SPI0.SR & SPI_SR_TCF)) ; // wait until final output done
  416. tmp = KINETISK_SPI0.POPR; // drain the final RX FIFO word
  417. }
  418. void waitTransmitComplete(uint32_t mcr) __attribute__((always_inline)) {
  419. uint32_t tmp __attribute__((unused));
  420. while (1) {
  421. uint32_t sr = KINETISK_SPI0.SR;
  422. if (sr & SPI_SR_EOQF) break; // wait for last transmit
  423. if (sr & 0xF0) tmp = KINETISK_SPI0.POPR;
  424. }
  425. KINETISK_SPI0.SR = SPI_SR_EOQF;
  426. SPI0_MCR = mcr;
  427. while (KINETISK_SPI0.SR & 0xF0) {
  428. tmp = KINETISK_SPI0.POPR;
  429. }
  430. }
  431. void beginSPITransaction(uint32_t clock = ILI9341_SPICLOCK) __attribute__((always_inline)) {
  432. SPI.beginTransaction(SPISettings(clock, MSBFIRST, SPI_MODE0));
  433. if (_csport)
  434. *_csport &= ~_cspinmask;
  435. }
  436. void endSPITransaction() __attribute__((always_inline)) {
  437. if (_csport)
  438. *_csport |= _cspinmask;
  439. SPI.endTransaction();
  440. }
  441. void writecommand_cont(uint8_t c) __attribute__((always_inline)) {
  442. KINETISK_SPI0.PUSHR = c | (pcs_command << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;
  443. waitFifoNotFull();
  444. }
  445. void writedata8_cont(uint8_t c) __attribute__((always_inline)) {
  446. KINETISK_SPI0.PUSHR = c | (pcs_data << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;
  447. waitFifoNotFull();
  448. }
  449. void writedata16_cont(uint16_t d) __attribute__((always_inline)) {
  450. KINETISK_SPI0.PUSHR = d | (pcs_data << 16) | SPI_PUSHR_CTAS(1) | SPI_PUSHR_CONT;
  451. waitFifoNotFull();
  452. }
  453. void writecommand_last(uint8_t c) __attribute__((always_inline)) {
  454. uint32_t mcr = SPI0_MCR;
  455. KINETISK_SPI0.PUSHR = c | (pcs_command << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_EOQ;
  456. waitTransmitComplete(mcr);
  457. }
  458. void writedata8_last(uint8_t c) __attribute__((always_inline)) {
  459. uint32_t mcr = SPI0_MCR;
  460. KINETISK_SPI0.PUSHR = c | (pcs_data << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_EOQ;
  461. waitTransmitComplete(mcr);
  462. }
  463. void writedata16_last(uint16_t d) __attribute__((always_inline)) {
  464. uint32_t mcr = SPI0_MCR;
  465. KINETISK_SPI0.PUSHR = d | (pcs_data << 16) | SPI_PUSHR_CTAS(1) | SPI_PUSHR_EOQ;
  466. waitTransmitComplete(mcr);
  467. }
  468. #endif
  469. void HLine(int16_t x, int16_t y, int16_t w, uint16_t color)
  470. __attribute__((always_inline)) {
  471. if((x >= _width) || (y >= _height) || (y < 0)) return;
  472. if(x < 0) { w += x; x = 0; }
  473. if((x+w-1) >= _width) w = _width-x;
  474. setAddr(x, y, x+w-1, y);
  475. writecommand_cont(ILI9341_RAMWR);
  476. do { writedata16_cont(color); } while (--w > 0);
  477. }
  478. void VLine(int16_t x, int16_t y, int16_t h, uint16_t color)
  479. __attribute__((always_inline)) {
  480. if((x >= _width) || (x < 0) || (y >= _height)) return;
  481. if(y < 0) { h += y; y = 0; }
  482. if((y+h-1) >= _height) h = _height-y;
  483. setAddr(x, y, x, y+h-1);
  484. writecommand_cont(ILI9341_RAMWR);
  485. do { writedata16_cont(color); } while (--h > 0);
  486. }
  487. void Pixel(int16_t x, int16_t y, uint16_t color)
  488. __attribute__((always_inline)) {
  489. if((x >= _width) || (x < 0) || (y >= _height) || (y < 0)) return;
  490. setAddr(x, y, x, y);
  491. writecommand_cont(ILI9341_RAMWR);
  492. writedata16_cont(color);
  493. }
  494. void drawFontBits(uint32_t bits, uint32_t numbits, uint32_t x, uint32_t y, uint32_t repeat);
  495. };
  496. #ifndef swap
  497. #define swap(a, b) { typeof(a) t = a; a = b; b = t; }
  498. #endif
  499. // To avoid conflict when also using Adafruit_GFX or any Adafruit library
  500. // which depends on Adafruit_GFX, #include the Adafruit library *BEFORE*
  501. // you #include ILI9341_t3.h.
  502. #ifndef _ADAFRUIT_GFX_H
  503. class Adafruit_GFX_Button {
  504. public:
  505. Adafruit_GFX_Button(void) { _gfx = NULL; }
  506. void initButton(ILI9341_t3 *gfx, int16_t x, int16_t y,
  507. uint8_t w, uint8_t h,
  508. uint16_t outline, uint16_t fill, uint16_t textcolor,
  509. const char *label, uint8_t textsize);
  510. void drawButton(bool inverted = false);
  511. bool contains(int16_t x, int16_t y);
  512. void press(boolean p) {
  513. laststate = currstate;
  514. currstate = p;
  515. }
  516. bool isPressed() { return currstate; }
  517. bool justPressed() { return (currstate && !laststate); }
  518. bool justReleased() { return (!currstate && laststate); }
  519. private:
  520. ILI9341_t3 *_gfx;
  521. int16_t _x, _y;
  522. uint16_t _w, _h;
  523. uint8_t _textsize;
  524. uint16_t _outlinecolor, _fillcolor, _textcolor;
  525. char _label[10];
  526. boolean currstate, laststate;
  527. };
  528. #endif
  529. #endif // __cplusplus
  530. #endif