Skip to content

Commit

Permalink
Merge pull request #9939 from bootc/add_m5stick_c_plus2
Browse files Browse the repository at this point in the history
Add the M5Stack M5Stick C Plus2 board
  • Loading branch information
tannewt authored Jan 7, 2025
2 parents 571589d + cbab23e commit 422681b
Show file tree
Hide file tree
Showing 6 changed files with 281 additions and 0 deletions.
137 changes: 137 additions & 0 deletions ports/espressif/boards/m5stack_stick_c_plus2/board.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2023 n0xa, 2025 bootc
//
// SPDX-License-Identifier: MIT

#include "supervisor/board.h"
#include "mpconfigboard.h"
#include "shared-bindings/busio/SPI.h"
#include "shared-bindings/busio/I2C.h"
#include "shared-bindings/fourwire/FourWire.h"
#include "shared-module/displayio/__init__.h"
#include "shared-module/displayio/mipi_constants.h"
#include "shared-bindings/board/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "driver/gpio.h"
#include "common-hal/microcontroller/Pin.h"

// display init sequence according to adafruit_st7735r.py library
uint8_t display_init_sequence[] = {
0x01, 0x80, 0x96, // SWRESET and Delay 150ms
0x11, 0x80, 0xff, // SLPOUT and Delay
0xb1, 0x03, 0x01, 0x2C, 0x2D, // _FRMCTR1
0xb2, 0x03, 0x01, 0x2C, 0x2D, // _FRMCTR2
0xb3, 0x06, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D, // _FRMCTR3
0xb4, 0x01, 0x07, // _INVCTR line inversion
0xc0, 0x03, 0xa2, 0x02, 0x84, // _PWCTR1 GVDD = 4.7V, 1.0uA
0xc1, 0x01, 0xc5, // _PWCTR2 VGH=14.7V, VGL=-7.35V
0xc2, 0x02, 0x0a, 0x00, // _PWCTR3 Opamp current small, Boost frequency
0xc3, 0x02, 0x8a, 0x2a,
0xc4, 0x02, 0x8a, 0xee,
0xc5, 0x01, 0x0e, // _VMCTR1 VCOMH = 4V, VOML = -1.1V
0x36, 0x01, 0xc8, // MADCTL Rotate display
0x21, 0x00, // _INVON
0x3a, 0x01, 0x05, // COLMOD - 16bit color
0xe0, 0x10, 0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10, // _GMCTRP1 Gamma
0xe1, 0x10, 0x03, 0x1d, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10, // _GMCTRN1
0x13, 0x80, 0x0a, // _NORON
0x29, 0x80, 0x64 // _DISPON
};

static void display_init(void) {
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
busio_spi_obj_t *spi = &bus->inline_bus;
common_hal_busio_spi_construct(spi, &pin_GPIO13, &pin_GPIO15, NULL, false);
common_hal_busio_spi_never_reset(spi);

bus->base.type = &fourwire_fourwire_type;

common_hal_fourwire_fourwire_construct(
bus,
spi,
&pin_GPIO14, // DC
&pin_GPIO5, // CS
&pin_GPIO12, // RST
10000000, // baudrate
0, // polarity
0 // phase
);

busdisplay_busdisplay_obj_t *display = &allocate_display()->display;
display->base.type = &busdisplay_busdisplay_type;

common_hal_busdisplay_busdisplay_construct(
display,
bus,
135, // width (after rotation)
240, // height (after rotation)
40, // column start
52, // row start
1, // rotation
16, // color depth
false, // grayscale
false, // pixels in a byte share a row. Only valid for depths < 8
1, // bytes per cell. Only valid for depths < 8
false, // reverse_pixels_in_byte. Only valid for depths < 8
true, // reverse_pixels_in_word
MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command
MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command
MIPI_COMMAND_WRITE_MEMORY_START, // write memory command
display_init_sequence,
sizeof(display_init_sequence),
&pin_GPIO27, // backlight pin
NO_BRIGHTNESS_COMMAND,
1.0f, // brightness
false, // single_byte_bounds
false, // data_as_commands
true, // auto_refresh
60, // native_frames_per_second
true, // backlight_on_high
false, // SH1107_addressing
50000 // backlight pwm frequency
);
}

void board_init(void) {
display_init();
}

bool board_requests_safe_mode(void) {
// Enable HOLD early on
config_pin_as_output_with_level(GPIO_NUM_4, true);

// Change the buttons to inputs
gpio_set_direction(GPIO_NUM_35, GPIO_MODE_INPUT);
gpio_set_pull_mode(GPIO_NUM_35, GPIO_FLOATING);
gpio_set_direction(GPIO_NUM_37, GPIO_MODE_INPUT);
gpio_set_pull_mode(GPIO_NUM_37, GPIO_FLOATING);
gpio_set_direction(GPIO_NUM_39, GPIO_MODE_INPUT);
gpio_set_pull_mode(GPIO_NUM_39, GPIO_FLOATING);

// Let the pins settle
mp_hal_delay_ms(1);

// Safe mode if BTN_A is held at boot (logic low)
return gpio_get_level(GPIO_NUM_37) == 0; // BTN_A
}

bool espressif_board_reset_pin_number(gpio_num_t pin_number) {
switch (pin_number) {
case GPIO_NUM_4: // HOLD
// HOLD(G4) pin must be set high to avoid a power off when battery powered
config_pin_as_output_with_level(pin_number, true);
return true;

case GPIO_NUM_35: // BTN_C/PWR
case GPIO_NUM_37: // BTN_A
case GPIO_NUM_39: // BTN_B
gpio_set_direction(pin_number, GPIO_MODE_INPUT);
gpio_set_pull_mode(pin_number, GPIO_FLOATING);
return true;

default:
return false;
}
return false;
}
28 changes: 28 additions & 0 deletions ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2023 n0xa, 2025 bootc
//
// SPDX-License-Identifier: MIT

