Skip to content

Commit

Permalink
7701
Browse files Browse the repository at this point in the history
  • Loading branch information
rzeldent committed Mar 8, 2024
1 parent 5d0258d commit a5a1c7a
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 140 deletions.
3 changes: 2 additions & 1 deletion include/esp_panel_st7701.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <esp_lcd.h>
#include <esp_lcd_types.h>
#include <esp_lcd_panel_rgb.h>
#include <esp_lcd_panel_vendor.h>

#ifdef __cplusplus
Expand All @@ -15,7 +16,7 @@ extern "C"
uint16_t init_cmds_size;
} st7701_vendor_config_t;

esp_err_t esp_lcd_new_panel_st7701(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *config, esp_lcd_panel_handle_t *handle);
esp_err_t esp_lcd_new_panel_st7701(const esp_lcd_panel_io_handle_t io, const esp_lcd_rgb_panel_config_t *panel_config, const esp_lcd_panel_dev_config_t *config, esp_lcd_panel_handle_t *handle);

#ifdef __cplusplus
}
Expand Down
200 changes: 65 additions & 135 deletions src/esp_panel_st7701.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#ifdef LCD_ST7701_SPI
#ifdef LCD_ST7701_PAR

#include <esp_panel_st7701.h>
#include <esp32-hal-log.h>
Expand All @@ -9,19 +9,18 @@
#include <esp_lcd_types.h>
#include <esp_lcd_panel_interface.h>
#include <esp_lcd_panel_io.h>
#include <esp_lcd_panel_ops.h>

//#define ST7701_CMD_SDIR (0xC7)
//#define ST7701_CMD_SS_BIT (1 << 2)
#define ST7701_CMD_CND2BKxSEL 0xFF

typedef struct
{
esp_lcd_panel_t base;
esp_lcd_panel_io_handle_t io;
esp_lcd_panel_dev_config_t config;
esp_lcd_panel_dev_config_t panel_dev_config;
// Data
int x_gap;
int y_gap;
uint8_t madctl;
esp_lcd_panel_t *lcd_panel;
} st7701_panel_t;

const lcd_init_cmd_t st7701_vendor_specific_init_default[] = {
Expand Down Expand Up @@ -76,16 +75,17 @@ esp_err_t st7701_reset(esp_lcd_panel_t *panel)

const st7701_panel_t *ph = (st7701_panel_t *)panel;

if (ph->config.reset_gpio_num != GPIO_NUM_NC)
esp_err_t res;

if (ph->panel_dev_config.reset_gpio_num != GPIO_NUM_NC)
{
// Hardware reset
gpio_set_level(ph->config.reset_gpio_num, ph->config.flags.reset_active_high);
gpio_set_level(ph->panel_dev_config.reset_gpio_num, ph->panel_dev_config.flags.reset_active_high);
vTaskDelay(pdMS_TO_TICKS(1));
gpio_set_level(ph->config.reset_gpio_num, !ph->config.flags.reset_active_high);
gpio_set_level(ph->panel_dev_config.reset_gpio_num, !ph->panel_dev_config.flags.reset_active_high);
}
else
{
esp_err_t res;
// Software reset
if ((res = esp_lcd_panel_io_tx_param(ph->io, LCD_CMD_SWRESET, NULL, 0)) != ESP_OK)
{
Expand All @@ -96,6 +96,12 @@ esp_err_t st7701_reset(esp_lcd_panel_t *panel)

vTaskDelay(pdMS_TO_TICKS(5));

if ((res = esp_lcd_panel_reset(ph->lcd_panel)) != ESP_OK)
{
log_e("Failed to reset RGB panel");
return res;
}

return ESP_OK;
}

Expand All @@ -108,16 +114,17 @@ esp_err_t st7701_init(esp_lcd_panel_t *panel)
const st7701_panel_t *ph = (st7701_panel_t *)panel;

esp_err_t res;
if ((res = esp_lcd_panel_io_tx_param(ph->io, LCD_CMD_SLPOUT, NULL, 0)) != ESP_OK)
const uint8_t bkxsel[] = {0x77, 0x01, 0x00, 0x00, 0x00};
if ((res = esp_lcd_panel_io_tx_param(ph->io, ST7701_CMD_CND2BKxSEL, bkxsel, sizeof(bkxsel))) != ESP_OK)
{
log_e("Sending SLPOUT failed");
log_e("Sending ST7701_CMD_CND2BKxSEL failed");
return res;
}

vTaskDelay(pdMS_TO_TICKS(100));

uint8_t colmod;
switch (ph->config.bits_per_pixel)
switch (ph->panel_dev_config.bits_per_pixel)
{
case 16: // RGB565
colmod = 0x50;
Expand All @@ -129,7 +136,7 @@ esp_err_t st7701_init(esp_lcd_panel_t *panel)
colmod = 0x70;
break;
default:
log_e("Invalid bits per pixel: %d. Only RGB565, RGB666 and RGB888 are supported", ph->config.bits_per_pixel);
log_e("Invalid bits per pixel: %d. Only RGB565, RGB666 and RGB888 are supported", ph->panel_dev_config.bits_per_pixel);
return ESP_ERR_INVALID_ARG;
}

Expand All @@ -142,10 +149,10 @@ esp_err_t st7701_init(esp_lcd_panel_t *panel)

const lcd_init_cmd_t *cmd = st7701_vendor_specific_init_default;
uint16_t cmds_size = sizeof(st7701_vendor_specific_init_default) / sizeof(lcd_init_cmd_t);
if (ph->config.vendor_config != NULL)
if (ph->panel_dev_config.vendor_config != NULL)
{
cmd = ((st7701_vendor_config_t *)ph->config.vendor_config)->init_cmds;
cmds_size = ((st7701_vendor_config_t *)ph->config.vendor_config)->init_cmds_size;
cmd = ((st7701_vendor_config_t *)ph->panel_dev_config.vendor_config)->init_cmds;
cmds_size = ((st7701_vendor_config_t *)ph->panel_dev_config.vendor_config)->init_cmds_size;
}

while (cmds_size-- > 0)
Expand All @@ -160,153 +167,61 @@ esp_err_t st7701_init(esp_lcd_panel_t *panel)
cmd++;
}

if ((res = esp_lcd_panel_init(ph->lcd_panel)) != ESP_OK)
{
log_e("Initializing panel failed");
return res;
}

return ESP_OK;
}

