status bar control

This commit is contained in:
Dan Halbert 2022-08-28 21:55:13 -04:00
parent aa5f892a11
commit 52080e24eb
25 changed files with 597 additions and 135 deletions

52
main.c
View File

@ -57,7 +57,6 @@
#include "supervisor/shared/stack.h" #include "supervisor/shared/stack.h"
#include "supervisor/shared/status_leds.h" #include "supervisor/shared/status_leds.h"
#include "supervisor/shared/tick.h" #include "supervisor/shared/tick.h"
#include "supervisor/shared/title_bar.h"
#include "supervisor/shared/traceback.h" #include "supervisor/shared/traceback.h"
#include "supervisor/shared/translate/translate.h" #include "supervisor/shared/translate/translate.h"
#include "supervisor/shared/workflow.h" #include "supervisor/shared/workflow.h"
@ -106,6 +105,10 @@
#include "shared-bindings/socketpool/__init__.h" #include "shared-bindings/socketpool/__init__.h"
#endif #endif
#if CIRCUITPY_STATUS_BAR
#include "supervisor/shared/status_bar.h"
#endif
#if CIRCUITPY_USB_HID #if CIRCUITPY_USB_HID
#include "shared-module/usb_hid/__init__.h" #include "shared-module/usb_hid/__init__.h"
#endif #endif
@ -208,6 +211,7 @@ STATIC const char *_current_executing_filename = NULL;
STATIC pyexec_result_t _exec_result = {0, MP_OBJ_NULL, 0}; STATIC pyexec_result_t _exec_result = {0, MP_OBJ_NULL, 0};
#if CIRCUITPY_STATUS_BAR
void supervisor_execution_status(void) { void supervisor_execution_status(void) {
mp_obj_exception_t *exception = MP_OBJ_TO_PTR(_exec_result.exception); mp_obj_exception_t *exception = MP_OBJ_TO_PTR(_exec_result.exception);
if (_current_executing_filename != NULL) { if (_current_executing_filename != NULL) {
@ -220,6 +224,7 @@ void supervisor_execution_status(void) {
serial_write_compressed(translate("Done")); serial_write_compressed(translate("Done"));
} }
} }
#endif
#define STRING_LIST(...) {__VA_ARGS__, ""} #define STRING_LIST(...) {__VA_ARGS__, ""}
@ -245,13 +250,23 @@ STATIC bool maybe_run_list(const char *const *filenames) {
} }
mp_hal_stdout_tx_str(_current_executing_filename); mp_hal_stdout_tx_str(_current_executing_filename);
serial_write_compressed(translate(" output:\n")); serial_write_compressed(translate(" output:\n"));
supervisor_title_bar_update();
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_update();
#endif
pyexec_file(_current_executing_filename, &_exec_result); pyexec_file(_current_executing_filename, &_exec_result);
#if CIRCUITPY_ATEXIT #if CIRCUITPY_ATEXIT
shared_module_atexit_execute(&_exec_result); shared_module_atexit_execute(&_exec_result);
#endif #endif
_current_executing_filename = NULL; _current_executing_filename = NULL;
supervisor_title_bar_update();
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_update();
#endif
return true; return true;
} }
@ -749,8 +764,10 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
if (ok_to_run) { if (ok_to_run) {
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE #ifdef CIRCUITPY_BOOT_OUTPUT_FILE
// Turn off title bar updates when writing out to boot_out.txt. #if CIRCUITPY_STATUS_BAR
supervisor_title_bar_suspend(); // Turn off status bar updates when writing out to boot_out.txt.
supervisor_status_bar_suspend();
#endif
vstr_t boot_text; vstr_t boot_text;
vstr_init(&boot_text, 512); vstr_init(&boot_text, 512);
boot_output = &boot_text; boot_output = &boot_text;
@ -778,7 +795,9 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
FATFS *fs = &vfs->fatfs; FATFS *fs = &vfs->fatfs;
boot_output = NULL; boot_output = NULL;
supervisor_title_bar_resume(); #if CIRCUITPY_STATUS_BAR
supervisor_status_bar_resume();
#endif
bool write_boot_output = true; bool write_boot_output = true;
FIL boot_output_file; FIL boot_output_file;
if (f_open(fs, &boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_READ) == FR_OK) { if (f_open(fs, &boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_READ) == FR_OK) {
@ -854,15 +873,23 @@ STATIC int run_repl(bool first_run) {
status_led_deinit(); status_led_deinit();
#endif #endif
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
supervisor_title_bar_suspend(); #if CIRCUITPY_STATUS_BAR
supervisor_status_bar_suspend();
#endif
exit_code = pyexec_raw_repl(); exit_code = pyexec_raw_repl();
supervisor_title_bar_resume(); #if CIRCUITPY_STATUS_BAR
supervisor_status_bar_resume();
#endif
} else { } else {
_current_executing_filename = "REPL"; _current_executing_filename = "REPL";
supervisor_title_bar_update(); #if CIRCUITPY_STATUS_BAR
supervisor_status_bar_update();
#endif
exit_code = pyexec_friendly_repl(); exit_code = pyexec_friendly_repl();
_current_executing_filename = NULL; _current_executing_filename = NULL;
supervisor_title_bar_update(); #if CIRCUITPY_STATUS_BAR
supervisor_status_bar_update();
#endif
} }
#if CIRCUITPY_ATEXIT #if CIRCUITPY_ATEXIT
pyexec_result_t result; pyexec_result_t result;
@ -959,7 +986,10 @@ int __attribute__((used)) main(void) {
run_boot_py(safe_mode); run_boot_py(safe_mode);
supervisor_workflow_start(); supervisor_workflow_start();
supervisor_title_bar_start();
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_start();
#endif
// Boot script is finished, so now go into REPL or run code.py. // Boot script is finished, so now go into REPL or run code.py.
int exit_code = PYEXEC_FORCED_EXIT; int exit_code = PYEXEC_FORCED_EXIT;

View File

@ -44,9 +44,12 @@ wifi_radio_obj_t common_hal_wifi_radio_obj;
#include "components/log/include/esp_log.h" #include "components/log/include/esp_log.h"
#include "supervisor/port.h" #include "supervisor/port.h"
#include "supervisor/shared/title_bar.h"
#include "supervisor/workflow.h" #include "supervisor/workflow.h"
#if CIRCUITPY_STATUS_BAR
#include "supervisor/shared/status_bar.h"
#endif
#include "esp_ipc.h" #include "esp_ipc.h"
#ifdef CONFIG_IDF_TARGET_ESP32 #ifdef CONFIG_IDF_TARGET_ESP32
@ -56,7 +59,9 @@ wifi_radio_obj_t common_hal_wifi_radio_obj;
static const char *TAG = "CP wifi"; static const char *TAG = "CP wifi";
STATIC void schedule_background_on_cp_core(void *arg) { STATIC void schedule_background_on_cp_core(void *arg) {
supervisor_title_bar_request_update(false); #if CIRCUITPY_STATUS_BAR
supervisor_status_bar_request_update(false);
#endif
// CircuitPython's VM is run in a separate FreeRTOS task from wifi callbacks. So, we have to // CircuitPython's VM is run in a separate FreeRTOS task from wifi callbacks. So, we have to
// notify the main task every time in case it's waiting for us. // notify the main task every time in case it's waiting for us.

View File

@ -101,6 +101,7 @@ endif
### ###
# Select which builtin modules to compile and include. # Select which builtin modules to compile and include.
# Keep alphabetical.
ifeq ($(CIRCUITPY_AESIO),1) ifeq ($(CIRCUITPY_AESIO),1)
SRC_PATTERNS += aesio/% SRC_PATTERNS += aesio/%
@ -175,11 +176,8 @@ endif
ifeq ($(CIRCUITPY_DOTENV),1) ifeq ($(CIRCUITPY_DOTENV),1)
SRC_PATTERNS += dotenv/% SRC_PATTERNS += dotenv/%
endif endif
ifeq ($(CIRCUITPY_PARALLELDISPLAY),1) ifeq ($(CIRCUITPY__EVE),1)
SRC_PATTERNS += paralleldisplay/% SRC_PATTERNS += _eve/%
endif
ifeq ($(CIRCUITPY_VECTORIO),1)
SRC_PATTERNS += vectorio/%
endif endif
ifeq ($(CIRCUITPY_FLOPPYIO),1) ifeq ($(CIRCUITPY_FLOPPYIO),1)
SRC_PATTERNS += floppyio/% SRC_PATTERNS += floppyio/%
@ -187,17 +185,12 @@ endif
ifeq ($(CIRCUITPY_FRAMEBUFFERIO),1) ifeq ($(CIRCUITPY_FRAMEBUFFERIO),1)
SRC_PATTERNS += framebufferio/% SRC_PATTERNS += framebufferio/%
endif endif
ifeq ($(CIRCUITPY__EVE),1)
SRC_PATTERNS += _eve/%
endif
ifeq ($(CIRCUITPY_FREQUENCYIO),1) ifeq ($(CIRCUITPY_FREQUENCYIO),1)
SRC_PATTERNS += frequencyio/% SRC_PATTERNS += frequencyio/%
endif endif
ifeq ($(CIRCUITPY_FUTURE),1) ifeq ($(CIRCUITPY_FUTURE),1)
SRC_PATTERNS += __future__/% SRC_PATTERNS += __future__/%
endif endif
ifeq ($(CIRCUITPY_GETPASS),1) ifeq ($(CIRCUITPY_GETPASS),1)
SRC_PATTERNS += getpass/% SRC_PATTERNS += getpass/%
endif endif
@ -237,6 +230,9 @@ endif
ifeq ($(CIRCUITPY_MDNS),1) ifeq ($(CIRCUITPY_MDNS),1)
SRC_PATTERNS += mdns/% SRC_PATTERNS += mdns/%
endif endif
ifeq ($(CIRCUITPY_MSGPACK),1)
SRC_PATTERNS += msgpack/%
endif
ifeq ($(CIRCUITPY_NEOPIXEL_WRITE),1) ifeq ($(CIRCUITPY_NEOPIXEL_WRITE),1)
SRC_PATTERNS += neopixel_write/% SRC_PATTERNS += neopixel_write/%
endif endif
@ -252,6 +248,12 @@ endif
ifeq ($(CIRCUITPY_DUALBANK),1) ifeq ($(CIRCUITPY_DUALBANK),1)
SRC_PATTERNS += dualbank/% SRC_PATTERNS += dualbank/%
endif endif
ifeq ($(CIRCUITPY_PARALLELDISPLAY),1)
SRC_PATTERNS += paralleldisplay/%
endif
ifeq ($(CIRCUITPY_PEW),1)
SRC_PATTERNS += _pew/%
endif
ifeq ($(CIRCUITPY_PIXELBUF),1) ifeq ($(CIRCUITPY_PIXELBUF),1)
SRC_PATTERNS += adafruit_pixelbuf/% SRC_PATTERNS += adafruit_pixelbuf/%
endif endif
@ -351,8 +353,8 @@ endif
ifeq ($(CIRCUITPY_USTACK),1) ifeq ($(CIRCUITPY_USTACK),1)
SRC_PATTERNS += ustack/% SRC_PATTERNS += ustack/%
endif endif
ifeq ($(CIRCUITPY_ZLIB),1) ifeq ($(CIRCUITPY_VECTORIO),1)
SRC_PATTERNS += zlib/% SRC_PATTERNS += vectorio/%
endif endif
ifeq ($(CIRCUITPY_VIDEOCORE),1) ifeq ($(CIRCUITPY_VIDEOCORE),1)
SRC_PATTERNS += videocore/% SRC_PATTERNS += videocore/%
@ -363,11 +365,8 @@ endif
ifeq ($(CIRCUITPY_WIFI),1) ifeq ($(CIRCUITPY_WIFI),1)
SRC_PATTERNS += wifi/% SRC_PATTERNS += wifi/%
endif endif
ifeq ($(CIRCUITPY_PEW),1) ifeq ($(CIRCUITPY_ZLIB),1)
SRC_PATTERNS += _pew/% SRC_PATTERNS += zlib/%
endif
ifeq ($(CIRCUITPY_MSGPACK),1)
SRC_PATTERNS += msgpack/%
endif endif
# All possible sources are listed here, and are filtered by SRC_PATTERNS in SRC_COMMON_HAL # All possible sources are listed here, and are filtered by SRC_PATTERNS in SRC_COMMON_HAL
@ -511,6 +510,7 @@ $(filter $(SRC_PATTERNS), \
qrio/PixelPolicy.c \ qrio/PixelPolicy.c \
qrio/QRInfo.c \ qrio/QRInfo.c \
supervisor/RunReason.c \ supervisor/RunReason.c \
supervisor/StatusBar.c \
wifi/AuthMode.c \ wifi/AuthMode.c \
wifi/Packet.c \ wifi/Packet.c \
) )
@ -611,6 +611,8 @@ SRC_SHARED_MODULE_ALL = \
socket/__init__.c \ socket/__init__.c \
storage/__init__.c \ storage/__init__.c \
struct/__init__.c \ struct/__init__.c \
supervisor/__init__.c \
supervisor/StatusBar.c \
synthio/MidiTrack.c \ synthio/MidiTrack.c \
synthio/__init__.c \ synthio/__init__.c \
terminalio/Terminal.c \ terminalio/Terminal.c \

View File

@ -0,0 +1,126 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 by Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdbool.h>
#include "py/obj.h"
#include "py/enum.h"
#include "py/runtime.h"
#include "py/objproperty.h"
#include "shared-bindings/supervisor/StatusBar.h"
//| class StatusBar:
//| """Current status of runtime objects.
//|
//| Usage::
//|
//| import supervisor
//|
//| supervisor.status_bar.console = False
//| """
//|
//| def __init__(self) -> None:
//| """You cannot create an instance of `supervisor.StatusBar`.
//| Use `supervisor.status_bar` to access the sole instance available."""
//| ...
//|
//| console: bool
//| """Whether status bar information is sent over the console (REPL) serial connection,
//| using OSC terminal escape codes that change the terminal's title. Default is ``True``.
//| If set to ``False``, status bar will be cleared and then disabled.
//| May be set in ``boot.py`` or later.
//| """
//|
STATIC mp_obj_t supervisor_status_bar_get_console(mp_obj_t self_in) {
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bool(shared_module_supervisor_status_bar_get_console(self));
#else
mp_raise_NotImplementedError(NULL);
#endif
}
MP_DEFINE_CONST_FUN_OBJ_1(supervisor_status_bar_get_console_obj, supervisor_status_bar_get_console);
STATIC mp_obj_t supervisor_status_bar_set_console(mp_obj_t self_in, mp_obj_t state_in) {
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_obj_t *self = MP_OBJ_TO_PTR(self_in);
shared_module_supervisor_status_bar_set_console(self, mp_obj_is_true(state_in));
return mp_const_none;
#else
mp_raise_NotImplementedError(NULL);
#endif
}
MP_DEFINE_CONST_FUN_OBJ_2(supervisor_status_bar_set_console_obj, supervisor_status_bar_set_console);
MP_PROPERTY_GETSET(supervisor_status_bar_console_obj,
(mp_obj_t)&supervisor_status_bar_get_console_obj,
(mp_obj_t)&supervisor_status_bar_set_console_obj);
//| display: bool
//| """Whether status bar information is displayed on the top line of the display.
//| Default is ``True``. If set to ``False``, status bar will be cleared and then disabled.
//| May be set in ``boot.py`` or later. Not available if `terminalio` is not available.
//| """
//|
STATIC mp_obj_t supervisor_status_bar_get_display(mp_obj_t self_in) {
#if CIRCUITPY_STATUS_BAR && CIRCUITPY_TERMINALIO
supervisor_status_bar_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bool(shared_module_supervisor_status_bar_get_display(self));
#else
mp_raise_NotImplementedError(NULL);
#endif
}
MP_DEFINE_CONST_FUN_OBJ_1(supervisor_status_bar_get_display_obj, supervisor_status_bar_get_display);
STATIC mp_obj_t supervisor_status_bar_set_display(mp_obj_t self_in, mp_obj_t state_in) {
#if CIRCUITPY_STATUS_BAR && CIRCUITPY_TERMINALIO
supervisor_status_bar_obj_t *self = MP_OBJ_TO_PTR(self_in);
shared_module_supervisor_status_bar_set_display(self, mp_obj_is_true(state_in));
return mp_const_none;
#else
mp_raise_NotImplementedError(NULL);
#endif
}
MP_DEFINE_CONST_FUN_OBJ_2(supervisor_status_bar_set_display_obj, supervisor_status_bar_set_display);
MP_PROPERTY_GETSET(supervisor_status_bar_display_obj,
(mp_obj_t)&supervisor_status_bar_get_display_obj,
(mp_obj_t)&supervisor_status_bar_set_display_obj);
STATIC const mp_rom_map_elem_t supervisor_status_bar_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_console), MP_ROM_PTR(&supervisor_status_bar_console_obj) },
{ MP_ROM_QSTR(MP_QSTR_display), MP_ROM_PTR(&supervisor_status_bar_display_obj) },
};
STATIC MP_DEFINE_CONST_DICT(supervisor_status_bar_locals_dict, supervisor_status_bar_locals_dict_table);
const mp_obj_type_t supervisor_status_bar_type = {
.base = { &mp_type_type },
.name = MP_QSTR_Status_Bar,
.locals_dict = (mp_obj_dict_t *)&supervisor_status_bar_locals_dict,
};

View File

@ -0,0 +1,42 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 by Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_STATUS_BAR_STATUS_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_STATUS_BAR_STATUS_H
#include <stdbool.h>
#include "py/obj.h"
#include "shared-module/supervisor/StatusBar.h"
extern const mp_obj_type_t supervisor_status_bar_type;
bool shared_module_supervisor_status_bar_get_console(supervisor_status_bar_obj_t *self);
void shared_module_supervisor_status_bar_set_console(supervisor_status_bar_obj_t *self, bool enabled);
bool shared_module_supervisor_status_bar_get_display(supervisor_status_bar_obj_t *self);
void shared_module_supervisor_status_bar_set_display(supervisor_status_bar_obj_t *self, bool enabled);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SUPERVISOR_STATUS_BAR_H

View File

@ -43,6 +43,7 @@
#include "shared-bindings/supervisor/__init__.h" #include "shared-bindings/supervisor/__init__.h"
#include "shared-bindings/time/__init__.h" #include "shared-bindings/time/__init__.h"
#include "shared-bindings/supervisor/Runtime.h" #include "shared-bindings/supervisor/Runtime.h"
#include "shared-bindings/supervisor/StatusBar.h"
//| """Supervisor settings""" //| """Supervisor settings"""
//| //|
@ -53,6 +54,14 @@
//| This object is the sole instance of `supervisor.Runtime`.""" //| This object is the sole instance of `supervisor.Runtime`."""
//| //|
//| status_bar: StatusBar
//| """The status bar, shown on an attached display, and also sent to
//| an attached terminal via OSC escape codes over the REPL serial connection.
//| The status bar reports the current IP or BLE connection, what file is running,
//| the last exception name and location, and firmware version information.
//| This object is the sole instance of `supervisor.StatusBar`."""
//|
//| def set_rgb_status_brightness(brightness: int) -> None: //| def set_rgb_status_brightness(brightness: int) -> None:
//| """Set brightness of status RGB LED from 0-255. This will take effect //| """Set brightness of status RGB LED from 0-255. This will take effect
//| after the current code finishes and the status LED is used to show //| after the current code finishes and the status LED is used to show
@ -301,6 +310,7 @@ STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_get_previous_traceback), MP_ROM_PTR(&supervisor_get_previous_traceback_obj) }, { MP_ROM_QSTR(MP_QSTR_get_previous_traceback), MP_ROM_PTR(&supervisor_get_previous_traceback_obj) },
{ MP_ROM_QSTR(MP_QSTR_disable_ble_workflow), MP_ROM_PTR(&supervisor_disable_ble_workflow_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_ble_workflow), MP_ROM_PTR(&supervisor_disable_ble_workflow_obj) },
{ MP_ROM_QSTR(MP_QSTR_reset_terminal), MP_ROM_PTR(&supervisor_reset_terminal_obj) }, { MP_ROM_QSTR(MP_QSTR_reset_terminal), MP_ROM_PTR(&supervisor_reset_terminal_obj) },
{ MP_ROM_QSTR(MP_QSTR_status_bar), MP_ROM_PTR(&shared_module_supervisor_status_bar_obj) },
}; };
STATIC MP_DEFINE_CONST_DICT(supervisor_module_globals, supervisor_module_globals_table); STATIC MP_DEFINE_CONST_DICT(supervisor_module_globals, supervisor_module_globals_table);

