ports/esp32/boards/M5CORE2: add support (#29)

* ports/esp32/boards/M5CORE2: add support for M5Stack Core2

* ports/esp32/boards/M5CORE2: adapting to lvgl 8
This commit is contained in:
Rop Gonggrijp 2021-06-01 23:14:21 +02:00 committed by GitHub
parent 4d3e3c8cf3
commit d8199947d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 230 additions and 0 deletions

View File

@ -0,0 +1,14 @@
# Board files for M5Stack Core2
To use, follow the instructions in the [root README](../../../../README.md) for this repository as well as in the [README for the ESP32 port](../../README.md) to prepare the prerequisites. Then to compile, go to the `ports/esp32` directory and execute
```text
export PORT=<your serial port>
export BOARD=M5CORE2
esptool.py erase_flash && \
make submodules && \
make -j $(nproc) && \
make deploy
```
You should now see a very simple example application with just one button that does show when it's being pressed but does nothing else. The drivers are loaded in `boot.py` while `main.py` contains this simple example. Both files reside in the accessible and changeable flash filesystem.

View File

@ -0,0 +1,2 @@
freeze("modules")
include("$(PORT_DIR)/boards/manifest.py")

View File

@ -0,0 +1 @@
../../../../../lib/lv_bindings/driver/generic/axp192.py

View File

@ -0,0 +1 @@
../../../../../lib/lv_bindings/driver/generic/ft6x36.py

View File

@ -0,0 +1,84 @@
import uos
from flashbdev import bdev
import lvgl as lv
def check_bootsec():
buf = bytearray(bdev.ioctl(5, 0)) # 5 is SEC_SIZE
bdev.readblocks(0, buf)
empty = True
for b in buf:
if b != 0xFF:
empty = False
break
if empty:
return True
fs_corrupted()
def fs_corrupted():
import time
while 1:
print(
"""\
The filesystem appears to be corrupted. If you had important data there, you
may want to make a flash snapshot to try to recover it. Otherwise, perform
factory reprogramming of MicroPython firmware (completely erase flash, followed
by firmware programming).
"""
)
time.sleep(3)
def setup():
check_bootsec()
print("Performing initial setup")
uos.VfsLfs2.mkfs(bdev)
vfs = uos.VfsLfs2(bdev)
uos.mount(vfs, "/")
with open("boot.py", "w") as f:
f.write(
"""\
# This file is executed on every boot (including wake-boot from deepsleep)
#import esp
#esp.osdebug(None)
#import webrepl
#webrepl.start()
# Power Management
from m5core2_power import Power
power = Power()
# LCD screen
from ili9XXX import ili9341
lcd = ili9341(mosi=23, miso=38, clk=18, dc=15, cs=5, invert=True, rot=0x10, width=320, height=240, rst=-1, power=-1, backlight=-1)
# Touch sensor
from ft6x36 import ft6x36
touch = ft6x36(width=320, height=280)
import lvgl as lv
"""
)
with open("board.py", "w") as f:
f.write(
"""\
name = "m5core2"
"""
)
with open("main.py", "w") as f:
f.write(
"""\
scr = lv.obj()
btn = lv.btn(scr)
btn.align(lv.ALIGN.CENTER, 0, 0)
label = lv.label(btn)
label.set_text("Button")
lv.scr_load(scr)
"""
)
return vfs

View File

@ -0,0 +1,91 @@
import axp192
from time import sleep
SDA = 21
SCL = 22
I2C_ADDRESS = 0x34
ESP_POWER = axp192.DCDC1_VOLTAGE
LCD_BACKLIGHT = axp192.DCDC3_VOLTAGE
LOGIC_AND_SD = axp192.LDO2_VOLTAGE
VIBRATOR = axp192.LDO3_VOLTAGE
class Power():
def __init__(self, i2c_dev=0, sda=SDA, scl=SCL, freq=400000, i2c_addr=I2C_ADDRESS, skip_init=False):
self.axp = axp192.AXP192(i2c_dev, sda, scl, freq, i2c_addr)
if skip_init:
return
print("Initialising M5Core2 power management")
self.axp.twiddle(axp192.VBUS_IPSOUT_CHANNEL, 0b11111011, 0x02)
print(" Vbus limit off")
self.axp.twiddle(axp192.GPIO2_CONTROL, 0b00000111, 0x00)
self.speaker(False)
print(" Speaker amplifier off")
self.axp.twiddle(axp192.BATTERY_CHARGE_CONTROL, 0b11100011, 0b10100010)
print(" RTC battery charging enabled (3v, 200uA)")
# If you set this too low or turn it off, you will need to do I2C mouth-to-mouth
# with another device to get your M5Core2 to come alive again. So don't do that.
self.axp.write(ESP_POWER, 3.35)
print(" ESP32 power voltage set to 3.35v")
self.axp.write(LCD_BACKLIGHT, 2.8)
print(" LCD backlight voltage set to 2.80v")
self.axp.write(LOGIC_AND_SD, 3.3)
print(" LCD logic and sdcard voltage set to 3.3v")
self.axp.twiddle(axp192.GPIO1_CONTROL, 0x07, 0x00)
self.led(True)
print(" LED on")
self.axp.twiddle(axp192.CHARGE_CONTROL_1, 0x0f, 0x00)
print(" Charge current set to 100 mA")
print(" Battery voltage now: {}v".format(self.axp.read(axp192.BATTERY_VOLTAGE)))
self.axp.twiddle(axp192.PEK, 0xff, 0x4c)
print(" Power key set, 4 seconds for hard shutdown")
self.axp.twiddle(axp192.ADC_ENABLE_1, 0x00, 0xff)
print(" Enabled all ADC channels")
self.int_5v(True)
print(" USB / battery powered, 5V bus on")
self.axp.twiddle(axp192.GPIO40_FUNCTION_CONTROL, 0x8d, 0x84)
self.axp.twiddle(axp192.GPIO40_SIGNAL_STATUS, 0x02, 0x00)
sleep(0.1)
self.axp.twiddle(axp192.GPIO40_SIGNAL_STATUS, 0x02, 0x02)
print(" LCD and touch reset")
sleep(0.1)
def led(self, state):
self.axp.twiddle(axp192.GPIO20_SIGNAL_STATUS, 0x02, 0x00 if state else 0x02)
def speaker(self, state):
self.axp.twiddle(axp192.GPIO20_SIGNAL_STATUS, 0x04, 0x04 if state else 0x00)
# True turns on at 2V, False or 0 turns off. Alternatively, specify a voltage in range 1.8 - 3.3 volts.
def vibrator(self, state):
if type(state) == bool and state:
self.axp.write(VIBRATOR, 2.0)
else:
self.axp.write(VIBRATOR, state)
def int_5v(self, state):
if state:
self.axp.twiddle(axp192.GPIO0_LDOIO0_VOLTAGE, 0xf0, 0xf0)
self.axp.twiddle(axp192.GPIO0_CONTROL, 0x07, 0x02)
self.axp.twiddle(axp192.DCDC13_LDO23_CONTROL, axp192.BIT_EXTEN_ENABLE, axp192.BIT_EXTEN_ENABLE)
else:
self.axp.twiddle(axp192.DCDC13_LDO23_CONTROL, axp192.BIT_EXTEN_ENABLE, 0)
self.axp.twiddle(axp192.GPIO0_CONTROL, 0x07, 0x01)

View File

@ -0,0 +1,11 @@
set(SDKCONFIG_DEFAULTS
boards/sdkconfig.base
boards/sdkconfig.ble
boards/sdkconfig.240mhz
boards/sdkconfig.spiram
boards/M5CORE2/sdkconfig.board
)
set(LV_CFLAGS -DLV_COLOR_DEPTH=16 -DLV_COLOR_16_SWAP=1)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)

