Hey everyone!
I've been pulling my hair out in few past days trying to get the display working, I have done it in IDF v4.4 (https://github.com/KamranAghlami/T-Display-S3.git) but for some reason I can't figure it out in version 5.0, I'm a software guy with relatively limited knowledge of hardware.
Thought I'd ask here if any one has done it or has any idea why my code isn't working.
I'll copy my example code which is based on esp32's i80 display example.
Thanks in advance
#include <stdio.h>
#include "string.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_timer.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_vendor.h"
#include "esp_lcd_panel_ops.h"
#include "driver/gpio.h"
#include "esp_err.h"
#include "esp_log.h"
static const char *TAG = "example";
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////// Please update the following configuration according to your LCD spec //////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (2 * 1000 * 1000)
#define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 1
#define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL
#define EXAMPLE_PIN_NUM_DATA0 39 // 6
#define EXAMPLE_PIN_NUM_DATA1 40 // 7
#define EXAMPLE_PIN_NUM_DATA2 41 // 8
#define EXAMPLE_PIN_NUM_DATA3 42 // 9
#define EXAMPLE_PIN_NUM_DATA4 45 // 10
#define EXAMPLE_PIN_NUM_DATA5 46 // 11
#define EXAMPLE_PIN_NUM_DATA6 47 // 12
#define EXAMPLE_PIN_NUM_DATA7 48 // 13
#define EXAMPLE_PIN_NUM_PCLK 8 // 5
#define EXAMPLE_PIN_NUM_CS 6 // 3
#define EXAMPLE_PIN_NUM_DC 7 // 4
#define EXAMPLE_PIN_NUM_RST 5 // 2
#define EXAMPLE_PIN_NUM_BK_LIGHT 38 // 1
#define EXAMPLE_PIN_NUM_POWER 15
// The pixel number in horizontal and vertical
#define EXAMPLE_LCD_H_RES 320
#define EXAMPLE_LCD_V_RES 170
// Bit number used to represent command and parameter
#define EXAMPLE_LCD_CMD_BITS 8
#define EXAMPLE_LCD_PARAM_BITS 8
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
// Supported alignment: 16, 32, 64. A higher alignment can enables higher burst transfer size, thus a higher i80 bus throughput.
#define EXAMPLE_PSRAM_DATA_ALIGNMENT 32
void *buf1 = NULL;
void *buf2 = NULL;
size_t buff_idx = 0;
static bool trans_done = true;
static void write_color(esp_lcd_panel_handle_t panel_handle)
{
if (!trans_done)
return;
trans_done = false;
void *buff = (buff_idx++ % 2) ? buf1 : buf2;
esp_lcd_panel_draw_bitmap(panel_handle, 32, 32, 64, 64, buff);
}
size_t trans_done_calls = 0;
static bool on_color_trans_done(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
{
trans_done = true;
trans_done_calls++;
return false;
}
static void tick_timer_cb(void *arg)
{
ESP_LOGI(TAG, "trans_done_calls: %zu", trans_done_calls);
trans_done_calls = 0;
}
void app_main(void)
{
gpio_config_t pwr_gpio_config = {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_POWER};
ESP_ERROR_CHECK(gpio_config(&pwr_gpio_config));
gpio_set_level(EXAMPLE_PIN_NUM_POWER, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
ESP_LOGI(TAG, "Turn off LCD backlight");
gpio_config_t bk_gpio_config = {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT};
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL);
ESP_LOGI(TAG, "Initialize Intel 8080 bus");
esp_lcd_i80_bus_handle_t i80_bus = NULL;
esp_lcd_i80_bus_config_t bus_config = {
.clk_src = LCD_CLK_SRC_DEFAULT,
.dc_gpio_num = EXAMPLE_PIN_NUM_DC,
.wr_gpio_num = EXAMPLE_PIN_NUM_PCLK,
.data_gpio_nums = {
EXAMPLE_PIN_NUM_DATA0,
EXAMPLE_PIN_NUM_DATA1,
EXAMPLE_PIN_NUM_DATA2,
EXAMPLE_PIN_NUM_DATA3,
EXAMPLE_PIN_NUM_DATA4,
EXAMPLE_PIN_NUM_DATA5,
EXAMPLE_PIN_NUM_DATA6,
EXAMPLE_PIN_NUM_DATA7,
},
.bus_width = CONFIG_EXAMPLE_LCD_I80_BUS_WIDTH,
.max_transfer_bytes = EXAMPLE_LCD_H_RES * 100 * sizeof(uint16_t),
.psram_trans_align = EXAMPLE_PSRAM_DATA_ALIGNMENT,
.sram_trans_align = 4,
};
ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
esp_lcd_panel_io_handle_t io_handle = NULL;
esp_lcd_panel_io_i80_config_t io_config = {
.cs_gpio_num = EXAMPLE_PIN_NUM_CS,
.pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
.trans_queue_depth = 20,
.dc_levels = {
.dc_idle_level = 0,
.dc_cmd_level = 0,
.dc_dummy_level = 0,
.dc_data_level = 1,
},
.flags = {
.swap_color_bytes = 1, // Swap can be done in LvGL (default) or DMA
},
.on_color_trans_done = on_color_trans_done,
.user_ctx = NULL,
.lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
.lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle));
esp_lcd_panel_handle_t panel_handle = NULL;
ESP_LOGI(TAG, "Install LCD driver of st7789");
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_PIN_NUM_RST,
.rgb_endian = LCD_RGB_ENDIAN_RGB,
.bits_per_pixel = 16,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
esp_lcd_panel_reset(panel_handle);
esp_lcd_panel_init(panel_handle);
// Set inversion, x/y coordinate order, x/y mirror according to your LCD module spec
// the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true));
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true));
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, false, true));
ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel_handle, 0, 35));
ESP_LOGI(TAG, "Turn on LCD backlight");
gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
ESP_LOGI(TAG, "Initialize UI");
// alloc draw buffers used by LVGL
// it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized
buf1 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 100 * 2, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
buf2 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 100 * 2, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
assert(buf1);
assert(buf2);
memset(buf1, 0x0, EXAMPLE_LCD_H_RES * 100 * 2);
memset(buf2, 0xff, EXAMPLE_LCD_H_RES * 100 * 2);
ESP_LOGI(TAG, "buf1@%p, buf2@%p", buf1, buf2);
const esp_timer_create_args_t tick_timer_args = {
.callback = &tick_timer_cb,
.name = "tick_timer"};
esp_timer_handle_t tick_timer = NULL;
ESP_ERROR_CHECK(esp_timer_create(&tick_timer_args, &tick_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(tick_timer, 1000000));
// user can flush pre-defined pattern to the screen before we turn on the screen or backlight
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
while (1)
{
write_color(panel_handle);
vTaskDelay(pdMS_TO_TICKS(10));
}
}