Merge pull request #6847 from dhalbert/status-bar-control

Allow enabling and disabling of status bar
This commit is contained in:
Dan Halbert 2022-09-08 10:48:36 -04:00 committed by GitHub
commit dd37c81136
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 626 additions and 135 deletions

58
main.c
View File

@ -57,7 +57,6 @@
#include "supervisor/shared/stack.h"
#include "supervisor/shared/status_leds.h"
#include "supervisor/shared/tick.h"
#include "supervisor/shared/title_bar.h"
#include "supervisor/shared/traceback.h"
#include "supervisor/shared/translate/translate.h"
#include "supervisor/shared/workflow.h"
@ -106,6 +105,10 @@
#include "shared-bindings/socketpool/__init__.h"
#endif
#if CIRCUITPY_STATUS_BAR
#include "supervisor/shared/status_bar.h"
#endif
#if CIRCUITPY_USB_HID
#include "shared-module/usb_hid/__init__.h"
#endif
@ -208,6 +211,7 @@ STATIC const char *_current_executing_filename = NULL;
STATIC pyexec_result_t _exec_result = {0, MP_OBJ_NULL, 0};
#if CIRCUITPY_STATUS_BAR
void supervisor_execution_status(void) {
mp_obj_exception_t *exception = MP_OBJ_TO_PTR(_exec_result.exception);
if (_current_executing_filename != NULL) {
@ -220,6 +224,7 @@ void supervisor_execution_status(void) {
serial_write_compressed(translate("Done"));
}
}
#endif
#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);
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);
#if CIRCUITPY_ATEXIT
shared_module_atexit_execute(&_exec_result);
#endif
_current_executing_filename = NULL;
supervisor_title_bar_update();
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_update();
#endif
return true;
}
@ -443,6 +458,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
// Finished executing python code. Cleanup includes filesystem flush and a board reset.
cleanup_after_vm(heap, _exec_result.exception);
_exec_result.exception = NULL;
// If a new next code file was set, that is a reason to keep it (obviously). Stuff this into
// the options because it can be treated like any other reason-for-stickiness bit. The
@ -749,8 +765,10 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
if (ok_to_run) {
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
// Turn off title bar updates when writing out to boot_out.txt.
supervisor_title_bar_suspend();
#if CIRCUITPY_STATUS_BAR
// Turn off status bar updates when writing out to boot_out.txt.
supervisor_status_bar_suspend();
#endif
vstr_t boot_text;
vstr_init(&boot_text, 512);
boot_output = &boot_text;
@ -778,7 +796,9 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
FATFS *fs = &vfs->fatfs;
boot_output = NULL;
supervisor_title_bar_resume();
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_resume();
#endif
bool write_boot_output = true;
FIL boot_output_file;
if (f_open(fs, &boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_READ) == FR_OK) {
@ -822,6 +842,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
port_post_boot_py(true);
cleanup_after_vm(heap, _exec_result.exception);
_exec_result.exception = NULL;
port_post_boot_py(false);
@ -854,15 +875,23 @@ STATIC int run_repl(bool first_run) {
status_led_deinit();
#endif
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();
supervisor_title_bar_resume();
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_resume();
#endif
} else {
_current_executing_filename = "REPL";
supervisor_title_bar_update();
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_update();
#endif
exit_code = pyexec_friendly_repl();
_current_executing_filename = NULL;
supervisor_title_bar_update();
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_update();
#endif
}
#if CIRCUITPY_ATEXIT
pyexec_result_t result;
@ -910,6 +939,10 @@ int __attribute__((used)) main(void) {
stack_init();
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_init();
#endif
#if CIRCUITPY_BLEIO
// Early init so that a reset press can cause BLE public advertising.
supervisor_bluetooth_init();
@ -959,7 +992,10 @@ int __attribute__((used)) main(void) {
run_boot_py(safe_mode);
supervisor_workflow_start();
supervisor_title_bar_start();
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_request_update(true);
#endif
// Boot script is finished, so now go into REPL or run code.py.
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 "supervisor/port.h"
#include "supervisor/shared/title_bar.h"
#include "supervisor/workflow.h"
#if CIRCUITPY_STATUS_BAR
#include "supervisor/shared/status_bar.h"
#endif
#include "esp_ipc.h"
#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 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
// 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.
# Keep alphabetical.
ifeq ($(CIRCUITPY_AESIO),1)
SRC_PATTERNS += aesio/%
@ -175,11 +176,8 @@ endif
ifeq ($(CIRCUITPY_DOTENV),1)
SRC_PATTERNS += dotenv/%
endif
ifeq ($(CIRCUITPY_PARALLELDISPLAY),1)
SRC_PATTERNS += paralleldisplay/%
endif
ifeq ($(CIRCUITPY_VECTORIO),1)
SRC_PATTERNS += vectorio/%
ifeq ($(CIRCUITPY__EVE),1)
SRC_PATTERNS += _eve/%
endif
ifeq ($(CIRCUITPY_FLOPPYIO),1)
SRC_PATTERNS += floppyio/%
@ -187,17 +185,12 @@ endif
ifeq ($(CIRCUITPY_FRAMEBUFFERIO),1)
SRC_PATTERNS += framebufferio/%
endif
ifeq ($(CIRCUITPY__EVE),1)
SRC_PATTERNS += _eve/%
endif
ifeq ($(CIRCUITPY_FREQUENCYIO),1)
SRC_PATTERNS += frequencyio/%
endif
ifeq ($(CIRCUITPY_FUTURE),1)
SRC_PATTERNS += __future__/%
endif
ifeq ($(CIRCUITPY_GETPASS),1)
SRC_PATTERNS += getpass/%
endif
@ -237,6 +230,9 @@ endif
ifeq ($(CIRCUITPY_MDNS),1)
SRC_PATTERNS += mdns/%
endif
ifeq ($(CIRCUITPY_MSGPACK),1)
SRC_PATTERNS += msgpack/%
endif
ifeq ($(CIRCUITPY_NEOPIXEL_WRITE),1)
SRC_PATTERNS += neopixel_write/%
endif
@ -252,6 +248,12 @@ endif
ifeq ($(CIRCUITPY_DUALBANK),1)
SRC_PATTERNS += dualbank/%
endif
ifeq ($(CIRCUITPY_PARALLELDISPLAY),1)
SRC_PATTERNS += paralleldisplay/%
endif
ifeq ($(CIRCUITPY_PEW),1)
SRC_PATTERNS += _pew/%
endif
ifeq ($(CIRCUITPY_PIXELBUF),1)
SRC_PATTERNS += adafruit_pixelbuf/%
endif
@ -351,8 +353,8 @@ endif
ifeq ($(CIRCUITPY_USTACK),1)
SRC_PATTERNS += ustack/%
endif
ifeq ($(CIRCUITPY_ZLIB),1)
SRC_PATTERNS += zlib/%
ifeq ($(CIRCUITPY_VECTORIO),1)
SRC_PATTERNS += vectorio/%
endif
ifeq ($(CIRCUITPY_VIDEOCORE),1)
SRC_PATTERNS += videocore/%
@ -363,11 +365,8 @@ endif
ifeq ($(CIRCUITPY_WIFI),1)
SRC_PATTERNS += wifi/%
endif
ifeq ($(CIRCUITPY_PEW),1)
SRC_PATTERNS += _pew/%
endif
ifeq ($(CIRCUITPY_MSGPACK),1)
SRC_PATTERNS += msgpack/%
ifeq ($(CIRCUITPY_ZLIB),1)
SRC_PATTERNS += zlib/%
endif
# 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/QRInfo.c \
supervisor/RunReason.c \
supervisor/StatusBar.c \
wifi/AuthMode.c \
wifi/Packet.c \
)
@ -611,6 +611,8 @@ SRC_SHARED_MODULE_ALL = \
socket/__init__.c \
storage/__init__.c \
struct/__init__.c \
supervisor/__init__.c \
supervisor/StatusBar.c \
synthio/MidiTrack.c \
synthio/__init__.c \
terminalio/Terminal.c \

View File

@ -0,0 +1,127 @@
/*
* 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. Persists across soft restarts.
//| """
//|
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. Persists across soft restarts.
//| 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/time/__init__.h"
#include "shared-bindings/supervisor/Runtime.h"
#include "shared-bindings/supervisor/StatusBar.h"
//| """Supervisor settings"""
//|
@ -53,6 +54,14 @@
//| 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:
//| """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
@ -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_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_status_bar), MP_ROM_PTR(&shared_module_supervisor_status_bar_obj) },
};
STATIC MP_DEFINE_CONST_DICT(supervisor_module_globals, supervisor_module_globals_table);

View File

@ -31,8 +31,10 @@
#include "py/obj.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 supervisor_status_bar_obj_t shared_module_supervisor_status_bar_obj;
extern mp_obj_t supervisor_ticks_ms(void);

View File

@ -56,26 +56,26 @@
//| * ``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
//| 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) {
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[] = {
{ MP_QSTR_scroll_area, 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_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 *title_bar = NULL;
if (args[ARG_title_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);
displayio_tilegrid_t *status_bar = NULL;
if (args[ARG_status_bar].u_obj != mp_const_none) {
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);
@ -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);
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);
}

View File

@ -34,7 +34,7 @@
extern const mp_obj_type_t terminalio_terminal_type;
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!
extern size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self,

View File

@ -0,0 +1,89 @@
/*
* 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) {
if (self->console == enabled) {
// Do nothing if not changing the state.
return;
}
if (self->written) {
// 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) {
if (self->display == enabled) {
// Do nothing if not changing the state.
return;
}
if (self->written) {
// Clear before changing state. If disabling, will remain cleared.
terminalio_terminal_clear_status_bar(&supervisor_terminal);
}
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->written = true;
self->update_in_progress = update_in_progress;
}

View File

@ -0,0 +1,43 @@
/*
* 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;
bool written;
} 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,37 @@
/*
* 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,
},
};

View File

@ -30,20 +30,31 @@
#include "shared-bindings/displayio/TileGrid.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,
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_y = 0;
self->font = font;
self->scroll_area = scroll_area;
self->title_bar = title_bar;
self->title_x = 0;
self->title_y = 0;
self->status_bar = status_bar;
self->status_x = 0;
self->status_y = 0;
self->first_row = 0;
common_hal_displayio_tilegrid_set_all_tiles(self->scroll_area, 0);
if (self->title_bar) {
common_hal_displayio_tilegrid_set_all_tiles(self->title_bar, 0);
if (self->status_bar) {
common_hal_displayio_tilegrid_set_all_tiles(self->status_bar, 0);
}
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) {
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;
uint16_t start_y = self->cursor_y;
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 (c == 0x1b && i[0] == '\\') {
self->in_osc_command = false;
self->title_x = 0;
self->title_y = 0;
self->status_x = 0;
self->status_y = 0;
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);
if (tile_index != 0xff) {
// Clear the tile grid before we start putting new info.
if (self->title_x == 0 && self->title_y == 0) {
common_hal_displayio_tilegrid_set_all_tiles(self->title_bar, 0);
if (self->status_x == 0 && self->status_y == 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);
self->title_x++;
if (self->title_x >= self->title_bar->width_in_tiles) {
self->title_y++;
self->title_x %= self->title_bar->width_in_tiles;
common_hal_displayio_tilegrid_set_tile(self->status_bar, self->status_x, self->status_y, tile_index);
self->status_x++;
if (self->status_x >= self->status_bar->width_in_tiles) {
self->status_y++;
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--;
}
} 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;
uint8_t j = 1;
for (; j < 6; j++) {

View File

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

View File

@ -42,7 +42,6 @@
#include "supervisor/serial.h"
#include "supervisor/shared/status_leds.h"
#include "supervisor/shared/tick.h"
#include "supervisor/shared/title_bar.h"
#include "supervisor/shared/translate/translate.h"
#include "py/mpstate.h"
@ -57,6 +56,10 @@
#include "bluetooth/ble_drv.h"
#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.
const uint8_t public_advertising_data[] = { 0x02, 0x01, 0x06, // 0-2 Flags
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 bool was_connected = false;
#if CIRCUITPY_STATUS_BAR
// To detect when the title bar changes.
STATIC bool _last_connected = false;
STATIC bool _last_advertising = false;
#endif
#if CIRCUITPY_STATUS_BAR
// Title bar status
bool supervisor_bluetooth_status_dirty(void) {
return _last_advertising != advertising ||
_last_connected != was_connected;
}
#endif
#if CIRCUITPY_STATUS_BAR
void supervisor_bluetooth_status(void) {
serial_write("BLE:");
if (advertising) {
@ -123,6 +131,7 @@ void supervisor_bluetooth_status(void) {
_last_connected = was_connected;
_last_advertising = advertising;
}
#endif
STATIC void supervisor_bluetooth_start_advertising(void) {
if (workflow_state != WORKFLOW_ENABLED) {
@ -273,9 +282,13 @@ void supervisor_bluetooth_background(void) {
supervisor_bluetooth_file_transfer_disconnected();
#endif
}
#if CIRCUITPY_STATUS_BAR
if (was_connected != is_connected) {
supervisor_title_bar_request_update(false);
supervisor_status_bar_request_update(false);
}
#endif
was_connected = is_connected;
if (!is_connected) {
supervisor_bluetooth_start_advertising();
@ -312,7 +325,10 @@ void supervisor_start_bluetooth(void) {
// Kick off advertisements
supervisor_bluetooth_background();
supervisor_title_bar_request_update(false);
#if CIRCUITPY_STATUS_BAR
supervisor_status_bar_request_update(false);
#endif
#endif
}

View File

@ -34,7 +34,6 @@
#include "shared-bindings/displayio/Palette.h"
#include "shared-bindings/displayio/TileGrid.h"
#include "supervisor/memory.h"
#include "supervisor/shared/title_bar.h"
#if CIRCUITPY_RGBMATRIX
#include "shared-module/displayio/__init__.h"
@ -46,6 +45,10 @@
#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h"
#endif
#if CIRCUITPY_STATUS_BAR
#include "supervisor/shared/status_bar.h"
#endif
#if CIRCUITPY_REPL_LOGO
extern uint32_t blinka_bitmap_data[];
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
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;
uint16_t width_in_tiles = width_px / scroll_area->tile_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;
#if CIRCUITPY_REPL_LOGO
title_bar->x = supervisor_blinka_sprite.pixel_width + 1;
// Align the title bar to the bottom of the logo.
title_bar->y = supervisor_blinka_sprite.pixel_height - title_bar->tile_height;
status_bar->x = supervisor_blinka_sprite.pixel_width + 1;
// Align the status bar to the bottom of the logo.
status_bar->y = supervisor_blinka_sprite.pixel_height - status_bar->tile_height;
#else
title_bar->x = 0;
title_bar->y = 0;
status_bar->x = 0;
status_bar->y = 0;
#endif
title_bar->top_left_y = 0;
title_bar->width_in_tiles = width_in_tiles;
title_bar->height_in_tiles = 1;
status_bar->top_left_y = 0;
status_bar->width_in_tiles = width_in_tiles;
status_bar->height_in_tiles = 1;
assert(width_in_tiles > 0);
title_bar->pixel_width = width_in_tiles * title_bar->tile_width;
title_bar->pixel_height = title_bar->tile_height;
title_bar->tiles = tiles;
title_bar->full_change = true;
status_bar->pixel_width = width_in_tiles * status_bar->tile_width;
status_bar->pixel_height = status_bar->tile_height;
status_bar->tiles = tiles;
status_bar->full_change = true;
scroll_area->x = 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
scroll_area->y = blinka_bitmap.height;
#else
scroll_area->y = title_bar->tile_height;
scroll_area->y = status_bar->tile_height;
#endif
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
@ -140,9 +143,9 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) {
scroll_area->tiles = tiles + width_in_tiles;
scroll_area->full_change = true;
common_hal_terminalio_terminal_construct(&supervisor_terminal, scroll_area, &supervisor_terminal_font, title_bar);
// Update the title bar since we just cleared the terminal.
supervisor_title_bar_update();
common_hal_terminalio_terminal_construct(&supervisor_terminal, scroll_area, &supervisor_terminal_font, status_bar);
// Do not update status bar until after boot.py has run, in case it is disabled.
}
#endif
@ -155,9 +158,9 @@ void supervisor_stop_terminal(void) {
free_memory(tilegrid_tiles);
tilegrid_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.title_bar = NULL;
supervisor_terminal.status_bar = NULL;
}
#endif
}
@ -165,13 +168,13 @@ void supervisor_stop_terminal(void) {
void supervisor_display_move_memory(void) {
#if CIRCUITPY_TERMINALIO
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) {
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;
} else {
scroll_area->tiles = NULL;
title_bar->tiles = NULL;
status_bar->tiles = NULL;
}
#endif
@ -195,7 +198,7 @@ void supervisor_display_move_memory(void) {
#if CIRCUITPY_TERMINALIO
#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 = {
.base = {.type = &mp_type_list },
.alloc = 3,
@ -203,7 +206,7 @@ mp_obj_list_t splash_children = {
.items = members,
};
#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 = {
.base = {.type = &mp_type_list },
.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.
extern displayio_bitmap_t supervisor_terminal_font_bitmap;
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;
#endif

View File

@ -41,6 +41,11 @@
#include "supervisor/shared/bluetooth/serial.h"
#endif
#if CIRCUITPY_STATUS_BAR
#include "shared-bindings/supervisor/__init__.h"
#include "shared-bindings/supervisor/StatusBar.h"
#endif
#if CIRCUITPY_USB
#include "tusb.h"
#endif
@ -276,11 +281,22 @@ void serial_write_substring(const char *text, uint32_t length) {
if (length == 0) {
return;
}
#if CIRCUITPY_TERMINALIO
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);
#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 (tud_vendor_connected()) {
tud_vendor_write(text, length);

View File

@ -27,9 +27,15 @@
#include <stdbool.h>
#include "genhdr/mpversion.h"
#include "py/mpconfig.h"
#include "shared-bindings/supervisor/__init__.h"
#include "shared-bindings/supervisor/StatusBar.h"
#include "supervisor/background_callback.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
#include "supervisor/shared/web_workflow/web_workflow.h"
@ -39,46 +45,56 @@
#include "supervisor/shared/bluetooth/bluetooth.h"
#endif
static background_callback_t title_bar_background_cb;
static background_callback_t status_bar_background_cb;
static bool _forced_dirty = 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) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
void supervisor_status_bar_update(void) {
if (_suspended) {
supervisor_title_bar_request_update(true);
supervisor_status_bar_request_update(true);
return;
}
_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
// 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
// but some may be cut off.
serial_write("\x1b" "]0;");
serial_write("🐍");
#if CIRCUITPY_WEB_WORKFLOW
supervisor_web_workflow_status();
serial_write(" | ");
#endif
#if CIRCUITPY_BLE_FILE_SERVICE || CIRCUITPY_SERIAL_BLE
supervisor_bluetooth_status();
serial_write(" | ");
#endif
supervisor_execution_status();
serial_write(" | ");
serial_write(MICROPY_GIT_TAG);
// Send string terminator
serial_write("\x1b" "\\");
supervisor_status_bar_set_update_in_progress(&shared_module_supervisor_status_bar_obj, false);
}
static void title_bar_background(void *data) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
static void status_bar_background(void *data) {
if (_suspended) {
return;
}
@ -92,42 +108,37 @@ static void title_bar_background(void *data) {
dirty = dirty || supervisor_bluetooth_status_dirty();
#endif
if (!dirty) {
return;
if (dirty) {
supervisor_status_bar_update();
}
supervisor_title_bar_update();
}
void supervisor_title_bar_start(void) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
title_bar_background_cb.fun = title_bar_background;
title_bar_background_cb.data = NULL;
supervisor_title_bar_request_update(true);
void supervisor_status_bar_start(void) {
supervisor_status_bar_request_update(true);
}
void supervisor_title_bar_request_update(bool force_dirty) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
void supervisor_status_bar_request_update(bool force_dirty) {
if (force_dirty) {
_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) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
void supervisor_status_bar_suspend(void) {
_suspended = true;
}
void supervisor_title_bar_resume(void) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
void supervisor_status_bar_resume(void) {
_suspended = false;
supervisor_title_bar_request_update(false);
supervisor_status_bar_request_update(false);
}
void supervisor_status_bar_init(void) {
status_bar_background_cb.fun = status_bar_background;
status_bar_background_cb.data = NULL;
shared_module_supervisor_status_bar_obj.console = true;
shared_module_supervisor_status_bar_obj.display = true;
shared_module_supervisor_status_bar_obj.update_in_progress = false;
shared_module_supervisor_status_bar_obj.written = false;
}

View File

@ -28,17 +28,21 @@
#include <stdbool.h>
void supervisor_title_bar_start(void);
void supervisor_title_bar_suspend(void);
void supervisor_title_bar_resume(void);
void supervisor_status_bar_init(void);
void supervisor_status_bar_start(void);
void supervisor_status_bar_suspend(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
// 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
// changed.
void supervisor_title_bar_request_update(bool force_dirty);
void supervisor_status_bar_request_update(bool force_dirty);
// Provided by main.c
void supervisor_execution_status(void);

View File

@ -31,11 +31,14 @@
#include "supervisor/port.h"
#include "supervisor/serial.h"
#include "supervisor/usb.h"
#include "supervisor/shared/title_bar.h"
#include "supervisor/shared/workflow.h"
#include "shared/runtime/interrupt_char.h"
#include "shared/readline/readline.h"
#if CIRCUITPY_STATUS_BAR
#include "supervisor/shared/status_bar.h"
#endif
#if CIRCUITPY_STORAGE
#include "shared-module/storage/__init__.h"
#endif
@ -244,8 +247,10 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
reset_to_bootloader();
}
} else {
#if CIRCUITPY_STATUS_BAR
// 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;
// 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 uint32_t _last_ip = 0;
static wifi_radio_error_t _last_wifi_status = WIFI_RADIO_ERROR_NONE;
#endif
static mdns_server_obj_t mdns;
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) {
return common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) != _last_enabled ||
_encoded_ip != _last_ip ||
_last_wifi_status != _wifi_status;
}
#endif
#if CIRCUITPY_STATUS_BAR
void supervisor_web_workflow_status(void) {
_last_enabled = common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj);
if (_last_enabled) {
@ -231,6 +236,7 @@ void supervisor_web_workflow_status(void) {
serial_write_compressed(translate("off"));
}
}
#endif
void supervisor_start_web_workflow(void) {
#if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI

View File

@ -29,9 +29,12 @@
#include "py/ringbuf.h"
#include "py/runtime.h"
#include "shared/runtime/interrupt_char.h"
#include "supervisor/shared/title_bar.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.
#include "esp_log.h"
@ -73,8 +76,10 @@ void websocket_handoff(socketpool_socket_obj_t *socket) {
socket->connected = false;
socket->num = -1;
#if CIRCUITPY_STATUS_BAR
// 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) {

View File

@ -15,7 +15,6 @@ SRC_SUPERVISOR = \
supervisor/shared/stack.c \
supervisor/shared/status_leds.c \
supervisor/shared/tick.c \
supervisor/shared/title_bar.c \
supervisor/shared/traceback.c \
supervisor/shared/translate/translate.c \
supervisor/shared/workflow.c \
@ -98,6 +97,12 @@ ifneq ($(wildcard supervisor/serial.c),)
SRC_SUPERVISOR += supervisor/serial.c
endif
ifeq ($(CIRCUITPY_STATUS_BAR),1)
SRC_SUPERVISOR += \
supervisor/shared/status_bar.c \
endif
ifeq ($(CIRCUITPY_USB),1)
SRC_SUPERVISOR += \
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(
"""\
displayio_tilegrid_t supervisor_terminal_title_bar_text_grid = {{
displayio_tilegrid_t supervisor_terminal_status_bar_text_grid = {{
.base = {{ .type = &displayio_tilegrid_type }},
.bitmap = (displayio_bitmap_t*) &supervisor_terminal_font_bitmap,
.pixel_shader = &supervisor_terminal_color,
@ -414,7 +414,7 @@ terminalio_terminal_obj_t supervisor_terminal = {
.cursor_x = 0,
.cursor_y = 0,
.scroll_area = NULL,
.title_bar = NULL
.status_bar = NULL
};
#endif