#pragma once

// Micropython setup

#define MICROPY_HW_BOARD_NAME "M5Stack Stick C Plus2"
#define MICROPY_HW_MCU_NAME "ESP32"

#define MICROPY_HW_LED_STATUS (&pin_GPIO19)

#define CIRCUITPY_BOARD_I2C (2)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO22, .sda = &pin_GPIO21}, \
{.scl = &pin_GPIO33, .sda = &pin_GPIO32}}

// For entering safe mode
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO37)

// Explanation of how a user got into safe mode
#define BOARD_USER_SAFE_MODE_ACTION MP_ERROR_TEXT("You pressed button A at start up.")

// UART pins attached to the USB-serial converter chip
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3)
20 changes: 20 additions & 0 deletions ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
CIRCUITPY_CREATOR_ID = 0x10151015
CIRCUITPY_CREATION_ID = 0x0032000C

IDF_TARGET = esp32

CIRCUITPY_ESP_FLASH_MODE = qio
CIRCUITPY_ESP_FLASH_FREQ = 80m
CIRCUITPY_ESP_FLASH_SIZE = 8MB

CIRCUITPY_ESP_PSRAM_MODE = qio
CIRCUITPY_ESP_PSRAM_FREQ = 80m
CIRCUITPY_ESP_PSRAM_SIZE = 2MB

# The safe mode wait gets us very close to the 3s time for the board to shut
# down when BTN_C/PWR is held down. We skip the wait and instead enter safe
# mode if BTN_A is held down during boot with no timeout.
CIRCUITPY_SKIP_SAFE_MODE_WAIT = 1

# Enable PDMIn for the microphone
CIRCUITPY_AUDIOBUSIO_PDMIN = 1
78 changes: 78 additions & 0 deletions ports/espressif/boards/m5stack_stick_c_plus2/pins.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2023 n0xa, 2025 bootc
//
// SPDX-License-Identifier: MIT

#include "shared-bindings/board/__init__.h"
#include "shared-module/displayio/__init__.h"

CIRCUITPY_BOARD_BUS_SINGLETON(grove_i2c, i2c, 1)

static const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS

// Pin port on the top
{ MP_ROM_QSTR(MP_QSTR_G26), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_G36), MP_ROM_PTR(&pin_GPIO36) }, // G36/G25 pin
{ MP_ROM_QSTR(MP_QSTR_G25), MP_ROM_PTR(&pin_GPIO25) }, // G36/G25 pin
{ MP_ROM_QSTR(MP_QSTR_G0), MP_ROM_PTR(&pin_GPIO0) }, // also PDM_MIC_CLK

// Grove port on the bottom
{ MP_ROM_QSTR(MP_QSTR_G32), MP_ROM_PTR(&pin_GPIO32) },
{ MP_ROM_QSTR(MP_QSTR_GROVE_SDA), MP_ROM_PTR(&pin_GPIO32) },
{ MP_ROM_QSTR(MP_QSTR_G33), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_GROVE_SCL), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_GROVE_I2C), MP_ROM_PTR(&board_grove_i2c_obj) },

// Buttons
{ MP_ROM_QSTR(MP_QSTR_G37), MP_ROM_PTR(&pin_GPIO37) },
{ MP_ROM_QSTR(MP_QSTR_BTN_A), MP_ROM_PTR(&pin_GPIO37) },
{ MP_ROM_QSTR(MP_QSTR_G39), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_BTN_B), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_G35), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_BTN_C), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_BTN_PWR), MP_ROM_PTR(&pin_GPIO35) }, // also WAKE

// Buzzer / Speaker
{ MP_ROM_QSTR(MP_QSTR_G2), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_GPIO2) },

// Red and IR LED (single pin)
{ MP_ROM_QSTR(MP_QSTR_G19), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_IR_LED), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO19) },

// LCD display
{ MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_LCD_BL), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)},

// Battery voltage sense
{ MP_ROM_QSTR(MP_QSTR_G38), MP_ROM_PTR(&pin_GPIO38) },
{ MP_ROM_QSTR(MP_QSTR_BAT_ADC), MP_ROM_PTR(&pin_GPIO38) },

// Microphone
{ MP_ROM_QSTR(MP_QSTR_PDM_MIC_CLK), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_G34), MP_ROM_PTR(&pin_GPIO34) },
{ MP_ROM_QSTR(MP_QSTR_PDM_MIC_DATA), MP_ROM_PTR(&pin_GPIO34) },

// Internal I2C (IMU and RTC)
{ MP_ROM_QSTR(MP_QSTR_G21), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_SYS_SDA), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_G22), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_SYS_SCL), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },

// Sleep/Wake signal
{ MP_ROM_QSTR(MP_QSTR_WAKE), MP_ROM_PTR(&pin_GPIO35) },

// Power hold
{ MP_ROM_QSTR(MP_QSTR_G4), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_HOLD), MP_ROM_PTR(&pin_GPIO4) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
14 changes: 14 additions & 0 deletions ports/espressif/boards/m5stack_stick_c_plus2/sdkconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#
# Espressif IoT Development Framework Configuration
#
#
# Component config
#
#
# LWIP
#
# end of LWIP

# end of Component config

# end of Espressif IoT Development Framework Configuration
4 changes: 4 additions & 0 deletions ports/espressif/supervisor/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,10 @@ safe_mode_t port_init(void) {
break;
}

if (board_requests_safe_mode()) {
return SAFE_MODE_USER;
}

return SAFE_MODE_NONE;
}

Expand Down

0 comments on commit 422681b

Please sign in to comment.