Interface OLED with ESP32 using ESP-IDF

In this ESP-IDF tutorial, we will show you how to interface SSD1306 OLED with ESP32. Organic Light Emitting Diode commonly known as OLED is used to display texts, bitmap images, and shapes. Due to its cost-effective nature and great view angle and pixel density. This guide includes a brief introduction to the 0.96-inch OLED display, interfacing with the ESP32 board, and then using SSD1306/SH1106 Driver for ESP-IDF to display texts, scrolling text, images, and animations on the OLED display.

Before we move ahead, make sure you have the latest version of VS Code installed on your system with the ESP-IDF extension configured.

SSD1306 0.96 inch OLED Display Introduction

An OLED is an organic light-emitting diode that consists of two organic thin films connected in series between two electric conductors. There are several versions of OLED displays available in the market. This guide focuses on SSD1306 0.96 inch OLED display which has 128×64 pixels. The SSD1306 controller is the major component of thus display, which allows I2C/SPI communication between microcontrollers. The OLED we will be using communicates through I2C only thus it has four pins that need to be connected with the ESP32 board.

The diagram below shows the pinout of the OLED display we will be using.

OLED Pinout I2C
Pinout of 0.96-inch OLED (I2C only)

As you can view in the pinout above, this OLED has 4 pins. This display requires a driving voltage of 3.3-5V. The VCC and GND pins are the power supply pins of the OLED connected with ESP32 Vin or 3.3V pin. The SCL and SDA pins are the I2C pins required to generate the clock signal and transmit the data respectively. These two pins will be connected with the I2C pins of the ESP32 board.

The table below shows some key specifications of this model.

Size0.96 inch
Terminals4
Pixels128×64
CommunicationI2C only
VCC3.3V-5V
Operating Temperature-40℃ to +80℃

Refer to the following article for an in-depth introduction to 0.96-inch OLED: Monochrome 0.96” OLED Display

ESP-IDF Interface OLED with ESP32

In this section, we will connect the SSD1306 OLED display with the ESP32 development board. Follow the connections as shown in the table below:

ESP32 boardSSD1306 OLED Display
3.3V or VinVCC
GPIO21(I2C SDA)SDA
GPIO22(I2C SCL)SCL
GNDGND

As we mentioned previously, the OLED display requires an operating voltage of 3.3-5V hence we can connect either the 3.3V pin or the Vin pin of the ESP32 module with the VCC pin of the display. The GND pins of both the pins will be common. To connect the I2C pins, we will use the default I2C pins of the ESP32 board. By default in ESP32, GPIO22 is set up as SCL pin and GPIO21 is set up as SDA pin. Therefore, we will connect SDA pin of display with GPIO21 and SCL pin of display with GPIO22.

ESP32 I2C Pins

ESP32 OLED Connection Diagram

The diagram below shows the connections between ESP32 board and OLED display. We have used the same connections as we described above.

ESP32 with OLED schematic diagram
Connection diagram for ESP32 and OLED Display

ESP-IDF ESP32 OLED Display and Scroll Text

Let’s set up a project in ESP-IDF to test our SSD1306 OLED display. We will demonstrate TextDemo by nopnop2002 uploaded on GitHub at the following link:

These examples use the SSD1306/SH1106 Driver for ESP-IDF.

Create Project

Open your VS Code and head over to View > Command Palette. Type ESP-IDF: New Project in the search bar and press enter.

Specify the project name and directory. We have named our project ‘ESP_IDF_ssd1306_TextDemo.’ For the ESP-IDF board, we have chosen the custom board option. For ESP-IDF target, we have chosen ESP32 module. Click ‘Choose Template’ button to proceed forward.

ESP32 OLED using ESP-IDF TextDemo project 1

In the Extension, select ESP-IDF option:

ESP-IDF in VS Code New Project 2

We will click the ‘sample_project’ under the get-started tab. Now click ‘Create project using template sample_project.’

ESP-IDF in VS Code New Project 3

You will get a notification that the project has been created. To open the project in a new window, click ‘Yes.’

Add Libraries

This opens esp-idf project that we created, inside the EXPLORER tab. There are several folders inside our project folder. This is the same for every project which you will create through ESP-IDF Explorer. Create a new folder named ‘components‘ and copy the files from the link given below into your project components folder. This will contain the libraries that will be required for this project.

OLED MenuConfig Settings ESP-IDF

Let’s first head over to the menuconfig. Opens the ESP-IDF SDK Configuration Editor. Scroll down and open the SSD1306 Configuration. Here we can set the SSD1306 configuration parameter according to our needs. This includes the UART interface, panel type, SCL GPIO pin, SDA GPIO pin and the reset GPIO pin. Here you can view that by default, ESP-IDF is using the interface as I2C, panel type as 128×64, SCL GPIO pin as 22, SDA GPIO pin as 21 and Reset GPIO pin as 33. You can alter these parameters according to your OLED display and then click the Save button found at the top. We will leave the configuration settings as default as they match our module.

ESP32 OLED using ESP-IDF TextDemo project SDK configuration editor

Alternatively, we can also set this config value with menuconfig. Open menuconfig by typing idf.py menuconfig in the terminal. This command opens the Espressif IoT Development Framework Configuration. Head over to SSD1306 Configuration and set the parameters accordingly.

Code

The main folder contains the source code meaning the main.c file will be found here. Inside the main.c we will write our program code. Go to main > main.c and open it. We will define the functions and the program code here. Copy the code from this link here.

This is our main.c file.

Note: All examples and library for this tutorial are taken from this GitHub repo.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

#include "ssd1306.h"
#include "font8x8_basic.h"

/*
 You have to set this config value with menuconfig
 CONFIG_INTERFACE
 for i2c
 CONFIG_MODEL
 CONFIG_SDA_GPIO
 CONFIG_SCL_GPIO
 CONFIG_RESET_GPIO
 for SPI
 CONFIG_CS_GPIO
 CONFIG_DC_GPIO
 CONFIG_RESET_GPIO
*/

#define tag "SSD1306"

