Add smooth (antialiased) fonts

This commit is contained in:
Bodmer 2018-02-24 19:02:20 +00:00
parent 02a902f617
commit 8752236ac2
34 changed files with 4031 additions and 1915 deletions

76
Extensions/Button.cpp Normal file
View File

@ -0,0 +1,76 @@
/***************************************************************************************
** Code for the GFX button UI element
** Grabbed from Adafruit_GFX library and enhanced to handle any label font
***************************************************************************************/
TFT_eSPI_Button::TFT_eSPI_Button(void) {
_gfx = 0;
}
// Classic initButton() function: pass center & size
void TFT_eSPI_Button::initButton(
TFT_eSPI *gfx, int16_t x, int16_t y, uint16_t w, uint16_t h,
uint16_t outline, uint16_t fill, uint16_t textcolor,
char *label, uint8_t textsize)
{
// Tweak arguments and pass to the newer initButtonUL() function...
initButtonUL(gfx, x - (w / 2), y - (h / 2), w, h, outline, fill,
textcolor, label, textsize);
}
// Newer function instead accepts upper-left corner & size
void TFT_eSPI_Button::initButtonUL(
TFT_eSPI *gfx, int16_t x1, int16_t y1, uint16_t w, uint16_t h,
uint16_t outline, uint16_t fill, uint16_t textcolor,
char *label, uint8_t textsize)
{
_x1 = x1;
_y1 = y1;
_w = w;
_h = h;
_outlinecolor = outline;
_fillcolor = fill;
_textcolor = textcolor;
_textsize = textsize;
_gfx = gfx;
strncpy(_label, label, 9);
}
void TFT_eSPI_Button::drawButton(boolean inverted) {
uint16_t fill, outline, text;
if(!inverted) {
fill = _fillcolor;
outline = _outlinecolor;
text = _textcolor;
} else {
fill = _textcolor;
outline = _outlinecolor;
text = _fillcolor;
}
uint8_t r = min(_w, _h) / 4; // Corner radius
_gfx->fillRoundRect(_x1, _y1, _w, _h, r, fill);
_gfx->drawRoundRect(_x1, _y1, _w, _h, r, outline);
_gfx->setTextColor(text);
_gfx->setTextSize(_textsize);
uint8_t tempdatum = _gfx->getTextDatum();
_gfx->setTextDatum(MC_DATUM);
_gfx->drawString(_label, _x1 + (_w/2), _y1 + (_h/2));
_gfx->setTextDatum(tempdatum);
}
boolean TFT_eSPI_Button::contains(int16_t x, int16_t y) {
return ((x >= _x1) && (x < (_x1 + _w)) &&
(y >= _y1) && (y < (_y1 + _h)));
}
void TFT_eSPI_Button::press(boolean p) {
laststate = currstate;
currstate = p;
}
boolean TFT_eSPI_Button::isPressed() { return currstate; }
boolean TFT_eSPI_Button::justPressed() { return (currstate && !laststate); }
boolean TFT_eSPI_Button::justReleased() { return (!currstate && laststate); }

38
Extensions/Button.h Normal file
View File

@ -0,0 +1,38 @@
/***************************************************************************************
// The following button class has been ported over from the Adafruit_GFX library so
// should be compatible.
// A slightly different implementation in this TFT_eSPI library allows the button
// legends to be in any font
***************************************************************************************/
class TFT_eSPI_Button {
public:
TFT_eSPI_Button(void);
// "Classic" initButton() uses center & size
void initButton(TFT_eSPI *gfx, int16_t x, int16_t y,
uint16_t w, uint16_t h, uint16_t outline, uint16_t fill,
uint16_t textcolor, char *label, uint8_t textsize);
// New/alt initButton() uses upper-left corner & size
void initButtonUL(TFT_eSPI *gfx, int16_t x1, int16_t y1,
uint16_t w, uint16_t h, uint16_t outline, uint16_t fill,
uint16_t textcolor, char *label, uint8_t textsize);
void drawButton(boolean inverted = false);
boolean contains(int16_t x, int16_t y);
void press(boolean p);
boolean isPressed();
boolean justPressed();
boolean justReleased();
private:
TFT_eSPI *_gfx;
int16_t _x1, _y1; // Coordinates of top-left corner
uint16_t _w, _h;
uint8_t _textsize;
uint16_t _outlinecolor, _fillcolor, _textcolor;
char _label[10];
boolean currstate, laststate;
};

511
Extensions/Smooth_font.cpp Normal file
View File