View File

@ -31,8 +31,10 @@
#include "py/obj.h" #include "py/obj.h"
#include "common-hal/supervisor/Runtime.h" #include "common-hal/supervisor/Runtime.h"
#include "shared-module/supervisor/StatusBar.h"
extern const super_runtime_obj_t common_hal_supervisor_runtime_obj; extern const super_runtime_obj_t common_hal_supervisor_runtime_obj;
extern supervisor_status_bar_obj_t shared_module_supervisor_status_bar_obj;
extern mp_obj_t supervisor_ticks_ms(void); extern mp_obj_t supervisor_ticks_ms(void);

View File

@ -56,26 +56,26 @@
//| * ``ESC [ nnnn ; mmmm H`` - Move the cursor to mmmm, nnnn. //| * ``ESC [ nnnn ; mmmm H`` - Move the cursor to mmmm, nnnn.
//| """ //| """
//| //|
//| def __init__(self, scroll_area: displayio.TileGrid, font: fontio.BuiltinFont, *, title_bar: displayio.TileGrid = None) -> None: //| def __init__(self, scroll_area: displayio.TileGrid, font: fontio.BuiltinFont, *, status_bar: displayio.TileGrid = None) -> None:
//| """Terminal manages tile indices and cursor position based on VT100 commands. The font should be //| """Terminal manages tile indices and cursor position based on VT100 commands. The font should be
//| a `fontio.BuiltinFont` and the TileGrid's bitmap should match the font's bitmap.""" //| a `fontio.BuiltinFont` and the TileGrid's bitmap should match the font's bitmap."""
//| ... //| ...
//| //|
STATIC mp_obj_t terminalio_terminal_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { STATIC mp_obj_t terminalio_terminal_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
enum { ARG_scroll_area, ARG_font, ARG_title_bar }; enum { ARG_scroll_area, ARG_font, ARG_status_bar };
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_scroll_area, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_scroll_area, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_font, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_font, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_title_bar, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, { MP_QSTR_status_bar, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } },
}; };
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
displayio_tilegrid_t *scroll_area = mp_arg_validate_type(args[ARG_scroll_area].u_obj, &displayio_tilegrid_type, MP_QSTR_scroll_area); displayio_tilegrid_t *scroll_area = mp_arg_validate_type(args[ARG_scroll_area].u_obj, &displayio_tilegrid_type, MP_QSTR_scroll_area);
displayio_tilegrid_t *title_bar = NULL; displayio_tilegrid_t *status_bar = NULL;
if (args[ARG_title_bar].u_obj != mp_const_none) { if (args[ARG_status_bar].u_obj != mp_const_none) {
title_bar = mp_arg_validate_type(args[ARG_title_bar].u_obj, &displayio_tilegrid_type, MP_QSTR_title_bar); status_bar = mp_arg_validate_type(args[ARG_status_bar].u_obj, &displayio_tilegrid_type, MP_QSTR_status_bar);
} }
fontio_builtinfont_t *font = mp_arg_validate_type(args[ARG_font].u_obj, &fontio_builtinfont_type, MP_QSTR_font); fontio_builtinfont_t *font = mp_arg_validate_type(args[ARG_font].u_obj, &fontio_builtinfont_type, MP_QSTR_font);
@ -83,7 +83,7 @@ STATIC mp_obj_t terminalio_terminal_make_new(const mp_obj_type_t *type, size_t n
terminalio_terminal_obj_t *self = m_new_obj(terminalio_terminal_obj_t); terminalio_terminal_obj_t *self = m_new_obj(terminalio_terminal_obj_t);
self->base.type = &terminalio_terminal_type; self->base.type = &terminalio_terminal_type;
common_hal_terminalio_terminal_construct(self, scroll_area, font, title_bar); common_hal_terminalio_terminal_construct(self, scroll_area, font, status_bar);
return MP_OBJ_FROM_PTR(self); return MP_OBJ_FROM_PTR(self);
} }

