From de8619027d46dd57d423eec25b269e9ff4046b76 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sat, 14 Nov 2020 01:38:09 +0000 Subject: [PATCH] Add ESP8266 LittleFS examples The ESP8266 has the LittleFS Flash filing system which is significantly faster than SPIFFS. New Smooth Font examples have been added that use LittleFS. --- User_Setup_Select.h | 2 +- .../LittleFS/Font_Demo_1/Font_Demo_1.ino | 181 ++++++++++++++ .../LittleFS/Font_Demo_1/Notes.ino | 56 +++++ .../Font_Demo_1/data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../Font_Demo_1/data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../LittleFS/Font_Demo_2/Font_Demo_2.ino | 230 +++++++++++++++++ .../LittleFS/Font_Demo_2/Notes.ino | 56 +++++ .../Font_Demo_2/data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../Font_Demo_2/data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../LittleFS/Font_Demo_3/Font_Demo_3.ino | 231 ++++++++++++++++++ .../LittleFS/Font_Demo_3/Notes.ino | 61 +++++ .../Font_Demo_3/data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../Font_Demo_3/data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../Font_Demo_3/data/NotoSansMonoSCB20.vlw | Bin 0 -> 15382 bytes .../LittleFS/Font_Demo_4/Font_Demo_4.ino | 140 +++++++++++ .../LittleFS/Font_Demo_4/Notes.ino | 56 +++++ .../Font_Demo_4/data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../Font_Demo_4/data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../Print_Smooth_Font/Print_Smooth_Font.ino | 149 +++++++++++ .../data/Final-Frontier-28.vlw | Bin 0 -> 25287 bytes .../Smooth_font_gradient.ino | 120 +++++++++ .../data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../Smooth_font_reading_TFT.ino | 165 +++++++++++++ .../data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../Unicode_test/LittleFS_functions.ino | 39 +++ .../LittleFS/Unicode_test/Unicode_test.ino | 152 ++++++++++++ .../Unicode_test/data/Final-Frontier-28.vlw | Bin 0 -> 25287 bytes .../Unicode_test/data/Latin-Hiragana-24.vlw | Bin 0 -> 54478 bytes .../Unicode_test/data/Unicode-Test-72.vlw | Bin 0 -> 36469 bytes 31 files changed, 1637 insertions(+), 1 deletion(-) create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_1/Font_Demo_1.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_1/Notes.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_1/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_1/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_2/Font_Demo_2.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_2/Notes.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_2/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_2/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_3/Font_Demo_3.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_3/Notes.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_3/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_3/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_3/data/NotoSansMonoSCB20.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_4/Font_Demo_4.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_4/Notes.ino create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_4/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Font_Demo_4/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Print_Smooth_Font/Print_Smooth_Font.ino create mode 100644 examples/Smooth Fonts/LittleFS/Print_Smooth_Font/data/Final-Frontier-28.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Smooth_font_gradient/Smooth_font_gradient.ino create mode 100644 examples/Smooth Fonts/LittleFS/Smooth_font_gradient/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Smooth_font_gradient/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino create mode 100644 examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Unicode_test/LittleFS_functions.ino create mode 100644 examples/Smooth Fonts/LittleFS/Unicode_test/Unicode_test.ino create mode 100644 examples/Smooth Fonts/LittleFS/Unicode_test/data/Final-Frontier-28.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Unicode_test/data/Latin-Hiragana-24.vlw create mode 100644 examples/Smooth Fonts/LittleFS/Unicode_test/data/Unicode-Test-72.vlw diff --git a/User_Setup_Select.h b/User_Setup_Select.h index 8ee352e..5a6d1ca 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -72,7 +72,7 @@ //#include // Setup file for ESP32 and TTGO T-CameraPlus ST7789 SPI bus TFT 240x240 //#include // Setup file for ESP32 and TTGO T-Watch ST7789 SPI bus TFT 240x240 -//#include // Setup file configured for ST7735 128 x 160 +//#include // Setup file configured for ST7735 128 x 128 animated eyes //#include // Setup file for ESP32 and SSD1963 TFT display diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_1/Font_Demo_1.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_1/Font_Demo_1.ino new file mode 100644 index 0000000..7d41d8d --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Font_Demo_1/Font_Demo_1.ino @@ -0,0 +1,181 @@ +/* + There are four different methods of plotting anti-aliased fonts to the screen. + + This sketch uses method 1, using tft.print() and tft.println() calls. + + In some cases the sketch shows what can go wrong too, so read the comments! + + The font is rendered WITHOUT a background, but a background colour needs to be + set so the anti-aliasing of the character is performed correctly. This is because + characters are drawn one by one. + + This method is good for static text that does not change often because changing + values may flicker. The text appears at the tft cursor coordinates. + + It is also possible to "print" text directly into a created sprite, for example using + spr.println("Hello"); and then push the sprite to the screen. That method is not + demonstrated in this sketch. + +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to LittleFS (must set at least 1M for LittleFS) using the +// "Tools" "ESP8266 LittleFS Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/earlephilhower/arduino-esp8266littlefs-plugin + +// Close the IDE and open again to see the new menu option. + +// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI +// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font + +// This sketch uses font files created from the Noto family of fonts: +// https://www.google.com/get/noto/ + +#define AA_FONT_SMALL "NotoSansBold15" +#define AA_FONT_LARGE "NotoSansBold36" + +// Font files are stored in Flash FS +#include +#include +#define FlashFS LittleFS + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); + + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(0); + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + bool font_missing = false; + if (LittleFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\nFont missing in Flash FS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\nFonts found OK."); +} + + +void loop() { + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set the font colour AND the background colour + // so the anti-aliasing works + + tft.setCursor(0, 0); // Set cursor at top left of screen + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Small font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.loadFont(AA_FONT_SMALL, LittleFS); // Must load the font first + + tft.println("Small 15pt font"); // println moves cursor down for a new line + + tft.println(); // New line + + tft.print("ABC"); // print leaves cursor at end of line + + tft.setTextColor(TFT_CYAN, TFT_BLACK); + tft.println("1234"); // Added to line after ABC + + tft.setTextColor(TFT_YELLOW, TFT_BLACK); + // print stream formatting can be used,see: + // https://www.arduino.cc/en/Serial/Print + int ivalue = 1234; + tft.println(ivalue); // print as an ASCII-encoded decimal + tft.println(ivalue, DEC); // print as an ASCII-encoded decimal + tft.println(ivalue, HEX); // print as an ASCII-encoded hexadecimal + tft.println(ivalue, OCT); // print as an ASCII-encoded octal + tft.println(ivalue, BIN); // print as an ASCII-encoded binary + + tft.println(); // New line + tft.setTextColor(TFT_MAGENTA, TFT_BLACK); + float fvalue = 1.23456; + tft.println(fvalue, 0); // no decimal places + tft.println(fvalue, 1); // 1 decimal place + tft.println(fvalue, 2); // 2 decimal places + tft.println(fvalue, 5); // 5 decimal places + + delay(5000); + + // Get ready for the next demo while we have this font loaded + tft.fillScreen(TFT_BLACK); + tft.setCursor(0, 0); // Set cursor at top left of screen + tft.setTextColor(TFT_WHITE, TFT_BLACK); + tft.println("Wrong and right ways to"); + tft.println("print changing values..."); + + tft.unloadFont(); // Remove the font to recover memory used + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.loadFont(AA_FONT_LARGE, LittleFS); // Load another different font + + //tft.fillScreen(TFT_BLACK); + + // Draw changing numbers - does not work unless a filled rectangle is drawn over the old text + for (int i = 0; i <= 20; i++) + { + tft.setCursor(50, 50); + tft.print(" "); // Overprinting old number with spaces DOES NOT WORK! + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.setCursor(50, 50); + tft.print(i / 10.0, 1); + + tft.fillRect (50, 90, 60, 40, TFT_BLACK); // Overprint with a filled rectangle + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.setCursor(50, 90); + tft.print(i / 10.0, 1); + + delay (200); + } + + delay(5000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font text wrapping + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_YELLOW, TFT_BLACK); // Change the font colour and the background colour + + tft.setCursor(0, 0); // Set cursor at top left of screen + + tft.println("Large font!"); + + tft.setTextWrap(true); // Wrap on width + tft.setTextColor(TFT_CYAN, TFT_BLACK); + tft.println("Long lines wrap to the next line"); + + tft.setTextWrap(false, false); // Wrap on width and height switched off + tft.setTextColor(TFT_MAGENTA, TFT_BLACK); + tft.println("Unless text wrap is switched off"); + + tft.unloadFont(); // Remove the font to recover memory used + + delay(8000); +} diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_1/Notes.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_1/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Font_Demo_1/Notes.ino @@ -0,0 +1,56 @@ +/* + +Information notes only: +====================== + +//These are the text plotting alignment (reference datum point) + +TL_DATUM = Top left (default) +TC_DATUM = Top centre +TR_DATUM = Top right + +ML_DATUM = Middle left +MC_DATUM = Middle centre +MR_DATUM = Middle right + +BL_DATUM = Bottom left +BC_DATUM = Bottom centre +BR_DATUM = Bottom right + +L_BASELINE = Left character baseline (Line the 'A' character would sit on) +C_BASELINE = Centre character baseline +R_BASELINE = Right character baseline + +// Basic colours already defined: + +TFT_BLACK 0x0000 +TFT_NAVY 0x000F +TFT_DARKGREEN 0x03E0 +TFT_DARKCYAN 0x03EF +TFT_MAROON 0x7800 +TFT_PURPLE 0x780F +TFT_OLIVE 0x7BE0 +TFT_LIGHTGREY 0xC618 +TFT_DARKGREY 0x7BEF +TFT_BLUE 0x001F +TFT_GREEN 0x07E0 +TFT_CYAN 0x07FF +TFT_RED 0xF800 +TFT_MAGENTA 0xF81F +TFT_YELLOW 0xFFE0 +TFT_WHITE 0xFFFF +TFT_ORANGE 0xFDA0 +TFT_GREENYELLOW 0xB7E0 +TFT_PINK 0xFC9F + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_1/data/NotoSansBold15.vlw b/examples/Smooth Fonts/LittleFS/Font_Demo_1/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_1/data/NotoSansBold36.vlw b/examples/Smooth Fonts/LittleFS/Font_Demo_1/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 K_&W^#+W!ZD7G}`^ literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_2/Font_Demo_2.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_2/Font_Demo_2.ino new file mode 100644 index 0000000..03ec36f --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Font_Demo_2/Font_Demo_2.ino @@ -0,0 +1,230 @@ +/* + There are four different methods of plotting anti-aliased fonts to the screen. + + This sketch uses method 2, using graphics calls plotting direct to the TFT: + tft.drawString(string, x, y); + tft.drawNumber(integer, x, y); + tft.drawFloat(float, dp, x, y); // dp = number of decimal places + + setTextDatum() and setTextPadding() functions work with those draw functions. + + This method is good for static text that does not change often because changing + values may flicker. + +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to LittleFS (must set at least 1M for LittleFS) using the +// "Tools" "ESP8266 LittleFS Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/earlephilhower/arduino-esp8266littlefs-plugin + +// Close the IDE and open again to see the new menu option. + +// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI +// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font + +// This sketch uses font files created from the Noto family of fonts: +// https://www.google.com/get/noto/ + +#define AA_FONT_SMALL "NotoSansBold15" +#define AA_FONT_LARGE "NotoSansBold36" + +// Font files are stored in Flash FS +#include +#include +#define FlashFS LittleFS + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(1); + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + bool font_missing = false; + if (LittleFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\nFont missing in Flash FS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\nFonts found OK."); +} + +void loop() { + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set the font colour and the background colour + + tft.setTextDatum(TC_DATUM); // Top Centre datum + + int xpos = tft.width() / 2; // Half the screen width + int ypos = 10; + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Small font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.loadFont(AA_FONT_SMALL, LittleFS); // Must load the font first + + tft.drawString("Small 15pt font", xpos, ypos); + + ypos += tft.fontHeight(); // Get the font height and move ypos down + + tft.setTextColor(TFT_GREEN, TFT_BLACK); + + // If the string does not fit the screen width, then the next character will wrap to a new line + tft.drawString("Ode To A Small Lump Of Green Putty I Found In My Armpit One Midsummer Morning", xpos, ypos); + + tft.setTextColor(TFT_GREEN, TFT_BLUE); // Background colour does not match the screen background! + tft.drawString("Anti-aliasing causes odd looking shadow effects if the text and screen background colours are not the same!", xpos, ypos + 60); + + tft.unloadFont(); // Remove the font to recover memory used + + delay(5000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.loadFont(AA_FONT_LARGE, LittleFS); // Load another different font + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_GREEN, TFT_BLUE); // Change the font colour and the background colour + + tft.drawString("36pt font", xpos, ypos); + + ypos += tft.fontHeight(); // Get the font height and move ypos down + + // Set text padding to 100 pixels wide area to over-write old values on screen + tft.setTextPadding(100); + + // Draw changing numbers - likely to flicker using this plot method! + for (int i = 0; i <= 20; i++) { + tft.drawFloat(i / 10.0, 1, xpos, ypos); + delay (200); + } + + tft.unloadFont(); // Remove the font to recover memory used + + delay(5000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Setting the 12 datum positions works with free fonts + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + // Integer numbers, floats and strings can be drawn relative to a x,y datum, e.g.: + // tft.drawNumber( 123, x, y); + // tft.drawFloat( 1.23, dp, x, y); // Where dp is number of decimal places to show + // tft.drawString( "Abc", x, y); + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_DARKGREY, TFT_BLACK); + + // Use middle of screen as datum + xpos = tft.width() /2; + ypos = tft.height()/2; + + tft.loadFont(AA_FONT_SMALL, LittleFS); + tft.setTextDatum(TL_DATUM); + tft.drawString("[Top left]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(TC_DATUM); + tft.drawString("[Top centre]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(TR_DATUM); + tft.drawString("[Top right]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(ML_DATUM); + tft.drawString("[Middle left]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(MC_DATUM); + tft.drawString("[Middle centre]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(MR_DATUM); + tft.drawString("[Middle right]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(BL_DATUM); + tft.drawString("[Bottom left]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(BC_DATUM); + tft.drawString("[Bottom centre]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(BR_DATUM); + tft.drawString("[Bottom right]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(L_BASELINE); + tft.drawString("[Left baseline]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(C_BASELINE); + tft.drawString("[Centre baseline]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(R_BASELINE); + tft.drawString("[Right baseline]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.unloadFont(); // Remove the font to recover memory used + + delay(4000); + +} + +// Draw a + mark centred on x,y +void drawDatumMarker(int x, int y) +{ + tft.drawLine(x - 5, y, x + 5, y, TFT_GREEN); + tft.drawLine(x, y - 5, x, y + 5, TFT_GREEN); +} diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_2/Notes.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_2/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Font_Demo_2/Notes.ino @@ -0,0 +1,56 @@ +/* + +Information notes only: +====================== + +//These are the text plotting alignment (reference datum point) + +TL_DATUM = Top left (default) +TC_DATUM = Top centre +TR_DATUM = Top right + +ML_DATUM = Middle left +MC_DATUM = Middle centre +MR_DATUM = Middle right + +BL_DATUM = Bottom left +BC_DATUM = Bottom centre +BR_DATUM = Bottom right + +L_BASELINE = Left character baseline (Line the 'A' character would sit on) +C_BASELINE = Centre character baseline +R_BASELINE = Right character baseline + +// Basic colours already defined: + +TFT_BLACK 0x0000 +TFT_NAVY 0x000F +TFT_DARKGREEN 0x03E0 +TFT_DARKCYAN 0x03EF +TFT_MAROON 0x7800 +TFT_PURPLE 0x780F +TFT_OLIVE 0x7BE0 +TFT_LIGHTGREY 0xC618 +TFT_DARKGREY 0x7BEF +TFT_BLUE 0x001F +TFT_GREEN 0x07E0 +TFT_CYAN 0x07FF +TFT_RED 0xF800 +TFT_MAGENTA 0xF81F +TFT_YELLOW 0xFFE0 +TFT_WHITE 0xFFFF +TFT_ORANGE 0xFDA0 +TFT_GREENYELLOW 0xB7E0 +TFT_PINK 0xFC9F + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_2/data/NotoSansBold15.vlw b/examples/Smooth Fonts/LittleFS/Font_Demo_2/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_2/data/NotoSansBold36.vlw b/examples/Smooth Fonts/LittleFS/Font_Demo_2/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 K_&W^#+W!ZD7G}`^ literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_3/Font_Demo_3.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_3/Font_Demo_3.ino new file mode 100644 index 0000000..f1189a9 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Font_Demo_3/Font_Demo_3.ino @@ -0,0 +1,231 @@ +/* + There are four different methods of plotting anti-aliased fonts to the screen. + + This sketch uses method 3, the font characters are first plotted in a Sprite, then the + Sprite is pushed to the screen. This method is very flexible and the Sprite can be + created, deleted, resized as needed. To render anit-aliased fonts well the Sprite + needs to be 16 bit. The fonts will render in 1 bit per pixel sprites but there + will then be no anti-aliasing. Using 1 bit per pixel Sprites is however useful + to use the extended Unicode range in fonts on mono displays like ePaper. + + A single Sprite can be re-used for plotting different values and graphics to + different positions on the screen. This makes this method a very powerful display tool, + for example round buttons can be created, making use of transparent colour plotting. + +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to LittleFS (must set at least 1M for LittleFS) using the +// "Tools" "ESP8266 LittleFS Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/earlephilhower/arduino-esp8266littlefs-plugin + +// Close the IDE and open again to see the new menu option. + +// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI +// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font + +// This sketch uses font files created from the Noto family of fonts: +// https://www.google.com/get/noto/ + +#define AA_FONT_SMALL "NotoSansBold15" +#define AA_FONT_LARGE "NotoSansBold36" +#define AA_FONT_MONO "NotoSansMonoSCB20" // NotoSansMono-SemiCondensedBold 20pt + +// Font files are stored in Flash FS +#include +#include +#define FlashFS LittleFS + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); +TFT_eSprite spr = TFT_eSprite(&tft); // Sprite class needs to be invoked + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(1); + + spr.setColorDepth(16); // 16 bit colour needed to show antialiased fonts + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + bool font_missing = false; + if (LittleFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansMonoSCB20.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\nFont missing in Flash FS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\nFonts found OK."); +} + +void loop() { + + tft.fillScreen(TFT_DARKGREY); + + int xpos = tft.width() / 2; // Half the screen width + int ypos = 50; + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Small font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + spr.loadFont(AA_FONT_SMALL, LittleFS); // Must load the font first into the sprite class + + spr.createSprite(100, 50); // Create a sprite 100 pixels wide and 50 high + + spr.fillSprite(TFT_BLUE); + + spr.drawRect(0, 0, 100, 50, TFT_WHITE); // Draw sprite border outline (so we see extent) + + spr.setTextColor(TFT_YELLOW, TFT_DARKGREY); // Set the sprite font colour and the background colour + + spr.setTextDatum(MC_DATUM); // Middle Centre datum + + spr.drawString("15pt font", 50, 25 ); // Coords of middle of 100 x 50 Sprite + + spr.pushSprite(10, 10); // Push to TFT screen coord 10, 10 + + spr.pushSprite(10, 70, TFT_BLUE); // Push to TFT screen, TFT_BLUE is transparent + + spr.unloadFont(); // Remove the font from sprite class to recover memory used + + delay(4000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.fillScreen(TFT_BLACK); + + // Beware: Sprites are a differerent "class" to TFT, so different fonts can be loaded + // in the tft and sprite instances, so load the font in the class instance you use! + // In this example this means the spr. instance. + + spr.loadFont(AA_FONT_LARGE, LittleFS); // Load another different font into the sprite instance + + // 100 x 50 sprite was created above and still exists... + + spr.fillSprite(TFT_GREEN); + + spr.setTextColor(TFT_BLACK, TFT_GREEN); // Set the font colour and the background colour + + spr.setTextDatum(MC_DATUM); // Middle Centre datum + + spr.drawString("Fits", 50, 25); // Make sure text fits in the Sprite! + spr.pushSprite(10, 10); // Push to TFT screen coord 10, 10 + + spr.fillSprite(TFT_RED); + spr.setTextColor(TFT_WHITE, TFT_RED); // Set the font colour and the background colour + + spr.drawString("Too big", 50, 25); // Text is too big to all fit in the Sprite! + spr.pushSprite(10, 70); // Push to TFT screen coord 10, 70 + + // Draw changing numbers - no flicker using this plot method! + + // >>>> Note: it is best to use drawNumber() and drawFloat() for numeric values <<<< + // >>>> this reduces digit position movement when the value changes <<<< + // >>>> drawNumber() and drawFloat() functions behave like drawString() and are <<<< + // >>>> supported by setTextDatum() and setTextPadding() <<<< + + spr.setTextDatum(TC_DATUM); // Top Centre datum + + spr.setTextColor(TFT_WHITE, TFT_BLUE); // Set the font colour and the background colour + + for (int i = 0; i <= 200; i++) { + spr.fillSprite(TFT_BLUE); + spr.drawFloat(i / 100.0, 2, 50, 10); // draw with 2 decimal places at 50,10 in sprite + spr.pushSprite(10, 130); // Push to TFT screen coord 10, 130 + delay (20); + } + + spr.unloadFont(); // Remove the font to recover memory used + + spr.deleteSprite(); // Recover memory + + delay(1000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Mono spaced font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + spr.loadFont(AA_FONT_MONO, LittleFS); // Mono spaced fonts have fixed intercharacter gaps to + // aid formatting + int bnum = 1; + + // Example of drawing buttons + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < 4; k++) + { + int x = 120 + k * 45; + int y = 40 + j * 30; + button(x, y, bnum++); + } + } + + for (int i = 0; i < 100; i++) + { + button(120, 160, i); + delay(50); + } + + spr.unloadFont(); + + delay(8000); +} + +// ######################################################################### +// Draw a number in a rounded rectangle with some transparent pixels +// Load the font before calling +// ######################################################################### +void button(int x, int y, int num ) +{ + + // Size of sprite + #define IWIDTH 40 + #define IHEIGHT 25 + + // Create a 16 bit sprite 40 pixels wide, 25 high (2000 bytes of RAM needed) + spr.setColorDepth(16); + spr.createSprite(IWIDTH, IHEIGHT); + + // Fill it with black (this will be the transparent colour this time) + spr.fillSprite(TFT_BLACK); + + // Draw a background for the numbers + spr.fillRoundRect( 0, 0, IWIDTH, IHEIGHT, 8, TFT_RED); + spr.drawRoundRect( 0, 0, IWIDTH, IHEIGHT, 8, TFT_WHITE); + + // Set the font parameters + + // Set text coordinate datum to middle centre + spr.setTextDatum(MC_DATUM); + + // Set the font colour and the background colour + spr.setTextColor(TFT_WHITE, TFT_RED); + + // Draw the number + spr.drawNumber(num, IWIDTH/2, 1 + IHEIGHT/2); + + // Push sprite to TFT screen CGRAM at coordinate x,y (top left corner) + // All black pixels will not be drawn hence will show as "transparent" + spr.pushSprite(x, y, TFT_BLACK); + + // Delete sprite to free up the RAM + spr.deleteSprite(); +} diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_3/Notes.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_3/Notes.ino new file mode 100644 index 0000000..bdab3d0 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Font_Demo_3/Notes.ino @@ -0,0 +1,61 @@ +/* + +Information notes only: +====================== + +Note: it is best to use drawNumber() and drawFloat() for numeric values + this reduces digit position movement when the value changes + drawNumber() and drawFloat() functions behave like drawString() and are + supported by setTextDatum() and setTextPadding() + +//These are the text plotting alignment (reference datum point) + +TL_DATUM = Top left (default) +TC_DATUM = Top centre +TR_DATUM = Top right + +ML_DATUM = Middle left +MC_DATUM = Middle centre +MR_DATUM = Middle right + +BL_DATUM = Bottom left +BC_DATUM = Bottom centre +BR_DATUM = Bottom right + +L_BASELINE = Left character baseline (Line the 'A' character would sit on) +C_BASELINE = Centre character baseline +R_BASELINE = Right character baseline + +// Basic colours already defined: + +TFT_BLACK 0x0000 +TFT_NAVY 0x000F +TFT_DARKGREEN 0x03E0 +TFT_DARKCYAN 0x03EF +TFT_MAROON 0x7800 +TFT_PURPLE 0x780F +TFT_OLIVE 0x7BE0 +TFT_LIGHTGREY 0xC618 +TFT_DARKGREY 0x7BEF +TFT_BLUE 0x001F +TFT_GREEN 0x07E0 +TFT_CYAN 0x07FF +TFT_RED 0xF800 +TFT_MAGENTA 0xF81F +TFT_YELLOW 0xFFE0 +TFT_WHITE 0xFFFF +TFT_ORANGE 0xFDA0 +TFT_GREENYELLOW 0xB7E0 +TFT_PINK 0xFC9F + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_3/data/NotoSansBold15.vlw b/examples/Smooth Fonts/LittleFS/Font_Demo_3/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_3/data/NotoSansBold36.vlw b/examples/Smooth Fonts/LittleFS/Font_Demo_3/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 K_&W^#+W!ZD7G}`^ literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_3/data/NotoSansMonoSCB20.vlw b/examples/Smooth Fonts/LittleFS/Font_Demo_3/data/NotoSansMonoSCB20.vlw new file mode 100644 index 0000000000000000000000000000000000000000..4045c621230f1d184991a5a74bf14d0785e2b913 GIT binary patch literal 15382 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 +#include +#define FlashFS LittleFS + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); +TFT_eSprite spr = TFT_eSprite(&tft); // Sprite class needs to be invoked + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(1); + + spr.setColorDepth(16); // 16 bit colour needed to show antialiased fonts + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + // ESP32 will crash if any of the fonts are missing + bool font_missing = false; + if (LittleFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\nFont missing in Flash FS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\nFonts found OK."); +} + +void loop() { + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set the font colour and the background colour + + tft.setTextDatum(TC_DATUM); // Top Centre datum + + int xpos = tft.width() / 2; // Half the screen width + int ypos = 50; + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Small font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + spr.loadFont(AA_FONT_SMALL, LittleFS); // Must load the font first into the sprite class + + spr.setTextColor(TFT_YELLOW, TFT_BLACK); // Set the sprite font colour and the background colour + + tft.setCursor(xpos - 50, ypos); // Set the tft cursor position, yes tft position! + spr.printToSprite("Small 15pt font"); // Prints to tft cursor position, tft cursor NOT moved + + ypos += spr.fontHeight(); // Get the font height and move ypos down + + spr.unloadFont(); // Remove the font from sprite class to recover memory used + + delay(4000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.fillScreen(TFT_BLACK); + + spr.loadFont(AA_FONT_LARGE, LittleFS); // Load another different font + + spr.setTextColor(TFT_WHITE, TFT_BLUE); // Set the font colour and the background colour + + tft.setCursor(xpos - 90, ypos); // Set the tft cursor position + spr.printToSprite("36pt font"); // Text is rendered via a minimally sized sprite + + ypos += spr.fontHeight(); // Get the font height and move ypos down + + // Draw changing numbers - no flicker using this plot method! + for (int i = 0; i <= 200; i++) { + tft.setCursor(10, 10); + // Number is converted to String type by (String) (number) + spr.printToSprite(" " + (String) (i / 100.0) + " "); // Space padding helps over-write old numbers + delay (20); + } + + spr.unloadFont(); // Remove the font to recover memory used + + delay(8000); +} diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_4/Notes.ino b/examples/Smooth Fonts/LittleFS/Font_Demo_4/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Font_Demo_4/Notes.ino @@ -0,0 +1,56 @@ +/* + +Information notes only: +====================== + +//These are the text plotting alignment (reference datum point) + +TL_DATUM = Top left (default) +TC_DATUM = Top centre +TR_DATUM = Top right + +ML_DATUM = Middle left +MC_DATUM = Middle centre +MR_DATUM = Middle right + +BL_DATUM = Bottom left +BC_DATUM = Bottom centre +BR_DATUM = Bottom right + +L_BASELINE = Left character baseline (Line the 'A' character would sit on) +C_BASELINE = Centre character baseline +R_BASELINE = Right character baseline + +// Basic colours already defined: + +TFT_BLACK 0x0000 +TFT_NAVY 0x000F +TFT_DARKGREEN 0x03E0 +TFT_DARKCYAN 0x03EF +TFT_MAROON 0x7800 +TFT_PURPLE 0x780F +TFT_OLIVE 0x7BE0 +TFT_LIGHTGREY 0xC618 +TFT_DARKGREY 0x7BEF +TFT_BLUE 0x001F +TFT_GREEN 0x07E0 +TFT_CYAN 0x07FF +TFT_RED 0xF800 +TFT_MAGENTA 0xF81F +TFT_YELLOW 0xFFE0 +TFT_WHITE 0xFFFF +TFT_ORANGE 0xFDA0 +TFT_GREENYELLOW 0xB7E0 +TFT_PINK 0xFC9F + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_4/data/NotoSansBold15.vlw b/examples/Smooth Fonts/LittleFS/Font_Demo_4/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Font_Demo_4/data/NotoSansBold36.vlw b/examples/Smooth Fonts/LittleFS/Font_Demo_4/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 K_&W^#+W!ZD7G}`^ literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Print_Smooth_Font/Print_Smooth_Font.ino b/examples/Smooth Fonts/LittleFS/Print_Smooth_Font/Print_Smooth_Font.ino new file mode 100644 index 0000000..cda3f32 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Print_Smooth_Font/Print_Smooth_Font.ino @@ -0,0 +1,149 @@ +/* + Sketch to demonstrate using the print class with smooth fonts + + Sketch is writtent for a 240 x 320 display + +// Upload the fonts and icons to LittleFS (must set at least 1M for LittleFS) using the +// "Tools" "ESP8266 LittleFS Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/earlephilhower/arduino-esp8266littlefs-plugin + + New font files in the .vlw format can be created using the Processing + sketch in the library Tools folder. The Processing sketch can convert + TrueType fonts in *.ttf or *.otf files. + + The library supports 16 bit unicode characters: + https://en.wikipedia.org/wiki/Unicode_font + + The characters supported are in the in the Basic Multilingal Plane: + https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane + + Make sure all the display driver and pin connenctions are correct by + editting the User_Setup.h file in the TFT_eSPI library folder. + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +// Font files are stored in Flash FS +#include +#include +#define FlashFS LittleFS + +// Graphics and font library +#include +#include + +TFT_eSPI tft = TFT_eSPI(); // Invoke library + +// ------------------------------------------------------------------------- +// Setup +// ------------------------------------------------------------------------- +void setup(void) { + Serial.begin(115200); // Used for messages + + tft.init(); + tft.setRotation(1); + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + listFiles(); // Lists the files so you can see what is in the SPIFFS + +} + +// ------------------------------------------------------------------------- +// Main loop +// ------------------------------------------------------------------------- +void loop() { + // Wrap test at right and bottom of screen + tft.setTextWrap(true, true); + + // Name of font file (library adds leading / and .vlw) + String fileName = "Final-Frontier-28"; + + // Font and background colour, background colour is used for anti-alias blending + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + // Load the font + tft.loadFont(fileName, LittleFS); + + // Display all characters of the font + tft.showFont(2000); + + // Set "cursor" at top left corner of display (0,0) + // (cursor will move to next line automatically during printing with 'tft.println' + // or stay on the line is there is room for the text with tft.print) + tft.setCursor(0, 0); + + // Set the font colour to be white with a black background, set text size multiplier to 1 + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + // We can now plot text on screen using the "print" class + tft.println("Hello World!"); + + // Set the font colour to be yellow + tft.setTextColor(TFT_YELLOW, TFT_BLACK); + tft.println(1234.56); + + // Set the font colour to be red + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println((uint32_t)3735928559, HEX); // Should print DEADBEEF + + // Set the font colour to be green with black background + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Anti-aliased font!"); + tft.println(""); + + // Test some print formatting functions + float fnumber = 123.45; + + // Set the font colour to be blue + tft.setTextColor(TFT_BLUE, TFT_BLACK); + tft.print("Float = "); tft.println(fnumber); // Print floating point number + tft.print("Binary = "); tft.println((int)fnumber, BIN); // Print as integer value in binary + tft.print("Hexadecimal = "); tft.println((int)fnumber, HEX); // Print as integer number in Hexadecimal + + // Unload the font to recover used RAM + tft.unloadFont(); + + delay(10000); +} + + +// ------------------------------------------------------------------------- +// List files in ESP8266 or ESP32 SPIFFS memory +// ------------------------------------------------------------------------- +void listFiles(void) { + Serial.println(); + Serial.println("Flash FS files found:"); + + fs::Dir dir = LittleFS.openDir("/"); // Root directory + String line = "====================================="; + + Serial.println(line); + Serial.println(" File name Size"); + Serial.println(line); + + while (dir.next()) { + String fileName = dir.fileName(); + Serial.print(fileName); + int spaces = 25 - fileName.length(); // Tabulate nicely + if (spaces < 0) spaces = 1; + while (spaces--) Serial.print(" "); + fs::File f = dir.openFile("r"); + Serial.print(f.size()); Serial.println(" bytes"); + yield(); + } + + Serial.println(line); + + Serial.println(); + delay(1000); +} + +// ------------------------------------------------------------------------- diff --git a/examples/Smooth Fonts/LittleFS/Print_Smooth_Font/data/Final-Frontier-28.vlw b/examples/Smooth Fonts/LittleFS/Print_Smooth_Font/data/Final-Frontier-28.vlw new file mode 100644 index 0000000000000000000000000000000000000000..2872fd554bbf34f5e1268770dd8ea3cf55cecdfd GIT binary patch literal 25287 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Smooth_font_gradient/Smooth_font_gradient.ino b/examples/Smooth Fonts/LittleFS/Smooth_font_gradient/Smooth_font_gradient.ino new file mode 100644 index 0000000..9e3ca8f --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Smooth_font_gradient/Smooth_font_gradient.ino @@ -0,0 +1,120 @@ +/* + This sketch is based on Font Demo 1. It introduces a method for rendering + anti-aliased fonts on a graded background. This is acheived by telling the + TFT_eSPI library the pixel color at each point on the screen. In this sketch + a graded background is drawn, the color of each pixel can therefore be + determined. The TFT does not need to support reading of the graphics memory. + The sketch could be adapted so only part of the screen is has a color gradient. + + The TFT_eSPI library must be given the name of the function in the sketch + that will return the pixel xolor at a position x,y on the TFT. In this + sketch that function is called gradientColor, so this line is included: + + tft.setCallback(gradientColor); + + TFT_eSPI will call this function during the rendering of the anti-aliased + font to blend the edges of each character with the returned color. + + If the TFT supports reading the screen RAM then the returned value can be + tft.readPixel(x,y) and anti-aliased text can the be drawn over any screen + image. See "Smooth_font_reading_TFT" example. +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to LittleFS (must set at least 1M for LittleFS) using the +// "Tools" "ESP8266 LittleFS Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/earlephilhower/arduino-esp8266littlefs-plugin + +// Close the IDE and open again to see the new menu option. + +// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI +// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font + +// This sketch uses font files created from the Noto family of fonts: +// https://www.google.com/get/noto/ + +#define AA_FONT_SMALL "NotoSansBold15" +#define AA_FONT_LARGE "NotoSansBold36" + +// Font files are stored in Flash FS +#include +#include +#define FlashFS LittleFS + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); + +#define TOP_COLOR TFT_RED +#define BOTTOM_COLOR TFT_BLACK + +#define GRADIENT_HEIGHT (9 + tft.fontHeight() * 5) // Gradient over 5 lines +#define OUTSIDE_GRADIENT TFT_BLUE + +uint16_t gradientColor(uint16_t x, uint16_t y) +{ + if (y > GRADIENT_HEIGHT) return OUTSIDE_GRADIENT; // Outside gradient area + uint8_t alpha = (255 * y) / GRADIENT_HEIGHT; // alpha is a value in the range 0-255 + return tft.alphaBlend(alpha, BOTTOM_COLOR, TOP_COLOR); +} + +void fillGradient() { + uint16_t w = tft.width(); + for (uint16_t y = 0; y < tft.height(); ++y) { + uint16_t color = gradientColor(0, y); // x not used here + tft.drawFastHLine(0, y, w, color); + } +} + +void setup(void) { + Serial.begin(115200); + + tft.begin(); + + tft.setCallback(gradientColor); // Switch on color callback for anti-aliased fonts + //tft.setCallback(nullptr); // Switch off callback (off by default) + + tft.setRotation(1); + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + bool font_missing = false; + if (LittleFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\nFont missing in Flash FS, did you upload it?"); + while (1) yield(); + } + else Serial.println("\nFonts found OK."); +} + + +void loop() { + + // Select a font size comensurate with screen size + if (tft.width()>= 320) + tft.loadFont(AA_FONT_LARGE, LittleFS); + else + tft.loadFont(AA_FONT_SMALL, LittleFS); + + fillGradient(); // Put here after selecting the font so fontHeight() is already set + + tft.setTextColor(TFT_WHITE); // Background color is ignored in gradient area + tft.setCursor(0, 10); // Set cursor at top left of screen + + uint32_t t = millis(); + tft.println(" Ode to a small\n lump of green\n putty I found\n in my armpit\n one midsummer\n morning "); + Serial.println(t = millis()-t); + + tft.unloadFont(); // Remove the font to recover memory used + + delay(2000); +} diff --git a/examples/Smooth Fonts/LittleFS/Smooth_font_gradient/data/NotoSansBold15.vlw b/examples/Smooth Fonts/LittleFS/Smooth_font_gradient/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Smooth_font_gradient/data/NotoSansBold36.vlw b/examples/Smooth Fonts/LittleFS/Smooth_font_gradient/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 K_&W^#+W!ZD7G}`^ literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino b/examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino new file mode 100644 index 0000000..52f2b91 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino @@ -0,0 +1,165 @@ +/* + This sketch is based on Font Demo 1. It introduces a method for rendering + anti-aliased fonts on an arbitrary background. This is acheived by reading + the pixel color at each point on the screen. The TFT must support reading + the graphics RAM of the screen memory. This sketch has been tested with + ILI9241 and ILI9481 serial and parallel screens. Other screens may or may + not work! + + The TFT_eSPI library must be given the name of the function in the sketch + that will return the pixel color at a position x,y on the TFT. In this + sketch that function is called pixelColor, so this line is included: + + tft.setCallback(pixelColor); + + TFT_eSPI will call this function during the rendering of the anti-aliased + font and use it to blend the edges of each character with the screen color. +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to LittleFS (must set at least 1M for LittleFS) using the +// "Tools" "ESP8266 LittleFS Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/earlephilhower/arduino-esp8266littlefs-plugin + +// Close the IDE and open again to see the new menu option. + +// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI +// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font + +// This sketch uses font files created from the Noto family of fonts: +// https://www.google.com/get/noto/ + +#define AA_FONT_SMALL "NotoSansBold15" +#define AA_FONT_LARGE "NotoSansBold36" + +// Font files are stored in Flash FS +#include +#include +#define FlashFS LittleFS + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); + +// Callback function to provide the pixel color at x,y +uint16_t pixelColor(uint16_t x, uint16_t y) { return tft.readPixel(x, y); } + + +void setup(void) { + Serial.begin(115200); + + tft.begin(); + + tft.setCallback(pixelColor); // The callback is only used durung font rendering + //tft.setCallback(nullptr); // Switch off callback (off by default) + + tft.setRotation(1); + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\n\Flash FS available!"); + + // ESP32 will crash if any of the fonts are missing, so check + bool font_missing = false; + if (LittleFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (LittleFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\nFont missing in Flash FS, did you upload it?"); + while (1) yield(); + } + else Serial.println("\nFonts found OK."); +} + + +void loop() { + + rainbow_fill(); // Fill the screen with rainbow colours + + // Select a font size comensurate with screen size + if (tft.width()>= 320) + tft.loadFont(AA_FONT_LARGE, LittleFS); + else + tft.loadFont(AA_FONT_SMALL, LittleFS); + + tft.setTextColor(TFT_BLACK, TFT_WHITE); // Background color is ignored if callback is set + tft.setCursor(0, 10); // Set cursor at top left of screen + + uint32_t t = millis(); + tft.println(" Ode to a small\n lump of green\n putty I found\n in my armpit\n one midsummer\n morning "); + Serial.println(t = millis()-t); + + tft.unloadFont(); // Remove the font to recover memory used + + delay(2000); +} + +// ######################################################################### +// Fill screen with a rainbow pattern +// ######################################################################### +byte red = 31; +byte green = 0; +byte blue = 0; +byte state = 0; +unsigned int colour = red << 11; // Colour order is RGB 5+6+5 bits each + +void rainbow_fill() +{ + // The colours and state are not initialised so the start colour changes each time the funtion is called + + for (int i = 319; i >= 0; i--) { + // Draw a vertical line 1 pixel wide in the selected colour + tft.drawFastHLine(0, i, tft.width(), colour); // in this example tft.width() returns the pixel width of the display + // This is a "state machine" that ramps up/down the colour brightnesses in sequence + switch (state) { + case 0: + green ++; + if (green == 64) { + green = 63; + state = 1; + } + break; + case 1: + red--; + if (red == 255) { + red = 0; + state = 2; + } + break; + case 2: + blue ++; + if (blue == 32) { + blue = 31; + state = 3; + } + break; + case 3: + green --; + if (green == 255) { + green = 0; + state = 4; + } + break; + case 4: + red ++; + if (red == 32) { + red = 31; + state = 5; + } + break; + case 5: + blue --; + if (blue == 255) { + blue = 0; + state = 0; + } + break; + } + colour = red << 11 | green << 5 | blue; + } +} diff --git a/examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/data/NotoSansBold15.vlw b/examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/data/NotoSansBold36.vlw b/examples/Smooth Fonts/LittleFS/Smooth_font_reading_TFT/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 K_&W^#+W!ZD7G}`^ literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Unicode_test/LittleFS_functions.ino b/examples/Smooth Fonts/LittleFS/Unicode_test/LittleFS_functions.ino new file mode 100644 index 0000000..fbdc0aa --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Unicode_test/LittleFS_functions.ino @@ -0,0 +1,39 @@ +/*==================================================================================== + This sketch supports the ESP6266 with LittleFS Flash filing system + + Created by Bodmer 15th Jan 2017 + ==================================================================================*/ + +//==================================================================================== +// Print a Flash FS directory list (root directory) +//==================================================================================== + +void listFiles(void) { + Serial.println(); + Serial.println("Flash FS files found:"); + + fs::Dir dir = LittleFS.openDir("/"); // Root directory + String line = "====================================="; + + Serial.println(line); + Serial.println(" File name Size"); + Serial.println(line); + + while (dir.next()) { + String fileName = dir.fileName(); + Serial.print(fileName); + int spaces = 25 - fileName.length(); // Tabulate nicely + if (spaces < 0) spaces = 1; + while (spaces--) Serial.print(" "); + fs::File f = dir.openFile("r"); + Serial.print(f.size()); Serial.println(" bytes"); + yield(); + } + + Serial.println(line); + + Serial.println(); + delay(1000); +} +//==================================================================================== + diff --git a/examples/Smooth Fonts/LittleFS/Unicode_test/Unicode_test.ino b/examples/Smooth Fonts/LittleFS/Unicode_test/Unicode_test.ino new file mode 100644 index 0000000..46f2fa0 --- /dev/null +++ b/examples/Smooth Fonts/LittleFS/Unicode_test/Unicode_test.ino @@ -0,0 +1,152 @@ +// Created by Bodmer 24th Jan 2017 - Tested in Arduino IDE 1.8.5 esp8266 Core 2.4.0 + +// The latest Arduino IDE versions support UTF-8 encoding of Unicode characters +// within sketches: +// https://playground.arduino.cc/Code/UTF-8 + +/* + The library expects strings to be in UTF-8 encoded format: + https://www.fileformat.info/info/unicode/utf8.htm + + Creating varaibles needs to be done with care when using character arrays: + char c = 'µ'; // Wrong + char bad[4] = "5µA"; // Wrong + char good[] = "5µA"; // Good + String okay = "5µA"; // Good + + This is because UTF-8 characters outside the basic Latin set occupy more than + 1 byte per character! A 16 bit unicode character occupies 3 bytes! + +*/ + + // Flash filing system + #include + #include + + +//==================================================================================== +// Libraries +//==================================================================================== +// Call up the FLASH filing system this is part of the ESP Core + +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +uint16_t bg = TFT_BLACK; +uint16_t fg = TFT_WHITE; + + +//==================================================================================== +// Setup +//==================================================================================== +void setup() +{ + Serial.begin(115200); // Used for messages and the C array generator + + Serial.println("NodeMCU vlw font test!"); + + if (!LittleFS.begin()) { + Serial.println("Flash FS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\nInitialisation done."); + + listFiles(); // Lists the files so you can see what is in the Flash FS + + tft.begin(); + tft.setRotation(0); // portrait + + fg = TFT_WHITE; + bg = TFT_BLACK; +} + +//==================================================================================== +// Loop +//==================================================================================== +void loop() +{ + tft.setTextColor(fg, bg); + + //---------------------------------------------------------------------------- + // Anti-aliased font test + + String test1 = "Hello World"; + + // Load a smooth font from Flash FS + tft.loadFont("Final-Frontier-28", LittleFS); + + tft.setRotation(0); + + // Show all characters on screen with 2 second (2000ms) delay between screens + tft.showFont(2000); // Note: This function moves the cursor position! + + tft.fillScreen(bg); + tft.setCursor(0,0); + + tft.println(test1); + + // Remove font parameters from memory to recover RAM + tft.unloadFont(); + + delay(2000); + + //---------------------------------------------------------------------------- + // We can have any random mix of characters in the font + + String test2 = "仝倀"; // Unicodes 0x4EDD, 0x5000 + + tft.loadFont("Unicode-Test-72", LittleFS); + + tft.setRotation(1); + + // Show all characters on screen with 2 second (2000ms) delay between screens + tft.showFont(2000); // Note: This function moves the cursor position! + + tft.fillScreen(bg); + tft.setCursor(0,0); +uint32_t dt = millis(); + tft.setTextColor(TFT_CYAN, bg); + tft.println(test2); + + tft.setTextColor(TFT_YELLOW, bg); + tft.println("12:00pm"); + + tft.setTextColor(TFT_MAGENTA, bg); + tft.println("1000Ω"); +Serial.println(millis()-dt); + // Remove font parameters from memory to recover RAM + tft.unloadFont(); + + delay(2000); + + //---------------------------------------------------------------------------- + // Latin and Hiragana font mix + + String test3 = "こんにちは"; + + tft.loadFont("Latin-Hiragana-24",LittleFS); + + tft.setRotation(0); +dt = millis(); + // Show all characters on screen with 2 second (2000ms) delay between screens + tft.showFont(2000); // Note: This function moves the cursor position! +Serial.println(millis()-dt); + tft.fillScreen(bg); + tft.setTextColor(TFT_GREEN, bg); + tft.setCursor(0,0); +dt = millis(); + tft.println("Konnichiwa"); + tft.println(test3); + tft.println(); + tft.println("Sayonara"); + tft.println("さようなら"); // Sayonara +Serial.println(millis()-dt); + // Remove font parameters from memory to recover RAM + tft.unloadFont(); + + delay(2000); + // + //---------------------------------------------------------------------------- +} +//==================================================================================== diff --git a/examples/Smooth Fonts/LittleFS/Unicode_test/data/Final-Frontier-28.vlw b/examples/Smooth Fonts/LittleFS/Unicode_test/data/Final-Frontier-28.vlw new file mode 100644 index 0000000000000000000000000000000000000000..2872fd554bbf34f5e1268770dd8ea3cf55cecdfd GIT binary patch literal 25287 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Unicode_test/data/Latin-Hiragana-24.vlw b/examples/Smooth Fonts/LittleFS/Unicode_test/data/Latin-Hiragana-24.vlw new file mode 100644 index 0000000000000000000000000000000000000000..b2f128b4ed054b8c3a488b361f6903e4b557722d GIT binary patch literal 54478 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®~4f}smG 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 E06d{_kN^Mx literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/LittleFS/Unicode_test/data/Unicode-Test-72.vlw b/examples/Smooth Fonts/LittleFS/Unicode_test/data/Unicode-Test-72.vlw new file mode 100644 index 0000000000000000000000000000000000000000..c4757564c98f7c46a98dc54f913b83808f2bcb79 GIT binary patch literal 36469 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