Merge remote-tracking branch 'origin/main' into espressif-camera-2

This commit is contained in:
Jeff Epler 2022-08-05 21:08:12 -05:00
commit 1a11ff864a
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
19 changed files with 439 additions and 226 deletions

View File

@ -863,6 +863,10 @@ msgstr ""
msgid "Display rotation must be in 90 degree increments"
msgstr ""
#: main.c
msgid "Done"
msgstr ""
#: shared-bindings/digitalio/DigitalInOut.c
msgid "Drive mode not used when direction is input."
msgstr ""
@ -1535,6 +1539,14 @@ msgstr ""
msgid "Odd parity is not supported"
msgstr ""
#: supervisor/shared/bluetooth/bluetooth.c
msgid "Off"
msgstr ""
#: supervisor/shared/bluetooth/bluetooth.c
msgid "Ok"
msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
#: ports/raspberrypi/common-hal/audiobusio/PDMIn.c
msgid "Only 8 or 16 bit mono with "
@ -1787,6 +1799,10 @@ msgstr ""
msgid "Received response was invalid"
msgstr ""
#: supervisor/shared/bluetooth/bluetooth.c
msgid "Reconnecting"
msgstr ""
#: shared-bindings/displayio/EPaperDisplay.c
msgid "Refresh too soon"
msgstr ""

93
main.c
View File

