diff --git a/components/micropython/vendor/ports/esp32/main.c b/components/micropython/vendor/ports/esp32/main.c index 9daf20a98c903fd6f3ac7d5c361cb99111bbd73f..d73c8c92482ea3fdddacd7e96de2cab12a87b3c4 100644 --- a/components/micropython/vendor/ports/esp32/main.c +++ b/components/micropython/vendor/ports/esp32/main.c @@ -119,7 +119,7 @@ soft_reset: // run boot-up scripts pyexec_frozen_module("_boot.py"); - pyexec_file_if_exists("boot.py"); + int ret = pyexec_file_if_exists("boot.py"); if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { int ret = pyexec_file_if_exists("/flash/sys/main.py"); if (ret & PYEXEC_FORCED_EXIT) { @@ -127,7 +127,15 @@ soft_reset: } } - st3m_mode_set(st3m_mode_kind_repl, NULL); + if (ret == 1) + { + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) + st3m_mode_set(st3m_mode_kind_mpremote, NULL); + else + st3m_mode_set(st3m_mode_kind_repl, NULL); + } + else + st3m_mode_set(st3m_mode_kind_exception, NULL); for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { diff --git a/components/micropython/vendor/ports/esp32/mphalport.c b/components/micropython/vendor/ports/esp32/mphalport.c index 392ffe99cf9acf8ca661fd68ab50897d0044eb0c..ee227698510d5fdc4db54abb140aa990e2c0ecda 100644 --- a/components/micropython/vendor/ports/esp32/mphalport.c +++ b/components/micropython/vendor/ports/esp32/mphalport.c @@ -34,6 +34,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_timer.h" +#include "st3m_term.h" #include "py/obj.h" #include "py/objstr.h" @@ -122,12 +123,14 @@ int mp_hal_stdin_rx_chr(void) { } } + void mp_hal_stdout_tx_strn(const char *str, size_t len) { // Only release the GIL if many characters are being sent bool release_gil = len > 20; if (release_gil) { MP_THREAD_GIL_EXIT(); } + st3m_term_feed(str, len); fwrite(str, len, 1, stdout); if (release_gil) { MP_THREAD_GIL_ENTER(); diff --git a/components/st3m/CMakeLists.txt b/components/st3m/CMakeLists.txt index 35564c8af43491c77f52bec560ecb7d4223493e3..85c25e2e98c5a60ca4d9fcea9fd5d2ec7a78c8a8 100644 --- a/components/st3m/CMakeLists.txt +++ b/components/st3m/CMakeLists.txt @@ -17,6 +17,7 @@ idf_component_register( st3m_captouch.c st3m_ringbuffer.c st3m_tar.c + st3m_term.c st3m_fs.c st3m_fs_flash.c st3m_fs_sd.c diff --git a/components/st3m/st3m_mode.c b/components/st3m/st3m_mode.c index 3f014161a187c41325edd18c451958deb8b110f8..e92ff8be9fcfcc56fb87edf51dd7f0201a10bbca 100644 --- a/components/st3m/st3m_mode.c +++ b/components/st3m/st3m_mode.c @@ -9,6 +9,7 @@ #include "st3m_gfx.h" #include "st3m_io.h" +#include "st3m_term.h" static st3m_mode_t _mode = { .kind = st3m_mode_kind_starting, @@ -62,17 +63,27 @@ void st3m_mode_update_display(bool *restartable) { case st3m_mode_kind_disk: st3m_gfx_splash("Disk Mode"); break; + case st3m_mode_kind_exception: + if (!_mode.shown) { + _mode.shown = true; + st3m_term_draw(6); + } + if (restartable != NULL) *restartable = true; + break; case st3m_mode_kind_repl: + case st3m_mode_kind_mpremote: if (!_mode.shown) { _mode.shown = true; const char *lines[] = { - "Send Ctrl-D over USB", - "or press left shoulder button", + "Send Ctrl-D over USB or", + "press left shoulder button", "to restart.", NULL, }; st3m_gfx_textview_t tv = { - .title = "In REPL", + .title = _mode.kind == st3m_mode_kind_repl + ? "In REPL" + : "mpremote active", .lines = lines, }; st3m_gfx_show_textview(&tv); @@ -133,4 +144,4 @@ void st3m_mode_init(void) { assert(_mu != NULL); xTaskCreate(_task, "mode", 4096, NULL, 1, NULL); -} \ No newline at end of file +} diff --git a/components/st3m/st3m_mode.h b/components/st3m/st3m_mode.h index 04f2957260be507ee7f365077a4433e6f1b9f2ca..b124e8396981de30727d7aa492f36f9b9f8f2558 100644 --- a/components/st3m/st3m_mode.h +++ b/components/st3m/st3m_mode.h @@ -9,6 +9,8 @@ typedef enum { st3m_mode_kind_repl = 3, st3m_mode_kind_disk = 4, st3m_mode_kind_fatal = 5, + st3m_mode_kind_exception = 6, + st3m_mode_kind_mpremote = 7, } st3m_mode_kind_t; typedef struct { @@ -33,4 +35,4 @@ void st3m_mode_set(st3m_mode_kind_t kind, const char *msg); // Update screen based on current mode immediately. Otherwise the screen gets // updated at a 10Hz cadence in a low-priority task. -void st3m_mode_update_display(bool *restartable); \ No newline at end of file +void st3m_mode_update_display(bool *restartable); diff --git a/components/st3m/st3m_term.c b/components/st3m/st3m_term.c new file mode 100644 index 0000000000000000000000000000000000000000..dda0284152e53c418514aee62e9d2df40f6c6365 --- /dev/null +++ b/components/st3m/st3m_term.c @@ -0,0 +1,83 @@ +#include "st3m_term.h" + +#include "st3m_gfx.h" + +/* a tiny dumb terminal */ + +#define ST3M_TERM_COLS 27 +#define ST3M_TERM_LINES 16 + +static char st3m_term[ST3M_TERM_LINES][ST3M_TERM_COLS]; +static int st3m_term_cx = 0; +static int st3m_term_cy = 0; + +void st3m_term_feed(const char *str, size_t len) { + for (int i = 0; i < len; i++) { + char c = str[i]; + switch (c) { + case '\t': { + char *space_buf = " "; + do { + st3m_term_feed(space_buf, 1); + } while ((st3m_term_cx & 7) != 0); + } break; + case '\b': + st3m_term_cx--; + if (st3m_term_cx < 0) st3m_term_cx = 0; + break; + case '\r': + st3m_term_cx = 0; + break; + case '\n': + st3m_term_cx = 0; + st3m_term_cy++; + if (st3m_term_cy >= ST3M_TERM_LINES) st3m_term_cy = 0; + memset(st3m_term[st3m_term_cy], 0, ST3M_TERM_COLS); + break; + default: + st3m_term[st3m_term_cy][st3m_term_cx] = c; + st3m_term_cx++; + if (st3m_term_cx >= ST3M_TERM_COLS) { + st3m_term_cx = 0; + st3m_term_cy++; + if (st3m_term_cy >= ST3M_TERM_LINES) st3m_term_cy = 0; + memset(st3m_term[st3m_term_cy], 0, ST3M_TERM_COLS); + } + } + } +} + +// returns a line from terminal scrollback +// line_no is a value 0..15 +const char *st3m_term_get_line(int line_no) { + return st3m_term[(st3m_term_cy - line_no - 1) & 15]; +} + +// draws the last bit of terminal output, avoiding the last skip_lines +// lines added. +void st3m_term_draw(int skip_lines) { + st3m_ctx_desc_t *target = st3m_gfx_drawctx_free_get(portMAX_DELAY); + Ctx *ctx = target->ctx; + float font_size = 20.0; + float y = 64; + + ctx_save(ctx); + + ctx_font_size(ctx, font_size); + ctx_text_align(ctx, CTX_TEXT_ALIGN_LEFT); // XXX this should not be needed + + ctx_gray(ctx, 0.0); + ctx_rectangle(ctx, -120, -120, 240, 240); + ctx_fill(ctx); + + ctx_gray(ctx, 1.0); + for (int i = 0; i < 7 && y > -70; i++) { + ctx_move_to(ctx, -100, y); + ctx_text(ctx, st3m_term_get_line(i + skip_lines)); + y -= font_size; + } + + ctx_restore(ctx); + + st3m_gfx_drawctx_pipe_put(target); +} diff --git a/components/st3m/st3m_term.h b/components/st3m/st3m_term.h new file mode 100644 index 0000000000000000000000000000000000000000..7982a760a697fca332808ab99e03205761023498 --- /dev/null +++ b/components/st3m/st3m_term.h @@ -0,0 +1,11 @@ +#pragma once + +#include "esp_err.h" + +#include <stdint.h> + +void st3m_imu_init(void); + +void st3m_term_feed(const char *str, size_t len); +const char *st3m_term_get_line(int line_no); +void st3m_term_draw(int skip_lines);