diff --git a/m5stack/boards/sdkconfig.base b/m5stack/boards/sdkconfig.base index 6e00b6b7..b8236cc0 100644 --- a/m5stack/boards/sdkconfig.base +++ b/m5stack/boards/sdkconfig.base @@ -3,11 +3,11 @@ CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 -# Compiler options: use -Os to reduce size, but keep full assertions +# Compiler options: use -O2 and disable assertions to improve performance # (CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is for IDF 4.0.2) CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y -CONFIG_COMPILER_OPTIMIZATION_SIZE=y -CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +CONFIG_COMPILER_OPTIMIZATION_PERF=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y # Application manager CONFIG_APP_EXCLUDE_PROJECT_VER_VAR=y diff --git a/m5stack/boards/sdkconfig.spiram_sx b/m5stack/boards/sdkconfig.spiram_sx index 18a0712c..ef24e908 100644 --- a/m5stack/boards/sdkconfig.spiram_sx +++ b/m5stack/boards/sdkconfig.spiram_sx @@ -1,5 +1,7 @@ # MicroPython on ESP32-S2 and ESP32-PAD1_subscript_3, ESP IDF configuration with SPIRAM support CONFIG_ESP32S2_SPIRAM_SUPPORT=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_MODE_QUAD=y CONFIG_SPIRAM_TYPE_AUTO=y CONFIG_DEFAULT_PSRAM_CLK_IO=30 CONFIG_DEFAULT_PSRAM_CS_IO=26 @@ -9,3 +11,5 @@ CONFIG_SPIRAM_BOOT_INIT=y CONFIG_SPIRAM_IGNORE_NOTFOUND=y CONFIG_SPIRAM_USE_MEMMAP=y CONFIG_SPIRAM_MEMTEST=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768 diff --git a/m5stack/cmodules/m5unified/m5unified.c b/m5stack/cmodules/m5unified/m5unified.c index ec14acf9..fcd0f137 100644 --- a/m5stack/cmodules/m5unified/m5unified.c +++ b/m5stack/cmodules/m5unified/m5unified.c @@ -11,6 +11,11 @@ #define MAKE_TABLE(prefix, func) \ { MP_ROM_QSTR(MP_QSTR_##func), MP_ROM_PTR(&prefix##_##func##_obj) } +// stream function +extern mp_uint_t gfx_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode); +extern mp_uint_t gfx_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode); +extern mp_uint_t gfx_ioctl(mp_obj_t self, mp_uint_t request, uintptr_t arg, int *errcode); + // -------- GFX common wrapper MAKE_METHOD_0(gfx, width); MAKE_METHOD_0(gfx, height); @@ -110,11 +115,23 @@ STATIC const mp_rom_map_elem_t gfxdevice_member_table[] = { TABLE_PARTS_GFX_BASE, MAKE_TABLE(gfx, startWrite), MAKE_TABLE(gfx, endWrite), + // stream function + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, }; STATIC MP_DEFINE_CONST_DICT(gfxdevice_member, gfxdevice_member_table); +// stream function +STATIC const mp_stream_p_t gfx_stream_p = { + .read = gfx_read, + .write = gfx_write, + .ioctl = gfx_ioctl, +}; + const mp_obj_type_t gfxdevice_type = { { &mp_type_type }, + .protocol = &gfx_stream_p, .locals_dict = (mp_obj_dict_t *)&gfxdevice_member, }; @@ -132,6 +149,7 @@ STATIC MP_DEFINE_CONST_DICT(gfxcanvas_member, gfxcanvas_member_table); const mp_obj_type_t gfxcanvas_type = { { &mp_type_type }, .flags = MP_TYPE_FLAG_IS_SUBCLASSED, + .protocol = &gfx_stream_p, .locals_dict = (mp_obj_dict_t *)&gfxcanvas_member, }; diff --git a/m5stack/libs/m5unified/M5GFX/src/lgfx/v1/LGFXBase.hpp b/m5stack/libs/m5unified/M5GFX/src/lgfx/v1/LGFXBase.hpp index e9fe530f..a502a9b4 100644 --- a/m5stack/libs/m5unified/M5GFX/src/lgfx/v1/LGFXBase.hpp +++ b/m5stack/libs/m5unified/M5GFX/src/lgfx/v1/LGFXBase.hpp @@ -523,6 +523,7 @@ namespace lgfx int32_t fontHeight(uint8_t font) const { return (int32_t)(((const BaseFont*)fontdata[font])->height * _text_style.size_y); } int32_t fontHeight(const IFont* font) const; int32_t fontHeight(void) const { return (int32_t)(_font_metrics.height * _text_style.size_y); } + int32_t fontWidth(void) const { return (int32_t)(_font_metrics.width * _text_style.size_x); } int32_t textLength(const char *string, int32_t width); int32_t textWidth(const char *string) { return textWidth(string, _font); }; int32_t textWidth(const char *string, const IFont* font); diff --git a/m5stack/libs/m5unified/mpy_m5gfx.cpp b/m5stack/libs/m5unified/mpy_m5gfx.cpp index 248965d5..6ddbab7d 100644 --- a/m5stack/libs/m5unified/mpy_m5gfx.cpp +++ b/m5stack/libs/m5unified/mpy_m5gfx.cpp @@ -16,6 +16,7 @@ extern "C" #include #include #include "mpy_m5gfx.h" + #include "esp_log.h" typedef struct _mp_obj_vfs_lfs2_t { mp_obj_base_t base; @@ -524,6 +525,134 @@ extern "C" return mp_const_none; } +// stream functions + mp_uint_t gfx_read(mp_obj_t self, void *buf, mp_uint_t size, int *errcode) + { + return 0; + } + + mp_uint_t gfx_write(mp_obj_t self, const byte *buf, mp_uint_t size, int *errcode) + { + auto gfx = getGfx(&self); + + static int32_t last_y_offset = gfx->getCursorY(); + const byte *i = buf; + gfx->fillRect(gfx->getCursorX(), gfx->getCursorY(), gfx->fontWidth(), gfx->fontHeight(), gfx->getTextStyle().back_rgb888); + while (i < buf + size) + { + uint8_t c = (uint8_t)utf8_get_char(i); + i = utf8_next_char(i); + if (c < 128) + { + if (c >= 0x20 && c <= 0x7e) + { + gfx->write(c); + } + else if (c == '\r') + { + gfx->write(c); + } + else if (c == '\n') + { + gfx->write(c); + last_y_offset = gfx->getCursorY(); + } + // Commands below are used by MicroPython in the REPL + else if (c == '\b') + { + int16_t x_offset = gfx->getCursorX(); + int16_t y_offset = gfx->getCursorY(); + if (x_offset == 0) { + x_offset = (int16_t)(gfx->fontWidth() * (gfx->width() / gfx->fontWidth())); + y_offset = y_offset - gfx->fontHeight(); + } + gfx->setCursor(x_offset - gfx->fontWidth(), y_offset); + } + else if (c == 0x1b) + { + if (i[0] == '[') + { + if (i[1] == 'K') + { + gfx->fillRect(gfx->getCursorX(), gfx->getCursorY(), gfx->fontWidth(), gfx->fontHeight(), gfx->getTextStyle().back_rgb888); + i += 2; + } + else { + // Handle commands of the form \x1b[####D + uint16_t n = 0; + uint8_t j = 1; + for (; j < 6; j++) + { + if ('0' <= i[j] && i[j] <= '9') + { + n = n * 10 + (i[j] - '0'); + } + else + { + c = i[j]; + break; + } + } + if (c == 'D') + { + // UP and DOWN KEY + if (gfx->getCursorY() > last_y_offset) + { + do { + gfx->fillRect(0, gfx->getCursorY(), gfx->width(), gfx->fontHeight(), gfx->getTextStyle().back_rgb888); + gfx->setCursor(gfx->getCursorX(), (gfx->getCursorY() - gfx->fontHeight())); + } while (gfx->getCursorY() > last_y_offset); + gfx->setCursor((gfx->fontWidth() * (gfx->width() / gfx->fontWidth())), last_y_offset); + } + if (gfx->getCursorY() == last_y_offset) + { + gfx->fillRect((gfx->fontWidth() * 4), gfx->getCursorY(), (gfx->width() - gfx->fontWidth() * 4), gfx->fontHeight(), gfx->getTextStyle().back_rgb888); + gfx->setCursor((gfx->fontWidth() * 4), gfx->getCursorY()); + } + } + if (c == 'J') + { + if (n == 2) + { + + } + } + if (c == ';') + { + uint16_t m = 0; + for (++j; j < 9; j++) + { + if ('0' <= i[j] && i[j] <= '9') + { + m = m * 10 + (i[j] - '0'); + } + else + { + c = i[j]; + break; + } + } + if (c == 'H') + { + + } + } + i += j + 1; + continue; + } + } + } + } + } + gfx->fillRect(gfx->getCursorX(), gfx->getCursorY(), gfx->fontWidth(), gfx->fontHeight(), gfx->getTextStyle().fore_rgb888); + return (i - buf); + } + + mp_uint_t gfx_ioctl(mp_obj_t self, mp_uint_t request, uintptr_t arg, int *errcode) + { + return 0; + } + const font_obj_t gfx_font_0_obj = {{ &mp_type_object }, &m5gfx::fonts::Font0 }; const font_obj_t gfx_font_2_obj = {{ &mp_type_object }, &m5gfx::fonts::Font2 }; const font_obj_t gfx_font_4_obj = {{ &mp_type_object }, &m5gfx::fonts::Font4 }; diff --git a/m5stack/libs/m5unified/mpy_m5gfx.h b/m5stack/libs/m5unified/mpy_m5gfx.h index c7c3b2f7..9942fcb9 100644 --- a/m5stack/libs/m5unified/mpy_m5gfx.h +++ b/m5stack/libs/m5unified/mpy_m5gfx.h @@ -3,6 +3,8 @@ #include #include #include +#include +#include typedef struct _gfx_obj_t { mp_obj_base_t base; diff --git a/m5stack/libs/m5unified/mpy_m5unified.h b/m5stack/libs/m5unified/mpy_m5unified.h index 6341bb52..f2050161 100644 --- a/m5stack/libs/m5unified/mpy_m5unified.h +++ b/m5stack/libs/m5unified/mpy_m5unified.h @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include "mpy_m5gfx.h" #include "mpy_m5btn.h" diff --git a/m5stack/main.c b/m5stack/main.c index 2ba61366..c9b033d6 100644 --- a/m5stack/main.c +++ b/m5stack/main.c @@ -101,7 +101,7 @@ void mp_task(void *pvParameter) { #if CONFIG_ESP32_SPIRAM_SUPPORT || CONFIG_SPIRAM_SUPPORT // Try to use the entire external SPIRAM directly for the heap size_t mp_task_heap_size; - void *mp_task_heap = (void *)0x3f800000; + void *mp_task_heap = (void *)SOC_EXTRAM_DATA_LOW; switch (esp_spiram_get_chip_size()) { case ESP_SPIRAM_SIZE_16MBITS: mp_task_heap_size = 2 * 1024 * 1024; @@ -120,7 +120,7 @@ void mp_task(void *pvParameter) { // Try to use the entire external SPIRAM directly for the heap size_t mp_task_heap_size; size_t esp_spiram_size = esp_spiram_get_size(); - void *mp_task_heap = (void *)0x3ff80000 - esp_spiram_size; + void *mp_task_heap = (void *)SOC_EXTRAM_DATA_HIGH - esp_spiram_size; if (esp_spiram_size > 0) { mp_task_heap_size = esp_spiram_size; } else { @@ -140,10 +140,7 @@ void mp_task(void *pvParameter) { mp_stack_set_limit(MP_TASK_STACK_SIZE - MP_TASK_STACK_LIMIT_MARGIN); gc_init(mp_task_heap, mp_task_heap + mp_task_heap_size); mp_init(); - mp_obj_list_init(mp_sys_path, 0); - mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); - mp_obj_list_init(mp_sys_argv, 0); readline_init0(); // initialise peripherals @@ -193,6 +190,8 @@ void mp_task(void *pvParameter) { mp_hal_stdout_tx_str("MPY: soft reboot\r\n"); // deinitialise peripherals + machine_pwm_deinit_all(); + // TODO: machine_rmt_deinit_all(); machine_pins_deinit(); machine_deinit(); usocket_events_deinit(); @@ -202,12 +201,20 @@ void mp_task(void *pvParameter) { goto soft_reset; } -void app_main(void) { +void boardctrl_startup(void) { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { nvs_flash_erase(); nvs_flash_init(); } +} + +void app_main(void) { + // Hook for a board to run code at start up. + // This defaults to initialising NVS. + MICROPY_BOARD_STARTUP(); + + // Create and transfer control to the MicroPython task. xTaskCreatePinnedToCore(mp_task, "mp_task", MP_TASK_STACK_SIZE / sizeof(StackType_t), NULL, MP_TASK_PRIORITY, &mp_main_task_handle, MP_TASK_COREID); } diff --git a/m5stack/main/CMakeLists.txt b/m5stack/main/CMakeLists.txt index 05d5039c..3175d3dc 100644 --- a/m5stack/main/CMakeLists.txt +++ b/m5stack/main/CMakeLists.txt @@ -45,7 +45,6 @@ set(MICROPY_SOURCE_DRIVERS set(MICROPY_SOURCE_PORT ${PROJECT_DIR}/main.c - ${PROJECT_DIR}/esp32_nvs.c ${PROJECT_DIR}/../micropython/ports/esp32/uart.c ${PROJECT_DIR}/../micropython/ports/esp32/usb.c ${PROJECT_DIR}/../micropython/ports/esp32/usb_serial_jtag.c @@ -63,15 +62,16 @@ set(MICROPY_SOURCE_PORT ${PROJECT_DIR}/../micropython/ports/esp32/machine_dac.c ${PROJECT_DIR}/../micropython/ports/esp32/machine_i2c.c ${PROJECT_DIR}/../micropython/ports/esp32/machine_i2s.c - ${PROJECT_DIR}/../micropython/ports/esp32/machine_pwm.c ${PROJECT_DIR}/../micropython/ports/esp32/machine_uart.c ${PROJECT_DIR}/../micropython/ports/esp32/modmachine.c ${PROJECT_DIR}/../micropython/ports/esp32/modnetwork.c ${PROJECT_DIR}/../micropython/ports/esp32/network_lan.c ${PROJECT_DIR}/../micropython/ports/esp32/network_ppp.c + ${PROJECT_DIR}/../micropython/ports/esp32/network_wlan.c ${PROJECT_DIR}/../micropython/ports/esp32/mpnimbleport.c ${PROJECT_DIR}/../micropython/ports/esp32/modsocket.c ${PROJECT_DIR}/../micropython/ports/esp32/modesp.c + ${PROJECT_DIR}/esp32_nvs.c ${PROJECT_DIR}/../micropython/ports/esp32/esp32_partition.c ${PROJECT_DIR}/../micropython/ports/esp32/esp32_rmt.c ${PROJECT_DIR}/../micropython/ports/esp32/esp32_ulp.c diff --git a/micropython b/micropython index 7c54b642..da4b38e7 160000 --- a/micropython +++ b/micropython @@ -1 +1 @@ -Subproject commit 7c54b6428058a236b8a48c93c255948ece7e718b +Subproject commit da4b38e7562dfa451917f9d7f344a7f26de8c7bd diff --git a/tests/display/drawcircle.py b/tests/display/drawcircle.py index f2a49b30..03ee9908 100644 --- a/tests/display/drawcircle.py +++ b/tests/display/drawcircle.py @@ -1,3 +1,5 @@ +# -*- encoding: utf-8 -*- +# draw moving circle with circle id import m5 from m5 import lcd import random @@ -38,30 +40,29 @@ def __init__(self, x, y, r, dx, dy, color, index): ) -def run(): - while True: - for ball in balls: - ball.x += ball.dx - ball.y += ball.dy +while True: + for ball in balls: + ball.x += ball.dx + ball.y += ball.dy - xmax = WIDTH - ball.r - xmin = ball.r - ymax = HEIGHT - ball.r - ymin = ball.r + xmax = WIDTH - ball.r + xmin = ball.r + ymax = HEIGHT - ball.r + ymin = ball.r - if ball.x <= xmin or ball.x >= xmax: - ball.dx *= -1 + if ball.x <= xmin or ball.x >= xmax: + ball.dx *= -1 - if ball.y <= ymin or ball.y >= ymax: - ball.dy *= -1 + if ball.y <= ymin or ball.y >= ymax: + ball.dy *= -1 - canvas.drawCircle(ball.x, ball.y, ball.r, ball.color) - canvas.setCursor(ball.x - 4, ball.y - 4) - canvas.print(str(ball.index), ball.color) + canvas.drawCircle(ball.x, ball.y, ball.r, ball.color) + canvas.setCursor(ball.x - 4, ball.y - 4) + canvas.print(str(ball.index), ball.color) - canvas.push(0, 0) + canvas.push(0, 0) - for ball in balls: - canvas.drawCircle(ball.x, ball.y, ball.r, lcd.BLACK) - canvas.setCursor(ball.x - 4, ball.y - 4) - canvas.print(str(ball.index), lcd.BLACK) + for ball in balls: + canvas.drawCircle(ball.x, ball.y, ball.r, lcd.BLACK) + canvas.setCursor(ball.x - 4, ball.y - 4) + canvas.print(str(ball.index), lcd.BLACK) diff --git a/tests/display/textscroll.py b/tests/display/textscroll.py index def3a51b..88bd3958 100644 --- a/tests/display/textscroll.py +++ b/tests/display/textscroll.py @@ -1,3 +1,5 @@ +# -*- encoding: utf-8 -*- +# text scroll import m5 import time