Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Espressif esp32s3 lcd ev v1.5 #9608

Merged
merged 9 commits into from
Sep 20, 2024
139 changes: 139 additions & 0 deletions ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/board.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
//
// SPDX-License-Identifier: MIT

#include "supervisor/board.h"
#include "mpconfigboard.h"
#include "shared-bindings/board/__init__.h"
#include "shared-bindings/busio/I2C.h"
#include "shared-bindings/dotclockframebuffer/DotClockFramebuffer.h"
#include "shared-bindings/dotclockframebuffer/__init__.h"
#include "shared-bindings/framebufferio/FramebufferDisplay.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-module/displayio/__init__.h"
#include "boards/espressif_esp32s3_lcd_ev_v1.5/board.h"

#define MP_DEFINE_BYTES_OBJ_WITH_NULL(obj_name, bin) mp_obj_str_t obj_name = {{&mp_type_bytes}, 0, sizeof(bin) - 1, (const byte *)bin}

static const uint8_t display_init_sequence[] = {
0xf0, 5, 0x55, 0xaa, 0x52, 0x08, 0x00,
0xf6, 2, 0x5a, 0x87,
0xc1, 1, 0x3f,
0xc2, 1, 0x0e,
0xc6, 1, 0xf8,
0xc9, 1, 0x10,
0xcd, 1, 0x25,
0xf8, 1, 0x8a,
0xac, 1, 0x45,
0xa0, 1, 0xdd,
0xa7, 1, 0x47,
0xfa, 4, 0x00, 0x00, 0x00, 0x04,
0x86, 4, 0x99, 0xa3, 0xa3, 0x51,
0xa3, 1, 0xee,
0xfd, 3, 0x3c, 0x3c, 0x00,
0x71, 1, 0x48,
0x72, 1, 0x48,
0x73, 2, 0x00, 0x44,
0x97, 1, 0xee,
0x83, 1, 0x93,
0x9a, 1, 0x72,
0x9b, 1, 0x5a,
0x82, 2, 0x2c, 0x2c,
0xb1, 1, 0x10,
0x6d, 32, 0x00, 0x1f, 0x19, 0x1a, 0x10, 0x0e, 0x0c, 0x0a, 0x02, 0x07, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x08, 0x01, 0x09, 0x0b, 0x0d, 0x0f, 0x1a, 0x19, 0x1f, 0x00,
0x64, 16, 0x38, 0x05, 0x01, 0xdb, 0x03, 0x03, 0x38, 0x04, 0x01, 0xdc, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a,
0x65, 16, 0x38, 0x03, 0x01, 0xdd, 0x03, 0x03, 0x38, 0x02, 0x01, 0xde, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a,
0x66, 16, 0x38, 0x01, 0x01, 0xdf, 0x03, 0x03, 0x38, 0x00, 0x01, 0xe0, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a,
0x67, 16, 0x30, 0x01, 0x01, 0xe1, 0x03, 0x03, 0x30, 0x02, 0x01, 0xe2, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a,
0x68, 13, 0x00, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a,
0x60, 8, 0x38, 0x08, 0x7a, 0x7a, 0x38, 0x09, 0x7a, 0x7a,
0x63, 8, 0x31, 0xe4, 0x7a, 0x7a, 0x31, 0xe5, 0x7a, 0x7a,
0x69, 7, 0x04, 0x22, 0x14, 0x22, 0x14, 0x22, 0x08,
0x6b, 1, 0x07,
0x7a, 2, 0x08, 0x13,
0x7b, 2, 0x08, 0x13,
0xd1, 52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff,
0xd2, 52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff,
0xd3, 52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff,
0xd4, 52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff,
0xd5, 52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff,
0xd6, 52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff,
0x3a, 1, 0x66,
0x3a, 1, 0x66,
0x11, 0x80, 120,
0x29, 0x0,
0, // trailing NUL for Python bytes() representation
};
MP_DEFINE_BYTES_OBJ_WITH_NULL(display_init_byte_obj, display_init_sequence);

static const char i2c_bus_init_sequence[] = {
2, 3, 0xf1, // set GPIO direction
2, 2, 0, // disable all output inversion
0, // trailing NUL for Python bytes() representation
};
MP_DEFINE_BYTES_OBJ_WITH_NULL(i2c_init_byte_obj, i2c_bus_init_sequence);

