PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

ST7735_t3.h 30KB

hace 3 años
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. /***************************************************
  2. This is a library for the Adafruit 1.8" SPI display.
  3. This library works with the Adafruit 1.8" TFT Breakout w/SD card
  4. ----> http://www.adafruit.com/products/358
  5. as well as Adafruit raw 1.8" TFT display
  6. ----> http://www.adafruit.com/products/618
  7. Check out the links above for our tutorials and wiring diagrams
  8. These displays use SPI to communicate, 4 or 5 pins are required to
  9. interface (RST is optional)
  10. Adafruit invests time and resources providing this open source code,
  11. please support Adafruit and open-source hardware by purchasing
  12. products from Adafruit!
  13. Written by Limor Fried/Ladyada for Adafruit Industries.
  14. MIT license, all text above must be included in any redistribution
  15. ****************************************************/
  16. #ifndef __ST7735_t3_H_
  17. #define __ST7735_t3_H_
  18. #include "Arduino.h"
  19. #include "DMAChannel.h"
  20. #ifdef __cplusplus
  21. #include <SPI.h>
  22. #endif
  23. #include "ILI9341_fonts.h"
  24. #ifndef DISABLE_ST77XX_FRAMEBUFFER
  25. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  26. #define ENABLE_ST77XX_FRAMEBUFFER
  27. #elif defined(__IMXRT1062__)
  28. #define ENABLE_ST77XX_FRAMEBUFFER
  29. #endif
  30. // Lets allow the user to define if they want T3.2 to enable frame buffer.
  31. // it will only work on subset of displays due to memory
  32. #define ENABLE_ST77XX_FRAMEBUFFER_T32
  33. #if defined(__MK20DX256__) && defined(ENABLE_ST77XX_FRAMEBUFFER_T32)
  34. #define ENABLE_ST77XX_FRAMEBUFFER
  35. #endif
  36. #endif
  37. #define ST7735_SPICLOCK 24000000
  38. //#define ST7735_SPICLOCK 16000000
  39. // some flags for initR() :(
  40. #define INITR_GREENTAB 0x0
  41. #define INITR_REDTAB 0x1
  42. #define INITR_BLACKTAB 0x2
  43. #define INITR_18GREENTAB INITR_GREENTAB
  44. #define INITR_18REDTAB INITR_REDTAB
  45. #define INITR_18BLACKTAB INITR_BLACKTAB
  46. #define INITR_144GREENTAB 0x1
  47. #define INITR_144GREENTAB_OFFSET 0x4
  48. #define INITR_MINI160x80 0x05
  49. #define INITR_MINI160x80_ST7735S 0x06
  50. #define INIT_ST7789_TABCOLOR 42 // Not used except as a indicator to the code...
  51. #define ST7735_TFTWIDTH 128
  52. #define ST7735_TFTWIDTH_80 80 // for mini
  53. // for 1.44" display
  54. #define ST7735_TFTHEIGHT_144 128
  55. // for 1.8" display and mini
  56. #define ST7735_TFTHEIGHT_160 160 // for 1.8" and mini display
  57. #define ST7735_NOP 0x00
  58. #define ST7735_SWRESET 0x01
  59. #define ST7735_RDDID 0x04
  60. #define ST7735_RDDST 0x09
  61. #define ST7735_SLPIN 0x10
  62. #define ST7735_SLPOUT 0x11
  63. #define ST7735_PTLON 0x12
  64. #define ST7735_NORON 0x13
  65. #define ST7735_INVOFF 0x20
  66. #define ST7735_INVON 0x21
  67. #define ST7735_DISPOFF 0x28
  68. #define ST7735_DISPON 0x29
  69. #define ST7735_CASET 0x2A
  70. #define ST7735_RASET 0x2B
  71. #define ST7735_RAMWR 0x2C
  72. #define ST7735_RAMRD 0x2E
  73. #define ST7735_PTLAR 0x30
  74. #define ST7735_COLMOD 0x3A
  75. #define ST7735_MADCTL 0x36
  76. #define ST7735_FRMCTR1 0xB1
  77. #define ST7735_FRMCTR2 0xB2
  78. #define ST7735_FRMCTR3 0xB3
  79. #define ST7735_INVCTR 0xB4
  80. #define ST7735_DISSET5 0xB6
  81. #define ST7735_PWCTR1 0xC0
  82. #define ST7735_PWCTR2 0xC1
  83. #define ST7735_PWCTR3 0xC2
  84. #define ST7735_PWCTR4 0xC3
  85. #define ST7735_PWCTR5 0xC4
  86. #define ST7735_VMCTR1 0xC5
  87. #define ST7735_RDID1 0xDA
  88. #define ST7735_RDID2 0xDB
  89. #define ST7735_RDID3 0xDC
  90. #define ST7735_RDID4 0xDD
  91. #define ST7735_PWCTR6 0xFC
  92. #define ST7735_GMCTRP1 0xE0
  93. #define ST7735_GMCTRN1 0xE1
  94. // Color definitions
  95. #define ST7735_BLACK 0x0000
  96. #define ST7735_BLUE 0x001F
  97. #define ST7735_RED 0xF800
  98. #define ST7735_GREEN 0x07E0
  99. #define ST7735_CYAN 0x07FF
  100. #define ST7735_MAGENTA 0xF81F
  101. #define ST7735_YELLOW 0xFFE0
  102. #define ST7735_WHITE 0xFFFF
  103. // Also define them in a non specific ST77XX specific name
  104. #define ST77XX_BLACK 0x0000
  105. #define ST77XX_WHITE 0xFFFF
  106. #define ST77XX_RED 0xF800
  107. #define ST77XX_GREEN 0x07E0
  108. #define ST77XX_BLUE 0x001F
  109. #define ST77XX_CYAN 0x07FF
  110. #define ST77XX_MAGENTA 0xF81F
  111. #define ST77XX_YELLOW 0xFFE0
  112. #define ST77XX_ORANGE 0xFC00
  113. #define ST77XX_PINK 0xF81F
  114. // Map fonts that were modified back to the ILI9341 font
  115. #define ST7735_t3_font_t ILI9341_t3_font_t
  116. // Lets see about supporting Adafruit fonts as well?
  117. #if __has_include(<gfxfont.h>)
  118. #include <gfxfont.h>
  119. #endif
  120. #ifndef _GFXFONT_H_
  121. #define _GFXFONT_H_
  122. /// Font data stored PER GLYPH
  123. typedef struct {
  124. uint16_t bitmapOffset; ///< Pointer into GFXfont->bitmap
  125. uint8_t width; ///< Bitmap dimensions in pixels
  126. uint8_t height; ///< Bitmap dimensions in pixels
  127. uint8_t xAdvance; ///< Distance to advance cursor (x axis)
  128. int8_t xOffset; ///< X dist from cursor pos to UL corner
  129. int8_t yOffset; ///< Y dist from cursor pos to UL corner
  130. } GFXglyph;
  131. /// Data stored for FONT AS A WHOLE
  132. typedef struct {
  133. uint8_t *bitmap; ///< Glyph bitmaps, concatenated
  134. GFXglyph *glyph; ///< Glyph array
  135. uint8_t first; ///< ASCII extents (first char)
  136. uint8_t last; ///< ASCII extents (last char)
  137. uint8_t yAdvance; ///< Newline distance (y axis)
  138. } GFXfont;
  139. #endif // _GFXFONT_H_
  140. #ifndef st7735_swap
  141. #define st7735_swap(a, b) { typeof(a) t = a; a = b; b = t; }
  142. #endif
  143. #ifdef __cplusplus
  144. #if defined(__IMXRT1062__) // Teensy 4.x
  145. // Also define these in lower memory so as to make sure they are not cached...
  146. // try work around DMA memory cached. So have a couple of buffers we copy frame buffer into
  147. // as to move it out of the memory that is cached...
  148. #define ST77XX_DMA_BUFFER_SIZE 512
  149. typedef struct {
  150. DMASetting _dmasettings[2];
  151. DMAChannel _dmatx;
  152. uint16_t _dma_buffer1[ST77XX_DMA_BUFFER_SIZE] __attribute__ ((aligned(4)));
  153. uint16_t _dma_buffer2[ST77XX_DMA_BUFFER_SIZE] __attribute__ ((aligned(4)));
  154. } ST7735DMA_Data;
  155. #endif
  156. #define CL(_r,_g,_b) ((((_r)&0xF8)<<8)|(((_g)&0xFC)<<3)|((_b)>>3))
  157. //These enumerate the text plotting alignment (reference datum point)
  158. #define TL_DATUM 0 // Top left (default)
  159. #define TC_DATUM 1 // Top centre
  160. #define TR_DATUM 2 // Top right
  161. #define ML_DATUM 3 // Middle left
  162. #define CL_DATUM 3 // Centre left, same as above
  163. #define MC_DATUM 4 // Middle centre
  164. #define CC_DATUM 4 // Centre centre, same as above
  165. #define MR_DATUM 5 // Middle right
  166. #define CR_DATUM 5 // Centre right, same as above
  167. #define BL_DATUM 6 // Bottom left
  168. #define BC_DATUM 7 // Bottom centre
  169. #define BR_DATUM 8 // Bottom right
  170. //#define L_BASELINE 9 // Left character baseline (Line the 'A' character would sit on)
  171. //#define C_BASELINE 10 // Centre character baseline
  172. //#define R_BASELINE 11 // Right character baseline
  173. class ST7735_t3 : public Print
  174. {
  175. public:
  176. ST7735_t3(uint8_t CS, uint8_t RS, uint8_t SID, uint8_t SCLK, uint8_t RST = -1);
  177. ST7735_t3(uint8_t CS, uint8_t RS, uint8_t RST = -1);
  178. void initB(void), // for ST7735B displays
  179. initR(uint8_t options = INITR_GREENTAB), // for ST7735R
  180. setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1),
  181. pushColor(uint16_t color, boolean last_pixel=false),
  182. fillScreen(uint16_t color),
  183. drawPixel(int16_t x, int16_t y, uint16_t color),
  184. drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color),
  185. drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color),
  186. fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
  187. inline void fillWindow(uint16_t color) {fillScreen(color);}
  188. virtual void setRotation(uint8_t r);
  189. void invertDisplay(boolean i);
  190. void setRowColStart(uint16_t x, uint16_t y);
  191. uint16_t rowStart() {return _rowstart;}
  192. uint16_t colStart() {return _colstart;}
  193. void setAddr(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
  194. __attribute__((always_inline)) {
  195. writecommand(ST7735_CASET); // Column addr set
  196. writedata16(x0+_xstart); // XSTART
  197. writedata16(x1+_xstart); // XEND
  198. writecommand(ST7735_RASET); // Row addr set
  199. writedata16(y0+_ystart); // YSTART
  200. writedata16(y1+_ystart); // YEND
  201. }
  202. ////
  203. // from Adafruit_GFX.h
  204. int16_t width(void) const { return _width; };
  205. int16_t height(void) const { return _height; }
  206. uint8_t getRotation(void);
  207. void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
  208. void drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color);
  209. void fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
  210. void fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color);
  211. void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
  212. void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
  213. void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
  214. void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
  215. void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
  216. void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
  217. void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
  218. void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size_x, uint8_t size_y);
  219. void inline drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size)
  220. { drawChar(x, y, c, color, bg, size, size);}
  221. static const int16_t CENTER = 9998;
  222. void setCursor(int16_t x, int16_t y, bool autoCenter=false);
  223. void getCursor(int16_t *x, int16_t *y);
  224. void setTextColor(uint16_t c);
  225. void setTextColor(uint16_t c, uint16_t bg);
  226. void setTextSize(uint8_t sx, uint8_t sy);
  227. void inline setTextSize(uint8_t s) { setTextSize(s,s); }
  228. uint8_t getTextSizeX();
  229. uint8_t getTextSizeY();
  230. uint8_t getTextSize();
  231. void setTextWrap(boolean w);
  232. boolean getTextWrap();
  233. //////
  234. virtual size_t write(uint8_t);
  235. virtual size_t write(const uint8_t *buffer, size_t size);
  236. int16_t getCursorX(void) const { return cursor_x; }
  237. int16_t getCursorY(void) const { return cursor_y; }
  238. void setFont(const ILI9341_t3_font_t &f);
  239. void setFont(const GFXfont *f = NULL);
  240. void setFontAdafruit(void) { setFont(); }
  241. void drawFontChar(unsigned int c);
  242. void drawGFXFontChar(unsigned int c);
  243. void getTextBounds(const uint8_t *buffer, uint16_t len, int16_t x, int16_t y,
  244. int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
  245. void getTextBounds(const char *string, int16_t x, int16_t y,
  246. int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
  247. void getTextBounds(const String &str, int16_t x, int16_t y,
  248. int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
  249. int16_t strPixelLen(const char * str);
  250. // added support for drawing strings/numbers/floats with centering
  251. // modified from tft_ili9341_ESP github library
  252. // Handle numbers
  253. int16_t drawNumber(long long_num,int poX, int poY);
  254. int16_t drawFloat(float floatNumber,int decimal,int poX, int poY);
  255. // Handle char arrays
  256. int16_t drawString(const String& string, int poX, int poY);
  257. int16_t drawString1(char string[], int16_t len, int poX, int poY);
  258. void setTextDatum(uint8_t datum);
  259. // added support for scrolling text area
  260. // https://github.com/vitormhenrique/ILI9341_t3
  261. // Discussion regarding this optimized version:
  262. //http://forum.pjrc.com/threads/26305-Highly-optimized-ILI9341-%28320x240-TFT-color-display%29-library
  263. //
  264. void setScrollTextArea(int16_t x, int16_t y, int16_t w, int16_t h);
  265. void setScrollBackgroundColor(uint16_t color);
  266. void enableScroll(void);
  267. void disableScroll(void);
  268. void scrollTextArea(uint8_t scrollSize);
  269. void resetScrollBackgroundColor(uint16_t color);
  270. uint16_t readPixel(int16_t x, int16_t y);
  271. void readRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t *pcolors);
  272. // setOrigin sets an offset in display pixels where drawing to (0,0) will appear
  273. // for example: setOrigin(10,10); drawPixel(5,5); will cause a pixel to be drawn at hardware pixel (15,15)
  274. void setOrigin(int16_t x = 0, int16_t y = 0) {
  275. _originx = x; _originy = y;
  276. //if (Serial) Serial.printf("Set Origin %d %d\n", x, y);
  277. updateDisplayClip();
  278. }
  279. void getOrigin(int16_t* x, int16_t* y) { *x = _originx; *y = _originy; }
  280. // setClipRect() sets a clipping rectangle (relative to any set origin) for drawing to be limited to.
  281. // Drawing is also restricted to the bounds of the display
  282. void setClipRect(int16_t x1, int16_t y1, int16_t w, int16_t h)
  283. { _clipx1 = x1; _clipy1 = y1; _clipx2 = x1+w; _clipy2 = y1+h;
  284. //if (Serial) Serial.printf("Set clip Rect %d %d %d %d\n", x1, y1, w, h);
  285. updateDisplayClip();
  286. }
  287. void setClipRect() {
  288. _clipx1 = 0; _clipy1 = 0; _clipx2 = _width; _clipy2 = _height;
  289. //if (Serial) Serial.printf("clear clip Rect\n");
  290. updateDisplayClip();
  291. }
  292. ////
  293. void sendCommand(uint8_t commandByte, const uint8_t *dataBytes, uint8_t numDataBytes);
  294. // Pass 8-bit (each) R,G,B, get back 16-bit packed color
  295. inline uint16_t Color565(uint8_t r, uint8_t g, uint8_t b) {
  296. return ((b & 0xF8) << 8) | ((g & 0xFC) << 3) | (r >> 3);
  297. }
  298. void setBitrate(uint32_t n);
  299. /* These are not for current use, 8-bit protocol only!
  300. uint8_t readdata(void),
  301. readcommand8(uint8_t);
  302. uint16_t readcommand16(uint8_t);
  303. uint32_t readcommand32(uint8_t);
  304. void dummyclock(void);
  305. */
  306. // Useful methods added from ili9341_t3
  307. void writeRect(int16_t x, int16_t y, int16_t w, int16_t h, const uint16_t *pcolors);
  308. // Frame buffer support
  309. #ifdef ENABLE_ST77XX_FRAMEBUFFER
  310. enum {ST77XX_DMA_INIT=0x01, ST77XX_DMA_CONT=0x02, ST77XX_DMA_FINISH=0x04,ST77XX_DMA_ACTIVE=0x80};
  311. // added support to use optional Frame buffer
  312. void setFrameBuffer(uint16_t *frame_buffer);
  313. uint8_t useFrameBuffer(boolean b); // use the frame buffer? First call will allocate
  314. void freeFrameBuffer(void); // explicit call to release the buffer
  315. void updateScreen(void); // call to say update the screen now.
  316. bool updateScreenAsync(bool update_cont = false); // call to say update the screen optinoally turn into continuous mode.
  317. void waitUpdateAsyncComplete(void);
  318. void endUpdateAsync(); // Turn of the continueous mode fla
  319. void dumpDMASettings();
  320. uint16_t *getFrameBuffer() {return _pfbtft;}
  321. uint32_t frameCount() {return _dma_frame_count; }
  322. boolean asyncUpdateActive(void) {return (_dma_state & ST77XX_DMA_ACTIVE);}
  323. void initDMASettings(void);
  324. #else
  325. // added support to use optional Frame buffer
  326. void setFrameBuffer(uint16_t *frame_buffer) {return;}
  327. uint8_t useFrameBuffer(boolean b) {return 0;}; // use the frame buffer? First call will allocate
  328. void freeFrameBuffer(void) {return;} // explicit call to release the buffer
  329. void updateScreen(void) {return;} // call to say update the screen now.
  330. bool updateScreenAsync(bool update_cont = false) {return false;} // call to say update the screen optinoally turn into continuous mode.
  331. void waitUpdateAsyncComplete(void) {return;}
  332. void endUpdateAsync() {return;} // Turn of the continueous mode fla
  333. void dumpDMASettings() {return;}
  334. uint32_t frameCount() {return 0; }
  335. uint16_t *getFrameBuffer() {return NULL;}
  336. boolean asyncUpdateActive(void) {return false;}
  337. #endif
  338. protected:
  339. uint8_t tabcolor;
  340. void spiwrite(uint8_t),
  341. spiwrite16(uint16_t d),
  342. writecommand(uint8_t c),
  343. writecommand_last(uint8_t c),
  344. writedata(uint8_t d),
  345. writedata_last(uint8_t d),
  346. writedata16(uint16_t d),
  347. writedata16_last(uint16_t d),
  348. commandList(const uint8_t *addr),
  349. commonInit(const uint8_t *cmdList, uint8_t mode=SPI_MODE0);
  350. void charBounds(char c, int16_t *x, int16_t *y,
  351. int16_t *minx, int16_t *miny, int16_t *maxx, int16_t *maxy);
  352. //uint8_t spiread(void);
  353. boolean hwSPI;
  354. ////
  355. int16_t cursor_x, cursor_y;
  356. bool _center_x_text = false;
  357. bool _center_y_text = false;
  358. int16_t _clipx1, _clipy1, _clipx2, _clipy2;
  359. int16_t _originx, _originy;
  360. int16_t _displayclipx1, _displayclipy1, _displayclipx2, _displayclipy2;
  361. bool _invisible = false;
  362. bool _standard = true; // no bounding rectangle or origin set.
  363. inline void updateDisplayClip() {
  364. _displayclipx1 = max(0,min(_clipx1+_originx, width()));
  365. _displayclipx2 = max(0,min(_clipx2+_originx, width()));
  366. _displayclipy1 = max(0,min(_clipy1+_originy, height()));
  367. _displayclipy2 = max(0,min(_clipy2+_originy, height()));
  368. _invisible = (_displayclipx1 == _displayclipx2 || _displayclipy1 == _displayclipy2);
  369. _standard = (_displayclipx1 == 0) && (_displayclipx2 == _width) && (_displayclipy1 == 0) && (_displayclipy2 == _height);
  370. if (Serial) {
  371. //Serial.printf("UDC (%d %d)-(%d %d) %d %d\n", _displayclipx1, _displayclipy1, _displayclipx2, _displayclipy2, _invisible, _standard);
  372. }
  373. }
  374. int16_t _width, _height;
  375. int16_t scroll_x, scroll_y, scroll_width, scroll_height;
  376. boolean scrollEnable,isWritingScrollArea; // If set, 'wrap' text at right edge of display
  377. uint16_t textcolor, textbgcolor, scrollbgcolor;
  378. uint32_t textcolorPrexpanded, textbgcolorPrexpanded;
  379. uint8_t textsize_x, textsize_y, rotation, textdatum;
  380. boolean wrap; // If set, 'wrap' text at right edge of display
  381. const ILI9341_t3_font_t *font;
  382. // Anti-aliased font support
  383. uint8_t fontbpp = 1;
  384. uint8_t fontbppindex = 0;
  385. uint8_t fontbppmask = 1;
  386. uint8_t fontppb = 8;
  387. uint8_t* fontalphalut;
  388. float fontalphamx = 1;
  389. uint32_t padX;
  390. // GFX Font support
  391. const GFXfont *gfxFont = nullptr;
  392. int8_t _gfxFont_min_yOffset = 0;
  393. // Opaque font chracter overlap?
  394. unsigned int _gfx_c_last;
  395. int16_t _gfx_last_cursor_x, _gfx_last_cursor_y;
  396. int16_t _gfx_last_char_x_write = 0;
  397. uint16_t _gfx_last_char_textcolor;
  398. uint16_t _gfx_last_char_textbgcolor;
  399. bool gfxFontLastCharPosFG(int16_t x, int16_t y);
  400. void drawFontBits(bool opaque, uint32_t bits, uint32_t numbits, int32_t x, int32_t y, uint32_t repeat);
  401. void drawFontPixel( uint8_t alpha, uint32_t x, uint32_t y );
  402. uint32_t fetchpixel(const uint8_t *p, uint32_t index, uint32_t x);
  403. uint16_t _colstart, _rowstart, _xstart, _ystart, _rot, _screenHeight, _screenWidth;
  404. SPISettings _spiSettings;
  405. #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  406. uint8_t _cs, _rs, _rst, _sid, _sclk;
  407. uint8_t pcs_data, pcs_command;
  408. uint32_t ctar;
  409. volatile uint8_t *datapin, *clkpin, *cspin, *rspin;
  410. SPIClass *_pspi = nullptr;
  411. uint8_t _spi_num; // Which buss is this spi on?
  412. KINETISK_SPI_t *_pkinetisk_spi;
  413. SPIClass::SPI_Hardware_t *_spi_hardware;
  414. void waitTransmitComplete(void);
  415. void waitTransmitComplete(uint32_t mcr);
  416. uint32_t _fifo_full_test;
  417. inline void beginSPITransaction() {
  418. if (_pspi) _pspi->beginTransaction(_spiSettings);
  419. if (cspin) *cspin = 0;
  420. }
  421. inline void endSPITransaction()
  422. {
  423. if (cspin) *cspin = 1;
  424. if (_pspi) _pspi->endTransaction();
  425. }
  426. #endif
  427. #if defined(__IMXRT1062__) // Teensy 4.x
  428. SPIClass *_pspi = nullptr;
  429. uint8_t _spi_num = 0; // Which buss is this spi on?
  430. IMXRT_LPSPI_t *_pimxrt_spi = nullptr;
  431. SPIClass::SPI_Hardware_t *_spi_hardware;
  432. uint8_t _pending_rx_count = 0;
  433. uint32_t _spi_tcr_current = 0;
  434. uint32_t _tcr_dc_assert;
  435. uint32_t _tcr_dc_not_assert;
  436. void DIRECT_WRITE_LOW(volatile uint32_t * base, uint32_t mask) __attribute__((always_inline)) {
  437. *(base+34) = mask;
  438. }
  439. void DIRECT_WRITE_HIGH(volatile uint32_t * base, uint32_t mask) __attribute__((always_inline)) {
  440. *(base+33) = mask;
  441. }
  442. #define TCR_MASK (LPSPI_TCR_PCS(3) | LPSPI_TCR_FRAMESZ(31) | LPSPI_TCR_CONT | LPSPI_TCR_RXMSK )
  443. void maybeUpdateTCR(uint32_t requested_tcr_state) {
  444. if ((_spi_tcr_current & TCR_MASK) != requested_tcr_state) {
  445. bool dc_state_change = (_spi_tcr_current & LPSPI_TCR_PCS(3)) != (requested_tcr_state & LPSPI_TCR_PCS(3));
  446. _spi_tcr_current = (_spi_tcr_current & ~TCR_MASK) | requested_tcr_state ;
  447. // only output when Transfer queue is empty.
  448. if (!dc_state_change || !_dcpinmask) {
  449. while ((_pimxrt_spi->FSR & 0x1f) ) ;
  450. _pimxrt_spi->TCR = _spi_tcr_current; // update the TCR
  451. } else {
  452. waitTransmitComplete();
  453. if (requested_tcr_state & LPSPI_TCR_PCS(3)) DIRECT_WRITE_HIGH(_dcport, _dcpinmask);
  454. else DIRECT_WRITE_LOW(_dcport, _dcpinmask);
  455. _pimxrt_spi->TCR = _spi_tcr_current & ~(LPSPI_TCR_PCS(3) | LPSPI_TCR_CONT); // go ahead and update TCR anyway?
  456. }
  457. }
  458. }
  459. inline void beginSPITransaction() {
  460. if (hwSPI) _pspi->beginTransaction(_spiSettings);
  461. if (!_dcport) _spi_tcr_current = _pimxrt_spi->TCR; // Only if DC is on hardware CS
  462. if (_csport)DIRECT_WRITE_LOW(_csport, _cspinmask);
  463. }
  464. inline void endSPITransaction() {
  465. if (_csport)DIRECT_WRITE_HIGH(_csport, _cspinmask);
  466. if (hwSPI) _pspi->endTransaction();
  467. }
  468. void waitFifoNotFull(void) {
  469. uint32_t tmp __attribute__((unused));
  470. do {
  471. if ((_pimxrt_spi->RSR & LPSPI_RSR_RXEMPTY) == 0) {
  472. tmp = _pimxrt_spi->RDR; // Read any pending RX bytes in
  473. if (_pending_rx_count) _pending_rx_count--; //decrement count of bytes still levt
  474. }
  475. } while ((_pimxrt_spi->SR & LPSPI_SR_TDF) == 0) ;
  476. }
  477. void waitTransmitComplete(void) {
  478. uint32_t tmp __attribute__((unused));
  479. // digitalWriteFast(2, HIGH);
  480. while (_pending_rx_count) {
  481. if ((_pimxrt_spi->RSR & LPSPI_RSR_RXEMPTY) == 0) {
  482. tmp = _pimxrt_spi->RDR; // Read any pending RX bytes in
  483. _pending_rx_count--; //decrement count of bytes still levt
  484. }
  485. }
  486. _pimxrt_spi->CR = LPSPI_CR_MEN | LPSPI_CR_RRF; // Clear RX FIFO
  487. // digitalWriteFast(2, LOW);
  488. }
  489. uint8_t _cs, _rs, _rst, _sid, _sclk;
  490. uint32_t _cspinmask;
  491. volatile uint32_t *_csport;
  492. uint32_t _dcpinmask;
  493. volatile uint32_t *_dcport;
  494. uint32_t _mosipinmask;
  495. volatile uint32_t *_mosiport;
  496. uint32_t _sckpinmask;
  497. volatile uint32_t *_sckport;
  498. uint32_t ctar;
  499. #endif
  500. #if defined(__MKL26Z64__)
  501. volatile uint8_t *dataport, *clkport, *csport, *rsport;
  502. uint8_t _cs, _rs, _rst, _sid, _sclk,
  503. datapinmask, clkpinmask, cspinmask, rspinmask;
  504. boolean hwSPI1;
  505. inline void beginSPITransaction() {
  506. if (hwSPI) SPI.beginTransaction(_spiSettings);
  507. else if (hwSPI1) SPI1.beginTransaction(_spiSettings);
  508. if (csport)*csport &= ~cspinmask;
  509. }
  510. inline void endSPITransaction() {
  511. if (csport) *csport |= cspinmask;
  512. if (hwSPI) SPI.endTransaction();
  513. else if (hwSPI1) SPI1.endTransaction();
  514. }
  515. #endif
  516. #ifdef ENABLE_ST77XX_FRAMEBUFFER
  517. // Add support for optional frame buffer
  518. uint16_t *_pfbtft; // Optional Frame buffer
  519. uint8_t _use_fbtft; // Are we in frame buffer mode?
  520. uint16_t *_we_allocated_buffer; // We allocated the buffer;
  521. uint32_t _count_pixels; // How big is the display in total pixels...
  522. // Add DMA support.
  523. // Note: We have enough memory to have more than one, so could have multiple active devices (one per SPI BUS)
  524. // All three devices have 3 SPI buss so hard coded
  525. static ST7735_t3 *_dmaActiveDisplay[3]; // Use pointer to this as a way to get back to object...
  526. volatile uint8_t _dma_state; // DMA status
  527. volatile uint32_t _dma_frame_count; // Can return a frame count...
  528. #if defined(__MK66FX1M0__)
  529. // T3.6 use Scatter/gather with chain to do transfer
  530. static DMASetting _dmasettings[3][4];
  531. DMAChannel _dmatx;
  532. uint8_t _cnt_dma_settings; // how many do we need for this display?
  533. #elif defined(__IMXRT1062__) // Teensy 4.x
  534. static ST7735DMA_Data _dma_data[3]; // one structure for each SPI buss...
  535. // try work around DMA memory cached. So have a couple of buffers we copy frame buffer into
  536. // as to move it out of the memory that is cached...
  537. volatile uint32_t _dma_pixel_index = 0;
  538. volatile uint16_t _dma_sub_frame_count = 0; // Can return a frame count...
  539. uint16_t _dma_buffer_size; // the actual size we are using <= DMA_BUFFER_SIZE;
  540. uint16_t _dma_cnt_sub_frames_per_frame;
  541. uint32_t _spi_fcr_save; // save away previous FCR register value
  542. #elif defined(__MK64FX512__)
  543. // T3.5 - had issues scatter/gather so do just use channels/interrupts
  544. // and update and continue
  545. uint8_t _cspinmask;
  546. volatile uint8_t *_csport = nullptr;
  547. DMAChannel _dmatx;
  548. DMAChannel _dmarx;
  549. uint32_t _dma_count_remaining;
  550. uint16_t _dma_write_size_words;
  551. #elif defined(__MK20DX256__)
  552. // For first pass maybe emulate T3.5 on SPI...
  553. uint8_t _cspinmask;
  554. volatile uint8_t *_csport = nullptr;
  555. DMAChannel _dmatx;
  556. DMAChannel _dmarx;
  557. uint16_t _dma_count_remaining;
  558. uint16_t _dma_write_size_words;
  559. #endif
  560. static void dmaInterrupt(void);
  561. static void dmaInterrupt1(void);
  562. static void dmaInterrupt2(void);
  563. void process_dma_interrupt(void);
  564. #endif
  565. void HLine(int16_t x, int16_t y, int16_t w, uint16_t color)
  566. __attribute__((always_inline))
  567. {
  568. #ifdef ENABLE_ST77XX_FRAMEBUFFER
  569. if (_use_fbtft) {
  570. drawFastHLine(x, y, w, color);
  571. return;
  572. }
  573. #endif
  574. x+=_originx;
  575. y+=_originy;
  576. // Rectangular clipping
  577. if((y < _displayclipy1) || (x >= _displayclipx2) || (y >= _displayclipy2)) return;
  578. if(x<_displayclipx1) { w = w - (_displayclipx1 - x); x = _displayclipx1; }
  579. if((x+w-1) >= _displayclipx2) w = _displayclipx2-x;
  580. if (w<1) return;
  581. setAddr(x, y, x+w-1, y);
  582. writecommand(ST7735_RAMWR);
  583. do { writedata16(color); } while (--w > 0);
  584. }
  585. void VLine(int16_t x, int16_t y, int16_t h, uint16_t color)
  586. __attribute__((always_inline))
  587. {
  588. #ifdef ENABLE_ST77XX_FRAMEBUFFER
  589. if (_use_fbtft) {
  590. drawFastVLine(x, y, h, color);
  591. return;
  592. }
  593. #endif
  594. x+=_originx;
  595. y+=_originy;
  596. // Rectangular clipping
  597. if((x < _displayclipx1) || (x >= _displayclipx2) || (y >= _displayclipy2)) return;
  598. if(y < _displayclipy1) { h = h - (_displayclipy1 - y); y = _displayclipy1;}
  599. if((y+h-1) >= _displayclipy2) h = _displayclipy2-y;
  600. if(h<1) return;
  601. setAddr(x, y, x, y+h-1);
  602. writecommand(ST7735_RAMWR);
  603. do { writedata16(color); } while (--h > 0);
  604. }
  605. /**
  606. * Found in a pull request for the Adafruit framebuffer library. Clever!
  607. * https://github.com/tricorderproject/arducordermini/pull/1/files#diff-d22a481ade4dbb4e41acc4d7c77f683d
  608. * Converts 0000000000000000rrrrrggggggbbbbb
  609. * into 00000gggggg00000rrrrr000000bbbbb
  610. * with mask 00000111111000001111100000011111
  611. * This is useful because it makes space for a parallel fixed-point multiply
  612. * This implements the linear interpolation formula: result = bg * (1.0 - alpha) + fg * alpha
  613. * This can be factorized into: result = bg + (fg - bg) * alpha
  614. * alpha is in Q1.5 format, so 0.0 is represented by 0, and 1.0 is represented by 32
  615. * @param fg Color to draw in RGB565 (16bit)
  616. * @param bg Color to draw over in RGB565 (16bit)
  617. * @param alpha Alpha in range 0-255
  618. **/
  619. uint16_t alphaBlendRGB565( uint32_t fg, uint32_t bg, uint8_t alpha )
  620. __attribute__((always_inline)) {
  621. alpha = ( alpha + 4 ) >> 3; // from 0-255 to 0-31
  622. bg = (bg | (bg << 16)) & 0b00000111111000001111100000011111;
  623. fg = (fg | (fg << 16)) & 0b00000111111000001111100000011111;
  624. uint32_t result = ((((fg - bg) * alpha) >> 5) + bg) & 0b00000111111000001111100000011111;
  625. return (uint16_t)((result >> 16) | result); // contract result
  626. }
  627. /**
  628. * Same as above, but fg and bg are premultiplied, and alpah is already in range 0-31
  629. */
  630. uint16_t alphaBlendRGB565Premultiplied( uint32_t fg, uint32_t bg, uint8_t alpha )
  631. __attribute__((always_inline)) {
  632. uint32_t result = ((((fg - bg) * alpha) >> 5) + bg) & 0b00000111111000001111100000011111;
  633. return (uint16_t)((result >> 16) | result); // contract result
  634. }
  635. void Pixel(int16_t x, int16_t y, uint16_t color)
  636. __attribute__((always_inline)) {
  637. x+=_originx;
  638. y+=_originy;
  639. //if((x < _displayclipx1) ||(x >= _displayclipx2) || (y < _displayclipy1) || (y >= _displayclipy2)) return;
  640. #ifdef ENABLE_ST77XX_FRAMEBUFFER
  641. if (_use_fbtft) {
  642. _pfbtft[y*_screenWidth + x] = color;
  643. return;
  644. }
  645. #endif
  646. setAddr(x, y, x, y);
  647. writecommand(ST7735_RAMWR);
  648. writedata16(color);
  649. }
  650. };
  651. // To avoid conflict when also using Adafruit_GFX or any Adafruit library
  652. // which depends on Adafruit_GFX, #include the Adafruit library *BEFORE*
  653. // you #include ST7735_t3.h.
  654. // Warning the implemention of class needs to be here, else the code
  655. // compiled in the c++ file will cause duplicate defines in the link phase.
  656. #define Adafruit_GFX_Button ST7735_Button
  657. class ST7735_Button {
  658. public:
  659. ST7735_Button(void) { _gfx = NULL; }
  660. void initButton(ST7735_t3 *gfx, int16_t x, int16_t y,
  661. uint8_t w, uint8_t h,
  662. uint16_t outline, uint16_t fill, uint16_t textcolor,
  663. const char *label, uint8_t textsize_x, uint8_t textsize_y) {
  664. _x = x;
  665. _y = y;
  666. _w = w;
  667. _h = h;
  668. _outlinecolor = outline;
  669. _fillcolor = fill;
  670. _textcolor = textcolor;
  671. _textsize_x = textsize_x;
  672. _textsize_y = textsize_y;
  673. _gfx = gfx;
  674. strncpy(_label, label, 9);
  675. _label[9] = 0;
  676. }
  677. void drawButton(bool inverted = false) {
  678. uint16_t fill, outline, text;
  679. if (! inverted) {
  680. fill = _fillcolor;
  681. outline = _outlinecolor;
  682. text = _textcolor;
  683. } else {
  684. fill = _textcolor;
  685. outline = _outlinecolor;
  686. text = _fillcolor;
  687. }
  688. _gfx->fillRoundRect(_x - (_w/2), _y - (_h/2), _w, _h, min(_w,_h)/4, fill);
  689. _gfx->drawRoundRect(_x - (_w/2), _y - (_h/2), _w, _h, min(_w,_h)/4, outline);
  690. _gfx->setCursor(_x - strlen(_label)*3*_textsize_x, _y-4*_textsize_y);
  691. _gfx->setTextColor(text);
  692. _gfx->setTextSize(_textsize_x, _textsize_y);
  693. _gfx->print(_label);
  694. }
  695. bool contains(int16_t x, int16_t y) {
  696. if ((x < (_x - _w/2)) || (x > (_x + _w/2))) return false;
  697. if ((y < (_y - _h/2)) || (y > (_y + _h/2))) return false;
  698. return true;
  699. }
  700. void press(boolean p) {
  701. laststate = currstate;
  702. currstate = p;
  703. }
  704. bool isPressed() { return currstate; }
  705. bool justPressed() { return (currstate && !laststate); }
  706. bool justReleased() { return (!currstate && laststate); }
  707. private:
  708. ST7735_t3 *_gfx;
  709. int16_t _x, _y;
  710. uint16_t _w, _h;
  711. uint8_t _textsize_x, _textsize_y;
  712. uint16_t _outlinecolor, _fillcolor, _textcolor;
  713. char _label[10];
  714. boolean currstate, laststate;
  715. };
  716. #endif //end cplus
  717. #endif