-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
TFT_eSPI.h
1011 lines (826 loc) · 46.4 KB
/
TFT_eSPI.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/***************************************************
Arduino TFT graphics library targeted at ESP8266
and ESP32 based boards.
This is a stand-alone library that contains the
hardware driver, the graphics functions and the
proportional fonts.
The built-in fonts 4, 6, 7 and 8 are Run Length
Encoded (RLE) to reduce the FLASH footprint.
Last review/edit by Bodmer: 04/02/22
****************************************************/
// Stop fonts etc. being loaded multiple times
#ifndef _TFT_eSPIH_
#define _TFT_eSPIH_
#define TFT_ESPI_VERSION "2.5.43"
// Bit level feature flags
// Bit 0 set: viewport capability
#define TFT_ESPI_FEATURES 1
/***************************************************************************************
** Section 1: Load required header files
***************************************************************************************/
//Standard support
#include <Arduino.h>
#include <Print.h>
#if !defined (TFT_PARALLEL_8_BIT) && !defined (RP2040_PIO_INTERFACE)
#include <SPI.h>
#endif
/***************************************************************************************
** Section 2: Load library and processor specific header files
***************************************************************************************/
// Include header file that defines the fonts loaded, the TFT drivers
// available and the pins to be used, etc. etc.
#ifdef CONFIG_TFT_eSPI_ESPIDF
#include "TFT_config.h"
#endif
// New ESP8266 board package uses ARDUINO_ARCH_ESP8266
// old package defined ESP8266
#if defined (ESP8266)
#ifndef ARDUINO_ARCH_ESP8266
#define ARDUINO_ARCH_ESP8266
#endif
#endif
// The following lines allow the user setup to be included in the sketch folder, see
// "Sketch_with_tft_setup" generic example.
#if !defined __has_include
#if !defined(DISABLE_ALL_LIBRARY_WARNINGS)
#warning Compiler does not support __has_include, so sketches cannot define the setup
#endif
#else
#if __has_include(<tft_setup.h>)
// Include the sketch setup file
#include <tft_setup.h>
#ifndef USER_SETUP_LOADED
// Prevent loading further setups
#define USER_SETUP_LOADED
#endif
#endif
#endif
#include <User_Setup_Select.h>
// Handle FLASH based storage e.g. PROGMEM
#if defined(ARDUINO_ARCH_RP2040)
#undef pgm_read_byte
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#undef pgm_read_word
#define pgm_read_word(addr) ({ \
typeof(addr) _addr = (addr); \
*(const unsigned short *)(_addr); \
})
#undef pgm_read_dword
#define pgm_read_dword(addr) ({ \
typeof(addr) _addr = (addr); \
*(const unsigned long *)(_addr); \
})
#elif defined(__AVR__)
#include <avr/pgmspace.h>
#elif defined(ARDUINO_ARCH_ESP8266) || defined(ESP32)
#include <pgmspace.h>
#else
#ifndef PROGMEM
#define PROGMEM
#endif
#endif
// Include the processor specific drivers
#if defined(CONFIG_IDF_TARGET_ESP32S3)
#include "Processors/TFT_eSPI_ESP32_S3.h"
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#include "Processors/TFT_eSPI_ESP32_C3.h"
#elif defined (ESP32)
#include "Processors/TFT_eSPI_ESP32.h"
#elif defined (ARDUINO_ARCH_ESP8266)
#include "Processors/TFT_eSPI_ESP8266.h"
#elif defined (STM32)
#include "Processors/TFT_eSPI_STM32.h"
#elif defined(ARDUINO_ARCH_RP2040)
#include "Processors/TFT_eSPI_RP2040.h"
#else
#include "Processors/TFT_eSPI_Generic.h"
#define GENERIC_PROCESSOR
#endif
/***************************************************************************************
** Section 3: Interface setup
***************************************************************************************/
#ifndef TAB_COLOUR
#define TAB_COLOUR 0
#endif
// If the SPI frequency is not defined, set a default
#ifndef SPI_FREQUENCY
#define SPI_FREQUENCY 20000000
#endif
// If the SPI read frequency is not defined, set a default
#ifndef SPI_READ_FREQUENCY
#define SPI_READ_FREQUENCY 10000000
#endif
// Some ST7789 boards do not work with Mode 0
#ifndef TFT_SPI_MODE
#if defined(ST7789_DRIVER) || defined(ST7789_2_DRIVER)
#define TFT_SPI_MODE SPI_MODE3
#else
#define TFT_SPI_MODE SPI_MODE0
#endif
#endif
// If the XPT2046 SPI frequency is not defined, set a default
#ifndef SPI_TOUCH_FREQUENCY
#define SPI_TOUCH_FREQUENCY 2500000
#endif
#ifndef SPI_BUSY_CHECK
#define SPI_BUSY_CHECK
#endif
// If half duplex SDA mode is defined then MISO pin should be -1
#ifdef TFT_SDA_READ
#ifdef TFT_MISO
#if TFT_MISO != -1
#undef TFT_MISO
#define TFT_MISO -1
#warning TFT_MISO set to -1
#endif
#endif
#endif
/***************************************************************************************
** Section 4: Setup fonts
***************************************************************************************/
// Use GLCD font in error case where user requests a smooth font file
// that does not exist (this is a temporary fix to stop ESP32 reboot)
#ifdef SMOOTH_FONT
#ifndef LOAD_GLCD
#define LOAD_GLCD
#endif
#endif
// Only load the fonts defined in User_Setup.h (to save space)
// Set flag so RLE rendering code is optionally compiled
#ifdef LOAD_GLCD
#include <Fonts/glcdfont.c>
#endif
#ifdef LOAD_FONT2
#include <Fonts/Font16.h>
#endif
#ifdef LOAD_FONT4
#include <Fonts/Font32rle.h>
#define LOAD_RLE
#endif
#ifdef LOAD_FONT6
#include <Fonts/Font64rle.h>
#ifndef LOAD_RLE
#define LOAD_RLE
#endif
#endif
#ifdef LOAD_FONT7
#include <Fonts/Font7srle.h>
#ifndef LOAD_RLE
#define LOAD_RLE
#endif
#endif
#ifdef LOAD_FONT8
#include <Fonts/Font72rle.h>
#ifndef LOAD_RLE
#define LOAD_RLE
#endif
#elif defined LOAD_FONT8N // Optional narrower version
#define LOAD_FONT8
#include <Fonts/Font72x53rle.h>
#ifndef LOAD_RLE
#define LOAD_RLE
#endif
#endif
#ifdef LOAD_GFXFF
// We can include all the free fonts and they will only be built into
// the sketch if they are used
#include <Fonts/GFXFF/gfxfont.h>
// Call up any user custom fonts
#include <User_Setups/User_Custom_Fonts.h>
#endif // #ifdef LOAD_GFXFF
// Create a null default font in case some fonts not used (to prevent crash)
const uint8_t widtbl_null[1] = {0};
PROGMEM const uint8_t chr_null[1] = {0};
PROGMEM const uint8_t* const chrtbl_null[1] = {chr_null};
// This is a structure to conveniently hold information on the default fonts
// Stores pointer to font character image address table, width table and height
typedef struct {
const uint8_t *chartbl;
const uint8_t *widthtbl;
uint8_t height;
uint8_t baseline;
} fontinfo;
// Now fill the structure
const PROGMEM fontinfo fontdata [] = {
#ifdef LOAD_GLCD
{ (const uint8_t *)font, widtbl_null, 0, 0 },
#else
{ (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 },
#endif
// GLCD font (Font 1) does not have all parameters
{ (const uint8_t *)chrtbl_null, widtbl_null, 8, 7 },
#ifdef LOAD_FONT2
{ (const uint8_t *)chrtbl_f16, widtbl_f16, chr_hgt_f16, baseline_f16},
#else
{ (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 },
#endif
// Font 3 current unused
{ (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 },
#ifdef LOAD_FONT4
{ (const uint8_t *)chrtbl_f32, widtbl_f32, chr_hgt_f32, baseline_f32},
#else
{ (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 },
#endif
// Font 5 current unused
{ (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 },
#ifdef LOAD_FONT6
{ (const uint8_t *)chrtbl_f64, widtbl_f64, chr_hgt_f64, baseline_f64},
#else
{ (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 },
#endif
#ifdef LOAD_FONT7
{ (const uint8_t *)chrtbl_f7s, widtbl_f7s, chr_hgt_f7s, baseline_f7s},
#else
{ (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 },
#endif
#ifdef LOAD_FONT8
{ (const uint8_t *)chrtbl_f72, widtbl_f72, chr_hgt_f72, baseline_f72}
#else
{ (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }
#endif
};
/***************************************************************************************
** Section 5: Font datum enumeration
***************************************************************************************/
//These enumerate the text plotting alignment (reference datum point)
#define TL_DATUM 0 // Top left (default)
#define TC_DATUM 1 // Top centre
#define TR_DATUM 2 // Top right
#define ML_DATUM 3 // Middle left
#define CL_DATUM 3 // Centre left, same as above
#define MC_DATUM 4 // Middle centre
#define CC_DATUM 4 // Centre centre, same as above
#define MR_DATUM 5 // Middle right
#define CR_DATUM 5 // Centre right, same as above
#define BL_DATUM 6 // Bottom left
#define BC_DATUM 7 // Bottom centre
#define BR_DATUM 8 // Bottom right
#define L_BASELINE 9 // Left character baseline (Line the 'A' character would sit on)
#define C_BASELINE 10 // Centre character baseline
#define R_BASELINE 11 // Right character baseline
/***************************************************************************************
** Section 6: Colour enumeration
***************************************************************************************/
// Default color definitions
#define TFT_BLACK 0x0000 /* 0, 0, 0 */
#define TFT_NAVY 0x000F /* 0, 0, 128 */
#define TFT_DARKGREEN 0x03E0 /* 0, 128, 0 */
#define TFT_DARKCYAN 0x03EF /* 0, 128, 128 */
#define TFT_MAROON 0x7800 /* 128, 0, 0 */
#define TFT_PURPLE 0x780F /* 128, 0, 128 */
#define TFT_OLIVE 0x7BE0 /* 128, 128, 0 */
#define TFT_LIGHTGREY 0xD69A /* 211, 211, 211 */
#define TFT_DARKGREY 0x7BEF /* 128, 128, 128 */
#define TFT_BLUE 0x001F /* 0, 0, 255 */
#define TFT_GREEN 0x07E0 /* 0, 255, 0 */
#define TFT_CYAN 0x07FF /* 0, 255, 255 */
#define TFT_RED 0xF800 /* 255, 0, 0 */
#define TFT_MAGENTA 0xF81F /* 255, 0, 255 */
#define TFT_YELLOW 0xFFE0 /* 255, 255, 0 */
#define TFT_WHITE 0xFFFF /* 255, 255, 255 */
#define TFT_ORANGE 0xFDA0 /* 255, 180, 0 */
#define TFT_GREENYELLOW 0xB7E0 /* 180, 255, 0 */
#define TFT_PINK 0xFE19 /* 255, 192, 203 */ //Lighter pink, was 0xFC9F
#define TFT_BROWN 0x9A60 /* 150, 75, 0 */
#define TFT_GOLD 0xFEA0 /* 255, 215, 0 */
#define TFT_SILVER 0xC618 /* 192, 192, 192 */
#define TFT_SKYBLUE 0x867D /* 135, 206, 235 */
#define TFT_VIOLET 0x915C /* 180, 46, 226 */
// Next is a special 16-bit colour value that encodes to 8 bits
// and will then decode back to the same 16-bit value.
// Convenient for 8-bit and 16-bit transparent sprites.
#define TFT_TRANSPARENT 0x0120 // This is actually a dark green
// Default palette for 4-bit colour sprites
static const uint16_t default_4bit_palette[] PROGMEM = {
TFT_BLACK, // 0 ^
TFT_BROWN, // 1 |
TFT_RED, // 2 |
TFT_ORANGE, // 3 |
TFT_YELLOW, // 4 Colours 0-9 follow the resistor colour code!
TFT_GREEN, // 5 |
TFT_BLUE, // 6 |
TFT_PURPLE, // 7 |
TFT_DARKGREY, // 8 |
TFT_WHITE, // 9 v
TFT_CYAN, // 10 Blue+green mix
TFT_MAGENTA, // 11 Blue+red mix
TFT_MAROON, // 12 Darker red colour
TFT_DARKGREEN,// 13 Darker green colour
TFT_NAVY, // 14 Darker blue colour
TFT_PINK // 15
};
/***************************************************************************************
** Section 7: Diagnostic support
***************************************************************************************/
// #define TFT_eSPI_DEBUG // Switch on debug support serial messages (not used yet)
// #define TFT_eSPI_FNx_DEBUG // Switch on debug support for function "x" (not used yet)
// This structure allows sketches to retrieve the user setup parameters at runtime
// by calling getSetup(), zero impact on code size unless used, mainly for diagnostics
typedef struct
{
String version = TFT_ESPI_VERSION;
String setup_info; // Setup reference name available to use in a user setup
uint32_t setup_id; // ID available to use in a user setup
int32_t esp; // Processor code
uint8_t trans; // SPI transaction support
uint8_t serial; // Serial (SPI) or parallel
#ifndef GENERIC_PROCESSOR
uint8_t port; // SPI port
#endif
uint8_t overlap; // ESP8266 overlap mode
uint8_t interface; // Interface type
uint16_t tft_driver; // Hexadecimal code
uint16_t tft_width; // Rotation 0 width and height
uint16_t tft_height;
uint8_t r0_x_offset; // Display offsets, not all used yet
uint8_t r0_y_offset;
uint8_t r1_x_offset;
uint8_t r1_y_offset;
uint8_t r2_x_offset;
uint8_t r2_y_offset;
uint8_t r3_x_offset;
uint8_t r3_y_offset;
int8_t pin_tft_mosi; // SPI pins
int8_t pin_tft_miso;
int8_t pin_tft_clk;
int8_t pin_tft_cs;
int8_t pin_tft_dc; // Control pins
int8_t pin_tft_rd;
int8_t pin_tft_wr;
int8_t pin_tft_rst;
int8_t pin_tft_d0; // Parallel port pins
int8_t pin_tft_d1;
int8_t pin_tft_d2;
int8_t pin_tft_d3;
int8_t pin_tft_d4;
int8_t pin_tft_d5;
int8_t pin_tft_d6;
int8_t pin_tft_d7;
int8_t pin_tft_led;
int8_t pin_tft_led_on;
int8_t pin_tch_cs; // Touch chip select pin
int16_t tft_spi_freq;// TFT write SPI frequency
int16_t tft_rd_freq; // TFT read SPI frequency
int16_t tch_spi_freq;// Touch controller read/write SPI frequency
} setup_t;
/***************************************************************************************
** Section 8: Class member and support functions
***************************************************************************************/
// Callback prototype for smooth font pixel colour read
typedef uint16_t (*getColorCallback)(uint16_t x, uint16_t y);
// Class functions and variables
class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has access to protected members
//--------------------------------------- public ------------------------------------//
public:
TFT_eSPI(int16_t _W = TFT_WIDTH, int16_t _H = TFT_HEIGHT);
// init() and begin() are equivalent, begin() included for backwards compatibility
// Sketch defined tab colour option is for ST7735 displays only
void init(uint8_t tc = TAB_COLOUR), begin(uint8_t tc = TAB_COLOUR);
// These are virtual so the TFT_eSprite class can override them with sprite specific functions
virtual void drawPixel(int32_t x, int32_t y, uint32_t color),
drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size),
drawLine(int32_t xs, int32_t ys, int32_t xe, int32_t ye, uint32_t color),
drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color),
drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color),
fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);
virtual int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font),
drawChar(uint16_t uniCode, int32_t x, int32_t y),
height(void),
width(void);
// Read the colour of a pixel at x,y and return value in 565 format
virtual uint16_t readPixel(int32_t x, int32_t y);
virtual void setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); // Note: start + end coordinates
// Push (aka write pixel) colours to the set window
virtual void pushColor(uint16_t color);
// These are non-inlined to enable override
virtual void begin_nin_write();
virtual void end_nin_write();
void setRotation(uint8_t r); // Set the display image orientation to 0, 1, 2 or 3
uint8_t getRotation(void); // Read the current rotation
// Change the origin position from the default top left
// Note: setRotation, setViewport and resetViewport will revert origin to top left corner of screen/sprite
void setOrigin(int32_t x, int32_t y);
int32_t getOriginX(void);
int32_t getOriginY(void);
void invertDisplay(bool i); // Tell TFT to invert all displayed colours
// The TFT_eSprite class inherits the following functions (not all are useful to Sprite class
void setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); // Note: start coordinates + width and height
// Viewport commands, see "Viewport_Demo" sketch
void setViewport(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDatum = true);
bool checkViewport(int32_t x, int32_t y, int32_t w, int32_t h);
int32_t getViewportX(void);
int32_t getViewportY(void);
int32_t getViewportWidth(void);
int32_t getViewportHeight(void);
bool getViewportDatum(void);
void frameViewport(uint16_t color, int32_t w);
void resetViewport(void);
// Clip input window to viewport bounds, return false if whole area is out of bounds
bool clipAddrWindow(int32_t* x, int32_t* y, int32_t* w, int32_t* h);
// Clip input window area to viewport bounds, return false if whole area is out of bounds
bool clipWindow(int32_t* xs, int32_t* ys, int32_t* xe, int32_t* ye);
// Push (aka write pixel) colours to the TFT (use setAddrWindow() first)
void pushColor(uint16_t color, uint32_t len), // Deprecated, use pushBlock()
pushColors(uint16_t *data, uint32_t len, bool swap = true), // With byte swap option
pushColors(uint8_t *data, uint32_t len); // Deprecated, use pushPixels()
// Write a solid block of a single colour
void pushBlock(uint16_t color, uint32_t len);
// Write a set of pixels stored in memory, use setSwapBytes(true/false) function to correct endianess
void pushPixels(const void * data_in, uint32_t len);
// Support for half duplex (bi-directional SDA) SPI bus where MOSI must be switched to input
#ifdef TFT_SDA_READ
#if defined (TFT_eSPI_ENABLE_8_BIT_READ)
uint8_t tft_Read_8(void); // Read 8-bit value from TFT command register
#endif
void begin_SDA_Read(void); // Begin a read on a half duplex (bi-directional SDA) SPI bus - sets MOSI to input
void end_SDA_Read(void); // Restore MOSI to output
#endif
// Graphics drawing
void fillScreen(uint32_t color),
drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color),
drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color),
fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color);
void fillRectVGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2);
void fillRectHGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2);
void drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color),
drawCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, uint32_t color),
fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color),
fillCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, int32_t delta, uint32_t color),
drawEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color),
fillEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color),
// Corner 1 Corner 2 Corner 3
drawTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color),
fillTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color);
// Smooth (anti-aliased) graphics drawing
// Draw a pixel blended with the background pixel colour (bg_color) specified, return blended colour
// If the bg_color is not specified, the background pixel colour will be read from TFT or sprite
uint16_t drawPixel(int32_t x, int32_t y, uint32_t color, uint8_t alpha, uint32_t bg_color = 0x00FFFFFF);
// Draw an anti-aliased (smooth) arc between start and end angles. Arc ends are anti-aliased.
// By default the arc is drawn with square ends unless the "roundEnds" parameter is included and set true
// Angle = 0 is at 6 o'clock position, 90 at 9 o'clock etc. The angles must be in range 0-360 or they will be clipped to these limits
// The start angle may be larger than the end angle. Arcs are always drawn clockwise from the start angle.
void drawSmoothArc(int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t startAngle, uint32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool roundEnds = false);
// As per "drawSmoothArc" except the ends of the arc are NOT anti-aliased, this facilitates dynamic arc length changes with
// arc segments and ensures clean segment joints.
// The sides of the arc are anti-aliased by default. If smoothArc is false sides will NOT be anti-aliased
void drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t startAngle, uint32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool smoothArc = true);
// Draw an anti-aliased filled circle at x, y with radius r
// Note: The thickness of line is 3 pixels to reduce the visible "braiding" effect of anti-aliasing narrow lines
// this means the inner anti-alias zone is always at r-1 and the outer zone at r+1
void drawSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t fg_color, uint32_t bg_color);
// Draw an anti-aliased filled circle at x, y with radius r
// If bg_color is not included the background pixel colour will be read from TFT or sprite
void fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color, uint32_t bg_color = 0x00FFFFFF);
// Draw a rounded rectangle that has a line thickness of r-ir+1 and bounding box defined by x,y and w,h
// The outer corner radius is r, inner corner radius is ir
// The inside and outside of the border are anti-aliased
void drawSmoothRoundRect(int32_t x, int32_t y, int32_t r, int32_t ir, int32_t w, int32_t h, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF, uint8_t quadrants = 0xF);
// Draw a filled rounded rectangle , corner radius r and bounding box defined by x,y and w,h
void fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color, uint32_t bg_color = 0x00FFFFFF);
// Draw a small anti-aliased filled circle at ax,ay with radius r (uses drawWideLine)
// If bg_color is not included the background pixel colour will be read from TFT or sprite
void drawSpot(float ax, float ay, float r, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF);
// Draw an anti-aliased wide line from ax,ay to bx,by width wd with radiused ends (radius is wd/2)
// If bg_color is not included the background pixel colour will be read from TFT or sprite
void drawWideLine(float ax, float ay, float bx, float by, float wd, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF);
// Draw an anti-aliased wide line from ax,ay to bx,by with different width at each end aw, bw and with radiused ends
// If bg_color is not included the background pixel colour will be read from TFT or sprite
void drawWedgeLine(float ax, float ay, float bx, float by, float aw, float bw, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF);
// Image rendering
// Swap the byte order for pushImage() and pushPixels() - corrects endianness
void setSwapBytes(bool swap);
bool getSwapBytes(void);
// Draw bitmap
void drawBitmap( int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor),
drawBitmap( int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor),
drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor),
drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor),
setBitmapColor(uint16_t fgcolor, uint16_t bgcolor); // Define the 2 colours for 1bpp sprites
// Set TFT pivot point (use when rendering rotated sprites)
void setPivot(int16_t x, int16_t y);
int16_t getPivotX(void), // Get pivot x
getPivotY(void); // Get pivot y
// The next functions can be used as a pair to copy screen blocks (or horizontal/vertical lines) to another location
// Read a block of pixels to a data buffer, buffer is 16-bit and the size must be at least w * h
void readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data);
// Write a block of pixels to the screen which have been read by readRect()
void pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data);
// These are used to render images or sprites stored in RAM arrays (used by Sprite class for 16bpp Sprites)
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data);
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t transparent);
// These are used to render images stored in FLASH (PROGMEM)
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transparent);
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data);
// These are used by Sprite class pushSprite() member function for 1, 4 and 8 bits per pixel (bpp) colours
// They are not intended to be used with user sketches (but could be)
// Set bpp8 true for 8bpp sprites, false otherwise. The cmap pointer must be specified for 4bpp
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, bool bpp8 = true, uint16_t *cmap = nullptr);
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, uint8_t transparent, bool bpp8 = true, uint16_t *cmap = nullptr);
// FLASH version
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint8_t *data, bool bpp8, uint16_t *cmap = nullptr);
// Render a 16-bit colour image with a 1bpp mask
void pushMaskedImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *img, uint8_t *mask);
// This next function has been used successfully to dump the TFT screen to a PC for documentation purposes
// It reads a screen area and returns the 3 RGB 8-bit colour values of each pixel in the buffer
// Set w and h to 1 to read 1 pixel's colour. The data buffer must be at least w * h * 3 bytes
void readRectRGB(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data);
// Text rendering - value returned is the pixel width of the rendered text
int16_t drawNumber(long intNumber, int32_t x, int32_t y, uint8_t font), // Draw integer using specified font number
drawNumber(long intNumber, int32_t x, int32_t y), // Draw integer using current font
// Decimal is the number of decimal places to render
// Use with setTextDatum() to position values on TFT, and setTextPadding() to blank old displayed values
drawFloat(float floatNumber, uint8_t decimal, int32_t x, int32_t y, uint8_t font), // Draw float using specified font number
drawFloat(float floatNumber, uint8_t decimal, int32_t x, int32_t y), // Draw float using current font
// Handle char arrays
// Use with setTextDatum() to position string on TFT, and setTextPadding() to blank old displayed strings
drawString(const char *string, int32_t x, int32_t y, uint8_t font), // Draw string using specified font number
drawString(const char *string, int32_t x, int32_t y), // Draw string using current font
drawString(const String& string, int32_t x, int32_t y, uint8_t font),// Draw string using specified font number
drawString(const String& string, int32_t x, int32_t y), // Draw string using current font
drawCentreString(const char *string, int32_t x, int32_t y, uint8_t font), // Deprecated, use setTextDatum() and drawString()
drawRightString(const char *string, int32_t x, int32_t y, uint8_t font), // Deprecated, use setTextDatum() and drawString()
drawCentreString(const String& string, int32_t x, int32_t y, uint8_t font),// Deprecated, use setTextDatum() and drawString()
drawRightString(const String& string, int32_t x, int32_t y, uint8_t font); // Deprecated, use setTextDatum() and drawString()
// Text rendering and font handling support functions
void setCursor(int16_t x, int16_t y), // Set cursor for tft.print()
setCursor(int16_t x, int16_t y, uint8_t font); // Set cursor and font number for tft.print()
int16_t getCursorX(void), // Read current cursor x position (moves with tft.print())
getCursorY(void); // Read current cursor y position
void setTextColor(uint16_t color), // Set character (glyph) color only (background not over-written)
setTextColor(uint16_t fgcolor, uint16_t bgcolor, bool bgfill = false), // Set character (glyph) foreground and background colour, optional background fill for smooth fonts
setTextSize(uint8_t size); // Set character size multiplier (this increases pixel size)
void setTextWrap(bool wrapX, bool wrapY = false); // Turn on/off wrapping of text in TFT width and/or height
void setTextDatum(uint8_t datum); // Set text datum position (default is top left), see Section 5 above
uint8_t getTextDatum(void);
void setTextPadding(uint16_t x_width); // Set text padding (background blanking/over-write) width in pixels
uint16_t getTextPadding(void); // Get text padding
#ifdef LOAD_GFXFF
void setFreeFont(const GFXfont *f = NULL), // Select the GFX Free Font
setTextFont(uint8_t font); // Set the font number to use in future
#else
void setFreeFont(uint8_t font), // Not used, historical fix to prevent an error
setTextFont(uint8_t font); // Set the font number to use in future
#endif
int16_t textWidth(const char *string, uint8_t font), // Returns pixel width of string in specified font
textWidth(const char *string), // Returns pixel width of string in current font
textWidth(const String& string, uint8_t font), // As above for String types
textWidth(const String& string),
fontHeight(uint8_t font), // Returns pixel height of specified font
fontHeight(void); // Returns pixel height of current font
// Used by library and Smooth font class to extract Unicode point codes from a UTF8 encoded string
uint16_t decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining),
decodeUTF8(uint8_t c);
// Support function to UTF8 decode and draw characters piped through print stream
size_t write(uint8_t);
// size_t write(const uint8_t *buf, size_t len);
// Used by Smooth font class to fetch a pixel colour for the anti-aliasing
void setCallback(getColorCallback getCol);
uint16_t fontsLoaded(void); // Each bit in returned value represents a font type that is loaded - used for debug/error handling only
// Low level read/write
void spiwrite(uint8_t); // legacy support only
#ifdef RM68120_DRIVER
void writecommand(uint16_t c); // Send a 16-bit command, function resets DC/RS high ready for data
void writeRegister8(uint16_t c, uint8_t d); // Write 8-bit data data to 16-bit command register
void writeRegister16(uint16_t c, uint16_t d); // Write 16-bit data data to 16-bit command register
#else
void writecommand(uint8_t c); // Send an 8-bit command, function resets DC/RS high ready for data
#endif
void writedata(uint8_t d); // Send data with DC/RS set high
void commandList(const uint8_t *addr); // Send a initialisation sequence to TFT stored in FLASH
uint8_t readcommand8( uint8_t cmd_function, uint8_t index = 0); // read 8 bits from TFT
uint16_t readcommand16(uint8_t cmd_function, uint8_t index = 0); // read 16 bits from TFT
uint32_t readcommand32(uint8_t cmd_function, uint8_t index = 0); // read 32 bits from TFT
// Colour conversion
// Convert 8-bit red, green and blue to 16 bits
uint16_t color565(uint8_t red, uint8_t green, uint8_t blue);
// Convert 8-bit colour to 16 bits
uint16_t color8to16(uint8_t color332);
// Convert 16-bit colour to 8 bits
uint8_t color16to8(uint16_t color565);
// Convert 16-bit colour to/from 24-bit, R+G+B concatenated into LS 24 bits
uint32_t color16to24(uint16_t color565);
uint32_t color24to16(uint32_t color888);
// Alpha blend 2 colours, see generic "alphaBlend_Test" example
// alpha = 0 = 100% background colour
// alpha = 255 = 100% foreground colour
uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc);
// 16-bit colour alphaBlend with alpha dither (dither reduces colour banding)
uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc, uint8_t dither);
// 24-bit colour alphaBlend with optional alpha dither
uint32_t alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8_t dither = 0);
// Direct Memory Access (DMA) support functions
// These can be used for SPI writes when using the ESP32 (original) or STM32 processors.
// DMA also works on a RP2040 processor with PIO based SPI and parallel (8 and 16-bit) interfaces
// Bear in mind DMA will only be of benefit in particular circumstances and can be tricky
// to manage by noobs. The functions have however been designed to be noob friendly and
// avoid a few DMA behaviour "gotchas".
//
// At best you will get a 2x TFT rendering performance improvement when using DMA because
// this library handles the SPI bus so efficiently during normal (non DMA) transfers. The best
// performance improvement scenario is the DMA transfer time is exactly the same as the time it
// takes for the processor to prepare the next image buffer and initiate another DMA transfer.
//
// DMA transfer to the TFT is done while the processor moves on to handle other tasks. Bear
// this in mind and watch out for "gotchas" like the image buffer going out of scope as the
// processor leaves a function or its content being changed while the DMA engine is reading it.
//
// The compiler MAY change the implied scope of a buffer which has been set aside by creating
// an array. For example a buffer defined before a "for-next" loop may get de-allocated when
// the loop ends. To avoid this use, for example, malloc() and free() to take control of when
// the buffer space is available and ensure it is not released until DMA is complete.
//
// Clearly you should not modify a buffer that is being DMA'ed to the TFT until the DMA is over.
// Use the dmaBusy() function to check this. Use tft.startWrite() before invoking DMA so the
// TFT chip select stays low. If you use tft.endWrite() before DMA is complete then the endWrite
// function will wait for the DMA to complete, so this may defeat any DMA performance benefit.
//
bool initDMA(bool ctrl_cs = false); // Initialise the DMA engine and attach to SPI bus - typically used in setup()
// Parameter "true" enables DMA engine control of TFT chip select (ESP32 only)
// For ESP32 only, TFT reads will not work if parameter is true
void deInitDMA(void); // De-initialise the DMA engine and detach from SPI bus - typically not used
// Push an image to the TFT using DMA, buffer is optional and grabs (double buffers) a copy of the image
// Use the buffer if the image data will get over-written or destroyed while DMA is in progress
//
// Note 1: If swapping colour bytes is defined, and the double buffer option is NOT used, then the bytes
// in the original image buffer content will be byte swapped by the function before DMA is initiated.
//
// Note 2: If part of the image will be off screen or outside of a set viewport, then the the original
// image buffer content will be altered to a correctly clipped image before DMA is initiated.
//
// The function will wait for the last DMA to complete if it is called while a previous DMA is still
// in progress, this simplifies the sketch and helps avoid "gotchas".
void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* data, uint16_t* buffer = nullptr);
#if defined (ESP32) // ESP32 only at the moment
// For case where pointer is a const and the image data must not be modified (clipped or byte swapped)
void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t const* data);
#endif
// Push a block of pixels into a window set up using setAddrWindow()
void pushPixelsDMA(uint16_t* image, uint32_t len);
// Check if the DMA is complete - use while(tft.dmaBusy); for a blocking wait
bool dmaBusy(void); // returns true if DMA is still in progress
void dmaWait(void); // wait until DMA is complete
bool DMA_Enabled = false; // Flag for DMA enabled state
uint8_t spiBusyCheck = 0; // Number of ESP32 transfer buffers to check
// Bare metal functions
void startWrite(void); // Begin SPI transaction
void writeColor(uint16_t color, uint32_t len); // Deprecated, use pushBlock()
void endWrite(void); // End SPI transaction
// Set/get an arbitrary library configuration attribute or option
// Use to switch ON/OFF capabilities such as UTF8 decoding - each attribute has a unique ID
// id = 0: reserved - may be used in future to reset all attributes to a default state
// id = 1: Turn on (a=true) or off (a=false) GLCD cp437 font character error correction
// id = 2: Turn on (a=true) or off (a=false) UTF8 decoding
// id = 3: Enable or disable use of ESP32 PSRAM (if available)
#define CP437_SWITCH 1
#define UTF8_SWITCH 2
#define PSRAM_ENABLE 3
void setAttribute(uint8_t id = 0, uint8_t a = 0); // Set attribute value
uint8_t getAttribute(uint8_t id = 0); // Get attribute value
// Used for diagnostic sketch to see library setup adopted by compiler, see Section 7 above
void getSetup(setup_t& tft_settings); // Sketch provides the instance to populate
bool verifySetupID(uint32_t id);
// Global variables
#if !defined (TFT_PARALLEL_8_BIT) && !defined (RP2040_PIO_INTERFACE)
static SPIClass& getSPIinstance(void); // Get SPI class handle
#endif
uint32_t textcolor, textbgcolor; // Text foreground and background colours
uint32_t bitmap_fg, bitmap_bg; // Bitmap foreground (bit=1) and background (bit=0) colours
uint8_t textfont, // Current selected font number
textsize, // Current font size multiplier
textdatum, // Text reference datum
rotation; // Display rotation (0-3)
uint8_t decoderState = 0; // UTF8 decoder state - not for user access
uint16_t decoderBuffer; // Unicode code-point buffer - not for user access
//--------------------------------------- private ------------------------------------//
private:
// Legacy begin and end prototypes - deprecated TODO: delete
void spi_begin();
void spi_end();
void spi_begin_read();
void spi_end_read();
// New begin and end prototypes
// begin/end a TFT write transaction
// For SPI bus the transmit clock rate is set
inline void begin_tft_write() __attribute__((always_inline));
inline void end_tft_write() __attribute__((always_inline));
// begin/end a TFT read transaction
// For SPI bus: begin lowers SPI clock rate, end reinstates transmit clock rate
inline void begin_tft_read() __attribute__((always_inline));
inline void end_tft_read() __attribute__((always_inline));
// Initialise the data bus GPIO and hardware interfaces
void initBus(void);
// Temporary library development function TODO: remove need for this
void pushSwapBytePixels(const void* data_in, uint32_t len);
// Same as setAddrWindow but exits with CGRAM in read mode
void readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h);
// Byte read prototype
uint8_t readByte(void);
// GPIO parallel bus input/output direction control
void busDir(uint32_t mask, uint8_t mode);
// Single GPIO input/output direction control
void gpioMode(uint8_t gpio, uint8_t mode);
// Smooth graphics helper
uint8_t sqrt_fraction(uint32_t num);
// Helper function: calculate distance of a point from a finite length line between two points
float wedgeLineDistance(float pax, float pay, float bax, float bay, float dr);
// Display variant settings
uint8_t tabcolor, // ST7735 screen protector "tab" colour (now invalid)
colstart = 0, rowstart = 0; // Screen display area to CGRAM area coordinate offsets
// Port and pin masks for control signals (ESP826 only) - TODO: remove need for this
volatile uint32_t *dcport, *csport;
uint32_t cspinmask, dcpinmask, wrpinmask, sclkpinmask;
#if defined(ESP32_PARALLEL)
// Bit masks for ESP32 parallel bus interface
uint32_t xclr_mask, xdir_mask; // Port set/clear and direction control masks
// Lookup table for ESP32 parallel bus interface uses 1kbyte RAM,
uint32_t xset_mask[256]; // Makes Sprite rendering test 33% faster, for slower macro equivalent
// see commented out #define set_mask(C) within TFT_eSPI_ESP32.h
#endif
//uint32_t lastColor = 0xFFFF; // Last colour - used to minimise bit shifting overhead
getColorCallback getColor = nullptr; // Smooth font callback function pointer
bool locked, inTransaction, lockTransaction; // SPI transaction and mutex lock flags
//-------------------------------------- protected ----------------------------------//
protected:
//int32_t win_xe, win_ye; // Window end coords - not needed
int32_t _init_width, _init_height; // Display w/h as input, used by setRotation()
int32_t _width, _height; // Display w/h as modified by current rotation
int32_t addr_row, addr_col; // Window position - used to minimise window commands
int16_t _xPivot; // TFT x pivot point coordinate for rotated Sprites
int16_t _yPivot; // TFT x pivot point coordinate for rotated Sprites
// Viewport variables
int32_t _vpX, _vpY, _vpW, _vpH; // Note: x start, y start, x end + 1, y end + 1
int32_t _xDatum;
int32_t _yDatum;
int32_t _xWidth;
int32_t _yHeight;
bool _vpDatum;
bool _vpOoB;
int32_t cursor_x, cursor_y, padX; // Text cursor x,y and padding setting
int32_t bg_cursor_x; // Background fill cursor
int32_t last_cursor_x; // Previous text cursor position when fill used
uint32_t fontsloaded; // Bit field of fonts loaded
uint8_t glyph_ab, // Smooth font glyph delta Y (height) above baseline
glyph_bb; // Smooth font glyph delta Y (height) below baseline
bool isDigits; // adjust bounding box for numbers to reduce visual jiggling
bool textwrapX, textwrapY; // If set, 'wrap' text at right and optionally bottom edge of display
bool _swapBytes; // Swap the byte order for TFT pushImage()
bool _booted; // init() or begin() has already run once
// User sketch manages these via set/getAttribute()
bool _cp437; // If set, use correct CP437 charset (default is OFF)
bool _utf8; // If set, use UTF-8 decoder in print stream 'write()' function (default ON)
bool _psram_enable; // Enable PSRAM use for library functions (TBD) and Sprites
uint32_t _lastColor; // Buffered value of last colour used
bool _fillbg; // Fill background flag (just for for smooth fonts at the moment)
#if defined (SSD1963_DRIVER)
uint16_t Cswap; // Swap buffer for SSD1963
uint8_t r6, g6, b6; // RGB buffer for SSD1963
#endif
#ifdef LOAD_GFXFF
GFXfont *gfxFont;
#endif
/***************************************************************************************
** Section 9: TFT_eSPI class conditional extensions
***************************************************************************************/
// Load the Touch extension
#ifdef TOUCH_CS
#if defined (TFT_PARALLEL_8_BIT) || defined (RP2040_PIO_INTERFACE)
#if !defined(DISABLE_ALL_LIBRARY_WARNINGS)
#error >>>>------>> Touch functions not supported in 8/16-bit parallel mode or with RP2040 PIO.
#endif
#else
#include "Extensions/Touch.h" // Loaded if TOUCH_CS is defined by user
#endif
#else
#if !defined(DISABLE_ALL_LIBRARY_WARNINGS)
#warning >>>>------>> TOUCH_CS pin not defined, TFT_eSPI touch functions will not be available!
#endif
#endif
// Load the Anti-aliased font extension
#ifdef SMOOTH_FONT
#include "Extensions/Smooth_font.h" // Loaded if SMOOTH_FONT is defined by user
#endif
}; // End of class TFT_eSPI
// Swap any type
template <typename T> static inline void
transpose(T& a, T& b) { T t = a; a = b; b = t; }
// Fast alphaBlend
template <typename A, typename F, typename B> static inline uint16_t
fastBlend(A alpha, F fgc, B bgc)
{
// Split out and blend 5-bit red and blue channels
uint32_t rxb = bgc & 0xF81F;
rxb += ((fgc & 0xF81F) - rxb) * (alpha >> 2) >> 6;
// Split out and blend 6-bit green channel
uint32_t xgx = bgc & 0x07E0;
xgx += ((fgc & 0x07E0) - xgx) * alpha >> 8;
// Recombine channels
return (rxb & 0xF81F) | (xgx & 0x07E0);
}