void app_main(void)
{
	SSD1306_t dev;
	int center, top, bottom;
	char lineChar[20];

#if CONFIG_I2C_INTERFACE
	ESP_LOGI(tag, "INTERFACE is i2c");
	ESP_LOGI(tag, "CONFIG_SDA_GPIO=%d",CONFIG_SDA_GPIO);
	ESP_LOGI(tag, "CONFIG_SCL_GPIO=%d",CONFIG_SCL_GPIO);
	ESP_LOGI(tag, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
	i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_I2C_INTERFACE

#if CONFIG_SPI_INTERFACE
	ESP_LOGI(tag, "INTERFACE is SPI");
	ESP_LOGI(tag, "CONFIG_MOSI_GPIO=%d",CONFIG_MOSI_GPIO);
	ESP_LOGI(tag, "CONFIG_SCLK_GPIO=%d",CONFIG_SCLK_GPIO);
	ESP_LOGI(tag, "CONFIG_CS_GPIO=%d",CONFIG_CS_GPIO);
	ESP_LOGI(tag, "CONFIG_DC_GPIO=%d",CONFIG_DC_GPIO);
	ESP_LOGI(tag, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
	spi_master_init(&dev, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_SPI_INTERFACE

#if CONFIG_FLIP
	dev._flip = true;
	ESP_LOGW(tag, "Flip upside down");
#endif

#if CONFIG_SSD1306_128x64
	ESP_LOGI(tag, "Panel is 128x64");
	ssd1306_init(&dev, 128, 64);
#endif // CONFIG_SSD1306_128x64
#if CONFIG_SSD1306_128x32
	ESP_LOGI(tag, "Panel is 128x32");
	ssd1306_init(&dev, 128, 32);
#endif // CONFIG_SSD1306_128x32

	ssd1306_clear_screen(&dev, false);
	ssd1306_contrast(&dev, 0xff);
  ssd1306_display_text_x3(&dev, 0, "Hello", 5, false);
  vTaskDelay(3000 / portTICK_PERIOD_MS);

#if CONFIG_SSD1306_128x64
	top = 2;
	center = 3;
	bottom = 8;
	ssd1306_display_text(&dev, 0, "SSD1306 128x64", 14, false);
	ssd1306_display_text(&dev, 1, "ABCDEFGHIJKLMNOP", 16, false);
	ssd1306_display_text(&dev, 2, "abcdefghijklmnop",16, false);
	ssd1306_display_text(&dev, 3, "Hello World!!", 13, false);
	//ssd1306_clear_line(&dev, 4, true);
	//ssd1306_clear_line(&dev, 5, true);
	//ssd1306_clear_line(&dev, 6, true);
	//ssd1306_clear_line(&dev, 7, true);
	ssd1306_display_text(&dev, 4, "SSD1306 128x64", 14, true);
	ssd1306_display_text(&dev, 5, "ABCDEFGHIJKLMNOP", 16, true);
	ssd1306_display_text(&dev, 6, "abcdefghijklmnop",16, true);
	ssd1306_display_text(&dev, 7, "Hello World!!", 13, true);
#endif // CONFIG_SSD1306_128x64

#if CONFIG_SSD1306_128x32
	top = 1;
	center = 1;
	bottom = 4;
	ssd1306_display_text(&dev, 0, "SSD1306 128x32", 14, false);
	ssd1306_display_text(&dev, 1, "Hello World!!", 13, false);
	//ssd1306_clear_line(&dev, 2, true);
	//ssd1306_clear_line(&dev, 3, true);
	ssd1306_display_text(&dev, 2, "SSD1306 128x32", 14, true);
	ssd1306_display_text(&dev, 3, "Hello World!!", 13, true);
#endif // CONFIG_SSD1306_128x32
	vTaskDelay(3000 / portTICK_PERIOD_MS);
	
	// Display Count Down
	uint8_t image[24];
	memset(image, 0, sizeof(image));
	ssd1306_display_image(&dev, top, (6*8-1), image, sizeof(image));
	ssd1306_display_image(&dev, top+1, (6*8-1), image, sizeof(image));
	ssd1306_display_image(&dev, top+2, (6*8-1), image, sizeof(image));
	for(int font=0x39;font>0x30;font--) {
		memset(image, 0, sizeof(image));
		ssd1306_display_image(&dev, top+1, (7*8-1), image, 8);
		memcpy(image, font8x8_basic_tr[font], 8);
		if (dev._flip) ssd1306_flip(image, 8);
		ssd1306_display_image(&dev, top+1, (7*8-1), image, 8);
		vTaskDelay(1000 / portTICK_PERIOD_MS);
	}
	
	// Scroll Up
	ssd1306_clear_screen(&dev, false);
	ssd1306_contrast(&dev, 0xff);
	ssd1306_display_text(&dev, 0, "---Scroll  UP---", 16, true);
	//ssd1306_software_scroll(&dev, 7, 1);
	ssd1306_software_scroll(&dev, (dev._pages - 1), 1);
	for (int line=0;line<bottom+10;line++) {
		lineChar[0] = 0x01;
		sprintf(&lineChar[1], " Line %02d", line);
		ssd1306_scroll_text(&dev, lineChar, strlen(lineChar), false);
		vTaskDelay(500 / portTICK_PERIOD_MS);
	}
	vTaskDelay(3000 / portTICK_PERIOD_MS);
	
	// Scroll Down
	ssd1306_clear_screen(&dev, false);
	ssd1306_contrast(&dev, 0xff);
	ssd1306_display_text(&dev, 0, "--Scroll  DOWN--", 16, true);
	//ssd1306_software_scroll(&dev, 1, 7);
	ssd1306_software_scroll(&dev, 1, (dev._pages - 1) );
	for (int line=0;line<bottom+10;line++) {
		lineChar[0] = 0x02;
		sprintf(&lineChar[1], " Line %02d", line);
		ssd1306_scroll_text(&dev, lineChar, strlen(lineChar), false);
		vTaskDelay(500 / portTICK_PERIOD_MS);
	}
	vTaskDelay(3000 / portTICK_PERIOD_MS);

	// Page Down
	ssd1306_clear_screen(&dev, false);
	ssd1306_contrast(&dev, 0xff);
	ssd1306_display_text(&dev, 0, "---Page	DOWN---", 16, true);
	ssd1306_software_scroll(&dev, 1, (dev._pages-1) );
	for (int line=0;line<bottom+10;line++) {
		//if ( (line % 7) == 0) ssd1306_scroll_clear(&dev);
		if ( (line % (dev._pages-1)) == 0) ssd1306_scroll_clear(&dev);
		lineChar[0] = 0x02;
		sprintf(&lineChar[1], " Line %02d", line);
		ssd1306_scroll_text(&dev, lineChar, strlen(lineChar), false);
		vTaskDelay(500 / portTICK_PERIOD_MS);
	}
	vTaskDelay(3000 / portTICK_PERIOD_MS);

	// Horizontal Scroll
	ssd1306_clear_screen(&dev, false);
	ssd1306_contrast(&dev, 0xff);
	ssd1306_display_text(&dev, center, "Horizontal", 10, false);
	ssd1306_hardware_scroll(&dev, SCROLL_RIGHT);
	vTaskDelay(5000 / portTICK_PERIOD_MS);
	ssd1306_hardware_scroll(&dev, SCROLL_LEFT);
	vTaskDelay(5000 / portTICK_PERIOD_MS);
	ssd1306_hardware_scroll(&dev, SCROLL_STOP);
	
	// Vertical Scroll
	ssd1306_clear_screen(&dev, false);
	ssd1306_contrast(&dev, 0xff);
	ssd1306_display_text(&dev, center, "Vertical", 8, false);
	ssd1306_hardware_scroll(&dev, SCROLL_DOWN);
	vTaskDelay(5000 / portTICK_PERIOD_MS);
	ssd1306_hardware_scroll(&dev, SCROLL_UP);
	vTaskDelay(5000 / portTICK_PERIOD_MS);
	ssd1306_hardware_scroll(&dev, SCROLL_STOP);
	
	// Invert
	ssd1306_clear_screen(&dev, true);
	ssd1306_contrast(&dev, 0xff);
	ssd1306_display_text(&dev, center, "  Good Bye!!", 12, true);
	vTaskDelay(5000 / portTICK_PERIOD_MS);


	// Fade Out
	ssd1306_fadeout(&dev);
	
#if 0
	// Fade Out
	for(int contrast=0xff;contrast>0;contrast=contrast-0x20) {
		ssd1306_contrast(&dev, contrast);
		vTaskDelay(40);
	}
#endif

	// Restart module
	esp_restart();
}

How the Code Works?

Note: This code is applicable for OLED displays with different panel types and interfaces. The #if #endif conditions will work according to the particular parameter defined. Hence, we will look at those parts which are applicable to our SSD1306 Configuration parameters.

Firstly, the code starts by including the necessary libraries that includes the FreeRTOS libraries to generate delays, ssd1306.h driver for the OLED functionality, font8x8_basic.h which contains 8×8 pixels ASCII font set and esp_log.h for debugging.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

#include "ssd1306.h"
#include "font8x8_basic.h"

Initialize I2C interface and OLED

Inside the app_main() function, firstly the I2C interface is configured. The current settings that we setup in the menuconfig will get printed in the terminal. This includes the interface type, SDA GPIO, SCL GPIO and Reset GPIO. Moreover, the I2C interface will be configured by calling the i2c_master_init() function and passing the address of the SSD1306_t structure, SDA pin, SCL pin and Reset pin as parameters inside it.

#if CONFIG_I2C_INTERFACE
	ESP_LOGI(tag, "INTERFACE is i2c");
	ESP_LOGI(tag, "CONFIG_SDA_GPIO=%d",CONFIG_SDA_GPIO);
	ESP_LOGI(tag, "CONFIG_SCL_GPIO=%d",CONFIG_SCL_GPIO);
	ESP_LOGI(tag, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
	i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_I2C_INTERFACE

The following statement will print the panel type on the terminal. Moreover, it will also initialize the OLED display by calling ssd1306_init() function. This takes in three parameters. The first parameter is the address of the SSD1306_t structure, the second parameter is the width and the third parameter is the height of the display in pixels. We are using a 128×64 display hence the width is 128 and the height is 64.

#if CONFIG_SSD1306_128x64
	ESP_LOGI(tag, "Panel is 128x64");
	ssd1306_init(&dev, 128, 64);
#endif // CONFIG_SSD1306_128x64

Clear Screen and Set Contrast

Next, we have a few function calls. First the screen of the OLED display is cleared using ssd1306_clear_screen(). This function takes in two parameters. The first is the address of the SSD1306_t structure and the second parameter is invert which is a bool variable. It is set as false. This means we have a dark background and the text will be displayed in white.

ssd1306_clear_screen(&dev, false);

Secondly, the contrast of the screen is set using ssd1306_contrast(). This function takes in two parameters. The first is the address of the SSD1306_t structure and the second parameter is the contrast value which is an int variable. It is set as 0xff.

ssd1306_contrast(&dev, 0xff);

Display Text

Then, the screen displays the text ‘Hello’ by calling the function ssd1306_display_text_x3(). This will be displayed on the screen for three seconds. It takes in five parameters. The first parameter is the address of the SSD1306_t structure. The second parameter is the page number of the composition data which is set as 0. The third parameter is the text that we want to display. It is “Hello” in this case. The fourth parameter is the length of the text which is specified as 5. Lastly, the fifth parameter is invert which is a bool variable. It is set as false. This means we have a dark background and the text will be displayed in white.

  ssd1306_display_text_x3(&dev, 0, "Hello", 5, false);
  vTaskDelay(3000 / portTICK_PERIOD_MS);
ESP32 OLED using ESP-IDF TextDemo project Display Text

Display Text and Invert

Next we have another block of code for the SSD1306 128×64 configuration. This displays a series of texts that fill the whole screen. We start by defining the top, center and bottom values. Then we call ssd_1306_display_text() several times to display various messages with invert values as both false and true. When the invert is set as false, we have a dark background and the text will be displayed in white. Likewise, when the invert is set as true, we have a bright background and the text is displayed in black. This function takes the same parameters as ssd1306_display_text_x3().

#if CONFIG_SSD1306_128x64
	top = 2;
	center = 3;
	bottom = 8;
	ssd1306_display_text(&dev, 0, "SSD1306 128x64", 14, false);
	ssd1306_display_text(&dev, 1, "ABCDEFGHIJKLMNOP", 16, false);
	ssd1306_display_text(&dev, 2, "abcdefghijklmnop",16, false);
	ssd1306_display_text(&dev, 3, "Hello World!!", 13, false);

	ssd1306_display_text(&dev, 4, "SSD1306 128x64", 14, true);
	ssd1306_display_text(&dev, 5, "ABCDEFGHIJKLMNOP", 16, true);
	ssd1306_display_text(&dev, 6, "abcdefghijklmnop",16, true);
	ssd1306_display_text(&dev, 7, "Hello World!!", 13, true);
#endif // CONFIG_SSD1306_128x64
ESP32 OLED using ESP-IDF TextDemo project Display Text and Invert

Display Numbers

Next we will display a series of numbers in the middle of the screen that will count down form 9 to 0. Each number will stay on the screen for a second and then it will disappear and the next number appears in its place.

	// Display Count Down
	uint8_t image[24];
	memset(image, 0, sizeof(image));
	ssd1306_display_image(&dev, top, (6*8-1), image, sizeof(image));
	ssd1306_display_image(&dev, top+1, (6*8-1), image, sizeof(image));
	ssd1306_display_image(&dev, top+2, (6*8-1), image, sizeof(image));
	for(int font=0x39;font>0x30;font--) {
		memset(image, 0, sizeof(image));
		ssd1306_display_image(&dev, top+1, (7*8-1), image, 8);
		memcpy(image, font8x8_basic_tr[font], 8);
		if (dev._flip) ssd1306_flip(image, 8);
		ssd1306_display_image(&dev, top+1, (7*8-1), image, 8);
		vTaskDelay(1000 / portTICK_PERIOD_MS);
	}
ESP32 OLED using ESP-IDF TextDemo project Count Down

Scroll Up and Down

Now we will scroll some texts up and down the screen. First, we will clear the screen and set the contrast. Then we will display the text “—Scroll UP—“. Then we call the function ssd1306_software_scroll() and pass three parameters inside it. The first parameter is the address of the SSD1306_t structure. The second parameter is start which is set as (dev._pages – 1) and the third parameter is end which is set as 1. Then we use a for loop to display a scrolling text that will start from Line 00 and end at Line 17 while scrolling from bottom to top (scroll up). This will be achieved by using the function ssd1306_scroll_text().

// Scroll Up
	ssd1306_clear_screen(&dev, false);
	ssd1306_contrast(&dev, 0xff);
	ssd1306_display_text(&dev, 0, "---Scroll  UP---", 16, true);

	ssd1306_software_scroll(&dev, (dev._pages - 1), 1);
	for (int line=0;line<bottom+10;line++) {
		lineChar[0] = 0x01;
		sprintf(&lineChar[1], " Line %02d", line);
		ssd1306_scroll_text(&dev, lineChar, strlen(lineChar), false);
		vTaskDelay(500 / portTICK_PERIOD_MS);
	}
	vTaskDelay(3000 / portTICK_PERIOD_MS);
	
ESP32 OLED using ESP-IDF TextDemo project Scroll Up

After the scroll up is complete we will move to scroll down. First, we will clear the screen and set the contrast. Then we will display the text “—Scroll DOWN—“. Then we call the function ssd1306_software_scroll() and pass three parameters inside it. The first parameter is the address of the SSD1306_t structure. The second parameter is start which is set as 1 and the third parameter is end which is set as (dev._pages – 1). Then we use a for loop to display a scrolling text that will start from Line 00 and end at Line 17 while scrolling from top to bottom (scroll down). This will be achieved by using the function ssd1306_scroll_text().

	// Scroll Down
	ssd1306_clear_screen(&dev, false);
	ssd1306_contrast(&dev, 0xff);
	ssd1306_display_text(&dev, 0, "--Scroll  DOWN--", 16, true);
	//ssd1306_software_scroll(&dev, 1, 7);
	ssd1306_software_scroll(&dev, 1, (dev._pages - 1) );
	for (int line=0;line<bottom+10;line++) {
		lineChar[0] = 0x02;
		sprintf(&lineChar[1], " Line %02d", line);
		ssd1306_scroll_text(&dev, lineChar, strlen(lineChar), false);
		vTaskDelay(500 / portTICK_PERIOD_MS);
	}
	vTaskDelay(3000 / portTICK_PERIOD_MS);
ESP32 OLED using ESP-IDF TextDemo project Scroll Down

Page Down

Next, we have a section of code for page down. It is similar to scrolling down however in this case the texts do not automatically scroll down but when they reach the end of the screen, they disappear and new ones take their place.

// Page Down
	ssd1306_clear_screen(&dev, false);
	ssd1306_contrast(&dev, 0xff);
	ssd1306_display_text(&dev, 0, "---Page	DOWN---", 16, true);
	ssd1306_software_scroll(&dev, 1, (dev._pages-1) );
	for (int line=0;line<bottom+10;line++) {

		if ( (line % (dev._pages-1)) == 0) ssd1306_scroll_clear(&dev);
		lineChar[0] = 0x02;
		sprintf(&lineChar[1], " Line %02d", line);
		ssd1306_scroll_text(&dev, lineChar, strlen(lineChar), false);
		vTaskDelay(500 / portTICK_PERIOD_MS);
	}
	vTaskDelay(3000 / portTICK_PERIOD_MS);
ESP32 OLED using ESP-IDF TextDemo project Page Down

Horizontal and Vertical Scroll

Next up we scroll the text “Horizontal”, horizontally across the screen. This is accomplished through the following section of code. Like always, it starts by clearing the screen and setting the contrast value. Next it displays the text “Horizontal” in the center with a black background and white text (invert is false). Then we use the ssd1306_hardware_scroll() function to first scroll the text towards right (SCROLL_RIGHT) and then after a delay of 5 seconds scroll it towards left (SCROLL_LEFT) and then stop (SCROLL_STOP) after another 5 seconds. This function only takes in two parameters. The first parameter is the address of the SSD1306_t structure and the second parameter is the scroll type.

// Horizontal Scroll
	ssd1306_clear_screen(&dev, false);
	ssd1306_contrast(&dev, 0xff);
	ssd1306_display_text(&dev, center, "Horizontal", 10, false);
	ssd1306_hardware_scroll(&dev, SCROLL_RIGHT);
	vTaskDelay(5000 / portTICK_PERIOD_MS);
	ssd1306_hardware_scroll(&dev, SCROLL_LEFT);
	vTaskDelay(5000 / portTICK_PERIOD_MS);
	ssd1306_hardware_scroll(&dev, SCROLL_STOP);
ESP32 OLED using ESP-IDF TextDemo project Horizontal Scroll

Similarly, we will scroll the text “Vertical”, vertically across the screen. This is accomplished through the following section of code. Like always, it starts by clearing the screen and setting the contrast value. Next it displays the text “Vertical” in the center with a black background and white text (invert is false). Then we use the ssd1306_hardware_scroll() function to first scroll the text down (SCROLL_DOWN) and then after a delay of 5 seconds scroll it back up (SCROLL_UP) and then stop (SCROLL_STOP) after another 5 seconds. This function only takes in two parameters. The first parameter is the address of the SSD1306_t structure and the second parameter is the scroll type.


	// Vertical Scroll
	ssd1306_clear_screen(&dev, false);
	ssd1306_contrast(&dev, 0xff);
	ssd1306_display_text(&dev, center, "Vertical", 8, false);
	ssd1306_hardware_scroll(&dev, SCROLL_DOWN);
	vTaskDelay(5000 / portTICK_PERIOD_MS);
	ssd1306_hardware_scroll(&dev, SCROLL_UP);
	vTaskDelay(5000 / portTICK_PERIOD_MS);
	ssd1306_hardware_scroll(&dev, SCROLL_STOP);
ESP32 OLED using ESP-IDF TextDemo project Vertical

Finally, after clearing the screen and setting the contrast, we will display the text ” Good Bye!!” in the center. The background will be white and the color of the text will be black. This is because invert is set as true in this case.

// Invert
	ssd1306_clear_screen(&dev, true);
	ssd1306_contrast(&dev, 0xff);
	ssd1306_display_text(&dev, center, "  Good Bye!!", 12, true);
	vTaskDelay(5000 / portTICK_PERIOD_MS);
ESP32 OLED using ESP-IDF TextDemo project Display Text and Invert 2

Then the screen slowly fades out and turns black. Shortly, the ESP32 board restarts again.

ssd1306_fadeout(&dev);
esp_restart();

Compiling the Sketch

To flash your chip, type the following command in the serial terminal. Remember to replace the COM port with the one through which your board is connected.

idf.py -p COMX flash monitor

After the code flashes successfully, you can view the informational messages being printed showing the SSD1306 configuration parameters and its status.

ESP32 OLED using ESP-IDF TextDemo project terminal

The OLED will start displaying all the different texts and scrolling features. Watch the video below to have a better insight.

ESP32 OLED with ESP-IDF Display Animation

After showing you how the to use SSD1306 driver to display text and apply various scrolling effects, let’s include some output results for some more examples that use the SSD1306/SH1106 Driver for ESP-IDF, provided by nopnop2002 on GitHub. We will demonstrate AnimationDemo by nopnop2002 uploaded on GitHub at the following link but use different image frames for demonstration.

Create Project

Open your VS Code and head over to View > Command Palette. Type ESP-IDF: New Project in the search bar and press enter.

Specify the project name and directory. We have named our project ‘ESP_IDF_SSD1306_AnimationDemo.’ For the ESP-IDF board, we have chosen the custom board option. For ESP-IDF target, we have chosen ESP32 module. Click ‘Choose Template’ button to proceed forward.

ESP32 OLED using ESP-IDF Create AnimationDemo project

In the Extension, select ESP-IDF option:

ESP-IDF in VS Code New Project 2

We will click the ‘sample_project’ under the get-started tab. Now click ‘Create project using template sample_project.’

ESP-IDF in VS Code New Project 3

You will get a notification that the project has been created. To open the project in a new window, click ‘Yes.’

Add Libraries

This opens project that we created, inside the EXPLORER tab. There are several folders inside our project folder. Create a new folder named ‘components’ and copy the files from this destination into your project folder. This will contain the libraries that will be required for this project.

SSD1306 Configuration

Let’s first head over to the menuconfig. Opens the ESP-IDF SDK Configuration Editor. Scroll down and open the SSD1306 Configuration. Here we can set the SSD1306 configuration parameter according to our needs. This includes the UART interface, panel type, SCL GPIO pin, SDA GPIO pin and the reset GPIO pin. Here you can view that by default, ESP-IDF is using the interface as I2C, panel type as 128×64, SCL GPIO pin as 22, SDA GPIO pin as 21 and Reset GPIO pin as 33. You can alter these parameters according to your OLED display and then click the Save button found at the top. We will leave the configuration settings as default as they match our module.

ESP32 OLED using ESP-IDF TextDemo project SDK configuration editor

Alternatively, we can also set this config value with menuconfig. Open menuconfig by typing idf.py menuconfig in the terminal. This command opens the Espressif IoT Development Framework Configuration. Head over to SSD1306 Configuration and set the parameters accordingly.

Code

Go to main > main.c and open it. We will define the functions and the program code here. This is our main.c file.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

#include "ssd1306.h"
#include "font8x8_basic.h"

/*
 You have to set this config value with menuconfig
 CONFIG_INTERFACE
 for i2c
 CONFIG_MODEL
 CONFIG_SDA_GPIO
 CONFIG_SCL_GPIO
 CONFIG_RESET_GPIO
 for SPI
 CONFIG_CS_GPIO
 CONFIG_DC_GPIO
 CONFIG_RESET_GPIO
*/

#define TAG "SSD1306"

const unsigned char myBitmap[4] [1024] = {

	// 'frame1, 64x128px

{	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x01, 0xff, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x01, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x01, 0xff, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x01, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x7c, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x7c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x7c, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x7c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xfe, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x1f, 
	0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x1f, 
	0xff, 0xff, 0xfe, 0x00, 0x00, 0x1f, 0xf0, 0x1f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x1f, 0xf0, 0x1f, 
	0xff, 0xff, 0xfe, 0x00, 0x00, 0x1f, 0xf0, 0x1f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x1f, 0xf0, 0x1f, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7f, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7f, 
	0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 
	0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x47, 0xf3, 0xff, 
	0xff, 0x80, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0x80, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 
	0xf8, 0x00, 0x78, 0x00, 0x03, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x78, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xf8, 0x00, 0x78, 0x00, 0x03, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x78, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xf8, 0x0f, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xff, 0xf8, 0x0f, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xf8, 0x0f, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xfe, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe2, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xc0, 0x00, 0x01, 0xcf, 0xff, 
	0xff, 0xfc, 0x00, 0xc0, 0x00, 0x01, 0xcf, 0xff, 0xff, 0xfc, 0x00, 0xc0, 0x00, 0x01, 0x8f, 0xff, 
	0xff, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x0f, 0xff, 
	0xff, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x0f, 0xff, 
	0xff, 0xf3, 0xe0, 0x00, 0x3f, 0xe0, 0x3f, 0xff, 0xff, 0xf3, 0xe0, 0x00, 0x7f, 0xf8, 0x3f, 0xff, 
	0xff, 0xf3, 0xe0, 0x00, 0x7f, 0xf8, 0x3f, 0xff, 0xff, 0xf3, 0xe0, 0x00, 0x7f, 0xf8, 0x3f, 0xff, 
	0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
}, 
	// 'frame2, 64x128px

{	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xfe, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xfe, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xfe, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x3f, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xe0, 0x7f, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x3f, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xe0, 0x7f, 0xff, 0xff, 
	0xff, 0xfe, 0x00, 0x0f, 0x80, 0x7f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x0f, 0x80, 0x7f, 0xff, 0xff, 
	0xff, 0xfe, 0x00, 0x0f, 0x80, 0x7f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x0f, 0x80, 0x7f, 0xff, 0xff, 
	0xff, 0xfe, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xfe, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x1f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xc0, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x0f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xc0, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x03, 0xff, 0x07, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x03, 0xff, 0x07, 0xff, 
	0xff, 0xf8, 0x00, 0x00, 0x03, 0xff, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x78, 0x07, 0xff, 
	0xff, 0xe0, 0x00, 0x00, 0x00, 0x78, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x78, 0x07, 0xff, 
	0xff, 0xe0, 0x00, 0x00, 0x00, 0x78, 0x07, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 
	0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 
	0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 
	0xe0, 0x06, 0x00, 0x00, 0x7c, 0x00, 0xff, 0xff, 0xe0, 0x06, 0x00, 0x00, 0x7c, 0x00, 0xff, 0xff, 
	0xe0, 0x06, 0x00, 0x00, 0x7c, 0x00, 0xff, 0xff, 0x80, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0x80, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x80, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0x80, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x83, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0x83, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x83, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0x83, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0xff, 0xfe, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x0f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xc0, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x0f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xc0, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xf0, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xf0, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x67, 0xff, 0xff, 
	0xff, 0xe0, 0x00, 0x01, 0x80, 0x67, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x67, 0xff, 0xff, 
	0xff, 0x00, 0x00, 0x01, 0x80, 0x07, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xe0, 0x07, 0xff, 0xff, 
	0xff, 0x00, 0x00, 0x0f, 0xe0, 0x07, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xe0, 0x07, 0xff, 0xff, 
	0xff, 0x00, 0x00, 0x0f, 0xe0, 0x07, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x3f, 0xfc, 0x1f, 0xff, 0xff, 
	0xff, 0x1e, 0x00, 0x3f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x3f, 0xfc, 0x1f, 0xff, 0xff, 
	0xff, 0x1e, 0x00, 0x3f, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
}, 
	// 'frame3, 64x128px

{	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x03, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x03, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xff, 0xc1, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xff, 0xc1, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x3e, 0x01, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3e, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x3e, 0x01, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3e, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x80, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x0c, 0x0f, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x00, 0x0c, 0x0f, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x0c, 0x0f, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x00, 0x0c, 0x0f, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x0f, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x0f, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x01, 0x80, 0x7f, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x01, 0xc0, 0x7f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x01, 0xc0, 0x7f, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x01, 0xc0, 0x7f, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x01, 0xc0, 0x7f, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xc0, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xc0, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x10, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x10, 0x01, 0xff, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x10, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x10, 0x01, 0x8f, 0xff, 
	0xff, 0xff, 0x9f, 0xff, 0xfe, 0x01, 0x8f, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xfe, 0x01, 0x8f, 0xff, 
	0xff, 0xff, 0x9f, 0xff, 0xfe, 0x01, 0x8f, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xfe, 0x01, 0x8f, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0f, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0f, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff
}, 
	// 'frame4, 64x128px

{	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xff, 
	0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xff, 
	0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x7f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xf8, 0x1f, 0xff, 
	0xff, 0xff, 0x00, 0x00, 0x7f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xc0, 0x1f, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x0f, 0xc0, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xc0, 0x1f, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x0f, 0xc0, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x80, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x80, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xf8, 0x0f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xe1, 0xf8, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xf8, 0x0f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xe1, 0xf8, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf8, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf8, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff
}
};


void app_main(void)
{
	SSD1306_t dev;

#if CONFIG_I2C_INTERFACE
	ESP_LOGI(TAG, "INTERFACE is i2c");
	ESP_LOGI(TAG, "CONFIG_SDA_GPIO=%d",CONFIG_SDA_GPIO);
	ESP_LOGI(TAG, "CONFIG_SCL_GPIO=%d",CONFIG_SCL_GPIO);
	ESP_LOGI(TAG, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
	i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_I2C_INTERFACE

#if CONFIG_SPI_INTERFACE
	ESP_LOGI(TAG, "INTERFACE is SPI");
	ESP_LOGI(TAG, "CONFIG_MOSI_GPIO=%d",CONFIG_MOSI_GPIO);
	ESP_LOGI(TAG, "CONFIG_SCLK_GPIO=%d",CONFIG_SCLK_GPIO);
	ESP_LOGI(TAG, "CONFIG_CS_GPIO=%d",CONFIG_CS_GPIO);
	ESP_LOGI(TAG, "CONFIG_DC_GPIO=%d",CONFIG_DC_GPIO);
	ESP_LOGI(TAG, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
	spi_master_init(&dev, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_SPI_INTERFACE


#if CONFIG_SSD1306_128x64
	ESP_LOGI(TAG, "Panel is 128x64");
	ssd1306_init(&dev, 128, 64);
#endif // CONFIG_SSD1306_128x64
#if CONFIG_SSD1306_128x32
	ESP_LOGE(TAG, "Panel is 128x32. This demo cannot be run.");
	while(1) { vTaskDelay(1); }
#endif // CONFIG_SSD1306_128x32

	ssd1306_contrast(&dev, 0xff);
	ssd1306_clear_screen(&dev, false);
	int count = 3;
	uint8_t segs[128];
	while(1) {
		TickType_t startTick = xTaskGetTickCount();
		// 1Ticks required
		for (int page=0;page<8;page++) {
			for (int seg=0;seg<128;seg++) {
				segs[seg] =  ssd1306_rotate_byte(myBitmap[count][seg*8+page]);
			}
			ssd1306_display_image(&dev, page, 0, segs, 128);
		}

		TickType_t endTick = xTaskGetTickCount();
		ESP_LOGD(TAG, "diffTick=%d", endTick - startTick);
		count--;
		if (count<0) count = 3;
		vTaskDelay(10);
	}
	vTaskDelay(2000 / portTICK_PERIOD_MS);
}

Compiling the Sketch

To flash your chip, type the following command in the serial terminal. Remember to replace the COM port with the one through which your board is connected.

idf.py -p COMX flash monitor

After the code flashes successfully, you can view the informational messages being printed showing the SSD1306 configuration parameters and its status.

ESP32 OLED using ESP-IDF AnimationDemo project terminal

The OLED will start displaying the moving animation. Watch the video below to have a better insight.

Display Counter value on OLED with ESP32 and ESP-IDF

In this section, we will demonstrate CounterDemo by nopnop2002 uploaded on GitHub at the following link:

Create Project

Open your VS Code and head over to View > Command Palette. Type ESP-IDF: New Project in the search bar and press enter.

Specify the project name and directory. We have named our project ‘ESP_IDF_SSD1306_CounterDemo.’ For the ESP-IDF board, we have chosen the custom board option. For ESP-IDF target, we have chosen ESP32 module. Click ‘Choose Template’ button to proceed forward.

ESP32 OLED using ESP-IDF Create CounterDemo project

In the Extension, select ESP-IDF option:

ESP-IDF in VS Code New Project 2

We will click the ‘sample_project’ under the get-started tab. Now click ‘Create project using template sample_project.’

ESP-IDF in VS Code New Project 3

You will get a notification that the project has been created. To open the project in a new window, click ‘Yes.’

Add Libraries

This opens project that we created, inside the EXPLORER tab. There are several folders inside our project folder. Create a new folder named ‘components‘ and copy the files from this destination into your project folder. This will contain the libraries that will be required for this project.

SSD1306 Configuration

Let’s first head over to the menuconfig. Opens the ESP-IDF SDK Configuration Editor. Scroll down and open the SSD1306 Configuration. Here we can set the SSD1306 configuration parameter according to our needs. This includes the UART interface, panel type, SCL GPIO pin, SDA GPIO pin, and the reset GPIO pin. Here you can view that by default, ESP-IDF is using the interface as I2C, panel type as 128×64, SCL GPIO pin as 22, SDA GPIO pin as 21 and Reset GPIO pin as 33. You can alter these parameters according to your OLED display and then click the Save button found at the top. We will leave the configuration settings as default as they match our module.

ESP32 OLED using ESP-IDF TextDemo project SDK configuration editor

Alternatively, we can also set this config value with menuconfig. Open menuconfig by typing idf.py menuconfig in the terminal. This command opens the Espressif IoT Development Framework Configuration. Head over to SSD1306 Configuration and set the parameters accordingly.

Code

Go to main > main.c and open it. We will define the functions and the program code here. Copy the code from this link here.

This is our main.c file.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

#include "ssd1306.h"
#include "font8x8_basic.h"

/*
 You have to set this config value with menuconfig
 CONFIG_INTERFACE
 for i2c
 CONFIG_MODEL
 CONFIG_SDA_GPIO
 CONFIG_SCL_GPIO
 CONFIG_RESET_GPIO
 for SPI
 CONFIG_CS_GPIO
 CONFIG_DC_GPIO
 CONFIG_RESET_GPIO
*/

#define TAG "SSD1306"

#define IMAGES 10

uint8_t segmentDisplay[IMAGES][192] = {
{
// https://www.iconspng.com/image/5656/seven-segment-display-gray-0
// 'seven-segment-display-gray-0', 32x48px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x06, 0xff, 0xff, 0x60, 
0x07, 0x7f, 0xfe, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x02, 0x00, 0x00, 0x40, 
0x02, 0x00, 0x00, 0x40, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0xff, 0xff, 0xe0, 
0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
// https://www.iconspng.com/image/5657/seven-segment-display-gray-1
// 'seven-segment-display-gray-1', 32x48px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x60, 
0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x40, 
0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0xe0, 
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
// https://www.iconspng.com/image/5658/seven-segment-display-gray-2
// 'seven-segment-display-gray-2', 32x48px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0x60, 
0x00, 0xff, 0xfe, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x7f, 0xfe, 0xe0, 0x01, 0xff, 0xff, 0xc0, 
0x03, 0xff, 0xff, 0x00, 0x07, 0x7f, 0xfe, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 
0x07, 0xff, 0xff, 0x80, 0x07, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
// https://www.iconspng.com/image/5659/seven-segment-display-gray-3
// 'seven-segment-display-gray-3', 32x48px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0x60, 
0x00, 0xff, 0xfe, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x7f, 0xfe, 0xe0, 0x01, 0xff, 0xff, 0x80, 
0x01, 0xff, 0xff, 0x40, 0x00, 0x7f, 0xfe, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xff, 0xff, 0xe0, 
0x01, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
// https://www.iconspng.com/image/5660/seven-segment-display-gray-4
// 'seven-segment-display-gray-4', 32x48px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x60, 
0x07, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x7f, 0xfe, 0xe0, 0x03, 0xff, 0xff, 0x80, 
0x00, 0xff, 0xff, 0x40, 0x00, 0x7f, 0xfe, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0xe0, 
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
// https://www.iconspng.com/image/5661/seven-segment-display-gray-5
// 'seven-segment-display-gray-5', 32x48px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xc0, 0x06, 0xff, 0xff, 0x80, 
0x07, 0x7f, 0xff, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x7f, 0xfe, 0x00, 0x03, 0xff, 0xff, 0x80, 
0x00, 0xff, 0xff, 0xc0, 0x00, 0x7f, 0xfe, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xff, 0xff, 0xe0, 
0x01, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
// https://www.iconspng.com/image/5662/seven-segment-display-gray-6
// 'seven-segment-display-gray-6', 32x48px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xc0, 0x06, 0xff, 0xff, 0x80, 
0x07, 0x7f, 0xff, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x7f, 0xfe, 0x00, 0x01, 0xff, 0xff, 0x80, 
0x02, 0xff, 0xff, 0xc0, 0x07, 0x7f, 0xfe, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0xff, 0xff, 0xe0, 
0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
// https://www.iconspng.com/image/5663/seven-segment-display
// 'seven-segment-display-gray-7', 32x48px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0x60, 
0x00, 0xff, 0xfe, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x40, 
0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0xe0, 
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
// https://www.iconspng.com/image/5664/seven-segment-display-gray-8
// 'seven-segment-display-gray-8', 32x48px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x06, 0xff, 0xff, 0x60, 
0x07, 0x7f, 0xfe, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x7f, 0xfe, 0xe0, 0x01, 0xff, 0xff, 0x80, 
0x02, 0xff, 0xff, 0x40, 0x07, 0x7f, 0xfe, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0xff, 0xff, 0xe0, 
0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
// https://www.iconspng.com/image/5665/seven-segment-display
// 'seven-segment-display-gray-9', 32x48px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x06, 0xff, 0xff, 0x60, 
0x07, 0x7f, 0xfe, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 
0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x7f, 0xfe, 0xe0, 0x03, 0xff, 0xff, 0x80, 
0x00, 0xff, 0xff, 0x40, 0x00, 0x7f, 0xfe, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xff, 0xff, 0xe0, 
0x01, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}
};


void app_main(void)
{
	SSD1306_t dev;

#if CONFIG_I2C_INTERFACE
	ESP_LOGI(TAG, "INTERFACE is i2c");
	ESP_LOGI(TAG, "CONFIG_SDA_GPIO=%d",CONFIG_SDA_GPIO);
	ESP_LOGI(TAG, "CONFIG_SCL_GPIO=%d",CONFIG_SCL_GPIO);
	ESP_LOGI(TAG, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
	i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_I2C_INTERFACE

#if CONFIG_SPI_INTERFACE
	ESP_LOGI(TAG, "INTERFACE is SPI");
	ESP_LOGI(TAG, "CONFIG_MOSI_GPIO=%d",CONFIG_MOSI_GPIO);
	ESP_LOGI(TAG, "CONFIG_SCLK_GPIO=%d",CONFIG_SCLK_GPIO);
	ESP_LOGI(TAG, "CONFIG_CS_GPIO=%d",CONFIG_CS_GPIO);
	ESP_LOGI(TAG, "CONFIG_DC_GPIO=%d",CONFIG_DC_GPIO);
	ESP_LOGI(TAG, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
	spi_master_init(&dev, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_SPI_INTERFACE

#if CONFIG_FLIP
	dev._flip = true;
	ESP_LOGW(TAG, "Flip upside down");
#endif

#if CONFIG_SSD1306_128x64
	ESP_LOGI(TAG, "Panel is 128x64");
	ssd1306_init(&dev, 128, 64);
#endif // CONFIG_SSD1306_128x64
#if CONFIG_SSD1306_128x32
	ESP_LOGE(TAG, "Panel is 128x32. This demo cannot be run.");
	while(1) { vTaskDelay(1); }
#endif // CONFIG_SSD1306_128x32
	ssd1306_contrast(&dev, 0xff);

	// Allocate memory
	uint8_t *buffer = (uint8_t *)malloc(8*128); // 8 page 128 pixel
	if (buffer == NULL) {
		ESP_LOGE(TAG, "malloc failed");
		while(1) { vTaskDelay(1); }
	}
	uint8_t *segmentImage = (uint8_t *)malloc(IMAGES*8*32); // 10 image 8 page 32pixel
	if (segmentImage == NULL) {
		ESP_LOGE(TAG, "malloc failed");
		while(1) { vTaskDelay(1); }
	}

	// Convert from segmentDisplay to segmentImage
	for (int imageIndex=0;imageIndex<IMAGES;imageIndex++) {
		ssd1306_clear_screen(&dev, false);
		ssd1306_bitmaps(&dev, 0, 8, segmentDisplay[imageIndex], 32, 48, false);
		vTaskDelay(200 / portTICK_PERIOD_MS);

		// Get from internal buffer to local buffer
		// buffer is [8][128] 8 page 128 pixel
		ssd1306_get_buffer(&dev, buffer);

		// Save from buffer to segmentImage
		// segmentImage is [10][8][32] 10 image 8 page 32 pixel
		int segmentImageIndex = imageIndex * 256;
		for (int page=0;page<8;page++) {
			//ESP_LOGI(TAG, "segmentImageIndex+page*32=%d", segmentImageIndex+page*32);
			memcpy(&segmentImage[segmentImageIndex+page*32], &buffer[page*128], 32);
			//ESP_LOGI(TAG, "page=%d", page);
			//ESP_LOG_BUFFER_HEXDUMP(TAG, &buffer[page*128], 32, ESP_LOG_INFO);
		}

#if 0
		ssd1306_clear_screen(&dev, false);
		for (int page=0;page<8;page++) {
			ssd1306_display_image(&dev, page, 0, &segmentImage[segmentImageIndex+page*32], 32);
			//ESP_LOGI(TAG, "page=%d", page);
			//ESP_LOG_BUFFER_HEXDUMP(TAG, &segmentImage[segmentImageIndex+page*32], 32, ESP_LOG_INFO);
		}
		vTaskDelay(1000 / portTICK_PERIOD_MS);
#endif
	}

	// I don't use this anymore
	free(buffer);

	int digit1 = 0;
	int digit2 = 0;
	int digit3 = 0;
	int digit4 = 0;
	ssd1306_clear_screen(&dev, false);
	for (int page=0;page<8;page++) {
		ssd1306_display_image(&dev, page, 0, &segmentImage[page*32], 32);
		ssd1306_display_image(&dev, page, 32, &segmentImage[page*32], 32);
		ssd1306_display_image(&dev, page, 64, &segmentImage[page*32], 32);
		ssd1306_display_image(&dev, page, 96, &segmentImage[page*32], 32);
		vTaskDelay(2);
	}

	while(1) {
		digit4++;
		if (digit4 == 10) {
			digit4 = 0;
			int segmentImageIndex4 = digit4 * 256;
			for (int page=0;page<8;page++) {
				ssd1306_display_image(&dev, page, 96, &segmentImage[segmentImageIndex4+page*32], 32);
			}
			digit3++;
			if (digit3 == 10) {
				digit3 = 0;
				digit2++;
				if (digit2 == 10) {
					digit2 = 0;
					digit1++;
					if (digit1 == 10) {
						digit1 = 0;
						digit2 = 0;
						digit3 = 0;
						digit4 = 0;
					}
					// Update digit1
					int segmentImageIndex1 = digit1 * 256;
					for (int page=0;page<8;page++) {
						ssd1306_display_image(&dev, page, 00, &segmentImage[segmentImageIndex1+page*32], 32);
					}
				}
				// Update digit2
				int segmentImageIndex2 = digit2 * 256;
				for (int page=0;page<8;page++) {
					ssd1306_display_image(&dev, page, 32, &segmentImage[segmentImageIndex2+page*32], 32);
				}
			}
			// Update digit3
			int segmentImageIndex3 = digit3 * 256;
			for (int page=0;page<8;page++) {
				ssd1306_display_image(&dev, page, 64, &segmentImage[segmentImageIndex3+page*32], 32);
			}
		} else {	
			// Update digit4
			int segmentImageIndex4 = digit4 * 256;
			for (int page=0;page<8;page++) {
				ssd1306_display_image(&dev, page, 96, &segmentImage[segmentImageIndex4+page*32], 32);
			}
		}
		vTaskDelay(8);
	} // end while
}

Compiling the Sketch

To flash your chip, type the following command in the serial terminal. Remember to replace the COM port with the one through which your board is connected.

idf.py -p COMX flash monitor

After the code flashes successfully, you can view the informational messages being printed showing the SSD1306 configuration parameters and its status.

ESP32 OLED using ESP-IDF CounterDemo project terminal

The OLED will start displaying the counter. Watch the video below to have a better insight.

ESP32 OLED with ESP-IDF Display Image

In this section, we will use ImageDemo by nopnop2002 uploaded on GitHub at the following link but use different images to demonstrate.

Create Project

Open your VS Code and head over to View > Command Palette. Type ESP-IDF: New Project in the search bar and press enter.

Specify the project name and directory. We have named our project ‘ESP_IDF_SSD1306_ImageDemo.’ For the ESP-IDF board, we have chosen the custom board option. For ESP-IDF target, we have chosen ESP32 module. Click ‘Choose Template’ button to proceed forward.

ESP32 OLED using ESP-IDF Create ImageDemo project

In the Extension, select ESP-IDF option:

ESP-IDF in VS Code New Project 2

We will click the ‘sample_project’ under the get-started tab. Now click ‘Create project using template sample_project.’

ESP-IDF in VS Code New Project 3

You will get a notification that the project has been created. To open the project in a new window, click ‘Yes.’

Add Libraries

This opens project that we created, inside the EXPLORER tab. There are several folders inside our project folder. Create a new folder named ‘components‘ and copy the files from this destination in your project folder. This will contain the libraries that will be required for this project.

SSD1306 Configuration

Let’s first head over to the menuconfig. Opens the ESP-IDF SDK Configuration Editor. Scroll down and open the SSD1306 Configuration. Here we can set the SSD1306 configuration parameter according to our needs. This includes the UART interface, panel type, SCL GPIO pin, SDA GPIO pin and the reset GPIO pin. Here you can view that by default, ESP-IDF is using the interface as I2C, panel type as 128×64, SCL GPIO pin as 22, SDA GPIO pin as 21 and Reset GPIO pin as 33. You can alter these parameters according to your OLED display and then click the Save button found at the top. We will leave the configuration settings as default as they match our module.

ESP32 OLED using ESP-IDF TextDemo project SDK configuration editor

Alternatively, we can also set this config value with menuconfig. Open menuconfig by typing idf.py menuconfig in the terminal. This command opens the Espressif IoT Development Framework Configuration. Head over to SSD1306 Configuration and set the parameters accordingly.

Code

Go to main > main.c and open it. We will define the functions and the program code here. This is our main.c file.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

#include "ssd1306.h"
#include "font8x8_basic.h"

/*
 You have to set this config value with menuconfig
 CONFIG_INTERFACE
 for i2c
 CONFIG_MODEL
 CONFIG_SDA_GPIO
 CONFIG_SCL_GPIO
 CONFIG_RESET_GPIO
 for SPI
 CONFIG_CS_GPIO
 CONFIG_DC_GPIO
 CONFIG_RESET_GPIO
*/

#define TAG "SSD1306"

uint8_t image1[] = {
// 'image1', 32x13px
0xfc, 0x00, 0x00, 0x3f, 0xf1, 0x03, 0x00, 0x0f, 0xc4, 0x3f, 0xf8, 0x23, 0x88, 0x07, 0xff, 0xf1, 
0xe0, 0x00, 0x00, 0xc7, 0xf8, 0x00, 0x00, 0x1f, 0xfc, 0x7f, 0xe0, 0x3f, 0xff, 0x01, 0xf8, 0xff, 
0xff, 0x80, 0x01, 0xff, 0xff, 0xe3, 0xc7, 0xff, 0xff, 0xf1, 0x8f, 0xff, 0xff, 0xfc, 0x3f, 0xff, 
0xff, 0xff, 0xff, 0xff
};

uint8_t image2 [1024] = {
// 'image2', 128x64px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x07, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x1e, 0x03, 0xff, 0xff, 0xfe, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x03, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xc0, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x07, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xf0, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0x00, 0xff, 0xf8, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x80, 0x3f, 0xfc, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x3c, 0x07, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x0f, 0xfe, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x70, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0xfc, 0x03, 0xff, 0x00, 0x00, 0x00, 
0x00, 0x00, 0xf0, 0x7f, 0xff, 0xff, 0xff, 0x80, 0x07, 0xff, 0xff, 0x01, 0xff, 0x80, 0x00, 0x00, 
0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0x80, 0x7f, 0x80, 0x00, 0x00, 
0x00, 0x01, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x7f, 0xff, 0xc0, 0x3f, 0xc0, 0x00, 0x00, 
0x00, 0x01, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xf0, 0x1f, 0xc0, 0x00, 0x00, 
0x00, 0x01, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xf8, 0x0f, 0xe0, 0x00, 0x00, 
0x00, 0x01, 0xc1, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x01, 0xff, 0xfc, 0x07, 0xe0, 0x00, 0x00, 
0x00, 0x01, 0xc3, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, 0x80, 0xff, 0xff, 0x03, 0xe0, 0x00, 0x00, 
0x00, 0x03, 0xc3, 0xc0, 0x1e, 0x00, 0x00, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0x81, 0xf0, 0x00, 0x00, 
0x00, 0x01, 0xc3, 0xcf, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xf0, 0x1f, 0xff, 0x80, 0xf0, 0x00, 0x00, 
0x00, 0x01, 0xc1, 0xff, 0xff, 0xff, 0xf0, 0x07, 0xff, 0xf8, 0x0f, 0xff, 0xc0, 0x40, 0x00, 0x00, 
0x00, 0x01, 0xc1, 0xff, 0xff, 0xff, 0xfc, 0x01, 0xff, 0xfe, 0x07, 0xff, 0xe0, 0x00, 0x00, 0x00, 
0x00, 0x01, 0xc1, 0xff, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0x03, 0xff, 0xf0, 0x00, 0x00, 0x00, 
0x00, 0x01, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0x01, 0xff, 0xf0, 0x00, 0x00, 0x00, 
0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0x80, 0xff, 0xf8, 0x00, 0x00, 0x00, 
0x00, 0x00, 0xe0, 0x7f, 0x00, 0x3f, 0xff, 0xf8, 0x0f, 0xff, 0xc0, 0xff, 0xf8, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x70, 0x10, 0x00, 0x03, 0xff, 0xfe, 0x07, 0xff, 0xc0, 0x7f, 0xfc, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x07, 0xff, 0xc0, 0x7f, 0xfc, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x03, 0xff, 0xe0, 0x7f, 0xfc, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x1e, 0x00, 0x3f, 0x00, 0x1f, 0xff, 0x01, 0xff, 0xf0, 0x7f, 0xf8, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x0f, 0x01, 0xff, 0xe0, 0x0f, 0xff, 0x81, 0xff, 0xf0, 0x3f, 0xf0, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x07, 0x81, 0xff, 0xf0, 0x0f, 0xff, 0x81, 0xff, 0xf0, 0x3f, 0xe0, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x01, 0xc3, 0xff, 0xf0, 0x0f, 0xff, 0x81, 0xff, 0xf0, 0x3f, 0x80, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0xf1, 0xff, 0xf0, 0x0f, 0xff, 0x81, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x3d, 0xff, 0xe0, 0x0f, 0xff, 0x81, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x01, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x3f, 0xff, 0x03, 0xff, 0xe0, 0x00, 0xf0, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x7f, 0xff, 0x07, 0xff, 0xe0, 0x03, 0xc0, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x1f, 0xfe, 0x03, 0xff, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x01, 0xf8, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xe1, 0x0c, 0x78, 0xfe, 0x1f, 0xf0, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xc0, 0x0c, 0x18, 0x07, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xf0, 0x0c, 0x18, 0x06, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x3e, 0x0c, 0x70, 0x7c, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x8c, 0x00, 0x07, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x8c, 0x00, 0x03, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x87, 0x0c, 0x01, 0x8f, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0xfe, 0x0c, 0x00, 0xf8, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};


void app_main(void)
{
	SSD1306_t dev;

#if CONFIG_I2C_INTERFACE
	ESP_LOGI(TAG, "INTERFACE is i2c");
	ESP_LOGI(TAG, "CONFIG_SDA_GPIO=%d",CONFIG_SDA_GPIO);
	ESP_LOGI(TAG, "CONFIG_SCL_GPIO=%d",CONFIG_SCL_GPIO);
	ESP_LOGI(TAG, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
	i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_I2C_INTERFACE

#if CONFIG_SPI_INTERFACE
	ESP_LOGI(TAG, "INTERFACE is SPI");
	ESP_LOGI(TAG, "CONFIG_MOSI_GPIO=%d",CONFIG_MOSI_GPIO);
	ESP_LOGI(TAG, "CONFIG_SCLK_GPIO=%d",CONFIG_SCLK_GPIO);
	ESP_LOGI(TAG, "CONFIG_CS_GPIO=%d",CONFIG_CS_GPIO);
	ESP_LOGI(TAG, "CONFIG_DC_GPIO=%d",CONFIG_DC_GPIO);
	ESP_LOGI(TAG, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
	spi_master_init(&dev, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_SPI_INTERFACE

#if CONFIG_FLIP
	dev._flip = true;
	ESP_LOGW(TAG, "Flip upside down");
#endif

#if CONFIG_SSD1306_128x64
	ESP_LOGI(TAG, "Panel is 128x64");
	ssd1306_init(&dev, 128, 64);
#endif // CONFIG_SSD1306_128x64
#if CONFIG_SSD1306_128x32
	ESP_LOGI(TAG, "Panel is 128x32");
	ssd1306_init(&dev, 128, 32);
#endif // CONFIG_SSD1306_128x32

	ssd1306_contrast(&dev, 0xff);

	while(1) {
		ssd1306_clear_screen(&dev, false);
#if CONFIG_SSD1306_128x64
		ssd1306_display_text(&dev, 0, "OLED IMAGE DEMO", 15, false);
#endif // CONFIG_SSD1306_128x64

#if CONFIG_SSD1306_128x32
		ssd1306_display_text(&dev, 0, "SSD1306 128x32", 14, false);
#endif // CONFIG_SSD1306_128x32
		
		int bitmapWidth = 4*8;
		int width = ssd1306_get_width(&dev);
		int xpos = width / 2; // center of width
		xpos = xpos - bitmapWidth/2; 
		int ypos = 16;
		ESP_LOGD(TAG, "width=%d xpos=%d", width, xpos);
		ssd1306_bitmaps(&dev, xpos, ypos, image1, 32, 13, false);
		vTaskDelay(3000 / portTICK_PERIOD_MS);

		for(int i=0;i<128;i++) {
			ssd1306_wrap_arround(&dev, SCROLL_RIGHT, 2, 3, 0);
		}
		vTaskDelay(2000 / portTICK_PERIOD_MS);

#if CONFIG_SSD1306_128x64
		ssd1306_clear_screen(&dev, false);
		ssd1306_bitmaps(&dev, 0, 0, image2, 128, 64, false);
		vTaskDelay(2000 / portTICK_PERIOD_MS);

		for(int i=0;i<64;i++) {
			ssd1306_wrap_arround(&dev, SCROLL_UP, 0, 127, 0);
		}
		vTaskDelay(2000 / portTICK_PERIOD_MS);

#endif
	}
}

Compiling the Sketch

To flash your chip, type the following command in the serial terminal. Remember to replace the COM port with the one through which your board is connected.

idf.py -p COMX flash monitor

After the code flashes successfully, you can view the informational messages being printed showing the SSD1306 configuration parameters and its status.

ESP32 OLED using ESP-IDF ImageDemo project terminal

The OLED will start displaying the images. Watch the video below to have a better insight.

ESP32 OLED with ESP-IDF Display Scrolling Image

In this section, we will demonstrate ImageScrollDemo by nopnop2002 uploaded on GitHub at the following link:

Create Project

Open your VS Code and head over to View > Command Palette. Type ESP-IDF: New Project in the search bar and press enter.

Specify the project name and directory. We have named our project ‘ESP_IDF_SSD1306_ImageScrollDemo.’ For the ESP-IDF board, we have chosen the custom board option. For ESP-IDF target, we have chosen ESP32 module. Click ‘Choose Template’ button to proceed forward.

ESP32 OLED using ESP-IDF Create ImageScrollDemo project

In the Extension, select ESP-IDF option:

ESP-IDF in VS Code New Project 2

We will click the ‘sample_project’ under the get-started tab. Now click ‘Create project using template sample_project.’

ESP-IDF in VS Code New Project 3

You will get a notification that the project has been created. To open the project in a new window, click ‘Yes.’

Add Libraries

This opens project that we created, inside the EXPLORER tab. There are several folders inside our project folder. Create a new folder named ‘components‘ and copy the files from this destination into your project folder. This will contain the libraries that will be required for this project.

SSD1306 Configuration

Let’s first head over to the menuconfig. Opens the ESP-IDF SDK Configuration Editor. Scroll down and open the SSD1306 Configuration. Here we can set the SSD1306 configuration parameter according to our needs. This includes the UART interface, panel type, SCL GPIO pin, SDA GPIO pin and the reset GPIO pin. Here you can view that by default, ESP-IDF is using the interface as I2C, panel type as 128×64, SCL GPIO pin as 22, SDA GPIO pin as 21 and Reset GPIO pin as 33. You can alter these parameters according to your OLED display and then click the Save button found at the top. We will leave the configuration settings as default as they match our module.

ESP32 OLED using ESP-IDF TextDemo project SDK configuration editor

Alternatively, we can also set this config value with menuconfig. Open menuconfig by typing idf.py menuconfig in the terminal. This command opens the Espressif IoT Development Framework Configuration. Head over to SSD1306 Configuration and set the parameters accordingly.

Code

Go to main > main.c and open it. We will define the functions and the program code here. Copy the code from this link here.

This is our main.c file.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

#include "ssd1306.h"
#include "font8x8_basic.h"

/*
 You have to set this config value with menuconfig
 CONFIG_INTERFACE
 for i2c
 CONFIG_MODEL
 CONFIG_SDA_GPIO
 CONFIG_SCL_GPIO
 CONFIG_RESET_GPIO
 for SPI
 CONFIG_CS_GPIO
 CONFIG_DC_GPIO
 CONFIG_RESET_GPIO
*/

#define TAG "SSD1306"

#define NUM_IMAGES 7

#define IMAGE_WIDTH 48

// (48/6)*62=372
#define BITMAPS 372
uint8_t segmentDisplay[NUM_IMAGES][BITMAPS] = {
{
// https://www.iconspng.com/image/94065/16-segment-display-h
// '16-segment-display-h', 48x62px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x70, 
0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 
0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x1e, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x1e, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x1e, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 
0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 
0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 
0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x27, 
0xf8, 0x1f, 0xf6, 0x00, 0x00, 0x1f, 0xfe, 0x7f, 0xf8, 0x00, 0x00, 0x1f, 0xfc, 0x7f, 0xf0, 0x00, 
0x00, 0x6f, 0xf0, 0x1f, 0xee, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x1e, 0x00, 0x01, 0xe0, 0x00, 0x00, 
0x1e, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x1e, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x1e, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x3e, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x3c, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x3c, 0x00, 
0x03, 0xc0, 0x00, 0x00, 0x3c, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x3c, 0x00, 0x03, 0xc0, 0x00, 0x00, 
0x3c, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x78, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x78, 0x00, 0x07, 0x80, 
0x00, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x00, 0x78, 0x00, 
0x07, 0x80, 0x00, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 
0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 
0x00, 0x00, 0xf0, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x60, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00
},
{
// https://www.iconspng.com/image/94062/16-segment-display-e
// '16-segment-display-e', 48x62px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0xff, 0xc0, 0xff, 0x80, 0x00, 0x01, 0xff, 0xe1, 0xff, 0xc0, 0x00, 0x01, 
0xff, 0xf3, 0xff, 0xc0, 0x00, 0x06, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 
0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x00, 
0x00, 0x6f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 
0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 
0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 
0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xff, 0xc7, 0xff, 0x00, 0x00, 
0x03, 0xff, 0xcf, 0xff, 0x80, 0x00, 0x07, 0xff, 0x87, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00
},
{
// '16-segment-display-l', 48x62px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 
0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 
0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 
0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xff, 0xc7, 0xff, 0x00, 0x00, 
0x03, 0xff, 0xcf, 0xff, 0x80, 0x00, 0x07, 0xff, 0x87, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00
},
{
// '16-segment-display-o', 48x62px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0xff, 0xc0, 0xff, 0xc0, 0x00, 0x01, 0xff, 0xe1, 0xff, 0xc0, 0x00, 0x01, 
0xff, 0xf3, 0xff, 0xc0, 0x00, 0x06, 0xff, 0xe3, 0xff, 0x30, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x70, 
0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 
0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x1e, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x1e, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x1e, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 
0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 
0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 
0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x20, 
0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x60, 0x00, 0x00, 0x0e, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x1e, 0x00, 0x01, 0xe0, 0x00, 0x00, 
0x1e, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x1e, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x1e, 0x00, 0x01, 0xe0, 
0x00, 0x00, 0x3e, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x3c, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x3c, 0x00, 
0x03, 0xc0, 0x00, 0x00, 0x3c, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x3c, 0x00, 0x03, 0xc0, 0x00, 0x00, 
0x3c, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x78, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x78, 0x00, 0x07, 0x80, 
0x00, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x00, 0x78, 0x00, 
0x07, 0x80, 0x00, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 
0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 
0x00, 0x00, 0xf0, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0d, 0xff, 0xc7, 0xff, 0x60, 0x00, 
0x03, 0xff, 0xcf, 0xff, 0x80, 0x00, 0x07, 0xff, 0x87, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00
},
{
// '16-segment-display-w', 48x62px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x70, 
0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 
0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x1e, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x1e, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x1e, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 
0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 
0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 
0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x20, 
0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 
0x00, 0x60, 0x06, 0xc0, 0x0e, 0x00, 0x00, 0xf0, 0x1c, 0xe0, 0x1e, 0x00, 0x01, 0xe0, 0x1c, 0x60, 
0x1e, 0x00, 0x01, 0xe0, 0x38, 0x70, 0x1e, 0x00, 0x01, 0xe0, 0x78, 0x70, 0x1e, 0x00, 0x01, 0xe0, 
0xf0, 0x70, 0x3e, 0x00, 0x01, 0xe0, 0xf0, 0x78, 0x3c, 0x00, 0x03, 0xe1, 0xe0, 0x78, 0x3c, 0x00, 
0x03, 0xc3, 0xe0, 0x78, 0x3c, 0x00, 0x03, 0xc3, 0xc0, 0x3c, 0x3c, 0x00, 0x03, 0xc7, 0xc0, 0x3c, 
0x3c, 0x00, 0x03, 0xcf, 0x80, 0x3e, 0x78, 0x00, 0x07, 0xdf, 0x00, 0x1e, 0x78, 0x00, 0x07, 0x9e, 
0x00, 0x1e, 0x78, 0x00, 0x07, 0xbe, 0x00, 0x1f, 0x78, 0x00, 0x07, 0xbc, 0x00, 0x0f, 0x78, 0x00, 
0x07, 0xf8, 0x00, 0x0f, 0x78, 0x00, 0x07, 0xf8, 0x00, 0x07, 0xf0, 0x00, 0x0f, 0x70, 0x00, 0x07, 
0xf0, 0x00, 0x0f, 0x40, 0x00, 0x02, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x0f, 0x00, 
0x00, 0x00, 0xf0, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x60, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00
},
{
// '16-segment-display-r', 48x62px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0xff, 0xc0, 0xff, 0xc0, 0x00, 0x01, 0xff, 0xe1, 0xff, 0xc0, 0x00, 0x01, 
0xff, 0xf3, 0xff, 0xc0, 0x00, 0x06, 0xff, 0xe3, 0xff, 0x30, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x70, 
0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 
0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x1e, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x1e, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x1e, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 
0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 
0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 
0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x78, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x27, 
0xf8, 0x1f, 0xf6, 0x00, 0x00, 0x1f, 0xfe, 0x7f, 0xf8, 0x00, 0x00, 0x1f, 0xfc, 0xff, 0xf0, 0x00, 
0x00, 0x6f, 0xf0, 0xdf, 0xe0, 0x00, 0x00, 0xf0, 0x00, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x60, 
0x00, 0x00, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x00, 0x01, 0xe0, 
0x00, 0x70, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x78, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x78, 0x00, 0x00, 
0x03, 0xc0, 0x00, 0x78, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3c, 
0x00, 0x00, 0x03, 0xc0, 0x00, 0x3e, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x1e, 0x00, 0x00, 0x07, 0x80, 
0x00, 0x1e, 0x00, 0x00, 0x07, 0x80, 0x00, 0x1f, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0f, 0x00, 0x00, 
0x07, 0x80, 0x00, 0x0f, 0x00, 0x00, 0x07, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x07, 
0x00, 0x00, 0x0f, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0f, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00
},
{
// '16-segment-display-d', 48x62px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0xff, 0xc0, 0xff, 0xc0, 0x00, 0x01, 0xff, 0xe1, 0xff, 0xc0, 0x00, 0x01, 
0xff, 0xf3, 0xff, 0xc0, 0x00, 0x00, 0xff, 0xeb, 0xff, 0x30, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x70, 
0x00, 0x00, 0x00, 0x3c, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x3c, 
0x00, 0xf0, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x78, 0x01, 0xe0, 0x00, 0x00, 
0x00, 0x78, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x78, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x78, 0x01, 0xe0, 
0x00, 0x00, 0x00, 0xf8, 0x01, 0xc0, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0xf0, 
0x03, 0xc0, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xc0, 0x00, 0x00, 
0x01, 0xf0, 0x03, 0xc0, 0x00, 0x00, 0x01, 0xf0, 0x07, 0x80, 0x00, 0x00, 0x01, 0xe0, 0x07, 0x80, 
0x00, 0x00, 0x01, 0xe0, 0x07, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x80, 0x00, 0x00, 0x00, 0xc0, 
0x07, 0x80, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 
0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, 
0x07, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x3c, 0x00, 
0x00, 0x00, 0x0f, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x00, 
0x3c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x78, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x78, 0x00, 0x00, 0x00, 
0x1e, 0x00, 0x78, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x78, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x78, 0x00, 
0x00, 0x00, 0x1e, 0x00, 0x78, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x3c, 0x00, 
0xf0, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xf0, 0x00, 0x00, 0x00, 
0x3c, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x38, 0x00, 0xf0, 0x00, 0x01, 0xff, 0xc7, 0xff, 0x60, 0x00, 
0x03, 0xff, 0xcf, 0xff, 0x80, 0x00, 0x07, 0xff, 0x87, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00
}
};

//                  H  E  L  L  O  SP  W  O  R  L  D
int imageTable[] = {0, 1, 2, 2, 3, -1, 4, 3, 5, 2, 6};


void app_main(void)
{
	SSD1306_t dev;

#if CONFIG_I2C_INTERFACE
	ESP_LOGI(TAG, "INTERFACE is i2c");
	ESP_LOGI(TAG, "CONFIG_SDA_GPIO=%d",CONFIG_SDA_GPIO);
	ESP_LOGI(TAG, "CONFIG_SCL_GPIO=%d",CONFIG_SCL_GPIO);
	ESP_LOGI(TAG, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
	i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_I2C_INTERFACE

#if CONFIG_SPI_INTERFACE
	ESP_LOGI(TAG, "INTERFACE is SPI");
	ESP_LOGI(TAG, "CONFIG_MOSI_GPIO=%d",CONFIG_MOSI_GPIO);
	ESP_LOGI(TAG, "CONFIG_SCLK_GPIO=%d",CONFIG_SCLK_GPIO);
	ESP_LOGI(TAG, "CONFIG_CS_GPIO=%d",CONFIG_CS_GPIO);
	ESP_LOGI(TAG, "CONFIG_DC_GPIO=%d",CONFIG_DC_GPIO);
	ESP_LOGI(TAG, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
	spi_master_init(&dev, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_SPI_INTERFACE

#if CONFIG_FLIP
	dev._flip = true;
	ESP_LOGW(TAG, "Flip upside down");
#endif

#if CONFIG_SSD1306_128x64
	ESP_LOGI(TAG, "Panel is 128x64");
	ssd1306_init(&dev, 128, 64);
#endif // CONFIG_SSD1306_128x64
#if CONFIG_SSD1306_128x32
	ESP_LOGE(TAG, "Panel is 128x32. This demo cannot be run.");
	while(1) { vTaskDelay(1); }
#endif // CONFIG_SSD1306_128x32
	ssd1306_contrast(&dev, 0xff);

	int numOfTable = sizeof(imageTable)/sizeof(int);
	ESP_LOGI(TAG, "numOfTable=%d", numOfTable);
	// Allocate memory
	uint8_t *buffer = (uint8_t *)malloc(8*128); // 8 page 128 pixel
	if (buffer == NULL) {
		ESP_LOGE(TAG, "malloc failed");
		while(1) { vTaskDelay(1); }
	}
	uint8_t *segmentImage = (uint8_t *)malloc(NUM_IMAGES*8*IMAGE_WIDTH); // 10 image 8 page 48 pixel
	if (segmentImage == NULL) {
		ESP_LOGE(TAG, "malloc failed");
		while(1) { vTaskDelay(1); }
	}

	// Convert from segmentDisplay to segmentImage
	for (int imageIndex=0;imageIndex<NUM_IMAGES;imageIndex++) {
		ssd1306_clear_screen(&dev, false);
		ssd1306_bitmaps(&dev, 0, 1, segmentDisplay[imageIndex], IMAGE_WIDTH, 62, false);
		vTaskDelay(200 / portTICK_PERIOD_MS);

		// Get from internal buffer to local buffer
		// buffer is [8][128] 8 page 128 pixel
		ssd1306_get_buffer(&dev, buffer);

		// Save from buffer to segmentImage
		// segmentImage is [10][8][IMAGE_WIDTH] 10 image 8 page 48 pixel
		int segmentImageIndex = imageIndex * BITMAPS;
		for (int page=0;page<8;page++) {
			//ESP_LOGI(TAG, "segmentImageIndex+page*IMAGE_WIDTH=%d", segmentImageIndex+page*IMAGE_WIDTH);
			memcpy(&segmentImage[segmentImageIndex+page*IMAGE_WIDTH], &buffer[page*128], IMAGE_WIDTH);
			//ESP_LOGI(TAG, "page=%d", page);
			//ESP_LOG_BUFFER_HEXDUMP(TAG, &buffer[page*128], IMAGE_WIDTH, ESP_LOG_INFO);
		}

#if 0
		ssd1306_clear_screen(&dev, false);
		for (int page=0;page<8;page++) {
			ssd1306_display_image(&dev, page, 0, &segmentImage[segmentImageIndex+page*IMAGE_WIDTH], IMAGE_WIDTH);
			//ESP_LOGI(TAG, "page=%d", page);
			//ESP_LOG_BUFFER_HEXDUMP(TAG, &segmentImage[segmentImageIndex+page*IMAGE_WIDTH], IMAGE_WIDTH, ESP_LOG_INFO);
		}
		vTaskDelay(1000 / portTICK_PERIOD_MS);
#endif
	}

	int imageIndex = 0;
	int imageSegment = 0;
	ssd1306_clear_screen(&dev, false);

	while(1) {

		// Shift segment data left by 2 bits
		for (int page=0;page<8;page++) {
			int bufferIndex = page*128;
			memcpy(&buffer[bufferIndex], &buffer[bufferIndex+2], 126);
		}

		// Insert 2 bits at the end of segment data
		if (imageTable[imageIndex] >= 0) {
			int segmentImageIndex = imageTable[imageIndex] * BITMAPS;
			for (int page=0;page<8;page++) {
				int bufferIndex = page*128+126;
				buffer[bufferIndex] = segmentImage[segmentImageIndex+page*IMAGE_WIDTH+imageSegment];
				buffer[bufferIndex+1] = segmentImage[segmentImageIndex+page*IMAGE_WIDTH+imageSegment+1];
			}
		} else {
			for (int page=0;page<8;page++) {
				int bufferIndex = page*128+126;
				buffer[bufferIndex] = 0;
				buffer[bufferIndex+1] = 0;
			}
		}
		imageSegment=imageSegment+2;	
		ssd1306_set_buffer(&dev, buffer);
		ssd1306_show_buffer(&dev);
		//vTaskDelay(5);

		// End of display of one character
		if (imageSegment == IMAGE_WIDTH) {
			imageIndex++;
			if (imageIndex == numOfTable) {
				// All characters have been displayed.
				// Scroll to last character.
				for (int segs=0;segs<64;segs++) {
					for (int page=0;page<8;page++) {
						int bufferIndex = page*128;
						memcpy(&buffer[bufferIndex], &buffer[bufferIndex+2], 126);
					}
					for (int page=0;page<8;page++) {
						int bufferIndex = page*128+126;
						buffer[bufferIndex]=0;
						buffer[bufferIndex+1]=0;
					}
					ssd1306_set_buffer(&dev, buffer);
					ssd1306_show_buffer(&dev);
				}
				imageIndex = 0;
			}
			imageSegment = 0;
		}
	} // end while
	free(buffer);
}

Compiling the Sketch

To flash your chip, type the following command in the serial terminal. Remember to replace the COM port with the one through which your board is connected.

idf.py -p COMX flash monitor

After the code flashes successfully, you can view the informational messages being printed showing the SSD1306 configuration parameters and its status.

ESP32 OLED using ESP-IDF ImageScrollDemo project terminal

The OLED will start displaying the alphabets images that will scroll across the screen, showing the message HELLO WORLD. Watch the video below to have a better insight.

You may also like to read:

6 thoughts on “Interface OLED with ESP32 using ESP-IDF”

  1. Nice tutorial.
    I was strugling to make it works. I looked for some detailed instructions, but found just some pieces of code and videos using arduino IDE.
    Nice work.

    Reply
  2. These examples only show how to display characters and bitmaps. What if i had a temp sensor and i wanted to display the temperature which is a float datatype. How to display that to the oled?

    Thanks

    Reply
  3. And why OLED only displays how the whole system is connected as you can see on your Demo. So the whole system is powered via USB from the ESP board. Note and if the voltage is 5V or 3.3V from the power supply to the ESP, the display does not display anything. Such a cool problem Why doesn’t the OLED light up.

    Reply

Leave a Comment