@ -0,0 +1,511 @@
// Coded by Bodmer 10/2/18, see license in root directory.
// This is part of the TFT_eSPI class and is associated with anti-aliased font functions
////////////////////////////////////////////////////////////////////////////////////////
// New anti-aliased (smoothed) font functions added below
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************
** Function name: loadFont
** Description: loads parameters from a new font vlw file stored in SPIFFS
*************************************************************************************x*/
void TFT_eSPI::loadFont(String fontName)
{
/*
The vlw font format does not appear to be documented anywhere, so some reverse
engineering has been applied!
Header of vlw file comprises 6 uint32_t parameters (24 bytes total):
1. The gCount (number of character glyphs)
2. A version number (0xB = 11 for the one I am using)
3. The font size (in points, not pixels)
4. Deprecated mboxY parameter (typically set to 0)
5. Ascent in pixels from baseline to top of "d"
6. Descent in pixels from baseline to bottom of "p"
Next are gCount sets of values for each glyph, each set comprises 7 int32t parameters (28 bytes):
1. Glyph Unicode stored as a 32 bit value
2. Height of bitmap bounding box
3. Width of bitmap bounding box
4. gxAdvance for cursor (setWidth in Processing)
5. dY = distance from cursor baseline to top of glyph bitmap (signed value +ve = up)
6. dX = distance from cursor to left side of glyph bitmap (signed value -ve = left)
7. padding value, typically 0
The bitmaps start next at 24 + (28 * gCount) bytes from the start of the file.
Each pixel is 1 byte, an 8 bit Alpha value which represents the transparency from
0xFF foreground colour, 0x00 background. The sketch uses a linear interpolation
between the foreground and background RGB component colours. e.g.
pixelRed = ((fgRed * alpha) + (bgRed * (255 - alpha))/255
To gain a performance advantage fixed point arithmetic is used with rounding and
division by 256 (shift right 8 bits is faster).
After the bitmaps is:
1 byte for font name string length (excludes null)
a zero terminated character string giving the font name
1 byte for Postscript name string length
a zero/one terminated character string giving the font name
last byte is 0 for non-anti-aliased and 1 for anti-aliased (smoothed)
Then the font name seen by Java when it's created
Then the postscript name of the font
Then a boolean to tell if smoothing is on or not.
Glyph bitmap example is:
// Cursor coordinate positions for this and next character are marked by 'C'
// C<------- gxAdvance ------->C gxAdvance is how far to move cursor for next glyph cursor position
// | |
// | | ascent is top of "d", descent is bottom of "p"
// +-- gdX --+ ascent
// | +-- gWidth--+ | gdX is offset to left edge of glyph bitmap
// | + x@.........@x + | gdX may be negative e.g. italic "y" tail extending to left of
// | | @@.........@@ | | cursor position, plot top left corner of bitmap at (cursorX + gdX)
// | | @@.........@@ gdY | gWidth and gHeight are glyph bitmap dimensions
// | | .@@@.....@@@@ | |
// | gHeight ....@@@@@..@@ + + <-- baseline
// | | ...........@@ |
// | | ...........@@ | gdY is the offset to the top edge of the bitmap
// | | .@@.......@@. descent plot top edge of bitmap at (cursorY + yAdvance - gdY)
// | + x..@@@@@@@..x | x marks the corner pixels of the bitmap
// | |
// +---------------------------+ yAdvance is y delta for the next line, font size or (ascent + descent)
// some fonts can overlay in y direction so may need a user adjust value
*/
_gFontFilename = "/" + fontName + ".vlw";
fontFile = SPIFFS.open( _gFontFilename, "r");
if(!fontFile) return;
//unloadFont();
fontFile.seek(0, fs::SeekSet);
gFont.gCount = (uint16_t)readInt32(); // glyph count in file
readInt32(); // vlw encoder version - discard
gFont.yAdvance = (uint16_t)readInt32(); // Font size in points, not pixels
readInt32(); // discard
gFont.ascent = (uint16_t)readInt32(); // top of "d"
gFont.descent = (uint16_t)readInt32(); // bottom of "p"
// These next gFont values will be updated when the Metrics are fetched
gFont.maxAscent = gFont.ascent; // Determined from metrics
gFont.maxDescent = gFont.descent; // Determined from metrics
gFont.yAdvance = gFont.ascent + gFont.descent;
gFont.spaceWidth = gFont.yAdvance / 4; // Guess at space width
fontLoaded = true;
// Fetch the metrics for each glyph
loadMetrics(gFont.gCount);
//fontFile.close();
}
/***************************************************************************************
** Function name: loadMetrics
** Description: Get the metrics for each glyph and store in RAM
*************************************************************************************x*/
//#define SHOW_ASCENT_DESCENT
void TFT_eSPI::loadMetrics(uint16_t gCount)
{
uint32_t headerPtr = 24;
uint32_t bitmapPtr = 24 + gCount * 28;
gUnicode = (uint16_t*)malloc( gCount * 2); // Unicode 16 bit Basic Multilingual Plane (0-FFFF)
gHeight = (uint8_t*)malloc( gCount ); // Height of glyph
gWidth = (uint8_t*)malloc( gCount ); // Width of glyph
gxAdvance = (uint8_t*)malloc( gCount ); // xAdvance - to move x cursor
gdY = (int8_t*)malloc( gCount ); // offset from bitmap top edge from lowest point in any character
gdX = (int8_t*)malloc( gCount ); // offset for bitmap left edge relative to cursor X
gBitmap = (uint32_t*)malloc( gCount * 4); // seek pointer to glyph bitmap in SPIFFS file
#ifdef SHOW_ASCENT_DESCENT
Serial.print("ascent = "); Serial.println(gFont.ascent);
Serial.print("descent = "); Serial.println(gFont.descent);
#endif
uint16_t gNum = 0;
fontFile.seek(headerPtr, fs::SeekSet);
while (gNum < gCount)
{
gUnicode[gNum] = (uint16_t)readInt32(); // Unicode code point value
gHeight[gNum] = (uint8_t)readInt32(); // Height of glyph
gWidth[gNum] = (uint8_t)readInt32(); // Width of glyph
gxAdvance[gNum] = (uint8_t)readInt32(); // xAdvance - to move x cursor
gdY[gNum] = (int8_t)readInt32(); // y delta from baseline
gdX[gNum] = (int8_t)readInt32(); // x delta from cursor
readInt32(); // ignored
// Different glyph sets have different ascent values not always based on "d", so get maximum glyph ascent
if (gdY[gNum] > gFont.maxAscent)
{
// Avoid UTF coding values and characters that tend to give duff values
if (((gUnicode[gNum] > 0x20) && (gUnicode[gNum] < 0xA0) && (gUnicode[gNum] != 0x7F)) || (gUnicode[gNum] > 0xFF))
{
gFont.maxAscent = gdY[gNum];
#ifdef SHOW_ASCENT_DESCENT
Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", maxAscent = "); Serial.println(gFont.maxAscent);
#endif
}
}
// Different glyph sets have different descent values not always based on "p", so get maximum glyph descent
if (((int16_t)gHeight[gNum] - (int16_t)gdY[gNum]) > gFont.maxDescent)
{
// Avoid UTF coding values and characters that tend to give duff values
if (((gUnicode[gNum] > 0x20) && (gUnicode[gNum] < 0xA0) && (gUnicode[gNum] != 0x7F)) || (gUnicode[gNum] > 0xFF))
{
gFont.maxDescent = gHeight[gNum] - gdY[gNum];
#ifdef SHOW_ASCENT_DESCENT
Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", maxDescent = "); Serial.println(gHeight[gNum] - gdY[gNum]);
#endif
}
}
gBitmap[gNum] = bitmapPtr;
headerPtr += 28;
bitmapPtr += gWidth[gNum] * gHeight[gNum];
gNum++;
yield();
}
gFont.yAdvance = gFont.maxAscent + gFont.maxDescent;
gFont.spaceWidth = (gFont.ascent + gFont.descent) * 2/7; // Guess at space width
}
/***************************************************************************************
** Function name: deleteMetrics
** Description: Delete the old glyph metrics and free up the memory
*************************************************************************************x*/
void TFT_eSPI::unloadFont( void )
{
if (gUnicode)
{
free(gUnicode);
gUnicode = NULL;
}
if (gHeight)
{
free(gHeight);
gHeight = NULL;
}
if (gWidth)
{
free(gWidth);
gWidth = NULL;
}
if (gxAdvance)
{
free(gxAdvance);
gxAdvance = NULL;
}
if (gdY)
{
free(gdY);
gdY = NULL;
}
if (gdX)
{
free(gdX);
gdX = NULL;
}
if (gBitmap)
{
free(gBitmap);
gBitmap = NULL;
}
fontFile.close();
fontLoaded = false;
}
/***************************************************************************************
** Function name: decodeUTF8
** Description: Line buffer UTF-8 decoder with fall-back to extended ASCII
*************************************************************************************x*/
#define DECODE_UTF8
uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining)
{
byte c = buf[(*index)++];
//Serial.print("Byte from string = 0x"); Serial.println(c, HEX);
#ifdef DECODE_UTF8
// 7 bit Unicode
if ((c & 0x80) == 0x00) return c;
// 11 bit Unicode
if (((c & 0xE0) == 0xC0) && (remaining > 1))
return ((c & 0x1F)<<6) | (buf[(*index)++]&0x3F);
// 16 bit Unicode
if (((c & 0xF0) == 0xE0) && (remaining > 2))
return ((c & 0x0F)<<12) | ((buf[(*index)++]&0x3F)<<6) | ((buf[(*index)++]&0x3F));
// 21 bit Unicode not supported so fall-back to extended ASCII
// if ((c & 0xF8) == 0xF0) return c;
#endif
return c; // fall-back to extended ASCII
}
/***************************************************************************************
** Function name: decodeUTF8
** Description: Serial UTF-8 decoder with fall-back to extended ASCII
*************************************************************************************x*/
uint16_t TFT_eSPI::decodeUTF8(uint8_t c)
{
#ifdef DECODE_UTF8
if (decoderState == 0)
{
// 7 bit Unicode
if ((c & 0x80) == 0x00) return (uint16_t)c;
// 11 bit Unicode
if ((c & 0xE0) == 0xC0)
{
decoderBuffer = ((c & 0x1F)<<6);
decoderState = 1;
return 0;
}
// 16 bit Unicode
if ((c & 0xF0) == 0xE0)
{
decoderBuffer = ((c & 0x0F)<<12);
decoderState = 2;
return 0;
}
// 21 bit Unicode not supported so fall-back to extended ASCII
if ((c & 0xF8) == 0xF0) return (uint16_t)c;
}
else
{
if (decoderState == 2)
{
decoderBuffer |= ((c & 0x3F)<<6);
decoderState--;
return 0;
}
else
{
decoderBuffer |= (c & 0x3F);
decoderState = 0;
return decoderBuffer;
}
}
#endif
return (uint16_t)c; // fall-back to extended ASCII
}
/***************************************************************************************
** Function name: alphaBlend
** Description: Blend foreground and background and return new colour
*************************************************************************************x*/
uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc)
{
// For speed use fixed point maths and rounding to permit a power of 2 division
uint16_t fgR = ((fgc >> 10) & 0x3E) + 1;
uint16_t fgG = ((fgc >> 4) & 0x7E) + 1;
uint16_t fgB = ((fgc << 1) & 0x3E) + 1;
uint16_t bgR = ((bgc >> 10) & 0x3E) + 1;
uint16_t bgG = ((bgc >> 4) & 0x7E) + 1;
uint16_t bgB = ((bgc << 1) & 0x3E) + 1;
// Shift right 1 to drop rounding bit and shift right 8 to divide by 256
uint16_t r = (((fgR * alpha) + (bgR * (255 - alpha))) >> 9);
uint16_t g = (((fgG * alpha) + (bgG * (255 - alpha))) >> 9);
uint16_t b = (((fgB * alpha) + (bgB * (255 - alpha))) >> 9);
// Combine RGB565 colours into 16 bits
return (r << 11) | (g << 5) | (b << 0);
}
/***************************************************************************************
** Function name: readInt32
** Description: Get a 32 bit integer from the font file
*************************************************************************************x*/
uint32_t TFT_eSPI::readInt32(void)
{
uint32_t val = 0;
val |= fontFile.read() << 24;
val |= fontFile.read() << 16;
val |= fontFile.read() << 8;
val |= fontFile.read();
return val;
}
/***************************************************************************************
** Function name: getUnicodeIndex
** Description: Get the font file index of a Unicode character
*************************************************************************************x*/
bool TFT_eSPI::getUnicodeIndex(uint16_t unicode, uint16_t *index)
{
for (uint16_t i = 0; i < gFont.gCount; i++)
{
if (gUnicode[i] == unicode)
{
*index = i;
return true;
}
}
return false;
}
/***************************************************************************************
** Function name: drawGlyph
** Description: Write a character to the TFT cursor position
*************************************************************************************x*/
// Expects file to be open
void TFT_eSPI::drawGlyph(uint16_t code)
{
if (code < 0x21)
{
if (code == 0x20) {
cursor_x += gFont.spaceWidth;
return;
}
if (code == '\n') {
cursor_x = 0;
cursor_y += gFont.yAdvance;
if (cursor_y >= _height) cursor_y = 0;
return;
}
}
uint16_t gNum = 0;
bool found = getUnicodeIndex(code, &gNum);
uint16_t fg = textcolor;
uint16_t bg = textbgcolor;
if (found)
{
if (textwrapX && (cursor_x + gWidth[gNum] + gdX[gNum] > _width))
{
cursor_y += gFont.yAdvance;
cursor_x = 0;
}
if (textwrapY && ((cursor_y + gFont.yAdvance) >= _height)) cursor_y = 0;
if (cursor_x == 0) cursor_x -= gdX[gNum];
fontFile.seek(gBitmap[gNum], fs::SeekSet); // This is taking >30ms for a significant position shift
uint8_t pbuffer[gWidth[gNum]];
uint16_t xs = 0;
uint16_t dl = 0;
for (int y = 0; y < gHeight[gNum]; y++)
{
fontFile.read(pbuffer, gWidth[gNum]); //<//
for (int x = 0; x < gWidth[gNum]; x++)
{
uint8_t pixel = pbuffer[x]; //<//
if (pixel)
{
if (pixel != 0xFF)
{
if (dl) { drawFastHLine( xs, y + cursor_y + gFont.maxAscent - gdY[gNum], dl, fg); dl = 0; }
drawPixel(x + cursor_x + gdX[gNum], y + cursor_y + gFont.maxAscent - gdY[gNum], alphaBlend(pixel, fg, bg));
}
else
{
if (dl==0) xs = x + cursor_x + gdX[gNum];
dl++;
}
}
else
{
if (dl) { drawFastHLine( xs, y + cursor_y + gFont.maxAscent - gdY[gNum], dl, fg); dl = 0; }
}
}
if (dl) { drawFastHLine( xs, y + cursor_y + gFont.maxAscent - gdY[gNum], dl, fg); dl = 0; }
}
cursor_x += gxAdvance[gNum];
}
else
{
// Not a Unicode in font so draw a rectangle and move on cursor
drawRect(cursor_x, cursor_y + gFont.maxAscent - gFont.ascent, gFont.spaceWidth, gFont.ascent, fg);
cursor_x += gFont.spaceWidth + 1;
}
}
/***************************************************************************************
** Function name: showFont
** Description: Page through all characters in font, td ms between screens
*************************************************************************************x*/
void TFT_eSPI::showFont(uint32_t td)
{
if(!fontLoaded) return;
// fontFile = SPIFFS.open( _gFontFilename, "r" );
if(!fontFile)
{
fontLoaded = false;
return;
}
int16_t cursorX = width(); // Force start of new page to initialise cursor
int16_t cursorY = height();// for the first character
uint32_t timeDelay = 0; // No delay before first page
fillScreen(textbgcolor);
for (uint16_t i = 0; i < gFont.gCount; i++)
{
// Check if this will need a new screen
if (cursorX + gdX[i] + gWidth[i] >= width()) {
cursorX = -gdX[i];
cursorY += gFont.yAdvance;
if (cursorY + gFont.maxAscent + gFont.descent >= height()) {
cursorX = -gdX[i];
cursorY = 0;
delay(timeDelay);
timeDelay = td;
fillScreen(textbgcolor);
}
}
setCursor(cursorX, cursorY);
drawGlyph(gUnicode[i]);
cursorX += gxAdvance[i];
//cursorX += printToSprite( cursorX, cursorY, i );
yield();
}
delay(timeDelay);
fillScreen(textbgcolor);
//fontFile.close();
}

54
Extensions/Smooth_font.h Normal file
View File

@ -0,0 +1,54 @@
// Coded by Bodmer 10/2/18, see license in root directory.
// This is part of the TFT_eSPI class and is associated with anti-aliased font functions
public:
// These are for the new antialiased fonts
void loadFont(String fontName);
void unloadFont( void );
bool getUnicodeIndex(uint16_t unicode, uint16_t *index);
uint16_t decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining);
uint16_t decodeUTF8(uint8_t c);
uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc);
void drawGlyph(uint16_t code);
void showFont(uint32_t td);
fs::File fontFile;
// This is for the whole font
typedef struct
{
uint16_t gCount; // Total number of characters
uint16_t yAdvance; // Line advance
uint16_t spaceWidth; // Width of a space character
int16_t ascent; // Height of top of 'd' above baseline, other characters may be taller
int16_t descent; // Offset to bottom of 'p', other characters may have a larger descent
uint16_t maxAscent; // Maximum ascent found in font
uint16_t maxDescent; // Maximum descent found in font
} fontMetrics;
fontMetrics gFont = { 0, 0, 0, 0, 0, 0, 0 };
// These are for the metrics for each individual glyph (so we don't need to seek this in file and waste time)
uint16_t* gUnicode = NULL; //UTF-16 code, the codes are searched so do not need to be sequential
uint8_t* gHeight = NULL; //cheight
uint8_t* gWidth = NULL; //cwidth
uint8_t* gxAdvance = NULL; //setWidth
int8_t* gdY = NULL; //topExtent
int8_t* gdX = NULL; //leftExtent
uint32_t* gBitmap = NULL; //file pointer to greyscale bitmap
String _gFontFilename;
uint8_t decoderState = 0; // UTF8 decoder state
uint16_t decoderBuffer; // Unicode code-point buffer
bool fontLoaded = false; // Flags when a anti-aliased font is loaded
private:
void loadMetrics(uint16_t gCount);
uint32_t readInt32(void);

1409
Extensions/Sprite.cpp Normal file

File diff suppressed because it is too large Load Diff

111
Extensions/Sprite.h Normal file
View File