View File

@ -34,7 +34,7 @@
extern const mp_obj_type_t terminalio_terminal_type; extern const mp_obj_type_t terminalio_terminal_type;
extern void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self, extern void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self,
displayio_tilegrid_t *scroll_area, const fontio_builtinfont_t *font, displayio_tilegrid_t *title_bar); displayio_tilegrid_t *scroll_area, const fontio_builtinfont_t *font, displayio_tilegrid_t *status_bar);
// Write characters. len is in characters NOT bytes! // Write characters. len is in characters NOT bytes!
extern size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, extern size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self,

View File

@ -0,0 +1,74 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdbool.h>
#include "py/obj.h"
#include "shared-bindings/supervisor/StatusBar.h"
#include "shared-bindings/supervisor/__init__.h"
#include "supervisor/shared/display.h"
#include "supervisor/shared/status_bar.h"
#if CIRCUITPY_TERMINALIO
#include "shared-module/terminalio/Terminal.h"
#endif
bool shared_module_supervisor_status_bar_get_console(supervisor_status_bar_obj_t *self) {
return self->console;
}
void shared_module_supervisor_status_bar_set_console(supervisor_status_bar_obj_t *self, bool enabled) {
// Clear before changing state. If disabling, will remain cleared.
supervisor_status_bar_clear();
self->console = enabled;
// Update may be ignored.
supervisor_status_bar_update();
}
bool shared_module_supervisor_status_bar_get_display(supervisor_status_bar_obj_t *self) {
return self->display;
}
#if CIRCUITPY_TERMINALIO
void shared_module_supervisor_status_bar_set_display(supervisor_status_bar_obj_t *self, bool enabled) {
terminalio_terminal_clear_status_bar(&supervisor_terminal);
// Clear before changing state. If disabling, will remain cleared.
self->display = enabled;
// Update may be ignored.
supervisor_status_bar_update();
}
#endif
bool supervisor_status_bar_get_update_in_progress(supervisor_status_bar_obj_t *self) {
return self->update_in_progress;
}
void supervisor_status_bar_set_update_in_progress(supervisor_status_bar_obj_t *self, bool update_in_progress) {
self->update_in_progress = update_in_progress;
}

