# TFT Display with Custom Fonts

**URL:** <https://community.particle.io/t/tft-display-with-custom-fonts/54423>\
**Category:** Firmware\
**Tags:** argon\
**Created:** [January 29, 2020, 4:02pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423 "2020-01-29T16:02:55Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![GeerGuy](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/geerguy/32/13023_2.png) [@GeerGuy](https://community.particle.io/u/GeerGuy)\
**Post date:** [January 29, 2020, 4:02pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/1 "2020-01-29T16:02:55Z")

</div>

Using these displays with an Argon:  
ST7735 128x160 TFT SPI  
ILI9341 240x320 TFT SPI

I would like to use larger custom fonts, but the refresh rate is very low. When using the built in fonts the update is fast with no noticeable flicker. With the custom fonts I only fill the area that needs to be set back to the background with a rectangle.

Currently using these libraries:  
Adafruit\_GFX\_RK  
Adafruit\_ST7735\_RK or Adafruit\_ILI9341\_RK

I have seen Arduinos use these same displays with much better refresh rates. There appears to be more optimized libraries available for them with custom fonts, can these be ported to Particle or should I be using different libraries or techniques?

SPI Clock Rate:  
I’m using hardware SPI with the default clock rate of 8MHz, which was measured on the clock pin. I would like to increase this, but I can’t figure out how to change it. Setting “\_freq” to 15000000 has no effect. Can this be done?

Thanks

---

<div class="post-metadata">

**Author:** ![armor](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/armor/32/18398_2.png) [@armor](https://community.particle.io/u/armor)\
**Post date:** [January 31, 2020, 11:47am UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/2 "2020-01-31T11:47:05Z")

</div>

I have been using both these displays for a while now and recently tried a 3.5" TFT (Adafruit with touch display HX8357) driven by an Argon. The speed issue is with the Argon SPI bus - the standard library uses 8MHz which is very slow (I think because of limit on SPI1), the speed can be increased to 32MHz on SPI which is better but not as good as the Photon 60MHz! The other factor is to ensure the SPI is using DMA as this speeds up writing larger areas to the screen memory. You need to look at Adafruit\_SPITFT.cpp /.h to see what has been set and modify it.

---

<div class="post-metadata">

**Author:** ![GeerGuy](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/geerguy/32/13023_2.png) [@GeerGuy](https://community.particle.io/u/GeerGuy)\
**Post date:** [January 31, 2020, 4:18pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/3 "2020-01-31T16:18:48Z")

</div>

I will look into increasing the SPI CLK.

Re-writing the SPI routines to use DMA is beyond me right now.

There is a older version of this library available in the IDE, but I can’t get it to work at all, it is supposed to be very fast for other devices.

> **[Bodmer/TFT\_eSPI](https://github.com/Bodmer/TFT_eSPI)**
>
> Arduino and PlatformIO IDE compatible TFT library optimised for the STM32, ESP8266 and ESP32 that supports different driver chips - Bodmer/TFT\_eSPI

---

<div class="post-metadata">

**Author:** ![jaafar](https://avatars.discourse-cdn.com/v4/letter/j/aca169/32.png) [@jaafar](https://community.particle.io/u/jaafar)\
**Post date:** [January 31, 2020, 5:04pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/4 "2020-01-31T17:04:54Z")

</div>

The limitation with refresh speed is not really dependent on SPI bus speed, at least that’s what I realized when I changed the SPI clock from 8MHz to 24MHz on Argon and Boron. The time is takes to update the whole 320\*240 screen is pretty much the same ~1.5 sec.  
I think it’s due to the way RTOS works, with task scheduling and other background operations. (I tested with [single threaded block](https://docs.particle.io/reference/device-os/firmware/boron/#single_threaded_block-) but didn’t change a thing in my case)

The trick I found to somehow get reasonable refresh times is by using the `AdafruitGFX` canvas objects, specifically `GFXcanvas16` object. I define the size of the canvas to be about the size of the area of the screen I’d like to refresh, specify both text color and background color and then send the buffer to the display internal frame buffer. See code snippet below:

```auto
canvas50by50 = new GFXcanvas16(50, 50);

canvas50by50->drawCircle(24, 24, 24, WHITE); // g-ball chart circle

canvas50by50->drawFastHLine(0, 24, 50, WHITE); // target H line

canvas50by50->drawFastVLine(24, 0, 50, WHITE); // target V line

// reset gball location to center

int16_t gball_center_x = 24;

int16_t gball_center_y = 24;

// longitudinal accel along Z-axis

// longitudinal acceleration displacement scaled for: 30 pixels/0.5G (auto-compensated for tilt)

gball_center_y = gball_center_y + int(accel[2]*60.0); //accelerating accel_z < 0 --> y down --> ball up

// lateral acceleration displacement scaled for: 25 pixels/0.5G along X-axis (not affected by tilt in this use case)

if (accel[0] >= 0.04 || accel[0] < -0.04 ) {

gball_center_x = gball_center_x + int(accel[0]*50.0); //turn left --> accel > 0 --> x up --> ball right

}

canvas50by50->fillCircle(gball_center_x, gball_center_y, 4, FLUO_GREEN);

// now transfer the canvas' buffer using a faster function(and hopefully DMA in the near future)

display.drawRGBBitmap(70, 14, canvas50by50->getBuffer(), 50, 50); **// ~ 64 ms**

delete canvas50by50;

```

Now `GFXcanvas16` object is a memory hoarder, taking 2 x width x length bytes, but it’s the faster to transfer compared to `GFXcanvas1` and `GFXcanvas8`, and with dynamic allocation, you can delete once no longer need as shown in the code example above.  
Hopefully @rickkas7 will spoil us with DMA transfers for AdafruitGFX on 3rd gen devices in the future.

---

<div class="post-metadata">

**Author:** ![GeerGuy](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/geerguy/32/13023_2.png) [@GeerGuy](https://community.particle.io/u/GeerGuy)\
**Post date:** [January 31, 2020, 6:17pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/5 "2020-01-31T18:17:30Z")

</div>

Can the canvas’ be used for custom fonts or only graphics?

That would be great, it looks like GFX libraries for most other devices have been greatly optimized over the years.

---

<div class="post-metadata">

**Author:** ![jaafar](https://avatars.discourse-cdn.com/v4/letter/j/aca169/32.png) [@jaafar](https://community.particle.io/u/jaafar)\
**Post date:** [January 31, 2020, 7:01pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/6 "2020-01-31T19:01:08Z")

</div>

You can use `GFXcanvas` the same way you use `AdafruitGFX` object, including any special font that comes with the library. Here’s another example that shows how it works:

```auto
GFXcanvas16 *rh_canvas = new GFXcanvas16(100, 30);
rh_canvas->setTextColor(ILI9341_CYAN, ILI9341_BLACK);
rh_canvas->setFont(&amp;FreeSans12pt7b);
rh_canvas->setCursor(0, 24);
rh_canvas->printf("%.0f", env_data.rel_hum);
rh_canvas->setFont(&amp;FreeSans9pt7b);
rh_canvas->print(" %RH");
tft.drawRGBBitmap(20, 160, rh_canvas->getBuffer(), 100, 30);
delete rh_canvas;

```

One thing to keep in mind is that the coordinates you set with `setCursor()` are relative to the canvas, and not to the whole display.

---

<div class="post-metadata">

**Author:** ![armor](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/armor/32/18398_2.png) [@armor](https://community.particle.io/u/armor)\
**Post date:** [February 2, 2020, 1:17pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/7 "2020-02-02T13:17:56Z")

</div>

DMA is marked as experimental in the Adafruit\_SPITFT.cpp code. I wasn’t suggesting you implement DMA!

I have seen some speed increase with 32MHz on the Argon but agree with @jaafar that it isn’t x4 faster and with the 480x320 resolution screen it is very slow. Maybe the whole SPI bus implementation is slower than the Photon? Another Gen3 issue?

---

<div class="post-metadata">

**Author:** ![GeerGuy](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/geerguy/32/13023_2.png) [@GeerGuy](https://community.particle.io/u/GeerGuy)\
**Post date:** [February 2, 2020, 5:17pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/8 "2020-02-02T17:17:30Z")

</div>

Using `GFXcanvas16` helps and makes it usable for my application.

I still can’t get the SPI clk to go over 8MHz though. Changing the setting in `Adafruit_ST77xx.cpp` does nothing.

```cpp
#define SPI_DEFAULT_FREQ 24000000

```

I also tried changing `_freq`, `freq` and using `initSPI(24000000)`

What am I missing?

---

<div class="post-metadata">

**Author:** ![armor](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/armor/32/18398_2.png) [@armor](https://community.particle.io/u/armor)\
**Post date:** [February 2, 2020, 5:34pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/9 "2020-02-02T17:34:07Z")

</div>

Are you using Workbench or web IDE? If workbench then you can do a thorough search of all the places it is declared and set. I think the issue may be that the default frequency is overwritten and hence it is forced back to be 8MHz. There are a lot of conditional compile statements.

GFXcanvas16 is a neat solution for quick updates but in any case with these TFTs you are writing to the screen memory.

---

<div class="post-metadata">

**Author:** ![GeerGuy](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/geerguy/32/13023_2.png) [@GeerGuy](https://community.particle.io/u/GeerGuy)\
**Post date:** [February 2, 2020, 5:41pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/10 "2020-02-02T17:41:22Z")

</div>

Workbench

I have other changes in the library, had to flip the red and blue 565 colors, and that works.

I changed every `_freq`, `freq`, `initSPI(freq)` and hard coded the change as well, but it always outputs 8MHz. Can’t find where it is forced back to 8MHz.

---

<div class="post-metadata">

**Author:** ![armor](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/armor/32/18398_2.png) [@armor](https://community.particle.io/u/armor)\
**Post date:** [February 3, 2020, 9:36am UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/11 "2020-02-03T09:36:55Z")

</div>

It could be that the SPI speed setting function isn’t working?

---

<div class="post-metadata">

**Author:** ![aklein24](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/aklein24/32/23813_2.png) [@aklein24](https://community.particle.io/u/aklein24)\
**Post date:** [March 15, 2020, 5:47pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/12 "2020-03-15T17:47:24Z")

</div>

Funny that you’re running into the SPI setting issue as well, I cannot for the life of me get the SPI clock to go faster than 8MHz either (and I’m working with the TFT). I changed the values in the library up AND down, and the clock speed stayed the same.

---

<div class="post-metadata">

**Author:** ![armor](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/armor/32/18398_2.png) [@armor](https://community.particle.io/u/armor)\
**Post date:** [March 15, 2020, 5:57pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/13 "2020-03-15T17:57:34Z")

</div>

I am pretty certain that the SPI speed setting function is working because I tried changing the speed with the touch screen controller and it does work any faster than 1MHz - thus with a Adafruit 3.5" screen with touch the whole SPI bus has to be run at 1MHz hence why it is so slow. I need to get out the screen and try it without the touch display controller.

---

<div class="post-metadata">

**Author:** ![aklein24](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/aklein24/32/23813_2.png) [@aklein24](https://community.particle.io/u/aklein24)\
**Post date:** [March 15, 2020, 6:18pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/14 "2020-03-15T18:18:10Z")

</div>

hm that’s a clue. I’m not using it with the touch controller right now and seeing the same behavior. Maybe the clock speed is changing but the effect is negligible? I didn’t see any way to read the actual SPI clock speed, how are you doing that?

---

<div class="post-metadata">

**Author:** ![armor](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/armor/32/18398_2.png) [@armor](https://community.particle.io/u/armor)\
**Post date:** [March 16, 2020, 7:09pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/15 "2020-03-16T19:09:17Z")

</div>

The problem is with SPITFT.h/.cpp this implementation of a multi-device SPI interface by Adafruit as used by Adafruit\_GFX. I believe that every SPI begin transmission has the SPISettings in it and there is no DMA which is definitely not what was in the previous iteration of Adafruit\_mfGFX. This must however be something to do with the Particle implementation of SPI for the Gen3 devices because I have moved my Gen2 devices to use the Adafruit\_GFX library and I am not seeing this throttling issue. @rickkas7 could you help give us the benefit of your knowledge here? Thanks

---

<div class="post-metadata">

**Author:** ![rickkas7](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/rickkas7/32/8681_2.png) [@rickkas7](https://community.particle.io/u/rickkas7)\
**Post date:** [March 16, 2020, 7:12pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/16 "2020-03-16T19:12:30Z")

</div>

Yes, changing the manipulation of the CS and DC lines from digitalWrite to pinSetFast/pinResetFast should dramatically improve performance. Switching to SPI DMA would also help.

However, using the offscreen bitmap is a really good way to improve performance in general. The problem is that each pixel write is a separate SPI transaction when directly writing to the display.

---

<div class="post-metadata">

**Author:** ![armor](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/armor/32/18398_2.png) [@armor](https://community.particle.io/u/armor)\
**Post date:** [March 16, 2020, 7:17pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/17 "2020-03-16T19:17:53Z")

</div>

Super fast response! I can change the SPITFTMacros.h file and try the pinSetFast/pinResetFast.  
Do you happen to know if the SPI DMA implementation works - it is surrounded by warnings of being highly experimental!

---

<div class="post-metadata">

**Author:** ![rickkas7](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/rickkas7/32/8681_2.png) [@rickkas7](https://community.particle.io/u/rickkas7)\
**Post date:** [March 16, 2020, 7:19pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/18 "2020-03-16T19:19:44Z")

</div>

I haven’t tried the SPI DMA. I didn’t try the pinSetFast/pinResetFast either, but I know someone who did and it made a big difference on Gen 3.

---

<div class="post-metadata">

**Author:** ![armor](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/armor/32/18398_2.png) [@armor](https://community.particle.io/u/armor)\
**Post date:** [March 17, 2020, 9:09pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/19 "2020-03-17T21:09:19Z")

</div>

I have gone back to my test sketch to use pinSetFast and pinResetFast and I am now finding it impossible to get the following to build. There are all sorts of ARDUINO not defined issues, then SPISettings then…

The includes in my sketch look like this

```auto
#include <Adafruit_HX8357_RK.h>
#include <Adafruit_STMPE610_RK.h>
#include <SdFat.h>
#include "Adafruit_ImageReader.h"
#include "FreeMono18pt7b.h"
#include "FreeMono9pt7b.h"

```

There seem to have been some changes in these libraries, so I deleted and reinstalled:

```auto
dependencies.Adafruit_HX8357_RK=1.0.8
dependencies.Adafruit_STMPE610_RK=1.0.1
dependencies.SdFat=1.0.16
dependencies.Adafruit_ImageReader=1.0.9
dependencies.Adafruit_GFX_RK=1.5.6

```

The errors suggest there is some mismatch -

```auto
In file included from /Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_GFX_RK/src/Adafruit_SPITFT.h:26:0,
                 from /Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_HX8357_RK/src/Adafruit_HX8357.h:36,
                 from /Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_HX8357_RK/src/Adafruit_HX8357_RK.h:4,
                 from /Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/src/zioxi_locker_ui.ino:8:
/Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_GFX_RK/src/Adafruit_GFX.h:6:0: warning: "ARDUINO" redefined
  #define ARDUINO 157
 ^
In file included from ./inc/SPI.h:1:0,
                 from /Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_GFX_RK/src/Adafruit_SPITFT.h:25,
                 from /Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_HX8357_RK/src/Adafruit_HX8357.h:36,
                 from /Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_HX8357_RK/src/Adafruit_HX8357_RK.h:4,
                 from /Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/src/zioxi_locker_ui.ino:8:
./inc/Arduino.h:16:0: note: this is the location of the previous definition
 #define ARDUINO 10800
 ^
/Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/src/zioxi_locker_ui.ino:73:62: error: use of deleted function 'Adafruit_HX8357::Adafruit_HX8357(const Adafruit_HX8357&)'
 Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);
                                                              ^
In file included from /Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_HX8357_RK/src/Adafruit_HX8357_RK.h:4:0,
                 from /Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/src/zioxi_locker_ui.ino:8:
/Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_HX8357_RK/src/Adafruit_HX8357.h:127:7: note: 'Adafruit_HX8357::Adafruit_HX8357(const Adafruit_HX8357&)' is implicitly deleted because the default definition would be ill-formed:
 class Adafruit_HX8357 : public Adafruit_SPITFT {
       ^
/Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_HX8357_RK/src/Adafruit_HX8357.h:127:7: error: use of deleted function 'Adafruit_SPITFT::Adafruit_SPITFT(const Adafruit_SPITFT&)'
In file included from /Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_HX8357_RK/src/Adafruit_HX8357.h:36:0,
                 from /Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_HX8357_RK/src/Adafruit_HX8357_RK.h:4,
                 from /Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/src/zioxi_locker_ui.ino:8:
/Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_GFX_RK/src/Adafruit_SPITFT.h:118:7: note: 'Adafruit_SPITFT::Adafruit_SPITFT(const Adafruit_SPITFT&)' is implicitly deleted because the default definition would be ill-formed:
 class Adafruit_SPITFT : public Adafruit_GFX {
       ^
/Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/lib/Adafruit_GFX_RK/src/Adafruit_SPITFT.h:404:9: error: union member 'Adafruit_SPITFT::<anonymous union>::hwspi' with non-trivial 'constexpr Adafruit_SPITFT::<anonymous union>::<anonymous struct>::<constructor>(const Adafruit_SPITFT::<anonymous union>::<anonymous struct>&)'
       } hwspi; ///< Hardware SPI values
         ^
/Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/src/zioxi_locker_ui.ino: In function 'void setup()':
/Users/wjsteen/Documents/Intelligent_Furniture_Project/VSC_Projects/zioxi_locker_ui/src/zioxi_locker_ui.ino:85:19: warning: unused variable 'stat' [-Wunused-variable]
   ImageReturnCode stat; // Status from image-reading functions

```

ARDUINO issues I can fix but the use of deleted function I really can’t see the problem.

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [March 17, 2020, 9:31pm UTC](https://community.particle.io/t/tft-display-with-custom-fonts/54423/20 "2020-03-17T21:31:48Z")

</div>

> [@armor](#):
>
> Adafruit\_HX8357 tft = Adafruit\_HX8357(TFT\_CS, TFT\_DC, TFT\_RST);

Try rewriting it this way

```cpp
Adafruit_HX8357 tft(TFT_CS, TFT_DC, TFT_RST);

```

[Next page](https://community.particle.io/t/tft-display-with-custom-fonts/54423.md?page=2)