@ -0,0 +1,111 @@
/***************************************************************************************
// The following class creates Sprites in RAM, graphics can then be drawn in the Sprite
// and rendered quickly onto the TFT screen. The class inherits the graphics functions
// from the TFT_eSPI class. Some functions are overridden by this class so that the
// graphics are written to the Sprite rather than the TFT.
***************************************************************************************/
class TFT_eSprite : public TFT_eSPI {
public:
TFT_eSprite(TFT_eSPI *tft);
// Create a sprite of width x height pixels, return a pointer to the RAM area
// Sketch can cast returned value to (uint16_t*) for 16 bit depth if needed
// RAM required is 1 byte per pixel for 8 bit colour depth, 2 bytes for 16 bit
void* createSprite(int16_t width, int16_t height);
// Delete the sprite to free up the RAM
void deleteSprite(void);
// Set the colour depth to 8 or 16 bits. Can be used to change depth an existing
// sprite, but clears it to black, returns a new pointer if sprite is re-created.
void* setColorDepth(int8_t b);
void drawPixel(uint32_t x, uint32_t y, uint32_t color);
void drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size),
fillSprite(uint32_t color),
// Define a window to push 16 bit colour pixels into is a raster order
// Colours are converted to 8 bit if depth is set to 8
setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1),
pushColor(uint32_t color),
pushColor(uint32_t color, uint16_t len),
// Push a pixel preformatted as a 8 or 16 bit colour (avoids conversion overhead)
writeColor(uint16_t color),
// Set the scroll zone, top left corner at x,y with defined width and height
// The colour (optional, black is default) is used to fill the gap after the scroll
setScrollRect(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t color = TFT_BLACK),
// Scroll the defined zone dx,dy pixels. Negative values left,up, positive right,down
// dy is optional (default is then no up/down scroll).
// The sprite coordinate frame does not move because pixels are moved
scroll(int16_t dx, int16_t dy = 0),
drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, 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),
// Set the sprite text cursor position for print class (does not change the TFT screen cursor)
setCursor(int16_t x, int16_t y);
// Read the colour of a pixel at x,y and return value in 565 format
uint16_t readPixel(int32_t x0, int32_t y0);
// Write an image (colour bitmap) to the sprite
void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint16_t *data);
void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, const uint16_t *data);
// Swap the byte order for pushImage() - corrects different image endianness
void setSwapBytes(bool swap);
bool getSwapBytes(void);
// Push the sprite to the TFT screen, this fn calls pushImage() in the TFT class.
// Optionally a "transparent" colour can be defined, pixels of that colour will not be rendered
void pushSprite(int32_t x, int32_t y);
void pushSprite(int32_t x, int32_t y, uint16_t transparent);
int16_t drawChar(unsigned int uniCode, int x, int y, int font),
drawChar(unsigned int uniCode, int x, int y);
// Return the width and height of the sprite
int16_t width(void),
height(void);
// Used by print class to print text to cursor position
size_t write(uint8_t);
// Functions associated with anti-aliased fonts
void drawGlyph(uint16_t code);
void printToSprite(String string);
void printToSprite(char *cbuffer, int len);
int16_t printToSprite(int16_t x, int16_t y, uint16_t index);
private:
TFT_eSPI *_tft;
protected:
uint16_t *_img; // pointer to 16 bit sprite
uint8_t *_img8; // pointer to 8 bit sprite
bool _created, _bpp16; // created and bits per pixel depth flags
bool _gFont = false;
int32_t _icursor_x, _icursor_y;
int32_t _xs, _ys, _xe, _ye, _xptr, _yptr; // for setWindow
int32_t _sx, _sy; // x,y for scroll zone
uint32_t _sw, _sh; // w,h for scroll zone
uint32_t _scolor; // gap fill colour for scroll zone
boolean _iswapBytes; // Swap the byte order for Sprite pushImage()
int32_t _iwidth, _iheight; // Sprite image width and height
};

319
Extensions/Touch.cpp Normal file
View File

@ -0,0 +1,319 @@
// The following touch screen support code by maxpautsch was merged 1/10/17
// https://github.com/maxpautsch
// Define TOUCH_CS is the user setup file to enable this code
// A demo is provided in examples Generic folder
// Additions by Bodmer to double sample and use Z value to improve detection reliability
// See license in root directory.
#ifdef TOUCH_CS // If a pin has been allocated to the Touch screen load functions
/***************************************************************************************
** Function name: getTouchRaw
** Description: read raw touch position. Return false if not pressed.
***************************************************************************************/
uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){
uint16_t tmp;
CS_H;
spi_begin_touch();
T_CS_L;
// Start bit + YP sample request for x position
tmp = SPI.transfer(0xd0);
tmp = SPI.transfer(0);
tmp = tmp <<5;
tmp |= 0x1f & (SPI.transfer(0)>>3);
*x = tmp;
// Start bit + XP sample request for y position
SPI.transfer(0x90);
tmp = SPI.transfer(0);
tmp = tmp <<5;
tmp |= 0x1f & (SPI.transfer(0)>>3);
*y = tmp;
T_CS_H;
spi_end_touch();
return true;
}
/***************************************************************************************
** Function name: getTouchRawZ
** Description: read raw pressure on touchpad and return Z value.
***************************************************************************************/
uint16_t TFT_eSPI::getTouchRawZ(void){
CS_H;
spi_begin_touch();
T_CS_L;
// Z sample request
uint16_t tz = 0xFFF;
SPI.transfer(0xb1);
tz += SPI.transfer16(0xc1) >> 3;
tz -= SPI.transfer16(0x91) >> 3;
T_CS_H;
spi_end_touch();
return tz;
}
/***************************************************************************************
** Function name: validTouch
** Description: read validated position. Return false if not pressed.
***************************************************************************************/
#define _RAWERR 10 // Deadband in position samples
uint8_t TFT_eSPI::validTouch(uint16_t *x, uint16_t *y, uint16_t threshold){
uint16_t x_tmp, y_tmp, x_tmp2, y_tmp2;
// Wait until pressure stops increasing
uint16_t z1 = 1;
uint16_t z2 = 0;
while (z1 > z2)
{
z2 = z1;
z1 = getTouchRawZ();
delay(1);
}
// Serial.print("Z = ");Serial.println(z1);
if (z1 <= threshold) return false;
getTouchRaw(&x_tmp,&y_tmp);
// Serial.print("Sample 1 x,y = "); Serial.print(x_tmp);Serial.print(",");Serial.print(y_tmp);
// Serial.print(", Z = ");Serial.println(z1);
delay(1); // Small delay to the next sample
if (getTouchRawZ() <= threshold) return false;
delay(2); // Small delay to the next sample
getTouchRaw(&x_tmp2,&y_tmp2);
// Serial.print("Sample 2 x,y = "); Serial.print(x_tmp2);Serial.print(",");Serial.println(y_tmp2);
// Serial.print("Sample difference = ");Serial.print(abs(x_tmp - x_tmp2));Serial.print(",");Serial.println(abs(y_tmp - y_tmp2));
if (abs(x_tmp - x_tmp2) > _RAWERR) return false;
if (abs(y_tmp - y_tmp2) > _RAWERR) return false;
*x = x_tmp;
*y = y_tmp;
return true;
}
/***************************************************************************************
** Function name: getTouch
** Description: read callibrated position. Return false if not pressed.
***************************************************************************************/
#define Z_THRESHOLD 350 // Touch pressure threshold for validating touches
uint8_t TFT_eSPI::getTouch(uint16_t *x, uint16_t *y, uint16_t threshold){
uint16_t x_tmp, y_tmp, xx, yy;
if (threshold<20) threshold = 20;
if (_pressTime > millis()) threshold=20;
uint8_t n = 5;
uint8_t valid = 0;
while (n--)
{
if (validTouch(&x_tmp, &y_tmp, threshold)) valid++;;
}
if (valid<1) { _pressTime = 0; return false; }
_pressTime = millis() + 50;
if(!touchCalibration_rotate){
xx=(x_tmp-touchCalibration_x0)*_width/touchCalibration_x1;
yy=(y_tmp-touchCalibration_y0)*_height/touchCalibration_y1;
if(touchCalibration_invert_x)
xx = _width - xx;
if(touchCalibration_invert_y)
yy = _height - yy;
} else {
yy=(x_tmp-touchCalibration_x0)*_height/touchCalibration_x1;
xx=(y_tmp-touchCalibration_y0)*_width/touchCalibration_y1;
if(touchCalibration_invert_x)
xx = _width - xx;
if(touchCalibration_invert_y)
yy = _height - yy;
}
if (xx >= _width || yy >= _height) return valid;
_pressX = xx;
_pressY = yy;
*x = _pressX;
*y = _pressY;
return valid;
}
/***************************************************************************************
** Function name: calibrateTouch
** Description: generates calibration parameters for touchscreen.
***************************************************************************************/
void TFT_eSPI::calibrateTouch(uint16_t *parameters, uint32_t color_fg, uint32_t color_bg, uint8_t size){
int16_t values[] = {0,0,0,0,0,0,0,0};
uint16_t x_tmp, y_tmp;
for(uint8_t i = 0; i<4; i++){
fillRect(0, 0, size+1, size+1, color_bg);
fillRect(0, _height-size-1, size+1, size+1, color_bg);
fillRect(_width-size-1, 0, size+1, size+1, color_bg);
fillRect(_width-size-1, _height-size-1, size+1, size+1, color_bg);
if (i == 5) break; // used to clear the arrows
switch (i) {
case 0: // up left
drawLine(0, 0, 0, size, color_fg);
drawLine(0, 0, size, 0, color_fg);
drawLine(0, 0, size , size, color_fg);
break;
case 1: // bot left
drawLine(0, _height-size-1, 0, _height-1, color_fg);
drawLine(0, _height-1, size, _height-1, color_fg);
drawLine(size, _height-size-1, 0, _height-1 , color_fg);
break;
case 2: // up right
drawLine(_width-size-1, 0, _width-1, 0, color_fg);
drawLine(_width-size-1, size, _width-1, 0, color_fg);
drawLine(_width-1, size, _width-1, 0, color_fg);
break;
case 3: // bot right
drawLine(_width-size-1, _height-size-1, _width-1, _height-1, color_fg);
drawLine(_width-1, _height-1-size, _width-1, _height-1, color_fg);
drawLine(_width-1-size, _height-1, _width-1, _height-1, color_fg);
break;
}
// user has to get the chance to release
if(i>0) delay(1000);
for(uint8_t j= 0; j<8; j++){
// Use a lower detect threshold as corners tend to be less sensitive
while(!validTouch(&x_tmp, &y_tmp, Z_THRESHOLD/4));
values[i*2 ] += x_tmp;
values[i*2+1] += y_tmp;
}
values[i*2 ] /= 8;
values[i*2+1] /= 8;
}
// check orientation
// from case 0 to case 1, the y value changed.
// If the measured delta of the touch x axis is bigger than the delta of the y axis, the touch and TFT axes are switched.
touchCalibration_rotate = false;
if(abs(values[0]-values[2]) > abs(values[1]-values[3])){
touchCalibration_rotate = true;
touchCalibration_x0 = (values[0] + values[4])/2; // calc min x
touchCalibration_x1 = (values[2] + values[6])/2; // calc max x
touchCalibration_y0 = (values[1] + values[3])/2; // calc min y
touchCalibration_y1 = (values[5] + values[7])/2; // calc max y
} else {
touchCalibration_x0 = (values[0] + values[2])/2; // calc min x
touchCalibration_x1 = (values[4] + values[6])/2; // calc max x
touchCalibration_y0 = (values[1] + values[5])/2; // calc min y
touchCalibration_y1 = (values[3] + values[7])/2; // calc max y
}
// in addition, the touch screen axis could be in the opposit direction of the TFT axis
touchCalibration_invert_x = false;
if(touchCalibration_x0 > touchCalibration_x1){
values[0]=touchCalibration_x0;
touchCalibration_x0 = touchCalibration_x1;
touchCalibration_x1 = values[0];
touchCalibration_invert_x = true;
}
touchCalibration_invert_y = false;
if(touchCalibration_y0 > touchCalibration_y1){
values[0]=touchCalibration_y0;
touchCalibration_y0 = touchCalibration_y1;
touchCalibration_y1 = values[0];
touchCalibration_invert_y = true;
}
// pre calculate
touchCalibration_x1 -= touchCalibration_x0;
touchCalibration_y1 -= touchCalibration_y0;
if(touchCalibration_x0 == 0) touchCalibration_x0 = 1;
if(touchCalibration_x1 == 0) touchCalibration_x1 = 1;
if(touchCalibration_y0 == 0) touchCalibration_y0 = 1;
if(touchCalibration_y1 == 0) touchCalibration_y1 = 1;
// export parameters, if pointer valid
if(parameters != NULL){
parameters[0] = touchCalibration_x0;
parameters[1] = touchCalibration_x1;
parameters[2] = touchCalibration_y0;
parameters[3] = touchCalibration_y1;
parameters[4] = touchCalibration_rotate | (touchCalibration_invert_x <<1) | (touchCalibration_invert_y <<2);
}
}
/***************************************************************************************
** Function name: setTouch
** Description: imports calibration parameters for touchscreen.
***************************************************************************************/
void TFT_eSPI::setTouch(uint16_t *parameters){
touchCalibration_x0 = parameters[0];
touchCalibration_x1 = parameters[1];
touchCalibration_y0 = parameters[2];
touchCalibration_y1 = parameters[3];
if(touchCalibration_x0 == 0) touchCalibration_x0 = 1;
if(touchCalibration_x1 == 0) touchCalibration_x1 = 1;
if(touchCalibration_y0 == 0) touchCalibration_y0 = 1;
if(touchCalibration_y1 == 0) touchCalibration_y1 = 1;
touchCalibration_rotate = parameters[4] & 0x01;
touchCalibration_invert_x = parameters[4] & 0x02;
touchCalibration_invert_y = parameters[4] & 0x04;
}
#else // TOUCH CS is not defined so generate dummy functions that do nothing
/***************************************************************************************
** Function name: Dummy functions for case where chip select pin is undefined
** Description:
***************************************************************************************/
uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){
return true;
}
uint16_t TFT_eSPI::getTouchRawZ(void){
return true;
}
uint8_t TFT_eSPI::validTouch(uint16_t *x, uint16_t *y, uint16_t threshold){
return true;
}
uint8_t TFT_eSPI::getTouch(uint16_t *x, uint16_t *y, uint16_t threshold){
return true;
}
void TFT_eSPI::calibrateTouch(uint16_t *parameters, uint32_t color_bg, uint32_t color_fg, uint8_t size){
}
void TFT_eSPI::setTouch(uint16_t *parameters){
}
#endif // TOUCH_CS

