B4R Question TTGO32 display drawing?


Licensed User
Longtime User

A while ago I bought a TTGO32(?) which is an esp32 variant with LCD and other thing default on the board.
As it required an USB-C cable (which I didn't have back then) to connect to it or to power it it went out of sight untill I bumped onto such cable today at work.

I can compile the basic program to it so that not the problem.

I didn't figure out yet how I can put text to the display.

I did some searching and found an Adafruit Gfx lib from Erel. I don't know if this will work with this board or not as it refuses to compile.

It always gives these errors in @Cableguy 's lcd example ...

In file included from C:\Users\xxx\DOWNLO~1\lcd-test\Objects\bin\sketch\rAdafruit_ST7735.h:3:0,
from C:\Users\xxx\DOWNLO~1\lcd-test\Objects\bin\sketch\B4RDefines.h:26,
from C:\Users\xxx\DOWNLO~1\lcd-test\Objects\src\src.ino:1:
Adafruit_ST7735.h:29:26: fatal error: Adafruit_GFX.h: No such file or directory

I installed the wrapped lib into the additional libs folder.
I also installed the lib in the arduino application but the error remains.

Any idea? :)


Licensed User
Longtime User
Upvote 0


Active Member
Licensed User
Longtime User
not sure if this is the same board as the Lilygo TTGO T-Display?
I got this working for text and graphics(565RGB and JPeg) following the information in:
and Bodmer on Github (TFT_eSPI.h / SPI.h)
Unfortunately my implementation is a bit piecemeal as I don't know how to 'wrap' the library.

example (cut and paste so may not work exactly as shown!:

Sub JpgImage(FileName As String)
   Dim bb() As Byte = FileName
   RunNative("JPegImage", bb)
End Sub

#If C

#include <TFT_eSPI.h>
#include <SPI.h>
#include <JPEGDecoder.h>  // JPEG decoder library
#include <FS.h>

TFT_eSPI tft = TFT_eSPI(135, 240);
void JPegImage(B4R::Object* o) {

       B4R::Array* b = (B4R::Array*)B4R::Object::toPointer(o);
        char* c = (char*)b->data;
        File jpgFile = SPIFFS.open(c, FILE_READ);
        renderJPEG(0, 0);


//from: https://stackoverflow.com/questions/54182286/how-To-convert-jpeg-byte-stream-into-jpeg-image-And-display-On-1-8-inch-tft-disp
void renderJPEG(int xpos, int ypos) {

  // retrieve infomration about the image
  uint16_t *pImg;
  uint16_t mcu_w = JpegDec.MCUWidth;
  uint16_t mcu_h = JpegDec.MCUHeight;
  uint32_t max_x = JpegDec.width;
  uint32_t max_y = JpegDec.height;

  // Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs)
  // Typically these MCUs are 16x16 pixel blocks
  // Determine the width and height of the right and bottom edge image blocks
  uint32_t min_w = minimum(mcu_w, max_x % mcu_w);
  uint32_t min_h = minimum(mcu_h, max_y % mcu_h);

  // save the current image block size
  uint32_t win_w = mcu_w;
  uint32_t win_h = mcu_h;

  // save the coordinate of the right and bottom edges to assist image cropping
  // to the screen size
  max_x += xpos;
  max_y += ypos;

  // read each MCU block until there are no more
  while ( JpegDec.read()) {

    // save a pointer to the image block
    pImg = JpegDec.pImage;

    // calculate where the image block should be drawn on the screen
    int mcu_x = JpegDec.MCUx * mcu_w + xpos;
    int mcu_y = JpegDec.MCUy * mcu_h + ypos;

    // check if the image block size needs to be changed for the right and bottom edges
    if (mcu_x + mcu_w <= max_x) win_w = mcu_w;
    else win_w = min_w;
    if (mcu_y + mcu_h <= max_y) win_h = mcu_h;
    else win_h = min_h;

    // calculate how many pixels must be drawn
    uint32_t mcu_pixels = win_w * win_h;

    // draw image block if it will fit on the screen
    if ( ( mcu_x + win_w) <= tft.width() && ( mcu_y + win_h) <= tft.height()) {

    //  Write all MCU pixels to the TFT window

      for (int jj=mcu_y;jj<mcu_y + win_h;jj++)
        for (int ii=mcu_x;ii<mcu_x + win_w ;ii++)
            tft.drawPixel(ii,jj,*pImg++ );
             //Serial.print  ("Pixel    : "); Serial.print(ii); Serial.print("   "); Serial.print(jj); Serial.print("   "); Serial.println(*pImg++);

    // stop drawing blocks if the bottom of the screen has been reached
    // the abort function will close the file
    else if ( ( mcu_y + win_h) >= tft.height()) JpegDec.abort();


#end if
Last edited:
Upvote 0


Licensed User
Longtime User
indeed it is a TTGO T-Display.

and I managed to get it working aswell but as you wrote a wrapped lib would be usefull as the library has a lot of functions
( (fill)rect, (fill)circle, (fill)elipse, (fill)triangle, lines etc) but I don't know how to pass the parameters from B4R to the inline C routines.

this is the library that I've put in my %userprofile%\documents\arduino\libraries


Edit: {

I used this but it seems to be the same or based on the Bodmer one but only has the parts needed for the TTGO T-Display and ports set correctly in the user_setup


here's the basic hello, world and the voltage example for those who are struggling to get this working aswell ...

Sub Process_Globals
    Public Serial1 As Serial
End Sub

Private Sub AppStart

    RunNative("tftInit", Null)

    Do While True
    RunNative("tftShowVoltage", Null)

End Sub

#if c

#include "TFT_eSPI.h"

//#define ADC_EN              14  //ADC_EN is the ADC detection enable port
#define ADC_PIN             34
//#define BUTTON_1            35
//#define BUTTON_2            0

TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library

void tftInit(B4R::Object* unused)
//    pinMode(ADC_EN, OUTPUT);
//    digitalWrite(ADC_EN, HIGH);

    tft.setTextDatum(MC_DATUM);    //centered string
    tft.drawString("Hello, world.", tft.width() / 2, tft.height() / 4);

void tftShowVoltage(B4R::Object* unused)
    int vref = 1100;
    uint16_t v = analogRead(ADC_PIN);
    float battery_voltage = ((float)v / 4095.0) * 2.0 * 3.3 * (vref / 1000.0);
    String voltage = "Voltage :" + String(battery_voltage) + "V";

    tft.fillRect(155,135/2-8,62,16,TFT_BLACK);    // only erase the value portion of the bitmap
    tft.print(voltage);                            // this gives less flashing than .drawString

//     tft.fillRect(0,135/2-8,240,14,TFT_BLACK);
//   tft.setTextDatum(MC_DATUM);
//   tft.drawString(voltage,  tft.width() / 2, tft.height() / 2 );
#End If


  • Color_test.zip
    1.3 KB · Views: 128
Last edited:
Upvote 0


Active Member
Licensed User
Longtime User
FYI The Bodmer files are also easy to configure for other displays. I have it working with 240 x 240 and 480 x 240 displays using ESP32s to drive them
Last edited:
Upvote 0