View File

@ -0,0 +1,42 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_SHARED_MODULE_SUPERVISOR_STATUS_BAR_H
#define MICROPY_INCLUDED_SHARED_MODULE_SUPERVISOR_STATUS_BAR_H
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
bool console;
bool display;
bool update_in_progress;
} supervisor_status_bar_obj_t;
extern bool supervisor_status_bar_get_update_in_progress(supervisor_status_bar_obj_t *self);
extern void supervisor_status_bar_set_update_in_progress(supervisor_status_bar_obj_t *self, bool in_progress);
#endif // MICROPY_INCLUDED_SHARED_MODULE_SUPERVISOR_STATUS_BAR_H

View File

@ -0,0 +1,39 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdbool.h>
#include "py/obj.h"
#include "shared-bindings/supervisor/StatusBar.h"
#include "shared-bindings/supervisor/__init__.h"
// The singleton supervisor.StatusBar object, bound to supervisor.status_bar
supervisor_status_bar_obj_t shared_module_supervisor_status_bar_obj = {
.base = {
.type = &supervisor_status_bar_type,
},
.console = true,
.display = true,
};

View File

@ -30,20 +30,31 @@
#include "shared-bindings/displayio/TileGrid.h" #include "shared-bindings/displayio/TileGrid.h"
#include "shared-bindings/terminalio/Terminal.h" #include "shared-bindings/terminalio/Terminal.h"
#if CIRCUITPY_STATUS_BAR
#include "shared-bindings/supervisor/__init__.h"
#include "shared-bindings/supervisor/StatusBar.h"
#endif
void terminalio_terminal_clear_status_bar(terminalio_terminal_obj_t *self) {
if (self->status_bar) {
common_hal_displayio_tilegrid_set_all_tiles(self->status_bar, 0);
}
}
void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self, void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self,
displayio_tilegrid_t *scroll_area, const fontio_builtinfont_t *font, displayio_tilegrid_t *scroll_area, const fontio_builtinfont_t *font,
displayio_tilegrid_t *title_bar) { displayio_tilegrid_t *status_bar) {
self->cursor_x = 0; self->cursor_x = 0;
self->cursor_y = 0; self->cursor_y = 0;
self->font = font; self->font = font;
self->scroll_area = scroll_area; self->scroll_area = scroll_area;
self->title_bar = title_bar; self->status_bar = status_bar;
self->title_x = 0; self->status_x = 0;
self->title_y = 0; self->status_y = 0;
self->first_row = 0; self->first_row = 0;
common_hal_displayio_tilegrid_set_all_tiles(self->scroll_area, 0); common_hal_displayio_tilegrid_set_all_tiles(self->scroll_area, 0);
if (self->title_bar) { if (self->status_bar) {
common_hal_displayio_tilegrid_set_all_tiles(self->title_bar, 0); common_hal_displayio_tilegrid_set_all_tiles(self->status_bar, 0);
} }
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, 1); common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, 1);
@ -54,6 +65,14 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
if (self->scroll_area == NULL) { if (self->scroll_area == NULL) {
return len; return len;
} }
#if CIRCUITPY_STATUS_BAR
// Skip the status bar OSC sequence if it's disabled for the display.
const bool status_bar_write_ok =
shared_module_supervisor_status_bar_get_display(&shared_module_supervisor_status_bar_obj) ||
!supervisor_status_bar_get_update_in_progress(&shared_module_supervisor_status_bar_obj);
#endif
const byte *i = data; const byte *i = data;
uint16_t start_y = self->cursor_y; uint16_t start_y = self->cursor_y;
while (i < data + len) { while (i < data + len) {
@ -62,21 +81,27 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
if (self->in_osc_command) { if (self->in_osc_command) {
if (c == 0x1b && i[0] == '\\') { if (c == 0x1b && i[0] == '\\') {
self->in_osc_command = false; self->in_osc_command = false;
self->title_x = 0; self->status_x = 0;
self->title_y = 0; self->status_y = 0;
i += 1; i += 1;
} else if (self->osc_command == 0 && self->title_bar != NULL && self->title_y < self->title_bar->height_in_tiles) { } else if (
#if CIRCUITPY_STATUS_BAR
status_bar_write_ok &&
#endif
self->osc_command == 0 &&
self->status_bar != NULL &&
self->status_y < self->status_bar->height_in_tiles) {
uint8_t tile_index = fontio_builtinfont_get_glyph_index(self->font, c); uint8_t tile_index = fontio_builtinfont_get_glyph_index(self->font, c);
if (tile_index != 0xff) { if (tile_index != 0xff) {
// Clear the tile grid before we start putting new info. // Clear the tile grid before we start putting new info.
if (self->title_x == 0 && self->title_y == 0) { if (self->status_x == 0 && self->status_y == 0) {
common_hal_displayio_tilegrid_set_all_tiles(self->title_bar, 0); common_hal_displayio_tilegrid_set_all_tiles(self->status_bar, 0);
} }
common_hal_displayio_tilegrid_set_tile(self->title_bar, self->title_x, self->title_y, tile_index); common_hal_displayio_tilegrid_set_tile(self->status_bar, self->status_x, self->status_y, tile_index);
self->title_x++; self->status_x++;
if (self->title_x >= self->title_bar->width_in_tiles) { if (self->status_x >= self->status_bar->width_in_tiles) {
self->title_y++; self->status_y++;
self->title_x %= self->title_bar->width_in_tiles; self->status_x %= self->status_bar->width_in_tiles;
} }
} }
} }
@ -98,7 +123,7 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
self->cursor_x--; self->cursor_x--;
} }
} else if (c == 0x1b) { } else if (c == 0x1b) {
// Handle commands of the form \x1b.####D where . is ignored. // Handle commands of the form [ESC].<digits><command-char> where . is not yet known.
uint16_t n = 0; uint16_t n = 0;
uint8_t j = 1; uint8_t j = 1;
for (; j < 6; j++) { for (; j < 6; j++) {

View File

@ -40,12 +40,14 @@ typedef struct {
uint16_t cursor_x; uint16_t cursor_x;
uint16_t cursor_y; uint16_t cursor_y;
displayio_tilegrid_t *scroll_area; displayio_tilegrid_t *scroll_area;
displayio_tilegrid_t *title_bar; displayio_tilegrid_t *status_bar;
uint16_t title_x; uint16_t status_x;
uint16_t title_y; uint16_t status_y;
uint16_t first_row; uint16_t first_row;
uint16_t osc_command; uint16_t osc_command;
bool in_osc_command; bool in_osc_command;
} terminalio_terminal_obj_t; } terminalio_terminal_obj_t;
extern void terminalio_terminal_clear_status_bar(terminalio_terminal_obj_t *self);
#endif /* SHARED_MODULE_TERMINALIO_TERMINAL_H */ #endif /* SHARED_MODULE_TERMINALIO_TERMINAL_H */

View File

@ -42,7 +42,6 @@
#include "supervisor/serial.h" #include "supervisor/serial.h"
#include "supervisor/shared/status_leds.h" #include "supervisor/shared/status_leds.h"
#include "supervisor/shared/tick.h" #include "supervisor/shared/tick.h"
#include "supervisor/shared/title_bar.h"
#include "supervisor/shared/translate/translate.h" #include "supervisor/shared/translate/translate.h"
#include "py/mpstate.h" #include "py/mpstate.h"
@ -57,6 +56,10 @@
#include "bluetooth/ble_drv.h" #include "bluetooth/ble_drv.h"
#endif #endif
#if CIRCUITPY_STATUS_BAR
#include "supervisor/shared/status_bar.h"
#endif
// This standard advertisement advertises the CircuitPython editing service and a CIRCUITPY short name. // This standard advertisement advertises the CircuitPython editing service and a CIRCUITPY short name.
const uint8_t public_advertising_data[] = { 0x02, 0x01, 0x06, // 0-2 Flags const uint8_t public_advertising_data[] = { 0x02, 0x01, 0x06, // 0-2 Flags
0x02, 0x0a, 0xec, // 3-5 TX power level -20 0x02, 0x0a, 0xec, // 3-5 TX power level -20
@ -94,16 +97,21 @@ STATIC bool ble_started = false;
STATIC uint8_t workflow_state = WORKFLOW_UNSET; STATIC uint8_t workflow_state = WORKFLOW_UNSET;
STATIC bool was_connected = false; STATIC bool was_connected = false;
#if CIRCUITPY_STATUS_BAR
// To detect when the title bar changes. // To detect when the title bar changes.
STATIC bool _last_connected = false; STATIC bool _last_connected = false;
STATIC bool _last_advertising = false; STATIC bool _last_advertising = false;
#endif
#if CIRCUITPY_STATUS_BAR
// Title bar status // Title bar status
bool supervisor_bluetooth_status_dirty(void) { bool supervisor_bluetooth_status_dirty(void) {
return _last_advertising != advertising || return _last_advertising != advertising ||
_last_connected != was_connected; _last_connected != was_connected;
} }
#endif
#if CIRCUITPY_STATUS_BAR
void supervisor_bluetooth_status(void) { void supervisor_bluetooth_status(void) {
serial_write("BLE:"); serial_write("BLE:");
if (advertising) { if (advertising) {
@ -123,6 +131,7 @@ void supervisor_bluetooth_status(void) {
_last_connected = was_connected; _last_connected = was_connected;
_last_advertising = advertising; _last_advertising = advertising;
} }
#endif
STATIC void supervisor_bluetooth_start_advertising(void) { STATIC void supervisor_bluetooth_start_advertising(void) {
if (workflow_state != WORKFLOW_ENABLED) { if (workflow_state != WORKFLOW_ENABLED) {
@ -273,9 +282,13 @@ void supervisor_bluetooth_background(void) {
supervisor_bluetooth_file_transfer_disconnected(); supervisor_bluetooth_file_transfer_disconnected();
#endif #endif
} }
#if CIRCUITPY_STATUS_BAR
if (was_connected != is_connected) { if (was_connected != is_connected) {
supervisor_title_bar_request_update(false); supervisor_status_bar_request_update(false);
} }
#endif
was_connected = is_connected; was_connected = is_connected;
if (!is_connected) { if (!is_connected) {
supervisor_bluetooth_start_advertising(); supervisor_bluetooth_start_advertising();
@ -312,7 +325,10 @@ void supervisor_start_bluetooth(void) {
// Kick off advertisements // Kick off advertisements
supervisor_bluetooth_background(); supervisor_bluetooth_background();
supervisor_title_bar_request_update(false);
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_request_update(false);
#endif
#endif #endif
} }

View File

@ -34,7 +34,6 @@
#include "shared-bindings/displayio/Palette.h" #include "shared-bindings/displayio/Palette.h"
#include "shared-bindings/displayio/TileGrid.h" #include "shared-bindings/displayio/TileGrid.h"
#include "supervisor/memory.h" #include "supervisor/memory.h"
#include "supervisor/shared/title_bar.h"
#if CIRCUITPY_RGBMATRIX #if CIRCUITPY_RGBMATRIX
#include "shared-module/displayio/__init__.h" #include "shared-module/displayio/__init__.h"
@ -46,6 +45,10 @@
#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h" #include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h"
#endif #endif
#if CIRCUITPY_STATUS_BAR
#include "supervisor/shared/status_bar.h"
#endif
#if CIRCUITPY_REPL_LOGO #if CIRCUITPY_REPL_LOGO
extern uint32_t blinka_bitmap_data[]; extern uint32_t blinka_bitmap_data[];
extern displayio_bitmap_t blinka_bitmap; extern displayio_bitmap_t blinka_bitmap;
@ -63,7 +66,7 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) {
#if CIRCUITPY_TERMINALIO #if CIRCUITPY_TERMINALIO
displayio_tilegrid_t *scroll_area = &supervisor_terminal_scroll_area_text_grid; displayio_tilegrid_t *scroll_area = &supervisor_terminal_scroll_area_text_grid;
displayio_tilegrid_t *title_bar = &supervisor_terminal_title_bar_text_grid; displayio_tilegrid_t *status_bar = &supervisor_terminal_status_bar_text_grid;
bool reset_tiles = false; bool reset_tiles = false;
uint16_t width_in_tiles = width_px / scroll_area->tile_width; uint16_t width_in_tiles = width_px / scroll_area->tile_width;
// determine scale based on width // determine scale based on width
@ -104,21 +107,21 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) {
uint8_t *tiles = (uint8_t *)tilegrid_tiles->ptr; uint8_t *tiles = (uint8_t *)tilegrid_tiles->ptr;
#if CIRCUITPY_REPL_LOGO #if CIRCUITPY_REPL_LOGO
title_bar->x = supervisor_blinka_sprite.pixel_width + 1; status_bar->x = supervisor_blinka_sprite.pixel_width + 1;
// Align the title bar to the bottom of the logo. // Align the status bar to the bottom of the logo.
title_bar->y = supervisor_blinka_sprite.pixel_height - title_bar->tile_height; status_bar->y = supervisor_blinka_sprite.pixel_height - status_bar->tile_height;
#else #else
title_bar->x = 0; status_bar->x = 0;
title_bar->y = 0; status_bar->y = 0;
#endif #endif
title_bar->top_left_y = 0; status_bar->top_left_y = 0;
title_bar->width_in_tiles = width_in_tiles; status_bar->width_in_tiles = width_in_tiles;
title_bar->height_in_tiles = 1; status_bar->height_in_tiles = 1;
assert(width_in_tiles > 0); assert(width_in_tiles > 0);
title_bar->pixel_width = width_in_tiles * title_bar->tile_width; status_bar->pixel_width = width_in_tiles * status_bar->tile_width;
title_bar->pixel_height = title_bar->tile_height; status_bar->pixel_height = status_bar->tile_height;
title_bar->tiles = tiles; status_bar->tiles = tiles;
title_bar->full_change = true; status_bar->full_change = true;
scroll_area->x = 0; scroll_area->x = 0;
scroll_area->top_left_y = 0; scroll_area->top_left_y = 0;
@ -131,7 +134,7 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) {
#if CIRCUITPY_REPL_LOGO #if CIRCUITPY_REPL_LOGO
scroll_area->y = blinka_bitmap.height; scroll_area->y = blinka_bitmap.height;
#else #else
scroll_area->y = title_bar->tile_height; scroll_area->y = status_bar->tile_height;
#endif #endif
int16_t extra_height = (scroll_area->pixel_height + scroll_area->y) - (height_px / scale); int16_t extra_height = (scroll_area->pixel_height + scroll_area->y) - (height_px / scale);
// Subtract extra height so that the bottom line fully shows. The top line will be under the // Subtract extra height so that the bottom line fully shows. The top line will be under the
@ -140,9 +143,11 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) {
scroll_area->tiles = tiles + width_in_tiles; scroll_area->tiles = tiles + width_in_tiles;
scroll_area->full_change = true; scroll_area->full_change = true;
common_hal_terminalio_terminal_construct(&supervisor_terminal, scroll_area, &supervisor_terminal_font, title_bar); common_hal_terminalio_terminal_construct(&supervisor_terminal, scroll_area, &supervisor_terminal_font, status_bar);
// Update the title bar since we just cleared the terminal. #if CIRCUITPY_STATUS_BAR
supervisor_title_bar_update(); // Update the status bar since we just cleared the terminal.
supervisor_status_bar_update();
#endif
} }
#endif #endif
@ -155,9 +160,9 @@ void supervisor_stop_terminal(void) {
free_memory(tilegrid_tiles); free_memory(tilegrid_tiles);
tilegrid_tiles = NULL; tilegrid_tiles = NULL;
supervisor_terminal_scroll_area_text_grid.tiles = NULL; supervisor_terminal_scroll_area_text_grid.tiles = NULL;
supervisor_terminal_title_bar_text_grid.tiles = NULL; supervisor_terminal_status_bar_text_grid.tiles = NULL;
supervisor_terminal.scroll_area = NULL; supervisor_terminal.scroll_area = NULL;
supervisor_terminal.title_bar = NULL; supervisor_terminal.status_bar = NULL;
} }
#endif #endif
} }
@ -165,13 +170,13 @@ void supervisor_stop_terminal(void) {
void supervisor_display_move_memory(void) { void supervisor_display_move_memory(void) {
#if CIRCUITPY_TERMINALIO #if CIRCUITPY_TERMINALIO
displayio_tilegrid_t *scroll_area = &supervisor_terminal_scroll_area_text_grid; displayio_tilegrid_t *scroll_area = &supervisor_terminal_scroll_area_text_grid;
displayio_tilegrid_t *title_bar = &supervisor_terminal_title_bar_text_grid; displayio_tilegrid_t *status_bar = &supervisor_terminal_status_bar_text_grid;
if (tilegrid_tiles != NULL) { if (tilegrid_tiles != NULL) {
title_bar->tiles = (uint8_t *)tilegrid_tiles->ptr; status_bar->tiles = (uint8_t *)tilegrid_tiles->ptr;
scroll_area->tiles = (uint8_t *)tilegrid_tiles->ptr + scroll_area->width_in_tiles; scroll_area->tiles = (uint8_t *)tilegrid_tiles->ptr + scroll_area->width_in_tiles;
} else { } else {
scroll_area->tiles = NULL; scroll_area->tiles = NULL;
title_bar->tiles = NULL; status_bar->tiles = NULL;
} }
#endif #endif
@ -195,7 +200,7 @@ void supervisor_display_move_memory(void) {
#if CIRCUITPY_TERMINALIO #if CIRCUITPY_TERMINALIO
#if CIRCUITPY_REPL_LOGO #if CIRCUITPY_REPL_LOGO
mp_obj_t members[] = { &supervisor_terminal_scroll_area_text_grid, &supervisor_blinka_sprite, &supervisor_terminal_title_bar_text_grid, }; mp_obj_t members[] = { &supervisor_terminal_scroll_area_text_grid, &supervisor_blinka_sprite, &supervisor_terminal_status_bar_text_grid, };
mp_obj_list_t splash_children = { mp_obj_list_t splash_children = {
.base = {.type = &mp_type_list }, .base = {.type = &mp_type_list },
.alloc = 3, .alloc = 3,
@ -203,7 +208,7 @@ mp_obj_list_t splash_children = {
.items = members, .items = members,
}; };
#else #else
mp_obj_t members[] = { &supervisor_terminal_scroll_area_text_grid, &supervisor_terminal_title_bar_text_grid,}; mp_obj_t members[] = { &supervisor_terminal_scroll_area_text_grid, &supervisor_terminal_status_bar_text_grid,};
mp_obj_list_t splash_children = { mp_obj_list_t splash_children = {
.base = {.type = &mp_type_list }, .base = {.type = &mp_type_list },
.alloc = 2, .alloc = 2,

View File

@ -45,7 +45,7 @@ extern const fontio_builtinfont_t supervisor_terminal_font;
// These will change so they must live in RAM. // These will change so they must live in RAM.
extern displayio_bitmap_t supervisor_terminal_font_bitmap; extern displayio_bitmap_t supervisor_terminal_font_bitmap;
extern displayio_tilegrid_t supervisor_terminal_scroll_area_text_grid; extern displayio_tilegrid_t supervisor_terminal_scroll_area_text_grid;
extern displayio_tilegrid_t supervisor_terminal_title_bar_text_grid; extern displayio_tilegrid_t supervisor_terminal_status_bar_text_grid;
extern terminalio_terminal_obj_t supervisor_terminal; extern terminalio_terminal_obj_t supervisor_terminal;
#endif #endif

View File

@ -41,6 +41,11 @@
#include "supervisor/shared/bluetooth/serial.h" #include "supervisor/shared/bluetooth/serial.h"
#endif #endif
#if CIRCUITPY_STATUS_BAR
#include "shared-bindings/supervisor/__init__.h"
#include "shared-bindings/supervisor/StatusBar.h"
#endif
#if CIRCUITPY_USB #if CIRCUITPY_USB
#include "tusb.h" #include "tusb.h"
#endif #endif
@ -276,11 +281,22 @@ void serial_write_substring(const char *text, uint32_t length) {
if (length == 0) { if (length == 0) {
return; return;
} }
#if CIRCUITPY_TERMINALIO #if CIRCUITPY_TERMINALIO
int errcode; int errcode;
// We might be writing
// If the status bar is disabled for the display, common_hal_terminalio_terminal_write() will not write it.
common_hal_terminalio_terminal_write(&supervisor_terminal, (const uint8_t *)text, length, &errcode); common_hal_terminalio_terminal_write(&supervisor_terminal, (const uint8_t *)text, length, &errcode);
#endif #endif
#if CIRCUITPY_STATUS_BAR
// If the status bar is disabled for the console, skip writing out the OSC sequence.
if (supervisor_status_bar_get_update_in_progress(&shared_module_supervisor_status_bar_obj) &&
!shared_module_supervisor_status_bar_get_console(&shared_module_supervisor_status_bar_obj)) {
return;
}
#endif
#if CIRCUITPY_USB_VENDOR #if CIRCUITPY_USB_VENDOR
if (tud_vendor_connected()) { if (tud_vendor_connected()) {
tud_vendor_write(text, length); tud_vendor_write(text, length);

View File

@ -27,9 +27,15 @@
#include <stdbool.h> #include <stdbool.h>
#include "genhdr/mpversion.h" #include "genhdr/mpversion.h"
#include "py/mpconfig.h" #include "py/mpconfig.h"
#include "shared-bindings/supervisor/__init__.h"
#include "shared-bindings/supervisor/StatusBar.h"
#include "supervisor/background_callback.h" #include "supervisor/background_callback.h"
#include "supervisor/serial.h" #include "supervisor/serial.h"
#include "supervisor/shared/title_bar.h" #include "supervisor/shared/status_bar.h"
#if CIRCUITPY_TERMINALIO
#include "shared-module/terminalio/Terminal.h"
#endif
#if CIRCUITPY_WEB_WORKFLOW #if CIRCUITPY_WEB_WORKFLOW
#include "supervisor/shared/web_workflow/web_workflow.h" #include "supervisor/shared/web_workflow/web_workflow.h"
@ -39,46 +45,56 @@
#include "supervisor/shared/bluetooth/bluetooth.h" #include "supervisor/shared/bluetooth/bluetooth.h"
#endif #endif
static background_callback_t title_bar_background_cb; static background_callback_t status_bar_background_cb;
static bool _forced_dirty = false; static bool _forced_dirty = false;
static bool _suspended = false; static bool _suspended = false;
// Clear if possible, but give up if we can't do it now.
void supervisor_status_bar_clear(void) {
if (!_suspended) {
supervisor_status_bar_set_update_in_progress(&shared_module_supervisor_status_bar_obj, true);
serial_write("\x1b" "]0;" "\x1b" "\\");
supervisor_status_bar_set_update_in_progress(&shared_module_supervisor_status_bar_obj, false);
}
}
void supervisor_title_bar_update(void) { void supervisor_status_bar_update(void) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
if (_suspended) { if (_suspended) {
supervisor_title_bar_request_update(true); supervisor_status_bar_request_update(true);
return; return;
} }
_forced_dirty = false; _forced_dirty = false;
supervisor_status_bar_set_update_in_progress(&shared_module_supervisor_status_bar_obj, true);
// Neighboring "" "" are concatenated by the compiler. Without this separation, the hex code // Neighboring "" "" are concatenated by the compiler. Without this separation, the hex code
// doesn't get terminated after two following characters and the value is invalid. // doesn't get terminated after two following characters and the value is invalid.
// This is the OSC command to set the title and the icon text. It can be up to 255 characters // This is the OSC command to set the title and the icon text. It can be up to 255 characters
// but some may be cut off. // but some may be cut off.
serial_write("\x1b" "]0;"); serial_write("\x1b" "]0;");
serial_write("🐍"); serial_write("🐍");
#if CIRCUITPY_WEB_WORKFLOW #if CIRCUITPY_WEB_WORKFLOW
supervisor_web_workflow_status(); supervisor_web_workflow_status();
serial_write(" | "); serial_write(" | ");
#endif #endif
#if CIRCUITPY_BLE_FILE_SERVICE || CIRCUITPY_SERIAL_BLE #if CIRCUITPY_BLE_FILE_SERVICE || CIRCUITPY_SERIAL_BLE
supervisor_bluetooth_status(); supervisor_bluetooth_status();
serial_write(" | "); serial_write(" | ");
#endif #endif
supervisor_execution_status(); supervisor_execution_status();
serial_write(" | "); serial_write(" | ");
serial_write(MICROPY_GIT_TAG); serial_write(MICROPY_GIT_TAG);
// Send string terminator // Send string terminator
serial_write("\x1b" "\\"); serial_write("\x1b" "\\");
supervisor_status_bar_set_update_in_progress(&shared_module_supervisor_status_bar_obj, false);
} }
static void title_bar_background(void *data) { static void status_bar_background(void *data) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
if (_suspended) { if (_suspended) {
return; return;
} }
@ -92,42 +108,29 @@ static void title_bar_background(void *data) {
dirty = dirty || supervisor_bluetooth_status_dirty(); dirty = dirty || supervisor_bluetooth_status_dirty();
#endif #endif
if (!dirty) { if (dirty) {
return; supervisor_status_bar_update();
} }
supervisor_title_bar_update();
} }
void supervisor_title_bar_start(void) { void supervisor_status_bar_start(void) {
#if !CIRCUITPY_STATUS_BAR status_bar_background_cb.fun = status_bar_background;
return; status_bar_background_cb.data = NULL;
#endif supervisor_status_bar_request_update(true);
title_bar_background_cb.fun = title_bar_background;
title_bar_background_cb.data = NULL;
supervisor_title_bar_request_update(true);
} }
void supervisor_title_bar_request_update(bool force_dirty) { void supervisor_status_bar_request_update(bool force_dirty) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
if (force_dirty) { if (force_dirty) {
_forced_dirty = true; _forced_dirty = true;
} }
background_callback_add_core(&title_bar_background_cb); background_callback_add_core(&status_bar_background_cb);
} }
void supervisor_title_bar_suspend(void) { void supervisor_status_bar_suspend(void) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
_suspended = true; _suspended = true;
} }
void supervisor_title_bar_resume(void) { void supervisor_status_bar_resume(void) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
_suspended = false; _suspended = false;
supervisor_title_bar_request_update(false); supervisor_status_bar_request_update(false);
} }

View File

@ -28,17 +28,19 @@
#include <stdbool.h> #include <stdbool.h>
void supervisor_title_bar_start(void); void supervisor_status_bar_start(void);
void supervisor_title_bar_suspend(void); void supervisor_status_bar_suspend(void);
void supervisor_title_bar_resume(void); void supervisor_status_bar_resume(void);
void supervisor_status_bar_clear(void);
// Update the title bar immediately. Useful from main.c where we know state has changed and the code // Update the title bar immediately. Useful from main.c where we know state has changed and the code
// will only be run once. // will only be run once.
void supervisor_title_bar_update(void); void supervisor_status_bar_update(void);
// Use this if requesting from the background, as code is executing or if the status may not have // Use this if requesting from the background, as code is executing or if the status may not have
// changed. // changed.
void supervisor_title_bar_request_update(bool force_dirty); void supervisor_status_bar_request_update(bool force_dirty);
// Provided by main.c // Provided by main.c
void supervisor_execution_status(void); void supervisor_execution_status(void);

View File

@ -31,11 +31,14 @@
#include "supervisor/port.h" #include "supervisor/port.h"
#include "supervisor/serial.h" #include "supervisor/serial.h"
#include "supervisor/usb.h" #include "supervisor/usb.h"
#include "supervisor/shared/title_bar.h"
#include "supervisor/shared/workflow.h" #include "supervisor/shared/workflow.h"
#include "shared/runtime/interrupt_char.h" #include "shared/runtime/interrupt_char.h"
#include "shared/readline/readline.h" #include "shared/readline/readline.h"
#if CIRCUITPY_STATUS_BAR
#include "supervisor/shared/status_bar.h"
#endif
#if CIRCUITPY_STORAGE #if CIRCUITPY_STORAGE
#include "shared-module/storage/__init__.h" #include "shared-module/storage/__init__.h"
#endif #endif
@ -244,8 +247,10 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
reset_to_bootloader(); reset_to_bootloader();
} }
} else { } else {
#if CIRCUITPY_STATUS_BAR
// We are connected, let's request a title bar update. // We are connected, let's request a title bar update.
supervisor_title_bar_request_update(true); supervisor_status_bar_request_update(true);
#endif
} }
} }

View File

@ -102,10 +102,12 @@ typedef struct {
static wifi_radio_error_t _wifi_status = WIFI_RADIO_ERROR_NONE; static wifi_radio_error_t _wifi_status = WIFI_RADIO_ERROR_NONE;
// Store last status state to compute dirty. #if CIRCUITPY_STATUS_BAR
// Store various last states to compute if status bar needs an update.
static bool _last_enabled = false; static bool _last_enabled = false;
static uint32_t _last_ip = 0; static uint32_t _last_ip = 0;
static wifi_radio_error_t _last_wifi_status = WIFI_RADIO_ERROR_NONE; static wifi_radio_error_t _last_wifi_status = WIFI_RADIO_ERROR_NONE;
#endif
static mdns_server_obj_t mdns; static mdns_server_obj_t mdns;
static uint32_t web_api_port = 80; static uint32_t web_api_port = 80;
@ -193,12 +195,15 @@ STATIC void _update_encoded_ip(void) {
} }
} }
#if CIRCUITPY_STATUS_BAR
bool supervisor_web_workflow_status_dirty(void) { bool supervisor_web_workflow_status_dirty(void) {
return common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) != _last_enabled || return common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) != _last_enabled ||
_encoded_ip != _last_ip || _encoded_ip != _last_ip ||
_last_wifi_status != _wifi_status; _last_wifi_status != _wifi_status;
} }
#endif
#if CIRCUITPY_STATUS_BAR
void supervisor_web_workflow_status(void) { void supervisor_web_workflow_status(void) {
_last_enabled = common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj); _last_enabled = common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj);
if (_last_enabled) { if (_last_enabled) {
@ -231,6 +236,7 @@ void supervisor_web_workflow_status(void) {
serial_write_compressed(translate("off")); serial_write_compressed(translate("off"));
} }
} }
#endif
void supervisor_start_web_workflow(void) { void supervisor_start_web_workflow(void) {
#if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI #if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI

View File

@ -29,9 +29,12 @@
#include "py/ringbuf.h" #include "py/ringbuf.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "shared/runtime/interrupt_char.h" #include "shared/runtime/interrupt_char.h"
#include "supervisor/shared/title_bar.h"
#include "supervisor/shared/web_workflow/web_workflow.h" #include "supervisor/shared/web_workflow/web_workflow.h"
#if CIRCUITPY_STATUS_BAR
#include "supervisor/shared/status_bar.h"
#endif
// TODO: Remove ESP specific stuff. For now, it is useful as we refine the server. // TODO: Remove ESP specific stuff. For now, it is useful as we refine the server.
#include "esp_log.h" #include "esp_log.h"
@ -73,8 +76,10 @@ void websocket_handoff(socketpool_socket_obj_t *socket) {
socket->connected = false; socket->connected = false;
socket->num = -1; socket->num = -1;
#if CIRCUITPY_STATUS_BAR
// Send the title bar for the new client. // Send the title bar for the new client.
supervisor_title_bar_request_update(true); supervisor_status_bar_request_update(true);
#endif
} }
bool websocket_connected(void) { bool websocket_connected(void) {

View File

@ -15,7 +15,6 @@ SRC_SUPERVISOR = \
supervisor/shared/stack.c \ supervisor/shared/stack.c \
supervisor/shared/status_leds.c \ supervisor/shared/status_leds.c \
supervisor/shared/tick.c \ supervisor/shared/tick.c \
supervisor/shared/title_bar.c \
supervisor/shared/traceback.c \ supervisor/shared/traceback.c \
supervisor/shared/translate/translate.c \ supervisor/shared/translate/translate.c \
supervisor/shared/workflow.c \ supervisor/shared/workflow.c \
@ -98,6 +97,12 @@ ifneq ($(wildcard supervisor/serial.c),)
SRC_SUPERVISOR += supervisor/serial.c SRC_SUPERVISOR += supervisor/serial.c
endif endif
ifeq ($(CIRCUITPY_STATUS_BAR),1)
SRC_SUPERVISOR += \
supervisor/shared/status_bar.c \
endif
ifeq ($(CIRCUITPY_USB),1) ifeq ($(CIRCUITPY_USB),1)
SRC_SUPERVISOR += \ SRC_SUPERVISOR += \
lib/tinyusb/src/class/cdc/cdc_device.c \ lib/tinyusb/src/class/cdc/cdc_device.c \

View File

@ -324,7 +324,7 @@ displayio_tilegrid_t supervisor_terminal_scroll_area_text_grid = {{
c_file.write( c_file.write(
"""\ """\
displayio_tilegrid_t supervisor_terminal_title_bar_text_grid = {{ displayio_tilegrid_t supervisor_terminal_status_bar_text_grid = {{
.base = {{ .type = &displayio_tilegrid_type }}, .base = {{ .type = &displayio_tilegrid_type }},
.bitmap = (displayio_bitmap_t*) &supervisor_terminal_font_bitmap, .bitmap = (displayio_bitmap_t*) &supervisor_terminal_font_bitmap,
.pixel_shader = &supervisor_terminal_color, .pixel_shader = &supervisor_terminal_color,
@ -414,7 +414,7 @@ terminalio_terminal_obj_t supervisor_terminal = {
.cursor_x = 0, .cursor_x = 0,
.cursor_y = 0, .cursor_y = 0,
.scroll_area = NULL, .scroll_area = NULL,
.title_bar = NULL .status_bar = NULL
}; };
#endif #endif