View File

@ -0,0 +1,2 @@
#define MICROPY_HW_BOARD_NAME "M5Stack Core2"
#define MICROPY_HW_MCU_NAME "ESP32"

View File

@ -0,0 +1,9 @@
SDKCONFIG += boards/sdkconfig.base
SDKCONFIG += boards/sdkconfig.spiram
SDKCONFIG += boards/sdkconfig.240mhz
SDKCONFIG += boards/M5CORE2/sdkconfig.board
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
PART_SRC = $(BOARD_DIR)/partitions.csv
LV_CFLAGS = -DLV_COLOR_DEPTH=16 -DLV_COLOR_16_SWAP=1

View File

@ -0,0 +1,9 @@
# Note: 4MB factory partition for large libraries such as lvgl.
# all the remaining space is used for a FAT partition containing
# the user's python programs.
#
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 0x400000,
vfs, data, fat, 0x410000, 0xBF0000,
1 # Note: 4MB factory partition for large libraries such as lvgl.
2 # all the remaining space is used for a FAT partition containing
3 # the user's python programs.
4 #
5 # Name, Type, SubType, Offset, Size, Flags
6 nvs, data, nvs, 0x9000, 0x6000,
7 phy_init, data, phy, 0xf000, 0x1000,
8 factory, app, factory, 0x10000, 0x400000,
9 vfs, data, fat, 0x410000, 0xBF0000,

View File

@ -0,0 +1,6 @@
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="boards/M5CORE2/partitions.csv"
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_ESPTOOLPY_FLASHSIZE="16MB"