24
Extensions/Touch.h Normal file
View File

@ -0,0 +1,24 @@
// Coded by Bodmer 10/2/18, see license in root directory.
// This is part of the TFT_eSPI class and is associated with the Touch Screen handlers
public:
uint8_t getTouchRaw(uint16_t *x, uint16_t *y);
uint16_t getTouchRawZ(void);
uint8_t getTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600);
void calibrateTouch(uint16_t *data, uint32_t color_fg, uint32_t color_bg, uint8_t size);
void setTouch(uint16_t *data);
private:
inline void spi_begin_touch() __attribute__((always_inline));
inline void spi_end_touch() __attribute__((always_inline));
// These are associated with the Touch Screen handlers
uint8_t validTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600);
// Initialise with example calibration values so processor does not crash if setTouch() not called in setup()
uint16_t touchCalibration_x0 = 300, touchCalibration_x1 = 3600, touchCalibration_y0 = 300, touchCalibration_y1 = 3600;
uint8_t touchCalibration_rotate = 1, touchCalibration_invert_x = 2, touchCalibration_invert_y = 0;
uint32_t _pressTime;
uint16_t _pressX, _pressY;

View File

@ -12,7 +12,7 @@
PROGMEM const unsigned char widtbl_f7s[96] = // character width table
{
12, 12, 12, 12, 12, 12, 12, 12, // char 32 - 39
12, 12, 12, 12, 12, 17, 12, 12, // char 40 - 47
12, 12, 12, 12, 12, 32, 12, 12, // char 40 - 47
32, 32, 32, 32, 32, 32, 32, 32, // char 48 - 55
32, 32, 12, 12, 12, 12, 12, 12, // char 56 - 63
12, 12, 12, 12, 12, 12, 12, 12, // char 64 - 71
@ -32,10 +32,12 @@ PROGMEM const unsigned char chr_f7s_20[] =
0x7F, 0x7F, 0x7F, 0x7F, 0x3F
};
// Make - sign look like a segment
PROGMEM const unsigned char chr_f7s_2D[] =
{
0x7F, 0x7F, 0x45, 0x8A, 0x05, 0x8A, 0x05, 0x8A,
0x05, 0x8A, 0x7F, 0x7F, 0x7F, 0x2B
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x27, 0x8E, 0x0E,
0x92, 0x0A, 0x96, 0x09, 0x94, 0x0C, 0x90, 0x7F,
0x7F, 0x7F, 0x7F, 0x7F, 0x47
};
PROGMEM const unsigned char chr_f7s_2E[] =

View File

@ -1,5 +1,7 @@
# TFT_eSPI
>>> This branch includes new antialiased font capability, this is a work-in-progress <<<
An Arduino IDE compatible graphics and fonts library for ESP8266 and ESP32 processors with a driver for ILI9341, ILI9163, ST7735 and S6D02A1 based TFT displays that support SPI.
The library also supports TFT displays designed for the Raspberry Pi that are based on a ILI9486 driver chip with a 480 x 320 pixel screen. This display must be of the Waveshare design and use a 16 bit serial interface based on the 74HC04, 74HC4040 and 2 x 74HC4094 logic chips. A modification to these displays is possible (see mod image in Tools folder) to make many graphics functions much faster (e.g. 23ms to clear the screen, 1.2ms to draw a 72 pixel high numeral).
@ -32,7 +34,7 @@ Configuration of the library font selections, pins used to interface with the TF
I have made some changes that will be uploaded soon that improves sprite and image rendering performance by up to 3x faster on the ESP8266. These updates are currently being tested/debugged.
**2. Anti-aliased fonts - see Smooth_font branch for beta version**
**2. Anti-aliased fonts**
I have been experimenting with anti-aliased font files in "vlw" format generated by the free [Processing IDE](https://processing.org/). This IDE can be used to generate font files from your computer's font set and include **any** Unicode characters. This means Greek, Japanese and any other UTF-16 glyphs can be used.

View File

@ -7,8 +7,8 @@
switch (rotation) {
case 0:
writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR);
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
#ifdef CGRAM_OFFSET
colstart = 0;
rowstart = 0;
@ -16,8 +16,8 @@
break;
case 1:
writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR);
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
#ifdef CGRAM_OFFSET
colstart = 0;
rowstart = 0;
@ -25,8 +25,8 @@
break;
case 2:
writedata(TFT_MAD_BGR);
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
#ifdef CGRAM_OFFSET
colstart = 0;
rowstart = 32;
@ -34,8 +34,8 @@
break;
case 3:
writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR);
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
#ifdef CGRAM_OFFSET
colstart = 32;
rowstart = 0;

View File

@ -11,8 +11,8 @@
#else
writedata(TFT_MAD_MX | TFT_MAD_BGR);
#endif
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 1:
#ifdef M5STACK
@ -20,8 +20,8 @@
#else
writedata(TFT_MAD_MV | TFT_MAD_BGR);
#endif
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
case 2:
#ifdef M5STACK
@ -29,8 +29,8 @@
#else
writedata(TFT_MAD_MY | TFT_MAD_BGR);
#endif
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 3:
#ifdef M5STACK
@ -38,8 +38,8 @@
#else
writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_BGR);
#endif
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
// These next rotations are for bottom up BMP drawing
case 4:
@ -48,8 +48,8 @@
#else
writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR);
#endif
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 5:
#ifdef M5STACK
@ -57,8 +57,8 @@
#else
writedata(TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_BGR);
#endif
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
case 6:
#ifdef M5STACK
@ -66,8 +66,8 @@
#else
writedata(TFT_MAD_BGR);
#endif
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 7:
#ifdef M5STACK
@ -75,8 +75,8 @@
#else
writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_BGR);
#endif
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
}

View File

@ -5,43 +5,43 @@
switch (rotation) {
case 0: // Portrait
writedata(TFT_MAD_BGR | TFT_MAD_MX);
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 1: // Landscape (Portrait + 90)
writedata(TFT_MAD_BGR | TFT_MAD_MV);
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
case 2: // Inverter portrait
writedata( TFT_MAD_BGR | TFT_MAD_MY);
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 3: // Inverted landscape
writedata(TFT_MAD_BGR | TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_MY);
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
case 4: // Portrait
writedata(TFT_MAD_BGR | TFT_MAD_MX | TFT_MAD_MY);
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 5: // Landscape (Portrait + 90)
writedata(TFT_MAD_BGR | TFT_MAD_MV | TFT_MAD_MX);
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
case 6: // Inverter portrait
writedata( TFT_MAD_BGR);
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 7: // Inverted landscape
writedata(TFT_MAD_BGR | TFT_MAD_MV | TFT_MAD_MY);
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
}

View File

@ -7,22 +7,22 @@
switch (rotation) {
case 0:
writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR);
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 1:
writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR);
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
case 2:
writedata(TFT_MAD_BGR);
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 3:
writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR);
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
}

View File

