Skip to content

Commit 885428e

Browse files
scarolanclaude
andcommitted
Add M5Stack CoreS3 SE board definition
The CoreS3 SE is a variant of the CoreS3 with the camera, IMU, magnetometer, proximity sensor, and audio codec removed, paired with the M5GO Battery Bottom3 which adds 10 NeoPixels (GPIO5) and an IR transmitter (GPIO7). Based on the CoreS3 board definition with the following changes: - Board name set to "M5Stack CoreS3 SE" - NEOPIXEL pin defined (GPIO5) for M5GO Bottom3 LEDs - Camera pin definitions and data tuple removed from pins.c - NEOPIXEL and IR named pin aliases added to pins.c - ESPCAMERA support disabled in mpconfigboard.mk - Camera-related AXP2101 power rails (ALDO2/ALDO3) disabled in board.c - Camera config removed from sdkconfig - SD card CS (GPIO4) driven high before display init to mitigate shared SPI bus contention (see #10536) Note: SD card does not work on any Core S3 variant in CircuitPython due to GPIO35 being shared between SPI MISO and display DC pin (upstream issues #10536, #6290). Tested on hardware: display, I2C (AXP2101, AW9523B, FT6336, BM8563), NeoPixels, IR pin, I2S speaker pins, Port B/C GPIOs all verified. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 47990e3 commit 885428e

File tree

5 files changed

+377
-0
lines changed

5 files changed

+377
-0
lines changed
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
#include "supervisor/board.h"
8+
#include "mpconfigboard.h"
9+
#include "shared-bindings/busio/SPI.h"
10+
#include "shared-bindings/busio/I2C.h"
11+
#include "shared-bindings/fourwire/FourWire.h"
12+
#include "shared-bindings/microcontroller/Pin.h"
13+
#include "shared-module/displayio/__init__.h"
14+
#include "shared-module/displayio/mipi_constants.h"
15+
#include "shared-bindings/board/__init__.h"
16+
#include "common-hal/microcontroller/Pin.h"
17+
18+
19+
#define DELAY 0x80
20+
#define AXP2101_I2C_ADDRESS 0x34
21+
#define AW9523B_I2C_ADDRESS 0x58
22+
23+
uint8_t display_init_sequence[] = {
24+
0x01, DELAY, 0x80, // Software reset then delay 0x80 (128ms)
25+
0xC8, 0x03, 0xFF, 0x93, 0x42, // Turn on the external command
26+
0xC0, 0x02, 0x12, 0x12, // Power Control 1
27+
0xC1, 0x01, 0x03, // Power Control 2
28+
0xC5, 0x01, 0xF2, // VCOM Control 1
29+
0xB0, 0x01, 0xE0, // RGB Interface SYNC Mode
30+
0xF6, 0x03, 0x01, 0x00, 0x00, // Interface control
31+
0XE0, 0x0F, 0x00, 0x0C, 0x11, 0x04, 0x11, 0x08, 0x37, 0x89, 0x4C, 0x06, 0x0C, 0x0A, 0x2E, 0x34, 0x0F, // Positive Gamma Correction
32+
0xE1, 0x0F, 0x00, 0x0B, 0x11, 0x05, 0x13, 0x09, 0x33, 0x67, 0x48, 0x07, 0x0E, 0x0B, 0x2E, 0x33, 0x0F, // Negative Gamma Correction
33+
0xB6, 0x04, 0x08, 0x82, 0x1D, 0x04, // Display Function Control
34+
0x3A, 0x01, 0x55, // COLMOD: Pixel Format Set 16 bit
35+
0x21, 0x00, // Display inversion ON
36+
0x36, 0x01, 0x08, // Memory Access Control: RGB order
37+
0x11, DELAY, 0x78, // Exit Sleep then delay 0x78 (120ms)
38+
0x29, DELAY, 0x78, // Display on then delay 0x78 (120ms)
39+
};
40+
41+
static bool display_init(void) {
42+
busio_spi_obj_t *spi = common_hal_board_create_spi(0);
43+
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
44+
bus->base.type = &fourwire_fourwire_type;
45+
46+
common_hal_fourwire_fourwire_construct(
47+
bus,
48+
spi,
49+
&pin_GPIO35, // DC
50+
&pin_GPIO3, // CS
51+
NULL, // RST
52+
40000000, // baudrate
53+
0, // polarity
54+
0 // phase
55+
);
56+
busdisplay_busdisplay_obj_t *display = &allocate_display()->display;
57+
display->base.type = &busdisplay_busdisplay_type;
58+
59+
common_hal_busdisplay_busdisplay_construct(
60+
display,
61+
bus,
62+
320, // width (after rotation)
63+
240, // height (after rotation)
64+
0, // column start
65+
0, // row start
66+
0, // rotation
67+
16, // color depth
68+
false, // grayscale
69+
false, // pixels in a byte share a row. Only valid for depths < 8
70+
1, // bytes per cell. Only valid for depths < 8
71+
false, // reverse_pixels_in_byte. Only valid for depths < 8
72+
true, // reverse_pixels_in_word
73+
MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command
74+
MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command
75+
MIPI_COMMAND_WRITE_MEMORY_START, // write memory command
76+
display_init_sequence,
77+
sizeof(display_init_sequence),
78+
NULL, // backlight pin
79+
NO_BRIGHTNESS_COMMAND,
80+
1.0f, // brightness
81+
false, // single_byte_bounds
82+
false, // data_as_commands
83+
true, // auto_refresh
84+
61, // native_frames_per_second
85+
true, // backlight_on_high
86+
false, // SH1107_addressing
87+
50000 // backlight pwm frequency
88+
);
89+
90+
return true;
91+
}
92+
93+
static bool axp2101_init(busio_i2c_obj_t *i2c) {
94+
int rc;
95+
uint8_t write_buf[2];
96+
97+
// 0x90 = 0b1011_0011 // LDOS ON/OFF control 0
98+
// Compared to CoreS3: ALDO2 (bit 2) and ALDO3 (bit 3) disabled (no ES7210/camera)
99+
write_buf[0] = 0x90;
100+
write_buf[1] = 0b10110011;
101+
rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf));
102+
if (rc != 0) {
103+
return false;
104+
}
105+
106+
// 0x92, 0x0D // ALDO1 set to 1.8v for AW88298
107+
write_buf[0] = 0x92;
108+
write_buf[1] = 0x0D;
109+
rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf));
110+
if (rc != 0) {
111+
return false;
112+
}
113+
114+
// 0x95, 0x1C // ALDO4 set to 3.3v for TF card slot
115+
write_buf[0] = 0x95;
116+
write_buf[1] = 0x1C;
117+
rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf));
118+
if (rc != 0) {
119+
return false;
120+
}
121+
122+
// 0x99, 0x18 // DLDO1 set to 2.9v for TFT backlight
123+
write_buf[0] = 0x99;
124+
write_buf[1] = 0x18;
125+
rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf));
126+
if (rc != 0) {
127+
return false;
128+
}
129+
130+
// 0x27, 0x00 // PowerKey Hold=1sec / PowerOff=4sec
131+
write_buf[0] = 0x27;
132+
write_buf[1] = 0x00;
133+
rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf));
134+
if (rc != 0) {
135+
return false;
136+
}
137+
138+
// 0x69, 0x11 // CHGLED setting
139+
write_buf[0] = 0x69;
140+
write_buf[1] = 0x11;
141+
rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf));
142+
if (rc != 0) {
143+
return false;
144+
}
145+
146+
// 0x10, 0x30 // PMU common config
147+
write_buf[0] = 0x10;
148+
write_buf[1] = 0x30;
149+
rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf));
150+
if (rc != 0) {
151+
return false;
152+
}
153+
154+
return true;
155+
}
156+
157+
static bool aw9523b_init(busio_i2c_obj_t *i2c) {
158+
int rc;
159+
uint8_t write_buf[2];
160+
161+
// 0x02 = 0b0000_0111 // AW_RST, BUD_OUT_EN, TOUCH_RST
162+
write_buf[0] = 0x02;
163+
write_buf[1] = 0b00000111;
164+
rc = common_hal_busio_i2c_write(i2c, AW9523B_I2C_ADDRESS, write_buf, sizeof(write_buf));
165+
if (rc != 0) {
166+
return false;
167+
}
168+
169+
// 0x03 = 0b1000_0011 // BOOST_EN, CAM_RST, LCD_RST
170+
write_buf[0] = 0x03;
171+
write_buf[1] = 0b10000011;
172+
rc = common_hal_busio_i2c_write(i2c, AW9523B_I2C_ADDRESS, write_buf, sizeof(write_buf));
173+
if (rc != 0) {
174+
return false;
175+
}
176+
177+
// 0x04 = 0b0001_1000 // Set TF_SW, ES_INT as input
178+
write_buf[0] = 0x04;
179+
write_buf[1] = 0b00011000;
180+
rc = common_hal_busio_i2c_write(i2c, AW9523B_I2C_ADDRESS, write_buf, sizeof(write_buf));
181+
if (rc != 0) {
182+
return false;
183+
}
184+
185+
// 0x05 = 0b0000_1100 // Set AW_INT, TOUCH_INT as input
186+
write_buf[0] = 0x05;
187+
write_buf[1] = 0b00001100;
188+
rc = common_hal_busio_i2c_write(i2c, AW9523B_I2C_ADDRESS, write_buf, sizeof(write_buf));
189+
if (rc != 0) {
190+
return false;
191+
}
192+
193+
// 0x11 = 0b0001_0000 // Set P0 outputs in push pull mode
194+
write_buf[0] = 0x11;
195+
write_buf[1] = 0b00010000;
196+
rc = common_hal_busio_i2c_write(i2c, AW9523B_I2C_ADDRESS, write_buf, sizeof(write_buf));
197+
if (rc != 0) {
198+
return false;
199+
}
200+
201+
return true;
202+
}
203+
204+
void board_init(void) {
205+
// Deselect SD card on shared SPI bus before display init (see #10536)
206+
config_pin_as_output_with_level(GPIO_NUM_4, true);
207+
208+
busio_i2c_obj_t *internal_i2c = common_hal_board_create_i2c(0);
209+
210+
if (!axp2101_init(internal_i2c)) {
211+
mp_printf(&mp_plat_print, "could not initialize AXP2101");
212+
return;
213+
}
214+
215+
if (!aw9523b_init(internal_i2c)) {
216+
mp_printf(&mp_plat_print, "could not initialize AW9523B");
217+
return;
218+
}
219+
220+
if (!display_init()) {
221+
mp_printf(&mp_plat_print, "could not initialize the display");
222+
return;
223+
}
224+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
#pragma once
8+
9+
// Micropython setup
10+
11+
#define MICROPY_HW_BOARD_NAME "M5Stack CoreS3 SE"
12+
#define MICROPY_HW_MCU_NAME "ESP32S3"
13+
14+
#define MICROPY_HW_NEOPIXEL (&pin_GPIO5)
15+
16+
#define CIRCUITPY_BOARD_I2C (2)
17+
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO11, .sda = &pin_GPIO12}, \
18+
{.scl = &pin_GPIO1, .sda = &pin_GPIO2}}
19+
20+
#define DEFAULT_SPI_BUS_SCK (&pin_GPIO36)
21+
#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO37)
22+
#define DEFAULT_SPI_BUS_MISO (&pin_GPIO35)
23+
24+
#define DEFAULT_UART_BUS_RX (&pin_GPIO18)
25+
#define DEFAULT_UART_BUS_TX (&pin_GPIO17)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
USB_VID = 0x303A
2+
USB_PID = 0x811B
3+
4+
USB_PRODUCT = "M5Stack CoreS3 SE"
5+
USB_MANUFACTURER = "M5Stack"
6+
7+
IDF_TARGET = esp32s3
8+
9+
CIRCUITPY_ESP_FLASH_MODE = qio
10+
CIRCUITPY_ESP_FLASH_FREQ = 80m
11+
CIRCUITPY_ESP_FLASH_SIZE = 16MB
12+
13+
CIRCUITPY_ESP_PSRAM_SIZE = 8MB
14+
CIRCUITPY_ESP_PSRAM_MODE = qio
15+
CIRCUITPY_ESP_PSRAM_FREQ = 80m
16+
17+
CIRCUITPY_PARALLELDISPLAYBUS = 0
18+
19+
OPTIMIZATION_FLAGS = -Os
20+
21+
# Include these Python libraries in firmware.
22+
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ConnectionManager
23+
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
24+
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Shapes
25+
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Text
26+
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_FakeRequests
27+
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
#include "shared-bindings/board/__init__.h"
8+
#include "shared-module/displayio/__init__.h"
9+
10+
CIRCUITPY_BOARD_BUS_SINGLETON(porta_i2c, i2c, 1)
11+
12+
static const mp_rom_map_elem_t board_module_globals_table[] = {
13+
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
14+
15+
// M5 Bus (except I2S)
16+
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO37) },
17+
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO35) },
18+
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO36) },
19+
20+
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) },
21+
{ MP_ROM_QSTR(MP_QSTR_D44), MP_ROM_PTR(&pin_GPIO44) },
22+
23+
{ MP_ROM_QSTR(MP_QSTR_PORTC_RX), MP_ROM_PTR(&pin_GPIO18) },
24+
{ MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) },
25+
{ MP_ROM_QSTR(MP_QSTR_A18), MP_ROM_PTR(&pin_GPIO18) },
26+
27+
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO12) },
28+
29+
{ MP_ROM_QSTR(MP_QSTR_PORTA_SDA), MP_ROM_PTR(&pin_GPIO2) },
30+
{ MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) },
31+
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) },
32+
33+
{ MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) },
34+
{ MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO6) },
35+
36+
{ MP_ROM_QSTR(MP_QSTR_PORTB_IN), MP_ROM_PTR(&pin_GPIO8) },
37+
{ MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) },
38+
{ MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_GPIO8) },
39+
40+
{ MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO5) },
41+
{ MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) },
42+
{ MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO5) },
43+
44+
{ MP_ROM_QSTR(MP_QSTR_PORTB_OUT), MP_ROM_PTR(&pin_GPIO9) },
45+
{ MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) },
46+
{ MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_GPIO9) },
47+
48+
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) },
49+
{ MP_ROM_QSTR(MP_QSTR_D43), MP_ROM_PTR(&pin_GPIO43) },
50+
51+
{ MP_ROM_QSTR(MP_QSTR_PORTC_TX), MP_ROM_PTR(&pin_GPIO17) },
52+
{ MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) },
53+
{ MP_ROM_QSTR(MP_QSTR_A17), MP_ROM_PTR(&pin_GPIO17) },
54+
55+
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO11) },
56+
57+
{ MP_ROM_QSTR(MP_QSTR_PORTA_SCL), MP_ROM_PTR(&pin_GPIO1) },
58+
{ MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) },
59+
60+
{ MP_ROM_QSTR(MP_QSTR_IR), MP_ROM_PTR(&pin_GPIO7) },
61+
{ MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) },
62+
{ MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO7) },
63+
64+
// I2S
65+
{ MP_ROM_QSTR(MP_QSTR_I2S_BIT_CLOCK), MP_ROM_PTR(&pin_GPIO34) },
66+
{ MP_ROM_QSTR(MP_QSTR_I2S_WORD_SELECT), MP_ROM_PTR(&pin_GPIO33) },
67+
{ MP_ROM_QSTR(MP_QSTR_I2S_DATA_OUT), MP_ROM_PTR(&pin_GPIO13) },
68+
{ MP_ROM_QSTR(MP_QSTR_I2S_DATA_IN), MP_ROM_PTR(&pin_GPIO14) },
69+
{ MP_ROM_QSTR(MP_QSTR_I2S_MASTER_CLOCK), MP_ROM_PTR(&pin_GPIO0) },
70+
71+
// Display
72+
{ MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO3) },
73+
{ MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO35) },
74+
75+
// Misc
76+
{ MP_ROM_QSTR(MP_QSTR_I2C_INTERRUPT), MP_ROM_PTR(&pin_GPIO21) },
77+
{ MP_ROM_QSTR(MP_QSTR_SDCARD_CS), MP_ROM_PTR(&pin_GPIO4) },
78+
{ MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) },
79+
80+
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
81+
{ MP_ROM_QSTR(MP_QSTR_PORTA_I2C), MP_ROM_PTR(&board_porta_i2c_obj) },
82+
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
83+
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
84+
85+
{ MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}
86+
};
87+
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#
2+
# Espressif IoT Development Framework Configuration
3+
#
4+
#
5+
# Component config
6+
#
7+
#
8+
# LWIP
9+
#
10+
# end of LWIP
11+
12+
# end of Component config
13+
14+
# end of Espressif IoT Development Framework Configuration

0 commit comments

Comments
 (0)