TTGO T-Display setup and speed problem


I’m following these instructions to set up ulisp on a TTGO T-Display.

I have got the latest esp32 boards installed (v2.0.9) and have selected the ESP32 Dev Module as the board.

When I try and compile ulisp (ESP Release 4.4c) I get the following error:

ulisp-esp/ulisp-esp.ino:5471:29: error: 'LED_BUILTIN' was not declared in this scope
   { string226, (fn_ptr_type)LED_BUILTIN, 0, NULL },
ulisp-esp/ulisp-esp.ino:5471:29: note: suggested alternative: 'BUILTINS'
   { string226, (fn_ptr_type)LED_BUILTIN, 0, NULL },

exit status 1

Compilation error: 'LED_BUILTIN' was not declared in this scope

I tried to fix this using the suggestion in this comment, adding near the top of the file:

#define LED_BUILTIN 13

The program then compiles and I can deploy it to the device. However, when I run something simple like a fill-screen command, it takes a second or so to actually fill the screen with the colour, it slowly writes to the colour to the screen a row at a time.

From youtube videos that I’ve seen (not using ulisp) people are able to draw to the screen very quickly, playing games etc on it. This makes me think that I’m doing something wrong or don’t have it set up correctly. Are these issues related at all?


Yes, that’s the correct fix for LED_BUILTIN. In a future version I’ll probably make it automatic.

Running graphics written in Lisp will be slower than the equivalent C, but the uLisp fill-screen command just calls the C function, so I would expect it to be the same speed.


Thanks @johnsondavies.

This is what I’m seeing with the program:

(defun main ()
  (fill-screen orange)
  (fill-screen red)
  (fill-screen orange)
  (fill-screen red)
  (fill-screen orange)
  (fill-screen red)
  (fill-screen orange)
  (fill-screen red)) 


Maybe I’ve misunderstood what fill-screen does? I’ll check out the C code. I’ll also try doing some things directly in C and see if I can write to the screen more quickly


In this video that I found on Youtube the C function fillScreen seems to fill the screen instantly on the same board.

I wonder where the difference is coming from?


Sorry all the messages, just logging things here as I find them out.
I uploaded the sketch from here and my display behaves in the same way as shown in this video.

Maybe it’s the behaviour of the Adafruit_GFX library that the fillScreen does a “wipe” fill rather then filling instantly.


So do you think the difference is explained by the TFT_eSPI library vs. the Adafruit GFX library?


It appears to be. I’ve got the TFT_eSPI library running on a board now and a fillScreen is instant with no wipe. I what I haven’t figured out yet is whether the “wipe” behaviour of the Adafruit GFX fillScreen function is intentional or not.


More likely that the TFT_eSPI library is faster because it’s using a faster SPI interface. It would be interesting to compare another command, such as:

(fill-circle 66 66 66)

or the C equivalent, using both libraries.


@jc-lisp was also wondering about that yesterday, saw your thread and figured it out just now:

The default initializer is not using hardware SPI (I checked by adding a crash in the if-using-software-spi branch in the adafruit driver).

To fix it, you do this:

  • Remap the HSPI pins (MOSI & MISO are swapped on that board for some reason)
  • Pass the remapped SPI instance to the Adafruit TFT lib
  • Init the remapped instance in initgfx()

/* — snip — */

#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#if defined(ARDUINO_ESP32_DEV)

// patch starts here
#define HSPI_MISO 26 // random pin, don’t care
#define HSPI_MOSI 19 // -> SDA on schematic
#define HSPI_SCLK 18 // -> SCL on schematic
#define HSPI_CS 5
static const int spiClk = 320000000;
SPIClass * hspi = new SPIClass(HSPI);

Adafruit_ST7789 tft = Adafruit_ST7789(hspi, 5, 16, 23);
// patch ends here

#define TFT_BACKLITE 4
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, MOSI, SCK, TFT_RST);

/* — snip — */

void initgfx () {
#if defined(gfxsupport)

// patch starts here
// patch ends here

tft.init(135, 240);

/* — snip — */

Here are my sources:

Enjoy your 1000% speedup :)


Thanks for the information. How does that compare with the latest T-Deck firmware here:

The uLisp T-deck firmware on GitHub:

With a default 240MHz clock this clears the screen with:

21827> (time (write-byte 12))
Time: 36 ms


thanks so much! I never got to the bottom of why it was so slow. I look forward to trying this out!


There is now a third release of the T-Deck firmware, with many improvements.

See: Making a LilyGO T-Deck uLisp Machine


Here’s what I get:

9215> (time (fill-screen))
Time: 24 ms

edit: Just wanna say that the ulisp on the T-deck looks pretty rad, I might get one myself!