@ -23,8 +23,8 @@
} else {
writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR);
}
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 1:
if (tabcolor == INITR_BLACKTAB) {
@ -44,8 +44,8 @@
} else {
writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_BGR);
}
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
case 2:
if (tabcolor == INITR_BLACKTAB) {
@ -65,8 +65,8 @@
} else {
writedata(TFT_MAD_BGR);
}
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 3:
if (tabcolor == INITR_BLACKTAB) {
@ -86,30 +86,30 @@
} else {
writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR);
}
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
// These next rotations are for bottum up BMP drawing
/* case 4:
writedata(ST7735_TFT_MAD_MX | ST7735_TFT_MAD_MY | ST7735_TFT_MAD_BGR);
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 5:
writedata(ST7735_TFT_MAD_MV | ST7735_TFT_MAD_MX | ST7735_TFT_MAD_BGR);
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
case 6:
writedata(ST7735_TFT_MAD_BGR);
_width = _width_orig;
_height = _height_orig;
_width = _init_width;
_height = _init_height;
break;
case 7:
writedata(ST7735_TFT_MAD_MY | ST7735_TFT_MAD_MV | ST7735_TFT_MAD_BGR);
_width = _height_orig;
_height = _width_orig;
_width = _init_height;
_height = _init_width;
break;
*/
}

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
/***************************************************
Arduino TFT graphics library targetted at ESP8266
Arduino TFT graphics library targeted at ESP8266
and ESP32 based boards.
This is a standalone library that contains the
hardware driver, the graphics funtions and the
hardware driver, the graphics functions and the
proportional fonts.
The larger fonts are Run Length Encoded to reduce
@ -74,6 +74,17 @@
#include <SPI.h>
#ifdef SMOOTH_FONT
// Call up the SPIFFS FLASH filing system for the anti-aliased fonts
#define FS_NO_GLOBALS
#include <FS.h>
#ifdef ESP32
#include "SPIFFS.h"
#endif
#endif
#if defined (ESP8266) && defined (D0_USED_FOR_DC)
#define DC_C digitalWrite(TFT_DC, LOW)
#define DC_D digitalWrite(TFT_DC, HIGH)
@ -255,7 +266,11 @@
template <typename T> static inline void
swap_coord(T& a, T& b) { T t = a; a = b; b = t; }
// This is a structure to conveniently hold infomation on the default fonts
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
// This is a structure to conveniently hold information on the default fonts
// Stores pointer to font character image address table, width table and height
// Create a null set in case some fonts not used (to prevent crash)
@ -318,7 +333,6 @@ const PROGMEM fontinfo fontdata [] = {
};
// Class functions and variables
class TFT_eSPI : public Print {
@ -343,9 +357,8 @@ class TFT_eSPI : public Print {
void setWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1),
pushColor(uint16_t color),
pushColor(uint16_t color, uint16_t len),
//pushColors(uint16_t *data, uint8_t len),
pushColors(uint8_t *data, uint32_t len),
pushColors(uint16_t *data, uint32_t len, bool swap = true), // With byte swap option
pushColors(uint8_t *data, uint32_t len),
fillScreen(uint32_t color);
@ -375,7 +388,7 @@ class TFT_eSPI : public Print {
setTextColor(uint16_t fgcolor, uint16_t bgcolor),
setTextSize(uint8_t size),
setTextWrap(boolean wrap),
setTextWrap(boolean wrapX, boolean wrapY = false),
setTextDatum(uint8_t datum),
setTextPadding(uint16_t x_width),
@ -427,13 +440,14 @@ class TFT_eSPI : public Print {
uint8_t getRotation(void),
getTextDatum(void),
color332(uint16_t color565); // Convert 16 bit colour to 8 bits
color16to8(uint16_t color565); // Convert 16 bit colour to 8 bits
int16_t getCursorX(void),
getCursorY(void);
uint16_t fontsLoaded(void),
color565(uint8_t r, uint8_t g, uint8_t b);
color565(uint8_t r, uint8_t g, uint8_t b),
color8to16(uint8_t color332); // Convert 8 bit colour to 16 bits
int16_t drawNumber(long long_num,int poX, int poY, int font),
drawNumber(long long_num,int poX, int poY),
@ -462,49 +476,39 @@ class TFT_eSPI : public Print {
void setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye);
// These are associated with the Touch Screen handlers
uint8_t getTouchRaw(uint16_t *x, uint16_t *y);
uint16_t getTouchRawZ(void);
uint8_t getTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600);
void calibrateTouch(uint16_t *data, uint32_t color_fg, uint32_t color_bg, uint8_t size);
void setTouch(uint16_t *data);
size_t write(uint8_t);
int32_t cursor_x, cursor_y;
uint32_t textcolor, textbgcolor;
private:
inline void spi_begin() __attribute__((always_inline));
inline void spi_end() __attribute__((always_inline));
inline void spi_begin_touch() __attribute__((always_inline));
inline void spi_end_touch() __attribute__((always_inline));
void readAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye);
uint8_t tabcolor,
colstart = 0, rowstart = 0; // some ST7735 displays need this changed
volatile uint32_t *dcport, *csport;//, *mosiport, *clkport, *rsport;
volatile uint32_t *dcport, *csport;
uint32_t cspinmask, dcpinmask, wrpinmask;//, mosipinmask, clkpinmask;
uint32_t cspinmask, dcpinmask, wrpinmask;
uint32_t lastColor = 0xFFFF;
// These are associated with the Touch Screen handlers
uint8_t validTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600);
// Initialise with example calibration values so processor does not crash if setTouch() not called in setup()
uint16_t touchCalibration_x0 = 300, touchCalibration_x1 = 3600, touchCalibration_y0 = 300, touchCalibration_y1 = 3600;
uint8_t touchCalibration_rotate = 1, touchCalibration_invert_x = 2, touchCalibration_invert_y = 0;
uint32_t _pressTime;
uint16_t _pressX, _pressY;
protected:
int32_t cursor_x, cursor_y, win_xe, win_ye, padX;
int32_t win_xe, win_ye, padX;
uint32_t _width_orig, _height_orig; // Display w/h as input, used by setRotation()
uint32_t _init_width, _init_height; // Display w/h as input, used by setRotation()
uint32_t _width, _height; // Display w/h as modified by current rotation
uint32_t textcolor, textbgcolor, fontsloaded, addr_row, addr_col;
uint32_t addr_row, addr_col;
uint32_t fontsloaded;
uint8_t glyph_ab, // glyph height above baseline
glyph_bb, // glyph height below baseline
@ -513,164 +517,32 @@ class TFT_eSPI : public Print {
textdatum, // Text reference datum
rotation; // Display rotation (0-3)
bool textwrap; // If set, 'wrap' text at right edge of display
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 locked, inTransaction; // Transaction and mutex lock flags for ESP32
bool _booted;
int32_t _lastColor;
#ifdef LOAD_GFXFF
GFXfont
*gfxFont;
GFXfont *gfxFont;
#endif
};
// Load the Touch extension
#ifdef TOUCH_CS
#include "Extensions/Touch.h"
#endif
/***************************************************************************************
// The following button class has been ported over from the Adafruit_GFX library so
// should be compatible.
// A slightly different implementation in this TFT_eSPI library allows the button
// legends to be in any font
***************************************************************************************/
// Load the Anti-aliased font extension
#ifdef SMOOTH_FONT
#include "Extensions/Smooth_font.h"
#endif
class TFT_eSPI_Button {
public:
TFT_eSPI_Button(void);
// "Classic" initButton() uses center & size
void initButton(TFT_eSPI *gfx, int16_t x, int16_t y,
uint16_t w, uint16_t h, uint16_t outline, uint16_t fill,
uint16_t textcolor, char *label, uint8_t textsize);
// New/alt initButton() uses upper-left corner & size
void initButtonUL(TFT_eSPI *gfx, int16_t x1, int16_t y1,
uint16_t w, uint16_t h, uint16_t outline, uint16_t fill,
uint16_t textcolor, char *label, uint8_t textsize);
void drawButton(boolean inverted = false);
boolean contains(int16_t x, int16_t y);
void press(boolean p);
boolean isPressed();
boolean justPressed();
boolean justReleased();
private:
TFT_eSPI *_gfx;
int16_t _x1, _y1; // Coordinates of top-left corner
uint16_t _w, _h;
uint8_t _textsize;
uint16_t _outlinecolor, _fillcolor, _textcolor;
char _label[10];
boolean currstate, laststate;
};
/***************************************************************************************
// The following class creates Sprites in RAM, graphics can then be drawn in the Sprite
// and rendered quickly onto the TFT screen. The class inherits the graphics functions
// from the TFT_eSPI class. Some functions are overridden by this class so that the
// graphics are written to the Sprite rather than the TFT.
***************************************************************************************/
class TFT_eSprite : public TFT_eSPI {
public:
TFT_eSprite(TFT_eSPI *tft);
// Create a sprite of width x height pixels, return a pointer to the RAM area
// Sketch can cast returned value to (uint16_t*) for 16 bit depth if needed
// RAM required is 1 byte per pixel for 8 bit colour depth, 2 bytes for 16 bit
uint8_t* createSprite(int16_t width, int16_t height);
// Delete the sprite to free up the RAM
void deleteSprite(void);
// Set the colour depth to 8 or 16 bits. Can be used to change depth an existing
// sprite, but clears it to black, returns a new pointer if sprite is re-created.
uint8_t* setColorDepth(int8_t b);
void drawPixel(uint32_t x, uint32_t y, uint32_t color);
void drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size),
fillSprite(uint32_t color),
// Define a window to push 16 bit colour pixels into is a raster order
// Colours are converted to 8 bit if depth is set to 8
setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1),
pushColor(uint32_t color),
pushColor(uint32_t color, uint16_t len),
// Push a pixel preformatted as a 8 or 16 bit colour (avoids conversion overhead)
writeColor(uint16_t color),
// Set the scroll zone, top left corner at x,y with defined width and height
// The colour (optional, black is default) is used to fill the gap after the scroll
setScrollRect(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t color = TFT_BLACK),
// Scroll the defined zone dx,dy pixels. Negative values left,up, positive right,down
// dy is optional (default is then no up/down scroll).
// The sprite coordinate frame does not move because pixels are moved
scroll(int16_t dx, int16_t dy = 0),
drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, 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),
// Set the sprite text cursor position for print class (does not change the TFT screen cursor)
setCursor(int16_t x, int16_t y);
// Read the colour of a pixel at x,y and return value in 565 format
uint16_t readPixel(int32_t x0, int32_t y0);
// Write an image (colour bitmap) to the sprite
void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint16_t *data);
void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, const uint16_t *data);
// Swap the byte order for pushImage() - corrects different image endianness
void setSwapBytes(bool swap);
bool getSwapBytes(void);
// Push the sprite to the TFT screen, this fn calls pushImage() in the TFT class.
// Optionally a "transparent" colour can be defined, pixels of that colour will not be rendered
void pushSprite(int32_t x, int32_t y);
void pushSprite(int32_t x, int32_t y, uint16_t transparent);
int16_t drawChar(unsigned int uniCode, int x, int y, int font),
drawChar(unsigned int uniCode, int x, int y);
// Return the width and height of the sprite
int16_t width(void),
height(void);
// Used by print class to print text to cursor position
size_t write(uint8_t);
private:
TFT_eSPI *_tft;
protected:
uint16_t *_img; // pointer to 16 bit sprite
uint8_t *_img8; // pointer to 8 bit sprite
bool _created, _bpp16; // created and bits per pixel depth flags
int32_t _icursor_x, _icursor_y;
int32_t _xs, _ys, _xe, _ye, _xptr, _yptr; // for setWindow
int32_t _sx, _sy; // x,y for scroll zone
uint32_t _sw, _sh; // w,h for scroll zone
uint32_t _scolor; // gap fill colour for scroll zone
boolean _iswapBytes; // Swap the byte order for Sprite pushImage()
int32_t _iwidth, _iheight; // Sprite image width and height
};
}; // End of class TFT_eSPI
// Load the Button Class
#include "Extensions/Button.h"
// Load the Sprite Class
#include "Extensions/Sprite.h"
#endif

View File