static const mcu_pin_obj_t *red_pins[] = {
&pin_GPIO1, &pin_GPIO2, &pin_GPIO42, &pin_GPIO41, &pin_GPIO40
};
static const mcu_pin_obj_t *green_pins[] = {
&pin_GPIO21, &pin_GPIO8, &pin_GPIO18, &pin_GPIO45, &pin_GPIO38, &pin_GPIO39
};
static const mcu_pin_obj_t *blue_pins[] = {
&pin_GPIO10, &pin_GPIO11, &pin_GPIO12, &pin_GPIO13, &pin_GPIO14
};
void board_init(void) {
dotclockframebuffer_framebuffer_obj_t *framebuffer = &allocate_display_bus_or_raise()->dotclock;
framebuffer->base.type = &dotclockframebuffer_framebuffer_type;

common_hal_dotclockframebuffer_framebuffer_construct(
framebuffer,
/* de */ &pin_GPIO17,
/* vsync */ &pin_GPIO3,
/* hsync */ &pin_GPIO46,
/* dclk */ &pin_GPIO9,
/* data */ red_pins, MP_ARRAY_SIZE(red_pins), green_pins, MP_ARRAY_SIZE(green_pins), blue_pins, MP_ARRAY_SIZE(blue_pins),
/* frequency */ 12000000,
/* width x height */ 480, 480,
/* horizontal: pulse, back & front porch, idle */ 13, 20, 40, false,
/* vertical: pulse, back & front porch, idle */ 15, 20, 40, false,
/* de_idle_high */ false,
/* pclk_active_high */ true,
/* pclk_idle_high */ false,
/* overscan_left */ 0
);

framebufferio_framebufferdisplay_obj_t *disp = &allocate_display_or_raise()->framebuffer_display;
disp->base.type = &framebufferio_framebufferdisplay_type;
common_hal_framebufferio_framebufferdisplay_construct(
disp,
framebuffer,
0,
true
);

busio_i2c_obj_t i2c;
i2c.base.type = &busio_i2c_type;
common_hal_busio_i2c_construct(&i2c, DEFAULT_I2C_BUS_SCL, DEFAULT_I2C_BUS_SDA, 400000, 255);
const int i2c_device_address = 32;

dotclockframebuffer_ioexpander_spi_bus spibus = {
.bus = &i2c,
.i2c_device_address = i2c_device_address,
.i2c_write_size = 2,
.addr_reg_shadow = { .u32 = 1 }, // GPIO data at register 1
.cs_mask = 0x100 << 1, // data payload is at byte 2
.mosi_mask = 0x100 << 3,
.clk_mask = 0x100 << 2,
};

static const mp_buffer_info_t bufinfo_display_init = { (void *)display_init_sequence, sizeof(display_init_sequence) - 1 };
static const mp_buffer_info_t bufinfo_i2c_bus_init = { (void *)i2c_bus_init_sequence, sizeof(i2c_bus_init_sequence) - 1 };
dotclockframebuffer_ioexpander_send_init_sequence(&spibus, &bufinfo_i2c_bus_init, &bufinfo_display_init);

common_hal_busio_i2c_deinit(&i2c);
}

// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.
11 changes: 11 additions & 0 deletions ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/board.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2023 Jeff Epler for Adafruit Industries
//
// SPDX-License-Identifier: MIT

#pragma once

#include "py/objstr.h"

extern mp_obj_str_t display_init_byte_obj, i2c_init_byte_obj;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
//
// SPDX-License-Identifier: MIT

#pragma once

// Micropython setup

#define MICROPY_HW_BOARD_NAME "Espressif-ESP32-S3-LCD-EV-Board_v1.5"
#define MICROPY_HW_MCU_NAME "ESP32S3"

#define MICROPY_HW_NEOPIXEL (&pin_GPIO4)

#define DEFAULT_I2C_BUS_SDA (&pin_GPIO47)
#define DEFAULT_I2C_BUS_SCL (&pin_GPIO48)

// UART pins attached to the USB-serial converter chip
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO43)
#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO44)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
USB_VID = 0x303A
USB_PID = 0x7011
USB_PRODUCT = "ESP32-S3-EV-LCD-Board_v1.5"
USB_MANUFACTURER = "Espressif"

IDF_TARGET = esp32s3

CIRCUITPY_ESP_FLASH_MODE = qio
CIRCUITPY_ESP_FLASH_FREQ = 80m
CIRCUITPY_ESP_FLASH_SIZE = 16MB

CIRCUITPY_ESP_PSRAM_SIZE = 8MB
CIRCUITPY_ESP_PSRAM_MODE = opi
CIRCUITPY_ESP_PSRAM_FREQ = 80m

CIRCUITPY_DOTCLOCKFRAMEBUFFER = 1
UF2_BOOTLOADER = 0
116 changes: 116 additions & 0 deletions ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/pins.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
//
// SPDX-License-Identifier: MIT

#include "py/objtuple.h"
#include "boards/espressif_esp32s3_lcd_ev_v1.5/board.h"
#include "shared-bindings/board/__init__.h"
#include "shared-module/displayio/__init__.h"

static const mp_rom_map_elem_t tft_io_expander_table[] = {
{ MP_ROM_QSTR(MP_QSTR_i2c_address), MP_ROM_INT(0x20)},
{ MP_ROM_QSTR(MP_QSTR_gpio_address), MP_ROM_INT(1)},
{ MP_ROM_QSTR(MP_QSTR_gpio_data_len), MP_ROM_INT(1)},
{ MP_ROM_QSTR(MP_QSTR_gpio_data), MP_ROM_INT(0xF1)},
{ MP_ROM_QSTR(MP_QSTR_cs_bit), MP_ROM_INT(1)},
{ MP_ROM_QSTR(MP_QSTR_mosi_bit), MP_ROM_INT(3)},
{ MP_ROM_QSTR(MP_QSTR_clk_bit), MP_ROM_INT(2)},
{ MP_ROM_QSTR(MP_QSTR_i2c_init_sequence), &i2c_init_byte_obj},
};
MP_DEFINE_CONST_DICT(tft_io_expander_dict, tft_io_expander_table);