esp_err_t st7701_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
{
log_v("panel:0x%08x, x_start:%d, y_start:%d, x_end:%d, y_end:%d, color_data:0x%08x", panel, x_start, y_start, x_end, y_end, color_data);
if (panel == NULL || color_data == NULL)
return ESP_ERR_INVALID_ARG;

const st7701_panel_t *ph = (st7701_panel_t *)panel;

if (x_start >= x_end)
{
log_w("X-start greater than the x-end");
return ESP_ERR_INVALID_ARG;
}

if (y_start >= y_end)
{
log_w("Y-start greater than the y-end");
return ESP_ERR_INVALID_ARG;
}

// Correct for gap
x_start += ph->x_gap;
x_end += ph->x_gap;
y_start += ph->y_gap;
y_end += ph->y_gap;

esp_err_t res;
const uint8_t caset[4] = {x_start >> 8, x_start, (x_end - 1) >> 8, (x_end - 1)};
const uint8_t raset[4] = {y_start >> 8, y_start, (y_end - 1) >> 8, (y_end - 1)};
if ((res = esp_lcd_panel_io_tx_param(ph->io, LCD_CMD_CASET, caset, sizeof(caset))) != ESP_OK ||
(res = esp_lcd_panel_io_tx_param(ph->io, LCD_CMD_RASET, raset, sizeof(raset))) != ESP_OK)
{
log_e("Sending CASET/RASET failed");
return res;
}

uint8_t bytes_per_pixel = (ph->config.bits_per_pixel + 0x7) >> 3;
size_t len = (x_end - x_start) * (y_end - y_start) * bytes_per_pixel;
if ((res = esp_lcd_panel_io_tx_color(ph->io, LCD_CMD_RAMWR, color_data, len)) != ESP_OK)
{
log_e("Sending RAMWR failed");
return res;
}

return ESP_OK;
return esp_lcd_panel_draw_bitmap(ph->lcd_panel, x_start, y_start, x_end, y_end, color_data);
}