@ -0,0 +1,483 @@
// Select the character range in the user configure section starting at line 100
/*
Software License Agreement (FreeBSD License)
Copyright (c) 2018 Bodmer (https://github.com/Bodmer)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
////////////////////////////////////////////////////////////////////////////////////////////////
// This is a processing sketch to create font files for the TFT_eSPI library:
// https://github.com/Bodmer/TFT_eSPI
// Coded by Bodmer January 2018
// See comments below in code for specifying the font parameters
// (point size, unicode blocks to include etc). Ranges of characers or
// specific individual unicodes can be included in the created font file/
// Created fonts are saved in the sketches "FontFiles" folder. Press Ctrl+K to
// see that folder.
// 16 bit unicodes in the range 0x0000 - 0xFFFF are supported.
// The sketch will convert True Type (a .ttf or .otf file) file stored in the
// sketches "Data" folder as well as your computers system fonts.
// To maximise rendering performance only include the characters you will use.
// Characters at the start of the file will render faster than those at the end.
// Once created the files must be loaded into the ESP32 or ESP8266 SPIFFS memory
// using the Arduino IDE plugin detailed here:
// https://github.com/esp8266/arduino-esp8266fs-plugin
// https://github.com/me-no-dev/arduino-esp32fs-plugin
// The sketch list all the available PC fonts to the console, you may need to increase
// console line count (in preferences.txt) to stop some fonts scrolling out of view.
// See link in File>Preferences to locate "preferences.txt" file. You must close
// Processing then edit the file lines. If Processing is not closed first then the
// edits will be overwritten by defaults! Edit "preferences.txt" as follows for
// 1000 lines, then save, then run Processing again:
/*
console.length=1000 // Line 4 in file
console.scrollback.lines=1000 // Line 7 in file
*/
// Useful links:
/*
https://en.wikipedia.org/wiki/Unicode_font
https://www.gnu.org/software/freefont/
https://www.gnu.org/software/freefont/sources/
https://www.gnu.org/software/freefont/ranges/
http://savannah.gnu.org/projects/freefont/
http://www.google.com/get/noto/
https://github.com/Bodmer/TFT_eSPI
https://github.com/esp8266/arduino-esp8266fs-plugin
https://github.com/me-no-dev/arduino-esp32fs-plugin
*/
////////////////////////////////////////////////////////////////////////////////////////////////
import java.awt.Desktop;
// >>>>>>>>>> USER CONFIGURED PARAMETERS START HERE <<<<<<<<<<
// Use font name for ttf files placed in the "Data" folder or the font number seen in IDE Console for system fonts
// the font numbers are listed when the sketch is run.
// | 1 2 | Maximum filename size for SPIFFS is 32 including leading /
// 1234567890123456789012345 and added point size and .vlw extension, so max is 25
String fontName = "Final-Frontier"; //Manually crop the filename length later after creation if needed
String fontType = ".ttf"; //SPIFFS does not accept underscore in filename!
//String fontType = ".otf";
// Use font number instead of name, -1 means use name above, or a value >=0 means use system font number from list.
int fontNumber = -1; // << Use [Number] in brackets from the fonts listed in console window
// Define the font size in points for the created font file
int fontSize = 28;
// Font size to use in the Processing sketch display window that pops up (can be different to above)
int displayFontSize = 28;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Next we specify which unicode blocks from the the Basic Multilingual Plane (BMP) are included in the final font file. //
// Note: The ttf/otf font file MAY NOT contain all possible Unicode characters, refer to the fonts online documentation. //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static final int[] unicodeBlocks = {
// The list below has been created from the table here: https://en.wikipedia.org/wiki/Unicode_block
// Remove // at start of lines below to include that unicode block, different code ranges can also be specified by
// editting the start and end of range values. Multiple lines from the list below can be included, limited only by
// the final font file size!
// Block range, //Block name, Code points, Assigned characters, Scripts
// First, last, //Range is inclusive of first and last codes
0x0021, 0x007E, //Basic Latin, 128, 128, Latin (52 characters), Common (76 characters)
//0x0080, 0x00FF, //Latin-1 Supplement, 128, 128, Latin (64 characters), Common (64 characters)
//0x0100, 0x017F, //Latin Extended-A, 128, 128, Latin
//0x0180, 0x024F, //Latin Extended-B, 208, 208, Latin
//0x0250, 0x02AF, //IPA Extensions, 96, 96, Latin
//0x02B0, 0x02FF, //Spacing Modifier Letters, 80, 80, Bopomofo (2 characters), Latin (14 characters), Common (64 characters)
//0x0300, 0x036F, //Combining Diacritical Marks, 112, 112, Inherited
//0x0370, 0x03FF, //Greek and Coptic, 144, 135, Coptic (14 characters), Greek (117 characters), Common (4 characters)
//0x0400, 0x04FF, //Cyrillic, 256, 256, Cyrillic (254 characters), Inherited (2 characters)
//0x0500, 0x052F, //Cyrillic Supplement, 48, 48, Cyrillic
//0x0530, 0x058F, //Armenian, 96, 89, Armenian (88 characters), Common (1 character)
//0x0590, 0x05FF, //Hebrew, 112, 87, Hebrew
//0x0600, 0x06FF, //Arabic, 256, 255, Arabic (237 characters), Common (6 characters), Inherited (12 characters)
//0x0700, 0x074F, //Syriac, 80, 77, Syriac
//0x0750, 0x077F, //Arabic Supplement, 48, 48, Arabic
//0x0780, 0x07BF, //Thaana, 64, 50, Thaana
//0x07C0, 0x07FF, //NKo, 64, 59, Nko
//0x0800, 0x083F, //Samaritan, 64, 61, Samaritan
//0x0840, 0x085F, //Mandaic, 32, 29, Mandaic
//0x0860, 0x086F, //Syriac Supplement, 16, 11, Syriac
//0x08A0, 0x08FF, //Arabic Extended-A, 96, 73, Arabic (72 characters), Common (1 character)
//0x0900, 0x097F, //Devanagari, 128, 128, Devanagari (124 characters), Common (2 characters), Inherited (2 characters)
//0x0980, 0x09FF, //Bengali, 128, 95, Bengali
//0x0A00, 0x0A7F, //Gurmukhi, 128, 79, Gurmukhi
//0x0A80, 0x0AFF, //Gujarati, 128, 91, Gujarati
//0x0B00, 0x0B7F, //Oriya, 128, 90, Oriya
//0x0B80, 0x0BFF, //Tamil, 128, 72, Tamil
//0x0C00, 0x0C7F, //Telugu, 128, 96, Telugu
//0x0C80, 0x0CFF, //Kannada, 128, 88, Kannada
//0x0D00, 0x0D7F, //Malayalam, 128, 117, Malayalam
//0x0D80, 0x0DFF, //Sinhala, 128, 90, Sinhala
//0x0E00, 0x0E7F, //Thai, 128, 87, Thai (86 characters), Common (1 character)
//0x0E80, 0x0EFF, //Lao, 128, 67, Lao
//0x0F00, 0x0FFF, //Tibetan, 256, 211, Tibetan (207 characters), Common (4 characters)
//0x1000, 0x109F, //Myanmar, 160, 160, Myanmar
//0x10A0, 0x10FF, //Georgian, 96, 88, Georgian (87 characters), Common (1 character)
//0x1100, 0x11FF, //Hangul Jamo, 256, 256, Hangul
//0x1200, 0x137F, //Ethiopic, 384, 358, Ethiopic
//0x1380, 0x139F, //Ethiopic Supplement, 32, 26, Ethiopic
//0x13A0, 0x13FF, //Cherokee, 96, 92, Cherokee
//0x1400, 0x167F, //Unified Canadian Aboriginal Syllabics, 640, 640, Canadian Aboriginal
//0x1680, 0x169F, //Ogham, 32, 29, Ogham
//0x16A0, 0x16FF, //Runic, 96, 89, Runic (86 characters), Common (3 characters)
//0x1700, 0x171F, //Tagalog, 32, 20, Tagalog
//0x1720, 0x173F, //Hanunoo, 32, 23, Hanunoo (21 characters), Common (2 characters)
//0x1740, 0x175F, //Buhid, 32, 20, Buhid
//0x1760, 0x177F, //Tagbanwa, 32, 18, Tagbanwa
//0x1780, 0x17FF, //Khmer, 128, 114, Khmer
//0x1800, 0x18AF, //Mongolian, 176, 156, Mongolian (153 characters), Common (3 characters)
//0x18B0, 0x18FF, //Unified Canadian Aboriginal Syllabics Extended, 80, 70, Canadian Aboriginal
//0x1900, 0x194F, //Limbu, 80, 68, Limbu
//0x1950, 0x197F, //Tai Le, 48, 35, Tai Le
//0x1980, 0x19DF, //New Tai Lue, 96, 83, New Tai Lue
//0x19E0, 0x19FF, //Khmer Symbols, 32, 32, Khmer
//0x1A00, 0x1A1F, //Buginese, 32, 30, Buginese
//0x1A20, 0x1AAF, //Tai Tham, 144, 127, Tai Tham
//0x1AB0, 0x1AFF, //Combining Diacritical Marks Extended, 80, 15, Inherited
//0x1B00, 0x1B7F, //Balinese, 128, 121, Balinese
//0x1B80, 0x1BBF, //Sundanese, 64, 64, Sundanese
//0x1BC0, 0x1BFF, //Batak, 64, 56, Batak
//0x1C00, 0x1C4F, //Lepcha, 80, 74, Lepcha
//0x1C50, 0x1C7F, //Ol Chiki, 48, 48, Ol Chiki
//0x1C80, 0x1C8F, //Cyrillic Extended-C, 16, 9, Cyrillic
//0x1CC0, 0x1CCF, //Sundanese Supplement, 16, 8, Sundanese
//0x1CD0, 0x1CFF, //Vedic Extensions, 48, 42, Common (15 characters), Inherited (27 characters)
//0x1D00, 0x1D7F, //Phonetic Extensions, 128, 128, Cyrillic (2 characters), Greek (15 characters), Latin (111 characters)
//0x1D80, 0x1DBF, //Phonetic Extensions Supplement, 64, 64, Greek (1 character), Latin (63 characters)
//0x1DC0, 0x1DFF, //Combining Diacritical Marks Supplement, 64, 63, Inherited
//0x1E00, 0x1EFF, //Latin Extended Additional, 256, 256, Latin
//0x1F00, 0x1FFF, //Greek Extended, 256, 233, Greek
//0x2000, 0x206F, //General Punctuation, 112, 111, Common (109 characters), Inherited (2 characters)
//0x2070, 0x209F, //Superscripts and Subscripts, 48, 42, Latin (15 characters), Common (27 characters)
//0x20A0, 0x20CF, //Currency Symbols, 48, 32, Common
//0x20D0, 0x20FF, //Combining Diacritical Marks for Symbols, 48, 33, Inherited
//0x2100, 0x214F, //Letterlike Symbols, 80, 80, Greek (1 character), Latin (4 characters), Common (75 characters)
//0x2150, 0x218F, //Number Forms, 64, 60, Latin (41 characters), Common (19 characters)
//0x2190, 0x21FF, //Arrows, 112, 112, Common
//0x2200, 0x22FF, //Mathematical Operators, 256, 256, Common
//0x2300, 0x23FF, //Miscellaneous Technical, 256, 256, Common
//0x2400, 0x243F, //Control Pictures, 64, 39, Common
//0x2440, 0x245F, //Optical Character Recognition, 32, 11, Common
//0x2460, 0x24FF, //Enclosed Alphanumerics, 160, 160, Common
//0x2500, 0x257F, //Box Drawing, 128, 128, Common
//0x2580, 0x259F, //Block Elements, 32, 32, Common
//0x25A0, 0x25FF, //Geometric Shapes, 96, 96, Common
//0x2600, 0x26FF, //Miscellaneous Symbols, 256, 256, Common
//0x2700, 0x27BF, //Dingbats, 192, 192, Common
//0x27C0, 0x27EF, //Miscellaneous Mathematical Symbols-A, 48, 48, Common
//0x27F0, 0x27FF, //Supplemental Arrows-A, 16, 16, Common
//0x2800, 0x28FF, //Braille Patterns, 256, 256, Braille
//0x2900, 0x297F, //Supplemental Arrows-B, 128, 128, Common
//0x2980, 0x29FF, //Miscellaneous Mathematical Symbols-B, 128, 128, Common
//0x2A00, 0x2AFF, //Supplemental Mathematical Operators, 256, 256, Common
//0x2B00, 0x2BFF, //Miscellaneous Symbols and Arrows, 256, 207, Common
//0x2C00, 0x2C5F, //Glagolitic, 96, 94, Glagolitic
//0x2C60, 0x2C7F, //Latin Extended-C, 32, 32, Latin
//0x2C80, 0x2CFF, //Coptic, 128, 123, Coptic
//0x2D00, 0x2D2F, //Georgian Supplement, 48, 40, Georgian
//0x2D30, 0x2D7F, //Tifinagh, 80, 59, Tifinagh
//0x2D80, 0x2DDF, //Ethiopic Extended, 96, 79, Ethiopic
//0x2DE0, 0x2DFF, //Cyrillic Extended-A, 32, 32, Cyrillic
//0x2E00, 0x2E7F, //Supplemental Punctuation, 128, 74, Common
//0x2E80, 0x2EFF, //CJK Radicals Supplement, 128, 115, Han
//0x2F00, 0x2FDF, //Kangxi Radicals, 224, 214, Han
//0x2FF0, 0x2FFF, //Ideographic Description Characters, 16, 12, Common
//0x3000, 0x303F, //CJK Symbols and Punctuation, 64, 64, Han (15 characters), Hangul (2 characters), Common (43 characters), Inherited (4 characters)
//0x3040, 0x309F, //Hiragana, 96, 93, Hiragana (89 characters), Common (2 characters), Inherited (2 characters)
//0x30A0, 0x30FF, //Katakana, 96, 96, Katakana (93 characters), Common (3 characters)
//0x3100, 0x312F, //Bopomofo, 48, 42, Bopomofo
//0x3130, 0x318F, //Hangul Compatibility Jamo, 96, 94, Hangul
//0x3190, 0x319F, //Kanbun, 16, 16, Common
//0x31A0, 0x31BF, //Bopomofo Extended, 32, 27, Bopomofo
//0x31C0, 0x31EF, //CJK Strokes, 48, 36, Common
//0x31F0, 0x31FF, //Katakana Phonetic Extensions, 16, 16, Katakana
//0x3200, 0x32FF, //Enclosed CJK Letters and Months, 256, 254, Hangul (62 characters), Katakana (47 characters), Common (145 characters)
//0x3300, 0x33FF, //CJK Compatibility, 256, 256, Katakana (88 characters), Common (168 characters)
//0x3400, 0x4DBF, //CJK Unified Ideographs Extension A, 6,592, 6,582, Han
//0x4DC0, 0x4DFF, //Yijing Hexagram Symbols, 64, 64, Common
//0x4E00, 0x9FFF, //CJK Unified Ideographs, 20,992, 20,971, Han
//0xA000, 0xA48F, //Yi Syllables, 1,168, 1,165, Yi
//0xA490, 0xA4CF, //Yi Radicals, 64, 55, Yi
//0xA4D0, 0xA4FF, //Lisu, 48, 48, Lisu
//0xA500, 0xA63F, //Vai, 320, 300, Vai
//0xA640, 0xA69F, //Cyrillic Extended-B, 96, 96, Cyrillic
//0xA6A0, 0xA6FF, //Bamum, 96, 88, Bamum
//0xA700, 0xA71F, //Modifier Tone Letters, 32, 32, Common
//0xA720, 0xA7FF, //Latin Extended-D, 224, 160, Latin (155 characters), Common (5 characters)
//0xA800, 0xA82F, //Syloti Nagri, 48, 44, Syloti Nagri
//0xA830, 0xA83F, //Common Indic Number Forms, 16, 10, Common
//0xA840, 0xA87F, //Phags-pa, 64, 56, Phags Pa
//0xA880, 0xA8DF, //Saurashtra, 96, 82, Saurashtra
//0xA8E0, 0xA8FF, //Devanagari Extended, 32, 30, Devanagari
//0xA900, 0xA92F, //Kayah Li, 48, 48, Kayah Li (47 characters), Common (1 character)
//0xA930, 0xA95F, //Rejang, 48, 37, Rejang
//0xA960, 0xA97F, //Hangul Jamo Extended-A, 32, 29, Hangul
//0xA980, 0xA9DF, //Javanese, 96, 91, Javanese (90 characters), Common (1 character)
//0xA9E0, 0xA9FF, //Myanmar Extended-B, 32, 31, Myanmar
//0xAA00, 0xAA5F, //Cham, 96, 83, Cham
//0xAA60, 0xAA7F, //Myanmar Extended-A, 32, 32, Myanmar
//0xAA80, 0xAADF, //Tai Viet, 96, 72, Tai Viet
//0xAAE0, 0xAAFF, //Meetei Mayek Extensions, 32, 23, Meetei Mayek
//0xAB00, 0xAB2F, //Ethiopic Extended-A, 48, 32, Ethiopic
//0xAB30, 0xAB6F, //Latin Extended-E, 64, 54, Latin (52 characters), Greek (1 character), Common (1 character)
//0xAB70, 0xABBF, //Cherokee Supplement, 80, 80, Cherokee
//0xABC0, 0xABFF, //Meetei Mayek, 64, 56, Meetei Mayek
//0xAC00, 0xD7AF, //Hangul Syllables, 11,184, 11,172, Hangul
//0xD7B0, 0xD7FF, //Hangul Jamo Extended-B, 80, 72, Hangul
//0xD800, 0xDB7F, //High Surrogates, 896, 0, Unknown
//0xDB80, 0xDBFF, //High Private Use Surrogates, 128, 0, Unknown
//0xDC00, 0xDFFF, //Low Surrogates, 1,024, 0, Unknown
//0xE000, 0xF8FF, //Private Use Area, 6,400, 6,400, Unknown
//0xF900, 0xFAFF, //CJK Compatibility Ideographs, 512, 472, Han
//0xFB00, 0xFB4F, //Alphabetic Presentation Forms, 80, 58, Armenian (5 characters), Hebrew (46 characters), Latin (7 characters)
//0xFB50, 0xFDFF, //Arabic Presentation Forms-A, 688, 611, Arabic (609 characters), Common (2 characters)
//0xFE00, 0xFE0F, //Variation Selectors, 16, 16, Inherited
//0xFE10, 0xFE1F, //Vertical Forms, 16, 10, Common
//0xFE20, 0xFE2F, //Combining Half Marks, 16, 16, Cyrillic (2 characters), Inherited (14 characters)
//0xFE30, 0xFE4F, //CJK Compatibility Forms, 32, 32, Common
//0xFE50, 0xFE6F, //Small Form Variants, 32, 26, Common
//0xFE70, 0xFEFF, //Arabic Presentation Forms-B, 144, 141, Arabic (140 characters), Common (1 character)
//0xFF00, 0xFFEF, //Halfwidth and Fullwidth Forms, 240, 225, Hangul (52 characters), Katakana (55 characters), Latin (52 characters), Common (66 characters)
//0xFFF0, 0xFFFF, //Specials, 16, 5, Common
//0x0030, 0x0039, //Example custom range (numbers 0-9)
//0x0041, 0x005A, //Example custom range (Upper case A-Z)
//0x0061, 0x007A, //Example custom range (Lower case a-z)
};
// Here we specify specific individual Unicodes to be included (appended at end of selected range)
static final int[] specificUnicodes = {
// Commonly used codes, add or remove // in next line
// 0x00A3, 0x00B0, 0x00B5, 0x03A9, 0x20AC, // £ ° µ Ω €
// Numbers and characters for showing time, change next line to //* to use
/*
0x002B, 0x002D, 0x002E, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, // - + . 0 1 2 3 4
0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x0061, 0x006D, // 5 6 7 8 9 : a m
0x0070, // p
//*/
// More characters, change next line to //* to use
/*
0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x010C, 0x010D,
0x010E, 0x010F, 0x0110, 0x0111, 0x0118, 0x0119, 0x011A, 0x011B,
0x0131, 0x0139, 0x013A, 0x013D, 0x013E, 0x0141, 0x0142, 0x0143,
0x0144, 0x0147, 0x0148, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154,
0x0155, 0x0158, 0x0159, 0x015A, 0x015B, 0x015E, 0x015F, 0x0160,
0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x016E, 0x016F, 0x0170,
0x0171, 0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E,
0x0192,
0x02C6, 0x02C7, 0x02D8, 0x02D9, 0x02DA, 0x02DB, 0x02DC, 0x02DD,
0x03A9, 0x03C0, 0x2013, 0x2014, 0x2018, 0x2019, 0x201A, 0x201C,
0x201D, 0x201E, 0x2020, 0x2021, 0x2022, 0x2026, 0x2030, 0x2039,
0x203A, 0x2044, 0x20AC,
0x2122, 0x2202, 0x2206, 0x220F,
0x2211, 0x221A, 0x221E, 0x222B, 0x2248, 0x2260, 0x2264, 0x2265,
0x25CA,
0xF8FF, 0xFB01, 0xFB02,
//*/
};
// >>>>>>>>>> USER CONFIGURED PARAMETERS END HERE <<<<<<<<<<
////////////////////////////////////////////////////////////////////////////////////////////////
// Variable to hold the inclusive Unicode range (16 bit values only for this sketch)
int firstUnicode = 0;
int lastUnicode = 0;
PFont myFont;
void setup() {
size(1000, 800);
// Print the available fonts to the console as a list:
String[] fontList = PFont.list();
printArray(fontList);
// Set the fontName from the array number or the defined fontName
if (fontNumber >= 0)
{
fontName = fontList[fontNumber];
fontType = "";
}
char[] charset;
int index = 0, count = 0;
int blockCount = unicodeBlocks.length;
for (int i = 0; i < blockCount; i+=2) {
firstUnicode = unicodeBlocks[i];
lastUnicode = unicodeBlocks[i+1];
if (lastUnicode < firstUnicode) {
delay(100);
System.err.println("ERROR: Bad Unicode range secified, last < first!");
System.err.print("first in range = 0x" + hex(firstUnicode, 4));
System.err.println(", last in range = 0x" + hex(lastUnicode, 4));
while (true);
}
// calculate the number of characters
count += (lastUnicode - firstUnicode + 1);
}
count += specificUnicodes.length;
println();
println("=====================");
println("Creating font file...");
println("Unicode blocks included = " + (blockCount/2));
println("Specific unicodes included = " + specificUnicodes.length);
println("Total number of characters = " + count);
if (count == 0) {
delay(100);
System.err.println("ERROR: No Unicode range or specific codes have been defined!");
while (true);
}
// allocate memory
charset = new char[count];
for (int i = 0; i < blockCount; i+=2) {
firstUnicode = unicodeBlocks[i];
lastUnicode = unicodeBlocks[i+1];
// loading the range specified
for (int code = firstUnicode; code <= lastUnicode; code++) {
charset[index] = Character.toChars(code)[0];
index++;
}
}
// loading the range specified
for (int i = 0; i < specificUnicodes.length; i++) {
charset[index] = Character.toChars(specificUnicodes[i])[0];
index++;
}
// Create the font in memory
myFont = createFont(fontName+fontType, 32, true, charset);
// Print a few characters to the sketch window
fill(0, 0, 0);
textFont(myFont);
// Set the left and top margin
int margin = displayFontSize;
translate(margin/2, margin);
int gapx = displayFontSize*10/8;
int gapy = displayFontSize*10/8;
index = 0;
fill(0);
textSize(displayFontSize);
for (int y = 0; y < height-gapy; y += gapy) {
int x = 0;
while (x < width) {
int unicode = charset[index];
float cwidth = textWidth((char)unicode) + 2;
if ( (x + cwidth) > (width - gapx) ) break;
// Draw the letter to the screen
text(new String(Character.toChars(unicode)), x, y);
// Move cursor
x += cwidth;
// Increment the counter
index++;
if (index >= count) break;
}
if (index >= count) break;
}
// creating font
PFont font;
font = createFont(fontName+fontType, fontSize, true, charset);
println("Created font " + fontName + ".vlw");
// creating file
try {
print("Saving to sketch FontFiles folder... ");
OutputStream output = createOutput("FontFiles/" + fontName + str(fontSize) + ".vlw");
font.save(output);
output.close();
println("OK!");
delay(100);
// Open up the FontFiles folder to access the saved file
String path = sketchPath();
Desktop.getDesktop().open(new File(path+"/FontFiles"));
System.err.println("All done! Note: Rectangles are displayed for non-existant characters.");
}
catch(IOException e) {
println("Doh! Failed to create the file");
}
}