static const mp_rom_obj_tuple_t tft_r_pins = {
{&mp_type_tuple},
5,
{
MP_ROM_PTR(&pin_GPIO1),
MP_ROM_PTR(&pin_GPIO2),
MP_ROM_PTR(&pin_GPIO42),
MP_ROM_PTR(&pin_GPIO41),
MP_ROM_PTR(&pin_GPIO40),
}
};

static const mp_rom_obj_tuple_t tft_g_pins = {
{&mp_type_tuple},
6,
{
MP_ROM_PTR(&pin_GPIO21),
MP_ROM_PTR(&pin_GPIO8),
MP_ROM_PTR(&pin_GPIO18),
MP_ROM_PTR(&pin_GPIO45),
MP_ROM_PTR(&pin_GPIO38),
MP_ROM_PTR(&pin_GPIO39),
}
};

static const mp_rom_obj_tuple_t tft_b_pins = {
{&mp_type_tuple},
5,
{
MP_ROM_PTR(&pin_GPIO10),
MP_ROM_PTR(&pin_GPIO11),
MP_ROM_PTR(&pin_GPIO12),
MP_ROM_PTR(&pin_GPIO13),
MP_ROM_PTR(&pin_GPIO14),
}
};

static const mp_rom_map_elem_t tft_pins_table[] = {
{ MP_ROM_QSTR(MP_QSTR_de), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_vsync), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_hsync), MP_ROM_PTR(&pin_GPIO46) },
{ MP_ROM_QSTR(MP_QSTR_dclk), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_red), MP_ROM_PTR(&tft_r_pins) },
{ MP_ROM_QSTR(MP_QSTR_green), MP_ROM_PTR(&tft_g_pins) },
{ MP_ROM_QSTR(MP_QSTR_blue), MP_ROM_PTR(&tft_b_pins) },
};
MP_DEFINE_CONST_DICT(tft_pins_dict, tft_pins_table);

static const mp_rom_map_elem_t tft_timings_table[] = {
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_INT(6500000) }, // nominal 16MHz, but display is unstable/tears at that frequency
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_INT(480) },
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_INT(480) },
{ MP_ROM_QSTR(MP_QSTR_hsync_pulse_width), MP_ROM_INT(13) },
{ MP_ROM_QSTR(MP_QSTR_hsync_front_porch), MP_ROM_INT(20) },
{ MP_ROM_QSTR(MP_QSTR_hsync_back_porch), MP_ROM_INT(40) },
{ MP_ROM_QSTR(MP_QSTR_hsync_idle_low), MP_ROM_FALSE },
{ MP_ROM_QSTR(MP_QSTR_vsync_pulse_width), MP_ROM_INT(15) },
{ MP_ROM_QSTR(MP_QSTR_vsync_front_porch), MP_ROM_INT(20) },
{ MP_ROM_QSTR(MP_QSTR_vsync_back_porch), MP_ROM_INT(40) },
{ MP_ROM_QSTR(MP_QSTR_vsync_idle_low), MP_ROM_FALSE },
{ MP_ROM_QSTR(MP_QSTR_de_idle_high), MP_ROM_FALSE },
{ MP_ROM_QSTR(MP_QSTR_pclk_active_high), MP_ROM_FALSE },
{ MP_ROM_QSTR(MP_QSTR_pclk_idle_high), MP_ROM_FALSE },
};
MP_DEFINE_CONST_DICT(tft_timings_dict, tft_timings_table);

static const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS

{ MP_ROM_QSTR(MP_QSTR_TFT_PINS), MP_ROM_PTR(&tft_pins_dict) },
{ MP_ROM_QSTR(MP_QSTR_TFT_TIMINGS), MP_ROM_PTR(&tft_timings_dict) },
{ MP_ROM_QSTR(MP_QSTR_TFT_IO_EXPANDER), MP_ROM_PTR(&tft_io_expander_dict) },
{ MP_ROM_QSTR(MP_QSTR_TFT_INIT_SEQUENCE), &display_init_byte_obj},

{ MP_ROM_QSTR(MP_QSTR_I2S_SCK), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_I2S_MCLK), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_I2S_WS), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_I2S_SDO), MP_ROM_PTR(&pin_GPIO6) },

{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) },
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) },

{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(DEFAULT_I2C_BUS_SCL) },
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(DEFAULT_I2C_BUS_SDA) },

{ MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) },

// boot mode button can be used in SW as well
{ MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) },

{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
15 changes: 15 additions & 0 deletions ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/sdkconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#
# Espressif IoT Development Framework Configuration
#
#
# Component config
#
#
# LWIP
#
CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3-lcd-ev-v1.5"
# end of LWIP

# end of Component config

# end of Espressif IoT Development Framework Configuration