esp_err_t st7701_invert_color(esp_lcd_panel_t *panel, bool invert)
{
log_v("panel:0x%08x, invert:%d", panel, invert);
if (panel == NULL)
return ESP_ERR_INVALID_ARG;

const st7701_panel_t *ph = (st7701_panel_t *)panel;

esp_err_t res;
if ((res = esp_lcd_panel_io_tx_param(ph->io, invert ? LCD_CMD_INVON : LCD_CMD_INVOFF, NULL, 0)) != ESP_OK)
{
log_e("Sending LCD_CMD_INVON/LCD_CMD_INVOFF failed");
return res;
}

return ESP_OK;
}

esp_err_t st7701_update_madctl(st7701_panel_t *ph)
{
esp_err_t res;
if ((res = esp_lcd_panel_io_tx_param(ph->io, LCD_CMD_MADCTL, &ph->madctl, 1)) != ESP_OK)
{
log_e("Sending LCD_CMD_MADCTL failed");
return res;
}

return ESP_OK;
return esp_lcd_panel_invert_color(ph->lcd_panel, invert);
}

esp_err_t st7701_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
{
log_v("panel:0x%08x, mirror_x:%d, mirror_y:%d", panel, mirror_x, mirror_y);
if (panel == NULL)
return ESP_ERR_INVALID_ARG;

st7701_panel_t *ph = (st7701_panel_t *)panel;

if (mirror_x)
ph->madctl |= LCD_CMD_MX_BIT;
else
ph->madctl &= ~LCD_CMD_MX_BIT;

if (mirror_y)
ph->madctl |= LCD_CMD_MY_BIT;
else
ph->madctl &= ~LCD_CMD_MY_BIT;

return st7701_update_madctl(ph);
return esp_lcd_panel_mirror(ph->lcd_panel, mirror_x, mirror_y);
}

esp_err_t st7701_swap_xy(esp_lcd_panel_t *panel, bool swap_xy)
{
log_v("panel:0x%08x, swap_xy:%d", panel, swap_xy);
if (panel == NULL)
return ESP_ERR_INVALID_ARG;

st7701_panel_t *ph = (st7701_panel_t *)panel;

if (swap_xy)
ph->madctl |= LCD_CMD_MV_BIT;
else
ph->madctl &= ~LCD_CMD_MV_BIT;

return st7701_update_madctl(ph);
return esp_lcd_panel_swap_xy(ph->lcd_panel, swap_xy);
}

esp_err_t st7701_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
{
log_v("panel:0x%08x, x_gap:%d, y_gap:%d", panel, x_gap, y_gap);
if (panel == NULL)
return ESP_ERR_INVALID_ARG;

st7701_panel_t *ph = (st7701_panel_t *)panel;

ph->x_gap = x_gap;
ph->y_gap = y_gap;

return ESP_OK;
return esp_lcd_panel_set_gap(ph->lcd_panel, x_gap, y_gap);
}

esp_err_t st7701_disp_off(esp_lcd_panel_t *panel, bool off)
{
log_v("panel:0x%08x, off:%d", panel, off);
if (panel == NULL)
return ESP_ERR_INVALID_ARG;

const st7701_panel_t *ph = (st7701_panel_t *)panel;

esp_err_t res;
if ((res = esp_lcd_panel_io_tx_param(ph->io, off ? LCD_CMD_DISPOFF : LCD_CMD_DISPON, NULL, 0)) != ESP_OK)
{
log_e("Sending LCD_CMD_DISPOFF/LCD_CMD_DISPON failed");
return res;
}

return ESP_OK;
return esp_lcd_panel_disp_off(ph->lcd_panel, off);
}

esp_err_t st7701_del(esp_lcd_panel_t *panel)
Expand All @@ -317,29 +232,31 @@ esp_err_t st7701_del(esp_lcd_panel_t *panel)

st7701_panel_t *ph = (st7701_panel_t *)panel;

// Delete the RGB Panel
esp_lcd_panel_del(ph->lcd_panel);
// Reset RESET
if (ph->config.reset_gpio_num != GPIO_NUM_NC)
gpio_reset_pin(ph->config.reset_gpio_num);
if (ph->panel_dev_config.reset_gpio_num != GPIO_NUM_NC)
gpio_reset_pin(ph->panel_dev_config.reset_gpio_num);

free(ph);

return ESP_OK;
}

