Starting from this post, we will begin to develop the #DIYConsole graphics library.

Adafruit provides ready to use graphics libraries for their products. They are great libraries, but not very suitable for high performance applications such as games, so we will develop our custom library to get the most out of the hardware.

The first step, which we will discuss in this post, is to initialize the display hardware.

Notes on the development environment

For the development of this project I will use Visual Studio Code and PlatformIO, but everything I do can be easily replicated in Arduino IDE or in any other IDE of your choice.

To proceed further, we need to install the ESP32 Arduino Core. I will not give specific instruction regarding creating a project, installing libraries or anything else. If you don’t know how to do something, check the documentation of your IDE.

 

The 3.5″ TFT Touchscreen Featherwing

This display is a 3.5″ TFT with a resolution of 320×480 pixels. It comes with a resistive touchscreen and a built in microSD card socket. For a complete description, check the product page on Adafruit website.

A HX8357-D chip drives the TFT panel (datasheet). This chip supports several interface modes, both parallel and serial. This Featherwing use serial interface to minimize the number of GPIOs connected at the expense of data transfer rate. More specifically, it use the DPI Type-C Option 3 4-wire serial mode, which need four lines (in addition to clock): Chip Select, Data/Command select, Serial input and Serial output.

So, we will use SPI (Serial Peripheral Interface) and an additional GPIO (for the Data/Command line) to communicate with the chip. This Featherwing default configuration is to use GPIO 15 for Chip Select and GPIO 33 for Data/Command.

 

HX8357-D communication protocol

The HX8357-D communication protocol is fairly straightforward (see page 34 of the datasheet). Communication is achieved by sending command packets consisting of a single command byte, followed by any parameters that the command requires.

To send a command:

  1. Drive low Chip Select
  2. Drive low Data/Command
  3. Send command byte
  4. Drive high Data/Command
  5. Send data (if any)
  6. Drive high Chip Select

 

Display initialization procedure

The initialization procedure of the HX8357-D chip consists of the following steps:

  1. Send Software Reset command
  2. Wait 5 ms: during this time, the chip loads all factory default values to registers.
  3. Send configuration commands: default values work just fine for me, except for panel type, that must be set to BGR, and pixel format that must be set to 16 bit. I also set the oscillator frequency to 100Hz to have a more stable image.
  4. Send Sleep Out command: turn off sleep mode, start the internal oscillator and panel scanning.
  5. Wait 5 ms: this is to allow time for the supply voltages and clock circuites to stabilize.
  6. Send Display On command

 

Let’s code!

We are ready to start coding our graphics library! We need to create two files, GFX.h and GFX.cpp:

/* GFX.h */

#ifndef _GFX_H
#define _GFX_H

#include <Arduino.h>
#include <SPI.h>

#define HX8357D_SPI_FREQUENCY   40000000
#define GPIO_HX8357D_CS         15  // Chip select line
#define GPIO_HX8357D_DC         33  // Data-Command line

// HX8357-D Commands
#define HX8357D_CMD_SWRESET     0x01
#define HX8357D_CMD_SLPOUT      0x11
#define HX8357D_CMD_DISPON      0x29
#define HX8357D_CMD_COLMOD      0x3A
#define HX8357D_CMD_SETOSC      0xB0
#define HX8357D_CMD_SETEXC      0xB9
#define HX8357D_CMD_SETPANEL    0xCC

class GFX {
    public:
    void begin();
};

#endif
/* GFX.cpp */

#include "GFX.h"

void GFX::begin() {
    // GPIOs setup
    pinMode(GPIO_HX8357D_DC, OUTPUT);
    pinMode(GPIO_HX8357D_CS, OUTPUT);
    digitalWrite(GPIO_HX8357D_DC, LOW);
    digitalWrite(GPIO_HX8357D_CS, HIGH);

    // Start SPI
    SPI.begin();

    // Start SPI transaction
    SPI.beginTransaction(SPISettings(HX8357D_SPI_FREQUENCY, MSBFIRST, SPI_MODE0));
    digitalWrite(GPIO_HX8357D_CS, LOW);

    // Software reset, reload factory defaults
    digitalWrite(GPIO_HX8357D_DC, LOW);
    SPI.write(HX8357D_CMD_SWRESET);
    digitalWrite(GPIO_HX8357D_DC, HIGH);
    delay(6); // Wait 5ms plus a safety margin
    
    // Enable extended commands - Required for SETOSC and SETPANEL commands
    digitalWrite(GPIO_HX8357D_DC, LOW);
    SPI.write(HX8357D_CMD_SETEXC);
    digitalWrite(GPIO_HX8357D_DC, HIGH);
    SPI.write(0xFF);
    SPI.write(0x83);
    SPI.write(0x57);

    // Set internal oscillator to 100Hz for normal mode
    digitalWrite(GPIO_HX8357D_DC, LOW);
    SPI.write(HX8357D_CMD_SETOSC);
    digitalWrite(GPIO_HX8357D_DC, HIGH);
    SPI.write(0x6E);

    // Set panel to BGR
    digitalWrite(GPIO_HX8357D_DC, LOW);
    SPI.write(HX8357D_CMD_SETPANEL);
    digitalWrite(GPIO_HX8357D_DC, HIGH);
    SPI.write(0x05);

    // Set pixel format to 16 bit
    digitalWrite(GPIO_HX8357D_DC, LOW);
    SPI.write(HX8357D_CMD_COLMOD);
    digitalWrite(GPIO_HX8357D_DC, HIGH);
    SPI.write(0x55);

    // Sleep out
    digitalWrite(GPIO_HX8357D_DC, LOW);
    SPI.write(HX8357D_CMD_SLPOUT);
    digitalWrite(GPIO_HX8357D_DC, HIGH);
    delay(6); // Wait 5ms plus a safety margin

    // Display on
    digitalWrite(GPIO_HX8357D_DC, LOW);
    SPI.write(HX8357D_CMD_DISPON);
    digitalWrite(GPIO_HX8357D_DC, HIGH);

    // End SPI transaction
    digitalWrite(GPIO_HX8357D_CS, HIGH);
    SPI.endTransaction();
}

Now, to test that everything is working, we need to create the main file that contains the Arduino setup and loop functions:

/* main.cpp or your_project_name.ino file */

#include <Arduino.h>
#include "GFX.h"

GFX gfx;

void setup() {
    gfx.begin();
}

void loop() {}

Note that if you create a .ino sketch file in Arduino IDE, you must remove the #include <Arduino.h> line.

You can find the complete code for this post here.

 

Testing

Upload the firmware. After the upload is completed and the ESP32 is resetted, the display will probably still show the last image that was on screen or some random noise (the initial state of video memory at power up is random). Not very exciting, but at least now the display is ready to use!



Not very exciting…

 

In the next post…

In the next post we will talk about screen buffers and finally we will start to draw some pixels on the screen!

If you have feedbacks, feel free to comment below or follow me on Twitter. See you soon!


0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

By continuing to browse this Website, you consent to the use of cookies. More information

This Website uses:

By continuing to browse this Website without changing the cookies settings of your browser or by clicking "Accept" below, you consent to the use of cookies.

Close