View File

@ -0,0 +1,33 @@
PlatformIO User notes:
It is possible to load settings from the calling program rather than modifying
the library for each project by modifying the "platformio.ini" file.
The User_Setup_Select.h file will not load the user setting header files if
USER_SETUP_LOADED is defined.
Instead of using #define, use the -D prefix, for example:
[env:esp32dev]
platform = https://github.com/platformio/platform-espressif32.git#feature/stage
board = esp32dev
framework = arduino
upload_port = ESP32-Test-2481CE9C.local
build_flags =
-Os
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
-DUSER_SETUP_LOADED=1
-DILI9163_DRIVER=1
-DTFT_WIDTH=128
-DTFT_HEIGHT=160
-DTFT_MISO=19
-DTFT_MOSI=23
-DTFT_SCLK=18
-DTFT_CS=5
-DTFT_DC=19
-DTFT_RST=-1
-DLOAD_GLCD=1
-DSPI_FREQUENCY=27000000
lib_extra_dirs = B:\Projects\ESP32\ESP32Lib

View File

@ -88,7 +88,7 @@
#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen
#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen
//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only
@ -164,10 +164,14 @@
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded
// this will save ~20kbytes of FLASH
#define SMOOTH_FONT
// ##################################################################################
//
// Section 4. Not used
@ -192,8 +196,8 @@
// #define SPI_FREQUENCY 5000000
// #define SPI_FREQUENCY 10000000
// #define SPI_FREQUENCY 20000000
#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3
// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS
//#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3
#define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS
// #define SPI_FREQUENCY 80000000
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
@ -210,4 +214,4 @@
// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex)
// so changing it here has no effect
// #define SUPPORT_TRANSACTIONS
#define SUPPORT_TRANSACTIONS

View File

@ -9,7 +9,7 @@
// changes being needed. It also improves the portability of users sketches to other
// hardware configurations and compatible libraries.
//
// Create a shortcut to this file on your desktop to permit quick access for editting.
// Create a shortcut to this file on your desktop to permit quick access for editing.
// Re-compile and upload after making and saving any changes to this file.
// Customised User_Setup files are stored in the "User_Setups" folder.
@ -34,6 +34,8 @@
//#include <User_Setups/Setup11_RPi_touch_ILI9486.h> // Setup file configured for my stock RPi TFT with touch
//#include <User_Setups/Setup12_M5Stack.h> // Setup file for the ESP32 based M5Stack
//#include <User_Setups/Setup99.h>
//#include <User_Setups/SetupX_Template.h> // Setup file template for copying/editting

View File