@ -204,6 +204,22 @@ STATIC void stop_mp(void) {
gc_deinit();
}
STATIC const char *_current_executing_filename = NULL;
STATIC pyexec_result_t _exec_result = {0, MP_OBJ_NULL, 0};
void supervisor_execution_status(void) {
mp_obj_exception_t *exception = MP_OBJ_TO_PTR(_exec_result.exception);
if (_current_executing_filename != NULL) {
serial_write(_current_executing_filename);
} else if ((_exec_result.return_code & PYEXEC_EXCEPTION) != 0 &&
exception != NULL) {
mp_printf(&mp_plat_print, "@%d %q", _exec_result.exception_line, exception->base.type->name);
} else {
serial_write_compressed(translate("Done"));
}
}
#define STRING_LIST(...) {__VA_ARGS__, ""}
// Look for the first file that exists in the list of filenames, using mp_import_stat().
@ -218,17 +234,23 @@ STATIC const char *first_existing_file_in_list(const char *const *filenames) {
return NULL;
}
STATIC bool maybe_run_list(const char *const *filenames, pyexec_result_t *exec_result) {
const char *filename = first_existing_file_in_list(filenames);
if (filename == NULL) {
STATIC bool maybe_run_list(const char *const *filenames) {
_exec_result.return_code = 0;
_exec_result.exception = MP_OBJ_NULL;
_exec_result.exception_line = 0;
_current_executing_filename = first_existing_file_in_list(filenames);
if (_current_executing_filename == NULL) {
return false;
}
mp_hal_stdout_tx_str(filename);
mp_hal_stdout_tx_str(_current_executing_filename);
serial_write_compressed(translate(" output:\n"));
pyexec_file(filename, exec_result);
supervisor_title_bar_update();
pyexec_file(_current_executing_filename, &_exec_result);
#if CIRCUITPY_ATEXIT
shared_module_atexit_execute(exec_result);
shared_module_atexit_execute(&_exec_result);
#endif
_current_executing_filename = NULL;
supervisor_title_bar_update();
return true;
}
@ -347,12 +369,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
}
#endif
pyexec_result_t result;
result.return_code = 0;
result.exception = MP_OBJ_NULL;
result.exception_line = 0;
bool skip_repl = false;
bool skip_wait = false;
bool found_main = false;
@ -391,7 +407,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
if (((next_code_info_t *)next_code_allocation->ptr)->filename[0] != '\0') {
const char *next_list[] = {((next_code_info_t *)next_code_allocation->ptr)->filename, ""};
// This is where the user's python code is actually executed:
found_main = maybe_run_list(next_list, &result);
found_main = maybe_run_list(next_list);
if (!found_main) {
serial_write(((next_code_info_t *)next_code_allocation->ptr)->filename);
serial_write_compressed(translate(" not found.\n"));
@ -401,11 +417,11 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
// Otherwise, default to the standard list of filenames
if (!found_main) {
// This is where the user's python code is actually executed:
found_main = maybe_run_list(supported_filenames, &result);
found_main = maybe_run_list(supported_filenames);
// If that didn't work, double check the extensions
#if CIRCUITPY_FULL_BUILD
if (!found_main) {
found_main = maybe_run_list(double_extension_filenames, &result);
found_main = maybe_run_list(double_extension_filenames);
if (found_main) {
serial_write_compressed(translate("WARNING: Your code filename has two extensions\n"));
}
@ -417,7 +433,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
// Print done before resetting everything so that we get the message over
// BLE before it is reset and we have a delay before reconnect.
if ((result.return_code & PYEXEC_RELOAD) && supervisor_get_run_reason() == RUN_REASON_AUTO_RELOAD) {
if ((_exec_result.return_code & PYEXEC_RELOAD) && supervisor_get_run_reason() == RUN_REASON_AUTO_RELOAD) {
serial_write_compressed(translate("\nCode stopped by auto-reload. Reloading soon.\n"));
} else {
serial_write_compressed(translate("\nCode done running.\n"));
@ -425,7 +441,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, result.exception);
cleanup_after_vm(heap, _exec_result.exception);
// 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
@ -436,7 +452,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
next_code_options |= SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET;
}
if (result.return_code & PYEXEC_RELOAD) {
if (_exec_result.return_code & PYEXEC_RELOAD) {
next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD;
// Reload immediately unless the reload is due to autoreload. In that
// case, we wait below to see if any other writes occur.
@ -444,7 +460,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
skip_repl = true;
skip_wait = true;
}
} else if (result.return_code == 0) {
} else if (_exec_result.return_code == 0) {
next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_SUCCESS;
if (next_code_options & SUPERVISOR_NEXT_CODE_OPT_RELOAD_ON_SUCCESS) {
skip_repl = true;
@ -455,12 +471,12 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
// Deep sleep cannot be skipped
// TODO: settings in deep sleep should persist, using a new sleep memory API
if (next_code_options & SUPERVISOR_NEXT_CODE_OPT_RELOAD_ON_ERROR
&& !(result.return_code & PYEXEC_DEEP_SLEEP)) {
&& !(_exec_result.return_code & PYEXEC_DEEP_SLEEP)) {
skip_repl = true;
skip_wait = true;
}
}
if (result.return_code & PYEXEC_FORCED_EXIT) {
if (_exec_result.return_code & PYEXEC_FORCED_EXIT) {
skip_repl = false;
skip_wait = true;
}
@ -478,12 +494,12 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
uint8_t blink_count;
bool led_active = false;
#if CIRCUITPY_ALARM
if (result.return_code & PYEXEC_DEEP_SLEEP) {
if (_exec_result.return_code & PYEXEC_DEEP_SLEEP) {
color = BLACK;
blink_count = 0;
} else
#endif
if (result.return_code != PYEXEC_EXCEPTION) {
if (_exec_result.return_code != PYEXEC_EXCEPTION) {
if (safe_mode == NO_SAFE_MODE) {
color = ALL_DONE;
blink_count = ALL_DONE_BLINKS;
@ -568,7 +584,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
// Sleep until our next interrupt.
#if CIRCUITPY_ALARM
if (result.return_code & PYEXEC_DEEP_SLEEP) {
if (_exec_result.return_code & PYEXEC_DEEP_SLEEP) {
const bool awoke_from_true_deep_sleep =
common_hal_mcu_processor_get_reset_reason() == RESET_REASON_DEEP_SLEEP_ALARM;
@ -730,10 +746,10 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
usb_set_defaults();
#endif
pyexec_result_t result = {0, MP_OBJ_NULL, 0};
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();
vstr_t boot_text;
vstr_init(&boot_text, 512);
boot_output = &boot_text;
@ -741,8 +757,17 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
// Write version info
mp_printf(&mp_plat_print, "%s\nBoard ID:%s\n", MICROPY_FULL_VERSION_INFO, CIRCUITPY_BOARD_ID);
#if CIRCUITPY_MICROCONTROLLER && COMMON_HAL_MCU_PROCESSOR_UID_LENGTH > 0
uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH];
common_hal_mcu_processor_get_uid(raw_id);
mp_printf(&mp_plat_print, "UID:");
for (uint8_t i = 0; i < COMMON_HAL_MCU_PROCESSOR_UID_LENGTH; i++) {
mp_printf(&mp_plat_print, "%02X", raw_id[i]);
}
mp_printf(&mp_plat_print, "\n");
#endif
bool found_boot = maybe_run_list(boot_py_filenames, &result);
bool found_boot = maybe_run_list(boot_py_filenames);
(void)found_boot;
@ -752,6 +777,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
FATFS *fs = &vfs->fatfs;
boot_output = NULL;
supervisor_title_bar_resume();
bool write_boot_output = true;
FIL boot_output_file;
if (f_open(fs, &boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_READ) == FR_OK) {
@ -794,7 +820,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
port_post_boot_py(true);
cleanup_after_vm(heap, result.exception);
cleanup_after_vm(heap, _exec_result.exception);
port_post_boot_py(false);
@ -831,7 +857,11 @@ STATIC int run_repl(bool first_run) {
exit_code = pyexec_raw_repl();
supervisor_title_bar_resume();
} else {
_current_executing_filename = "REPL";
supervisor_title_bar_update();
exit_code = pyexec_friendly_repl();
_current_executing_filename = NULL;
supervisor_title_bar_update();
}
#if CIRCUITPY_ATEXIT
pyexec_result_t result;
@ -841,6 +871,13 @@ STATIC int run_repl(bool first_run) {
}
#endif
cleanup_after_vm(heap, MP_OBJ_SENTINEL);
// Also reset bleio. The above call omits it in case workflows should continue. In this case,
// we're switching straight to another VM so we want to reset.
#if CIRCUITPY_BLEIO
bleio_reset();
#endif
#if CIRCUITPY_STATUS_LED
status_led_init();
new_status_color(BLACK);

View File

@ -164,6 +164,9 @@ CFLAGS += \
-msoft-float \
-mfloat-abi=soft \
-DSAMD21
LIBS := libs/libgcc-12.1.0-Os-v6-m-nofp.a -lc
else
LIBS := -lgcc -lc
endif
ifeq ($(CHIP_FAMILY), samd51)
CFLAGS += \
@ -200,7 +203,6 @@ endif
CFLAGS += -Wno-stringop-overread -Wno-stringop-overflow
LDFLAGS = $(CFLAGS) -nostartfiles -Wl,-nostdlib -Wl,-T,$(GENERATED_LD_FILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nano.specs
LIBS := -lgcc -lc
# Use toolchain libm if we're not using our own.
ifndef INTERNAL_LIBM

Binary file not shown.

View File

@ -449,15 +449,23 @@ bool common_hal_bleio_adapter_set_address(bleio_adapter_obj_t *self, bleio_addre
return sd_ble_gap_addr_set(&local_address) == NRF_SUCCESS;
}
uint16_t bleio_adapter_get_name(char *buf, uint16_t len) {
uint16_t full_len = 0;
sd_ble_gap_device_name_get(NULL, &full_len);
uint32_t err_code = sd_ble_gap_device_name_get((uint8_t *)buf, &len);
if (err_code != NRF_SUCCESS) {
return 0;
}
return full_len;
}
mp_obj_str_t *common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self) {
uint16_t len = 0;
sd_ble_gap_device_name_get(NULL, &len);
uint8_t buf[len];
uint32_t err_code = sd_ble_gap_device_name_get(buf, &len);
if (err_code != NRF_SUCCESS) {
return NULL;
}
return mp_obj_new_str((char *)buf, len);
char buf[len];
bleio_adapter_get_name(buf, len);
return mp_obj_new_str(buf, len);
}
void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char *name) {

View File

@ -372,7 +372,7 @@ CFLAGS += -DCIRCUITPY_SSL=$(CIRCUITPY_SSL)
CIRCUITPY_STAGE ?= 0
CFLAGS += -DCIRCUITPY_STAGE=$(CIRCUITPY_STAGE)
CIRCUITPY_STATUS_BAR ?= $(CIRCUITPY_WEB_WORKFLOW)
CIRCUITPY_STATUS_BAR ?= 1
CFLAGS += -DCIRCUITPY_STATUS_BAR=$(CIRCUITPY_STATUS_BAR)
CIRCUITPY_STORAGE ?= 1

View File

@ -158,10 +158,10 @@ MP_PROPERTY_GETSET(bleio_adapter_address_obj,
//| The name is "CIRCUITPY" + the last four hex digits of ``adapter.address``,
//| to make it easy to distinguish multiple CircuitPython boards."""
//|
STATIC mp_obj_t bleio_adapter_get_name(mp_obj_t self) {
STATIC mp_obj_t _bleio_adapter_get_name(mp_obj_t self) {
return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_name(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_name_obj, bleio_adapter_get_name);
MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_name_obj, _bleio_adapter_get_name);
STATIC mp_obj_t bleio_adapter_set_name(mp_obj_t self, mp_obj_t new_name) {

View File

@ -50,6 +50,9 @@ extern bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self);
extern bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self);
extern bool common_hal_bleio_adapter_set_address(bleio_adapter_obj_t *self, bleio_address_obj_t *address);
// Copies the adapter name into the given buffer up to len and returns the full length (may be more
// than len if the buffer was too short.)
uint16_t bleio_adapter_get_name(char *buf, uint16_t len);
extern mp_obj_str_t *common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self);
extern void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char *name);

View File

@ -33,6 +33,8 @@
#include "shared-bindings/supervisor/RunReason.h"
#include "shared-bindings/supervisor/Runtime.h"
#include "supervisor/shared/reload.h"
#if (CIRCUITPY_USB)
#include "tusb.h"
#endif
@ -105,7 +107,7 @@ void supervisor_set_run_reason(supervisor_run_reason_t run_reason) {
}
//| run_reason: RunReason
//| """Returns why CircuitPython started running this particular time."""
//| """Why CircuitPython started running this particular time."""
//|
STATIC mp_obj_t supervisor_runtime_get_run_reason(mp_obj_t self) {
return cp_enum_find(&supervisor_run_reason_type, _run_reason);
@ -115,11 +117,34 @@ MP_DEFINE_CONST_FUN_OBJ_1(supervisor_runtime_get_run_reason_obj, supervisor_runt
MP_PROPERTY_GETTER(supervisor_runtime_run_reason_obj,
(mp_obj_t)&supervisor_runtime_get_run_reason_obj);
//| autoreload: bool
//| """Whether CircuitPython may autoreload based on workflow writes to the filesystem."""
//|
STATIC mp_obj_t supervisor_runtime_get_autoreload(mp_obj_t self) {
return mp_obj_new_bool(autoreload_is_enabled());
}
MP_DEFINE_CONST_FUN_OBJ_1(supervisor_runtime_get_autoreload_obj, supervisor_runtime_get_autoreload);
STATIC mp_obj_t supervisor_runtime_set_autoreload(mp_obj_t self, mp_obj_t state_in) {
if (mp_obj_is_true(state_in)) {
autoreload_enable();
} else {
autoreload_disable();
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(supervisor_runtime_set_autoreload_obj, supervisor_runtime_set_autoreload);
MP_PROPERTY_GETSET(supervisor_runtime_autoreload_obj,
(mp_obj_t)&supervisor_runtime_get_autoreload_obj,
(mp_obj_t)&supervisor_runtime_set_autoreload_obj);
STATIC const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_usb_connected), MP_ROM_PTR(&supervisor_runtime_usb_connected_obj) },
{ MP_ROM_QSTR(MP_QSTR_serial_connected), MP_ROM_PTR(&supervisor_runtime_serial_connected_obj) },
{ MP_ROM_QSTR(MP_QSTR_serial_bytes_available), MP_ROM_PTR(&supervisor_runtime_serial_bytes_available_obj) },
{ MP_ROM_QSTR(MP_QSTR_run_reason), MP_ROM_PTR(&supervisor_runtime_run_reason_obj) },
{ MP_ROM_QSTR(MP_QSTR_autoreload), MP_ROM_PTR(&supervisor_runtime_autoreload_obj) },
};
STATIC MP_DEFINE_CONST_DICT(supervisor_runtime_locals_dict, supervisor_runtime_locals_dict_table);

View File

@ -53,27 +53,6 @@
//| This object is the sole instance of `supervisor.Runtime`."""
//|
//| def enable_autoreload() -> None:
//| """Enable autoreload based on USB file write activity."""
//| ...
//|
STATIC mp_obj_t supervisor_enable_autoreload(void) {
autoreload_enable();
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(supervisor_enable_autoreload_obj, supervisor_enable_autoreload);
//| def disable_autoreload() -> None:
//| """Disable autoreload based on USB file write activity until
//| `enable_autoreload` is called."""
//| ...
//|
STATIC mp_obj_t supervisor_disable_autoreload(void) {
autoreload_disable();
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(supervisor_disable_autoreload_obj, supervisor_disable_autoreload);
//| 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
@ -312,8 +291,6 @@ MP_DEFINE_CONST_FUN_OBJ_2(supervisor_reset_terminal_obj, supervisor_reset_termin
STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_supervisor) },
{ MP_ROM_QSTR(MP_QSTR_enable_autoreload), MP_ROM_PTR(&supervisor_enable_autoreload_obj) },
{ MP_ROM_QSTR(MP_QSTR_disable_autoreload), MP_ROM_PTR(&supervisor_disable_autoreload_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_rgb_status_brightness), MP_ROM_PTR(&supervisor_set_rgb_status_brightness_obj) },
{ MP_ROM_QSTR(MP_QSTR_runtime), MP_ROM_PTR(&common_hal_supervisor_runtime_obj) },
{ MP_ROM_QSTR(MP_QSTR_reload), MP_ROM_PTR(&supervisor_reload_obj) },

View File

@ -39,8 +39,11 @@
#include "common-hal/_bleio/__init__.h"
#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"
@ -75,18 +78,13 @@ const uint8_t public_advertising_data[] = { 0x02, 0x01, 0x06, // 0-2 Flags
const uint8_t private_advertising_data[] = { 0x02, 0x01, 0x06, // 0-2 Flags
0x02, 0x0a, 0x00 // 3-5 TX power level 0
};
// This scan response advertises the full CIRCPYXXXX device name.
uint8_t circuitpython_scan_response_data[] = {
0x0a, 0x09, 0x43, 0x49, 0x52, 0x50, 0x59, 0x00, 0x00, 0x00, 0x00,
#if CIRCUITPY_SERIAL_BLE
0x11, 0x06, 0x6e, 0x68, 0x74, 0x79, 0x50, 0x74, 0x69, 0x75, 0x63, 0x72, 0x69, 0x43, 0x01, 0x00, 0xaf, 0xad
#endif
};
// This scan response advertises the full device name (if it fits.)
uint8_t circuitpython_scan_response_data[31];
#if CIRCUITPY_BLE_FILE_SERVICE || CIRCUITPY_SERIAL_BLE
STATIC bool boot_in_discovery_mode = false;
STATIC bool advertising = false;
STATIC bool _private_advertising = false;
STATIC bool ble_started = false;
#define WORKFLOW_UNSET 0
@ -96,6 +94,36 @@ STATIC bool ble_started = false;
STATIC uint8_t workflow_state = WORKFLOW_UNSET;
STATIC bool was_connected = false;
// To detect when the title bar changes.
STATIC bool _last_connected = false;
STATIC bool _last_advertising = false;
// Title bar status
bool supervisor_bluetooth_status_dirty(void) {
return _last_advertising != advertising ||
_last_connected != was_connected;
}
void supervisor_bluetooth_status(void) {
serial_write("BLE:");
if (advertising) {
if (_private_advertising) {
serial_write_compressed(translate("Reconnecting"));
} else {
const char *name = (char *)circuitpython_scan_response_data + 2;
int len = MIN(strlen(name), sizeof(circuitpython_scan_response_data) - 2);
serial_write_substring(name, len);
}
} else if (was_connected) {
serial_write_compressed(translate("Ok"));
} else {
serial_write_compressed(translate("Off"));
}
_last_connected = was_connected;
_last_advertising = advertising;
}
STATIC void supervisor_bluetooth_start_advertising(void) {
if (workflow_state != WORKFLOW_ENABLED) {
return;
@ -118,6 +146,7 @@ STATIC void supervisor_bluetooth_start_advertising(void) {
size_t adv_len = sizeof(private_advertising_data);
const uint8_t *scan_response = NULL;
size_t scan_response_len = 0;
_private_advertising = true;
// Advertise with less power when doing so publicly to reduce who can hear us. This will make it
// harder for someone with bad intentions to pair from a distance.
if (!bonded) {
@ -126,6 +155,18 @@ STATIC void supervisor_bluetooth_start_advertising(void) {
adv_len = sizeof(public_advertising_data);
scan_response = circuitpython_scan_response_data;
scan_response_len = sizeof(circuitpython_scan_response_data);
uint16_t max_name_len = sizeof(circuitpython_scan_response_data) - 2;
uint16_t name_len = bleio_adapter_get_name((char *)circuitpython_scan_response_data + 2,
max_name_len);
if (name_len > max_name_len) {
circuitpython_scan_response_data[0] = max_name_len + 1;
circuitpython_scan_response_data[1] = 0x8;
} else {
circuitpython_scan_response_data[0] = name_len + 1;
circuitpython_scan_response_data[1] = 0x9;
}
scan_response_len = circuitpython_scan_response_data[0] + 1;
_private_advertising = false;
}
uint32_t status = _common_hal_bleio_adapter_start_advertising(&common_hal_bleio_adapter_obj,
true,
@ -232,10 +273,15 @@ void supervisor_bluetooth_background(void) {
supervisor_bluetooth_file_transfer_disconnected();
#endif
}
if (was_connected != is_connected) {
supervisor_title_bar_request_update(false);
}
was_connected = is_connected;
if (!is_connected) {
supervisor_bluetooth_start_advertising();
return;
} else {
advertising = false;
}
#if CIRCUITPY_BLE_FILE_SERVICE
@ -247,7 +293,7 @@ void supervisor_bluetooth_background(void) {
void supervisor_start_bluetooth(void) {
#if CIRCUITPY_BLE_FILE_SERVICE || CIRCUITPY_SERIAL_BLE
if (workflow_state != WORKFLOW_ENABLED) {
if (workflow_state != WORKFLOW_ENABLED || ble_started) {
return;
}
@ -266,6 +312,7 @@ void supervisor_start_bluetooth(void) {
// Kick off advertisements
supervisor_bluetooth_background();
supervisor_title_bar_request_update(false);
#endif
}
@ -277,6 +324,8 @@ void supervisor_stop_bluetooth(void) {
return;
}
ble_started = false;
#if CIRCUITPY_SERIAL_BLE
supervisor_stop_bluetooth_serial();
#endif

View File

@ -38,4 +38,8 @@ void supervisor_stop_bluetooth(void);
void supervisor_bluetooth_enable_workflow(void);
void supervisor_bluetooth_disable_workflow(void);
// Title bar status
bool supervisor_bluetooth_status_dirty(void);
void supervisor_bluetooth_status(void);
#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_H

View File

@ -34,6 +34,7 @@
#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"
@ -65,7 +66,7 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) {
displayio_tilegrid_t *title_bar = &supervisor_terminal_title_bar_text_grid;
bool reset_tiles = false;
uint16_t width_in_tiles = width_px / scroll_area->tile_width;
// determine scale based on h
// determine scale based on width
if (width_in_tiles < 80) {
scale = 1;
}
@ -103,9 +104,9 @@ 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 = blinka_bitmap.width;
title_bar->x = supervisor_blinka_sprite.pixel_width + 1;
// Align the title bar to the bottom of the logo.
title_bar->y = blinka_bitmap.height - title_bar->tile_height;
title_bar->y = supervisor_blinka_sprite.pixel_height - title_bar->tile_height;
#else
title_bar->x = 0;
title_bar->y = 0;
@ -120,11 +121,6 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) {
title_bar->full_change = true;
scroll_area->x = 0;
#if CIRCUITPY_REPL_LOGO
scroll_area->y = blinka_bitmap.height;
#else
scroll_area->y = scroll_area->tile_height;
#endif
scroll_area->top_left_y = 0;
scroll_area->width_in_tiles = width_in_tiles;
scroll_area->height_in_tiles = height_in_tiles - 1;
@ -132,10 +128,21 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) {
assert(height_in_tiles > 1);
scroll_area->pixel_width = width_in_tiles * scroll_area->tile_width;
scroll_area->pixel_height = (height_in_tiles - 1) * scroll_area->tile_height;
#if CIRCUITPY_REPL_LOGO
scroll_area->y = blinka_bitmap.height;
#else
scroll_area->y = title_bar->tile_height;
#endif
int16_t extra_height = (scroll_area->pixel_height + scroll_area->y) - height_px;
// Subtract extra height so that the bottom line fully shows. The top line will be under the
// title bar and Blinka logo.
scroll_area->y -= extra_height;
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();
}
#endif
@ -186,126 +193,9 @@ void supervisor_display_move_memory(void) {
#endif
}
#if CIRCUITPY_REPL_LOGO
uint32_t blinka_bitmap_data[32] = {
0x00000011, 0x11000000,
0x00000111, 0x53100000,
0x00000111, 0x56110000,
0x00000111, 0x11140000,
0x00000111, 0x20002000,
0x00000011, 0x13000000,
0x00000001, 0x11200000,
0x00000000, 0x11330000,
0x00000000, 0x01122000,
0x00001111, 0x44133000,
0x00032323, 0x24112200,
0x00111114, 0x44113300,
0x00323232, 0x34112200,
0x11111144, 0x44443300,
0x11111111, 0x11144401,
0x23232323, 0x21111110
};
displayio_bitmap_t blinka_bitmap = {
.base = {.type = &displayio_bitmap_type },
.width = 16,
.height = 16,
.data = blinka_bitmap_data,
.stride = 2,
.bits_per_value = 4,
.x_shift = 3,
.x_mask = 0x7,
.bitmask = 0xf,
.read_only = true
};
_displayio_color_t blinka_colors[7] = {
{
.rgb888 = 0x000000,
.rgb565 = 0x0000,
.luma = 0x00,
.chroma = 0,
.transparent = true
},
{
.rgb888 = 0x8428bc,
.rgb565 = 0x8978,
.luma = 0xff, // We cheat the luma here. It is actually 0x60
.hue = 184,
.chroma = 148
},
{
.rgb888 = 0xff89bc,
.rgb565 = 0xFCB8,
.luma = 0xb5,
.hue = 222,
.chroma = 118
},
{
.rgb888 = 0x7beffe,
.rgb565 = 0x869F,
.luma = 0xe0,
.hue = 124,
.chroma = 131
},
{
.rgb888 = 0x51395f,
.rgb565 = 0x5A0D,
.luma = 0x47,
.hue = 185,
.chroma = 38
},
{
.rgb888 = 0xffffff,
.rgb565 = 0xffff,
.luma = 0xff,
.chroma = 0
},
{
.rgb888 = 0x0736a0,
.rgb565 = 0x01f5,
.luma = 0x44,
.hue = 147,
.chroma = 153
},
};
displayio_palette_t blinka_palette = {
.base = {.type = &displayio_palette_type },
.colors = blinka_colors,
.color_count = 7,
.needs_refresh = false
};
displayio_tilegrid_t blinka_sprite = {
.base = {.type = &displayio_tilegrid_type },
.bitmap = &blinka_bitmap,
.pixel_shader = &blinka_palette,
.x = 0,
.y = 0,
.pixel_width = 16,
.pixel_height = 16,
.bitmap_width_in_tiles = 1,
.width_in_tiles = 1,
.height_in_tiles = 1,
.tile_width = 16,
.tile_height = 16,
.top_left_x = 16,
.top_left_y = 16,
.tiles = 0,
.partial_change = false,
.full_change = false,
.hidden = false,
.hidden_by_parent = false,
.moved = false,
.inline_tiles = true,
.in_group = true
};
#endif
#if CIRCUITPY_TERMINALIO
#if CIRCUITPY_REPL_LOGO
mp_obj_t members[] = { &blinka_sprite, &supervisor_terminal_title_bar_text_grid, &supervisor_terminal_scroll_area_text_grid, };
mp_obj_t members[] = { &supervisor_terminal_scroll_area_text_grid, &supervisor_blinka_sprite, &supervisor_terminal_title_bar_text_grid, };
mp_obj_list_t splash_children = {
.base = {.type = &mp_type_list },
.alloc = 3,
@ -313,7 +203,7 @@ mp_obj_list_t splash_children = {
.items = members,
};
#else
mp_obj_t members[] = { &supervisor_terminal_title_bar_text_grid, &supervisor_terminal_scroll_area_text_grid, };
mp_obj_t members[] = { &supervisor_terminal_scroll_area_text_grid, &supervisor_terminal_title_bar_text_grid,};
mp_obj_list_t splash_children = {
.base = {.type = &mp_type_list },
.alloc = 2,
@ -323,7 +213,7 @@ mp_obj_list_t splash_children = {
#endif
#else
#if CIRCUITPY_REPL_LOGO
mp_obj_t members[] = { &blinka_sprite };
mp_obj_t members[] = { &supervisor_blinka_sprite };
mp_obj_list_t splash_children = {
.base = {.type = &mp_type_list },
.alloc = 1,

View File

@ -29,10 +29,11 @@
#include <stdint.h>
#include "shared-bindings/displayio/TileGrid.h"
#if CIRCUITPY_TERMINALIO
#include "shared-bindings/displayio/Bitmap.h"
#include "shared-bindings/displayio/TileGrid.h"
#include "shared-bindings/fontio/BuiltinFont.h"
#include "shared-bindings/terminalio/Terminal.h"
@ -46,9 +47,11 @@ 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 terminalio_terminal_obj_t supervisor_terminal;
#endif
// Always shown.
extern displayio_tilegrid_t supervisor_blinka_sprite;
void supervisor_start_terminal(uint16_t width_px, uint16_t height_px);
void supervisor_stop_terminal(void);

View File

@ -34,11 +34,47 @@
#if CIRCUITPY_WEB_WORKFLOW
#include "supervisor/shared/web_workflow/web_workflow.h"
#endif
#if CIRCUITPY_BLE_FILE_SERVICE || CIRCUITPY_SERIAL_BLE
#include "supervisor/shared/bluetooth/bluetooth.h"
#endif
static background_callback_t title_bar_background_cb;
static bool _forced_dirty = false;
static bool _suspended = false;
void supervisor_title_bar_update(void) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
if (_suspended) {
supervisor_title_bar_request_update(true);
return;
}
_forced_dirty = false;
// 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" "\\");
}
static void title_bar_background(void *data) {
#if !CIRCUITPY_STATUS_BAR
return;
@ -52,23 +88,14 @@ static void title_bar_background(void *data) {
dirty = dirty || supervisor_web_workflow_status_dirty();
#endif
#if CIRCUITPY_BLE_FILE_SERVICE || CIRCUITPY_SERIAL_BLE
dirty = dirty || supervisor_bluetooth_status_dirty();
#endif
if (!dirty) {
return;
}
_forced_dirty = false;
// 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();
#endif
serial_write("|");
serial_write(MICROPY_GIT_TAG);
// Send string terminator
serial_write("\x1b" "\\");
supervisor_title_bar_update();
}
void supervisor_title_bar_start(void) {

View File

@ -31,4 +31,14 @@
void supervisor_title_bar_start(void);
void supervisor_title_bar_suspend(void);
void supervisor_title_bar_resume(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);
// 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);
// Provided by main.c
void supervisor_execution_status(void);

View File

@ -196,10 +196,20 @@ bool supervisor_web_workflow_status_dirty(void) {
}
void supervisor_web_workflow_status(void) {
serial_write_compressed(translate("Wi-Fi: "));
_last_enabled = common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj);
if (_last_enabled) {
uint32_t ipv4_address = wifi_radio_get_ipv4_address(&common_hal_wifi_radio_obj);
if (ipv4_address != 0) {
_update_encoded_ip();
_last_ip = _encoded_ip;
mp_printf(&mp_plat_print, "%s", _our_ip_encoded);
if (web_api_port != 80) {
mp_printf(&mp_plat_print, ":%d", web_api_port);
}
// TODO: Use these unicode to show signal strength: ▂▄▆█
return;
}
serial_write_compressed(translate("Wi-Fi: "));
_last_wifi_status = _wifi_status;
if (_wifi_status == WIFI_RADIO_ERROR_AUTH_EXPIRE ||
_wifi_status == WIFI_RADIO_ERROR_AUTH_FAIL) {
@ -210,15 +220,10 @@ void supervisor_web_workflow_status(void) {
_last_ip = 0;
serial_write_compressed(translate("No IP"));
} else {
_update_encoded_ip();
_last_ip = _encoded_ip;
mp_printf(&mp_plat_print, "%s", _our_ip_encoded);
if (web_api_port != 80) {
mp_printf(&mp_plat_print, ":%d", web_api_port);
}
// TODO: Use these unicode to show signal strength: ▂▄▆█
}
} else {
// Keep Wi-Fi print separate so its data can be matched with the one above.
serial_write_compressed(translate("Wi-Fi: "));
serial_write_compressed(translate("off"));
}
}

View File

@ -185,9 +185,8 @@ ifeq ($(CIRCUITPY_DISPLAYIO), 1)
SRC_SUPERVISOR += \
supervisor/shared/display.c
ifeq ($(CIRCUITPY_TERMINALIO), 1)
# Include the display resources because it includes the Blinka logo as well.
SUPERVISOR_O += $(BUILD)/autogen_display_resources-$(TRANSLATION).o
endif
endif
# Preserve double quotes in these values by single-quoting them.

View File

@ -104,14 +104,170 @@ c_file = args.output_c_file
c_file.write(
"""\
#include "shared-bindings/displayio/Bitmap.h"
#include "shared-bindings/displayio/Palette.h"
#include "supervisor/shared/display.h"
"""
)
c_file.write(
"""\
#if CIRCUITPY_REPL_LOGO
"""
)
if tile_y == 16:
blinka_size = 16
c_file.write(
"""\
uint32_t blinka_bitmap_data[32] = {
0x00000011, 0x11000000,
0x00000111, 0x53100000,
0x00000111, 0x56110000,
0x00000111, 0x11140000,
0x00000111, 0x20002000,
0x00000011, 0x13000000,
0x00000001, 0x11200000,
0x00000000, 0x11330000,
0x00000000, 0x01122000,
0x00001111, 0x44133000,
0x00032323, 0x24112200,
0x00111114, 0x44113300,
0x00323232, 0x34112200,
0x11111144, 0x44443300,
0x11111111, 0x11144401,
0x23232323, 0x21111110
};
"""
)
else:
blinka_size = 12
c_file.write(
"""\
uint32_t blinka_bitmap_data[28] = {
0x00000111, 0x00000000,
0x00001153, 0x10000000,
0x00001156, 0x11000000,
0x00001111, 0x14000000,
0x00000112, 0x00200000,
0x00000011, 0x30000000,
0x00000011, 0x20000000,
0x00011144, 0x13000000,
0x00232324, 0x12000000,
0x01111444, 0x13000000,
0x32323234, 0x12010000,
0x11111144, 0x44100000
};
"""
)
c_file.write(
"""\
displayio_bitmap_t blinka_bitmap = {{
.base = {{.type = &displayio_bitmap_type }},
.width = {0},
.height = {0},
.data = blinka_bitmap_data,
.stride = 2,
.bits_per_value = 4,
.x_shift = 3,
.x_mask = 0x7,
.bitmask = 0xf,
.read_only = true
}};
_displayio_color_t blinka_colors[7] = {{
{{
.rgb888 = 0x000000,
.rgb565 = 0x0000,
.luma = 0x00,
.chroma = 0,
.transparent = true
}},
{{
.rgb888 = 0x8428bc,
.rgb565 = 0x8978,
.luma = 0xff, // We cheat the luma here. It is actually 0x60
.hue = 184,
.chroma = 148
}},
{{
.rgb888 = 0xff89bc,
.rgb565 = 0xFCB8,
.luma = 0xb5,
.hue = 222,
.chroma = 118
}},
{{
.rgb888 = 0x7beffe,
.rgb565 = 0x869F,
.luma = 0xe0,
.hue = 124,
.chroma = 131
}},
{{
.rgb888 = 0x51395f,
.rgb565 = 0x5A0D,
.luma = 0x47,
.hue = 185,
.chroma = 38
}},
{{
.rgb888 = 0xffffff,
.rgb565 = 0xffff,
.luma = 0xff,
.chroma = 0
}},
{{
.rgb888 = 0x0736a0,
.rgb565 = 0x01f5,
.luma = 0x44,
.hue = 147,
.chroma = 153
}},
}};
displayio_palette_t blinka_palette = {{
.base = {{.type = &displayio_palette_type }},
.colors = blinka_colors,
.color_count = 7,
.needs_refresh = false
}};
displayio_tilegrid_t supervisor_blinka_sprite = {{
.base = {{.type = &displayio_tilegrid_type }},
.bitmap = &blinka_bitmap,
.pixel_shader = &blinka_palette,
.x = 0,
.y = 0,
.pixel_width = {0},
.pixel_height = {0},
.bitmap_width_in_tiles = 1,
.width_in_tiles = 1,
.height_in_tiles = 1,
.tile_width = {0},
.tile_height = {0},
.top_left_x = {0},
.top_left_y = {0},
.tiles = 0,
.partial_change = false,
.full_change = false,
.hidden = false,
.hidden_by_parent = false,
.moved = false,
.inline_tiles = true,
.in_group = true
}};
#endif
""".format(
blinka_size
)
)
c_file.write(
"""\
#if CIRCUITPY_TERMINALIO
_displayio_color_t terminal_colors[2] = {
{
.rgb888 = 0x000000,
@ -260,5 +416,7 @@ terminalio_terminal_obj_t supervisor_terminal = {
.scroll_area = NULL,
.title_bar = NULL
};
#endif
"""
)