esp_err_t esp_lcd_new_panel_st7701(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *config, esp_lcd_panel_handle_t *handle)
esp_err_t esp_lcd_new_panel_st7701(const esp_lcd_panel_io_handle_t io, const esp_lcd_rgb_panel_config_t *rgb_panel_config, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *panel_handle)
{
log_v("io:0x%08x, config:0x%08x, handle:0x%08x", io, config, handle);
if (io == NULL || config == NULL || handle == NULL)
log_v("panel_io_handle:0x%08x, rgb_panel_config:0x%08x, panel_dev_config:0x%08x, panel_handle:0x%08x", io, rgb_panel_config, panel_dev_config, panel_handle);
if (io == NULL || rgb_panel_config == NULL || panel_dev_config == NULL || panel_handle == NULL)
return ESP_ERR_INVALID_ARG;

if (config->reset_gpio_num != GPIO_NUM_NC && !GPIO_IS_VALID_GPIO(config->reset_gpio_num))
if (panel_dev_config->reset_gpio_num != GPIO_NUM_NC && !GPIO_IS_VALID_GPIO(panel_dev_config->reset_gpio_num))
{
log_e("Invalid GPIO RST pin: %d", config->reset_gpio_num);
log_e("Invalid GPIO RST pin: %d", panel_dev_config->reset_gpio_num);
return ESP_ERR_INVALID_ARG;
}

uint8_t madctl;
switch (config->color_space)
switch (panel_dev_config->color_space)
{
case ESP_LCD_COLOR_SPACE_RGB:
madctl = 0;
Expand All @@ -348,15 +265,15 @@ esp_err_t esp_lcd_new_panel_st7701(const esp_lcd_panel_io_handle_t io, const esp
madctl = LCD_CMD_BGR_BIT;
break;
default:
log_e("Invalid color space: %d. Only RGB and BGR are supported", config->color_space);
log_e("Invalid color space: %d. Only RGB and BGR are supported", panel_dev_config->color_space);
return ESP_ERR_INVALID_ARG;
}

if (config->reset_gpio_num != GPIO_NUM_NC)
if (panel_dev_config->reset_gpio_num != GPIO_NUM_NC)
{
esp_err_t res;
const gpio_config_t cfg = {
.pin_bit_mask = BIT64(config->reset_gpio_num),
.pin_bit_mask = BIT64(panel_dev_config->reset_gpio_num),
.mode = GPIO_MODE_OUTPUT};
if ((res = gpio_config(&cfg)) != ESP_OK)
{
Expand All @@ -365,6 +282,18 @@ esp_err_t esp_lcd_new_panel_st7701(const esp_lcd_panel_io_handle_t io, const esp
}
}

// Create RGB panel
esp_err_t res;
esp_lcd_panel_handle_t lcd_panel;

if ((res = esp_lcd_new_rgb_panel(rgb_panel_config, &lcd_panel)) != ESP_OK)
{
log_e("Unable to create RGB panel");
return res;
}

log_d("lcd_panel: 0x%08x", lcd_panel);

st7701_panel_t *ph = heap_caps_calloc(1, sizeof(st7701_panel_t), MALLOC_CAP_DEFAULT);
if (ph == NULL)
{
Expand All @@ -373,8 +302,9 @@ esp_err_t esp_lcd_new_panel_st7701(const esp_lcd_panel_io_handle_t io, const esp
}

ph->io = io;
memcpy(&ph->config, config, sizeof(esp_lcd_panel_dev_config_t));
memcpy(&ph->panel_dev_config, panel_dev_config, sizeof(esp_lcd_panel_dev_config_t));
ph->madctl = madctl;
ph->lcd_panel = lcd_panel;

ph->base.del = st7701_del;
ph->base.reset = st7701_reset;
Expand All @@ -386,8 +316,8 @@ esp_err_t esp_lcd_new_panel_st7701(const esp_lcd_panel_io_handle_t io, const esp
ph->base.set_gap = st7701_set_gap;
ph->base.disp_off = st7701_disp_off;

log_d("handle: 0x%08x", ph);
*handle = (esp_lcd_panel_handle_t)ph;
log_d("panel_handle: 0x%08x", ph);
*panel_handle = (esp_lcd_panel_handle_t)ph;

return ESP_OK;
}
Expand Down
Loading

0 comments on commit a5a1c7a

Please sign in to comment.