@ -0,0 +1,195 @@
/*
Sketch to demonstrate using the print class with smooth fonts
Sketch is writtent for a 240 x 320 display
Load the font file into SPIFFS first by using the Arduino IDE
Sketch Data Upload menu option. Font files must be stored in the
sketch data folder (Ctrl+k to view).
https://github.com/esp8266/arduino-esp8266fs-plugin
https://github.com/me-no-dev/arduino-esp32fs-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.
Note: SPIFFS does not accept an underscore _ in filenames!
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 file is stored in SPIFFS
#define FS_NO_GLOBALS
#include <FS.h>
// Graphics and font library
#include <TFT_eSPI.h>
#include <SPI.h>
TFT_eSPI tft = TFT_eSPI(); // Invoke library
// -------------------------------------------------------------------------
// Setup
// -------------------------------------------------------------------------
void setup(void) {
Serial.begin(115200); // Used for messages
tft.init();
tft.setRotation(1);
if (!SPIFFS.begin()) {
Serial.println("SPIFFS initialisation failed!");
while (1) yield(); // Stay here twiddling thumbs waiting
}
Serial.println("\r\nInitialisation done.");
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);
// 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("SPIFFS files found:");
#ifdef ESP32
listDir(SPIFFS, "/", true);
#else
fs::Dir dir = SPIFFS.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);
#endif
Serial.println();
delay(1000);
}
#ifdef ESP32
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
Serial.printf("Listing directory: %s\n", dirname);
fs::File root = fs.open(dirname);
if (!root) {
Serial.println("Failed to open directory");
return;
}
if (!root.isDirectory()) {
Serial.println("Not a directory");
return;
}
fs::File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.print("DIR : ");
String fileName = file.name();
Serial.print(fileName);
if (levels) {
listDir(fs, file.name(), levels - 1);
}
} else {
String fileName = file.name();
Serial.print(" " + fileName);
int spaces = 32 - fileName.length(); // Tabulate nicely
if (spaces < 1) spaces = 1;
while (spaces--) Serial.print(" ");
String fileSize = (String) file.size();
spaces = 8 - fileSize.length(); // Tabulate nicely
if (spaces < 1) spaces = 1;
while (spaces--) Serial.print(" ");
Serial.println(fileSize + " bytes");
}
file = root.openNextFile();
}
}
#endif
// -------------------------------------------------------------------------

View File

@ -0,0 +1,83 @@
/*====================================================================================
This sketch supports for the ESP6266 and ESP32 SPIFFS filing system
Created by Bodmer 15th Jan 2017
==================================================================================*/
//====================================================================================
// Print a SPIFFS directory list (root directory)
//====================================================================================
void listFiles(void) {
Serial.println();
Serial.println("SPIFFS files found:");
#ifdef ESP32
listDir(SPIFFS, "/", true);
#else
fs::Dir dir = SPIFFS.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);
#endif
Serial.println();
delay(1000);
}
//====================================================================================
#ifdef ESP32
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
Serial.printf("Listing directory: %s\n", dirname);
fs::File root = fs.open(dirname);
if (!root) {
Serial.println("Failed to open directory");
return;
}
if (!root.isDirectory()) {
Serial.println("Not a directory");
return;
}
fs::File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.print("DIR : ");
String fileName = file.name();
Serial.print(fileName);
if (levels) {
listDir(fs, file.name(), levels - 1);
}
} else {
String fileName = file.name();
Serial.print(" " + fileName);
int spaces = 32 - fileName.length(); // Tabulate nicely
if (spaces < 1) spaces = 1;
while (spaces--) Serial.print(" ");
String fileSize = (String) file.size();
spaces = 8 - fileSize.length(); // Tabulate nicely
if (spaces < 1) spaces = 1;
while (spaces--) Serial.print(" ");
Serial.println(fileSize + " bytes");
}
file = root.openNextFile();
}
}
#endif

View File

@ -0,0 +1,148 @@
// 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!
*/
//====================================================================================
// Libraries
//====================================================================================
// Call up the SPIFFS FLASH filing system this is part of the ESP Core
#include <TFT_eSPI.h> // 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 (!SPIFFS.begin()) {
Serial.println("SPIFFS initialisation failed!");
while (1) yield(); // Stay here twiddling thumbs waiting
}
Serial.println("\r\nInitialisation done.");
listFiles(); // Lists the files so you can see what is in the SPIFFS
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 SPIFFS
tft.loadFont("Final-Frontier-28");
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");
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);
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Ω");
// Remove font parameters from memory to recover RAM
tft.unloadFont();
delay(2000);
//----------------------------------------------------------------------------
// Latin and Hiragana font mix
String test3 = "こんにちは";
tft.loadFont("Latin-Hiragana-24");
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.setTextColor(TFT_GREEN, bg);
tft.setCursor(0,0);
tft.println("Konnichiwa");
tft.println(test3);
tft.println();
tft.println("Sayonara");
tft.println("さようなら"); // Sayonara
// Remove font parameters from memory to recover RAM
tft.unloadFont();
delay(2000);
//
//----------------------------------------------------------------------------
}
//====================================================================================

View File

@ -0,0 +1,194 @@
/*
This tests the alpha blending function that is used with the antialiased
fonts:
Alpha = 0 = 100% background, alpha = 255 = 100% foreground colour
blendedColor = tft.alphaBlend(alpha, fg_color, bg_color);
The alphaBlend() function operates on 16 bit colours only
A test is included where the colours are mapped to 8 bits after blending
Information on alpha blending is here
https://en.wikipedia.org/wiki/Alpha_compositing
Example for library:
https://github.com/Bodmer/TFT_eSPI
The sketch has been tested on a 320x240 ILI9341 based TFT, it
could be adapted for other screen sizes.
Created by Bodmer 10/2/18
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
#########################################################################
*/
#include <TFT_eSPI.h> // Include the graphics library
TFT_eSPI tft = TFT_eSPI(); // Create object "tft"
// -------------------------------------------------------------------------
// Setup
// -------------------------------------------------------------------------
void setup(void) {
tft.init();
tft.setRotation(0);
tft.fillScreen(TFT_DARKGREY);
}
// -------------------------------------------------------------------------
// Main loop
// -------------------------------------------------------------------------
void loop()
{
// 16 bit colours (5 bits red, 6 bits green, 5 bits blue)
// Blend from white to full spectrum
for (int a = 0; a < 256; a+=2) // Alpha 0 = 100% background, alpha 255 = 100% foreground
{
for (int c = 0; c < 192; c++) tft.drawPixel(c, a/2, tft.alphaBlend(a, rainbow(c), TFT_WHITE));
}
// Blend from full spectrum to black
for (int a = 255; a > 2; a-=2)
{
for (int c = 0; c < 192; c++) tft.drawPixel(c, 128 + (255-a)/2, tft.alphaBlend(a, rainbow(c), TFT_BLACK));
}
// Blend from white to black (32 grey levels)
for (uint16_t a = 0; a < 255; a++) // Alpha 0 = 100% background, alpha 255 = 100% foreground
{
tft.drawFastHLine(192, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_WHITE));
tft.drawFastHLine(204, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_RED));
tft.drawFastHLine(216, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_GREEN));
tft.drawFastHLine(228, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_BLUE));
}
delay(4000);
// Blend from white to colour (32 grey levels)
for (uint16_t a = 0; a < 255; a++) // Alpha 0 = 100% background, alpha 255 = 100% foreground
{
//tft.drawFastHLine(192, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_WHITE));
tft.drawFastHLine(204, a, 12, tft.alphaBlend(a, TFT_RED, TFT_WHITE));
tft.drawFastHLine(216, a, 12, tft.alphaBlend(a, TFT_GREEN, TFT_WHITE));
tft.drawFastHLine(228, a, 12, tft.alphaBlend(a, TFT_BLUE, TFT_WHITE));
}
delay(4000);
//*
// Decrease to 8 bit colour (3 bits red, 3 bits green, 2 bits blue)
// Blend from white to full spectrum
for (int a = 0; a < 256; a+=2) // Alpha 0 = 100% background, alpha 255 = 100% foreground
{
// Convert blended 16 bit colour to 8 bits to reduce colour resolution, then map back to 16 bits for displaying
for (int c = 0; c < 192; c++) tft.drawPixel(c, a/2, tft.color8to16(tft.color16to8(tft.alphaBlend(a, rainbow(c), 0xFFFF))));
}
// Blend from full spectrum to black
for (int a = 255; a > 2; a-=2)
{
// Convert blended 16 bit colour to 8 bits to reduce colour resolution, then map back to 16 bits for displaying
for (int c = 0; c < 192; c++) tft.drawPixel(c, 128 + (255-a)/2, tft.color8to16(tft.color16to8(tft.alphaBlend(a, rainbow(c), 0))));
}
// Blend from white to black (4 grey levels - it will draw 4 more with a blue tinge due to lower blue bit count)
// Blend from black to a primary colour
for (uint16_t a = 0; a < 255; a++) // Alpha 0 = 100% background, alpha 255 = 100% foreground
{
tft.drawFastHLine(192, a, 12, tft.color8to16(tft.color16to8(tft.alphaBlend(a, TFT_BLACK, TFT_WHITE))));
tft.drawFastHLine(204, a, 12, tft.color8to16(tft.color16to8(tft.alphaBlend(a, TFT_BLACK, TFT_RED))));
tft.drawFastHLine(216, a, 12, tft.color8to16(tft.color16to8(tft.alphaBlend(a, TFT_BLACK, TFT_GREEN))));
tft.drawFastHLine(228, a, 12, tft.color8to16(tft.color16to8(tft.alphaBlend(a, TFT_BLACK, TFT_BLUE))));
}
delay(4000);
//*/
/*
// 16 bit colours (5 bits red, 6 bits green, 5 bits blue)
for (int a = 0; a < 256; a+=2) // Alpha 0 = 100% background, alpha 255 = 100% foreground
{
for (int c = 0; c < 192; c++) tft.drawPixel(c, a/2, tft.alphaBlend(a, rainbow(c), TFT_CYAN));
}
// Blend from full spectrum to cyan
for (int a = 255; a > 2; a-=2)
{
for (int c = 0; c < 192; c++) tft.drawPixel(c, 128 + (255-a)/2, tft.alphaBlend(a, rainbow(c), TFT_YELLOW));
}
//*/
/*
// Blend other colour transitions for test purposes
for (uint16_t a = 0; a < 255; a++) // Alpha 0 = 100% background, alpha 255 = 100% foreground
{
tft.drawFastHLine(192, a, 12, tft.alphaBlend(a, TFT_WHITE, TFT_WHITE)); // Should show as solid white
tft.drawFastHLine(204, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_BLACK)); // Should show as solid black
tft.drawFastHLine(216, a, 12, tft.alphaBlend(a, TFT_YELLOW, TFT_CYAN)); // Brightness should be fairly even
tft.drawFastHLine(228, a, 12, tft.alphaBlend(a, TFT_CYAN, TFT_MAGENTA));// Brightness should be fairly even
}
delay(4000);
//*/
}
// #########################################################################
// Return a 16 bit rainbow colour
// #########################################################################
unsigned int rainbow(byte value)
{
// If 'value' is in the range 0-159 it is converted to a spectrum colour
// from 0 = red through to 127 = blue to 159 = violet
// Extending the range to 0-191 adds a further violet to red band
value = value%192;
byte red = 0; // Red is the top 5 bits of a 16 bit colour value
byte green = 0; // Green is the middle 6 bits, but only top 5 bits used here
byte blue = 0; // Blue is the bottom 5 bits
byte sector = value >> 5;
byte amplit = value & 0x1F;
switch (sector)
{
case 0:
red = 0x1F;
green = amplit; // Green ramps up
blue = 0;
break;
case 1:
red = 0x1F - amplit; // Red ramps down
green = 0x1F;
blue = 0;
break;
case 2:
red = 0;
green = 0x1F;
blue = amplit; // Blue ramps up
break;
case 3:
red = 0;
green = 0x1F - amplit; // Green ramps down
blue = 0x1F;
break;
case 4:
red = amplit; // Red ramps up
green = 0;
blue = 0x1F;
break;
case 5:
red = 0x1F;
green = 0;
blue = 0x1F - amplit; // Blue ramps down
break;
}
return red << 11 | green << 6 | blue;
}

View File

@ -56,7 +56,8 @@ getRotation KEYWORD2
getTextDatum KEYWORD2
fontsLoaded KEYWORD2
color565 KEYWORD2
color332 KEYWORD2
color16to8 KEYWORD2
color8to16 KEYWORD2
drawNumber KEYWORD2
drawFloat KEYWORD2
drawString KEYWORD2
@ -98,3 +99,8 @@ pushBitmap KEYWORD2
pushSprite KEYWORD2
setScrollRect KEYWORD2
scroll KEYWORD2
alphaBlend KEYWORD2
showFont KEYWORD2
loadFont KEYWORD2
unloadFont KEYWORD2

View File

@ -1,6 +1,6 @@
{
"name": "TFT_eSPI",
"version": "0.18.17",
"version": "0.18.20",
"keywords": "tft, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486",
"description": "A TFT SPI graphics library for ESP8266 and ESP32",
"repository":

View File

@ -1,5 +1,5 @@
name=TFT_eSPI
version=0.18.17
version=0.18.20
author=Bodmer
maintainer=Bodmer
sentence=A fast TFT library for ESP8266 processors and the Arduino IDE

View File

@ -28,7 +28,7 @@ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvStartvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
Selected functions from the Adafruit_GFX library (as it was in 2015) have
been imported into the TFT_eSPI.cpp file and modified to improve
perfromance, add features and make them compatible with the ESP8266 and
performance, add features and make them compatible with the ESP8266 and
ESP32.
The fonts from the Adafruit_GFX and Button functions were added later.
@ -68,7 +68,7 @@ POSSIBILITY OF SUCH DAMAGE.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^End^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Due to the evolution of the TFT_eSPI library the orignal code may no longer
Due to the evolution of the TFT_eSPI library the original code may no longer
be recognisable, however in most cases the function names can be used as a
reference point since the aim is to retain a level of compatibility with
the popular Adafruit_GFX graphics functions.