Wi-Fi autoconnect and title bar status
This adds support for CIRCUITPY_WIFI_SSID and CIRCUITPY_WIFI_PASSWORD in `/.env`. When both are defined, CircuitPython will attempt to connect to the network even when user code isn't running. If the user code attempts to a network with the same SSID, it will return immediately. Connecting to another SSID will disconnect from the auto-connected network. If the user code initiates the connection, then it will be shutdown after user code exits. (Should match <8 behavior.) This PR also reworks the default displayio terminal. It now supports a title bar TileGrid in addition to the (newly renamed) scroll area. The default title bar is the top row of the display and is positioned to the right of the Blinka logo when it is enabled. The scroll area is now below the Blinka logo. The Wi-Fi auto-connect code now uses the title bar to show its state including the IP address when connected. It does this through the "standard" OSC control sequence `ESC ] 0 ; <s> ESC \` where <s> is the title bar string. This is commonly supported by terminals so it should work over USB and UART as well. Related to #6174
This commit is contained in:
parent
6925a00138
commit
6446010753
@ -120,7 +120,7 @@ Behavior
|
|||||||
make each file independent from each other.
|
make each file independent from each other.
|
||||||
|
|
||||||
- ``boot.py`` runs only once on start up before
|
- ``boot.py`` runs only once on start up before
|
||||||
USB is initialized. This lays the ground work for configuring USB at
|
workflows are initialized. This lays the ground work for configuring USB at
|
||||||
startup rather than it being fixed. Since serial is not available,
|
startup rather than it being fixed. Since serial is not available,
|
||||||
output is written to ``boot_out.txt``.
|
output is written to ``boot_out.txt``.
|
||||||
- ``code.py`` (or ``main.py``) is run after every reload until it
|
- ``code.py`` (or ``main.py``) is run after every reload until it
|
||||||
@ -135,7 +135,10 @@ Behavior
|
|||||||
possible to fix code that causes nasty crashes by making it available through mass storage after
|
possible to fix code that causes nasty crashes by making it available through mass storage after
|
||||||
the crash. A reset (the button) is needed after it's fixed to get back into normal mode.
|
the crash. A reset (the button) is needed after it's fixed to get back into normal mode.
|
||||||
- RGB status LED indicating CircuitPython state.
|
- RGB status LED indicating CircuitPython state.
|
||||||
- Re-runs ``code.py`` or other main file after file system writes over USB mass storage. (Disable with
|
- One green flash - code completed without error.
|
||||||
|
- Two red flashes - code ended due to an exception.
|
||||||
|
- Three yellow flashes - safe mode. May be due to CircuitPython internal error.
|
||||||
|
- Re-runs ``code.py`` or other main file after file system writes by a workflow. (Disable with
|
||||||
``supervisor.disable_autoreload()``)
|
``supervisor.disable_autoreload()``)
|
||||||
- Autoreload is disabled while the REPL is active.
|
- Autoreload is disabled while the REPL is active.
|
||||||
- Main is one of these: ``code.txt``, ``code.py``, ``main.py``,
|
- Main is one of these: ``code.txt``, ``code.py``, ``main.py``,
|
||||||
|
40
docs/environment.rst
Normal file
40
docs/environment.rst
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
Environment Variables
|
||||||
|
=====================
|
||||||
|
|
||||||
|
CircuitPython 8.0.0 introduces support for environment variables. Environment
|
||||||
|
variables are commonly used to store "secrets" such as Wi-Fi passwords and API
|
||||||
|
keys. This method *does not* make them secure. It only separates them from the
|
||||||
|
code.
|
||||||
|
|
||||||
|
CircuitPython supports these by mimicking the `dotenv <https://github.com/theskumar/python-dotenv>`_
|
||||||
|
CPython library. Other languages such as Javascript, PHP and Ruby also have
|
||||||
|
dotenv libraries.
|
||||||
|
|
||||||
|
These libraries store environment variables in a ``.env`` file. Here is a simple
|
||||||
|
example:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
KEY1='value1'
|
||||||
|
# Comment
|
||||||
|
KEY2='value2
|
||||||
|
is multiple lines'
|
||||||
|
|
||||||
|
CircuitPython uses the ``.env`` at the drive root (no folder) as the environment.
|
||||||
|
User code can access the values from the file using `os.getenv()`. It is
|
||||||
|
recommended to save any values used repeatedly in a variable because `os.getenv()`
|
||||||
|
will parse the ``/.env`` on every access.
|
||||||
|
|
||||||
|
CircuitPython behavior
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
CircuitPython will also read the environment to configure its behavior. Other
|
||||||
|
keys are ignored by CircuitPython. Here are the keys it uses:
|
||||||
|
|
||||||
|
CIRCUITPY_WIFI_PASSWORD
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Wi-Fi password used to auto connect to CIRCUITPY_WIFI_SSID
|
||||||
|
|
||||||
|
CIRCUITPY_WIFI_SSID
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
Wi-Fi SSID to auto-connect to even if user code is not running.
|
@ -22,6 +22,7 @@ Full Table of Contents
|
|||||||
supported_ports.rst
|
supported_ports.rst
|
||||||
troubleshooting.rst
|
troubleshooting.rst
|
||||||
drivers.rst
|
drivers.rst
|
||||||
|
environment.rst
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
@ -1375,6 +1375,10 @@ msgstr ""
|
|||||||
msgid "No I2C device at address: 0x%x"
|
msgid "No I2C device at address: 0x%x"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: supervisor/shared/web_workflow/web_workflow.c
|
||||||
|
msgid "No IP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/common-hal/busio/SPI.c
|
#: ports/espressif/common-hal/busio/SPI.c
|
||||||
#: ports/mimxrt10xx/common-hal/busio/SPI.c
|
#: ports/mimxrt10xx/common-hal/busio/SPI.c
|
||||||
msgid "No MISO Pin"
|
msgid "No MISO Pin"
|
||||||
@ -2254,6 +2258,10 @@ msgid ""
|
|||||||
"To list built-in modules type `help(\"modules\")`.\n"
|
"To list built-in modules type `help(\"modules\")`.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: supervisor/shared/web_workflow/web_workflow.c
|
||||||
|
msgid "Wi-Fi: "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: main.c
|
#: main.c
|
||||||
msgid "Woken up by alarm.\n"
|
msgid "Woken up by alarm.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3579,6 +3587,10 @@ msgstr ""
|
|||||||
msgid "odd-length string"
|
msgid "odd-length string"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: supervisor/shared/web_workflow/web_workflow.c
|
||||||
|
msgid "off"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: extmod/ulab/code/numpy/create.c extmod/ulab/code/utils/utils.c
|
#: extmod/ulab/code/numpy/create.c extmod/ulab/code/utils/utils.c
|
||||||
msgid "offset is too large"
|
msgid "offset is too large"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
33
main.c
33
main.c
@ -101,6 +101,10 @@
|
|||||||
#include "shared-module/memorymonitor/__init__.h"
|
#include "shared-module/memorymonitor/__init__.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CIRCUITPY_SOCKETPOOL
|
||||||
|
#include "shared-bindings/socketpool/__init__.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
|
||||||
@ -290,6 +294,16 @@ STATIC void cleanup_after_vm(supervisor_allocation *heap, mp_obj_t exception) {
|
|||||||
keypad_reset();
|
keypad_reset();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Close user-initiated sockets.
|
||||||
|
#if CIRCUITPY_SOCKETPOOL
|
||||||
|
socketpool_user_reset();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Turn off user initiated WiFi connections.
|
||||||
|
#if CIRCUITPY_WIFI
|
||||||
|
wifi_user_reset();
|
||||||
|
#endif
|
||||||
|
|
||||||
// reset_board_buses() first because it may release pins from the never_reset state, so that
|
// reset_board_buses() first because it may release pins from the never_reset state, so that
|
||||||
// reset_port() can reset them.
|
// reset_port() can reset them.
|
||||||
#if CIRCUITPY_BOARD
|
#if CIRCUITPY_BOARD
|
||||||
@ -303,6 +317,9 @@ STATIC void cleanup_after_vm(supervisor_allocation *heap, mp_obj_t exception) {
|
|||||||
stop_mp();
|
stop_mp();
|
||||||
free_memory(heap);
|
free_memory(heap);
|
||||||
supervisor_move_memory();
|
supervisor_move_memory();
|
||||||
|
|
||||||
|
// Let the workflows know we've reset in case they want to restart.
|
||||||
|
supervisor_workflow_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
|
STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
|
||||||
@ -889,21 +906,7 @@ int __attribute__((used)) main(void) {
|
|||||||
|
|
||||||
run_boot_py(safe_mode);
|
run_boot_py(safe_mode);
|
||||||
|
|
||||||
// Start USB after giving boot.py a chance to tweak behavior.
|
supervisor_workflow_start();
|
||||||
#if CIRCUITPY_USB
|
|
||||||
// Setup USB connection after heap is available.
|
|
||||||
// It needs the heap to build descriptors.
|
|
||||||
usb_init();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Set up any other serial connection.
|
|
||||||
serial_init();
|
|
||||||
|
|
||||||
#if CIRCUITPY_BLEIO
|
|
||||||
bleio_reset();
|
|
||||||
supervisor_bluetooth_enable_workflow();
|
|
||||||
supervisor_start_bluetooth();
|
|
||||||
#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;
|
||||||
|
@ -117,6 +117,10 @@ void board_init(void) {
|
|||||||
true, // backlight_on_high
|
true, // backlight_on_high
|
||||||
false, // SH1107_addressing
|
false, // SH1107_addressing
|
||||||
50000); // backlight pwm frequency
|
50000); // backlight pwm frequency
|
||||||
|
|
||||||
|
#if CIRCUITPY_DEBUG
|
||||||
|
common_hal_never_reset_pin(DEFAULT_UART_BUS_TX);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool espressif_board_reset_pin_number(gpio_num_t pin_number) {
|
bool espressif_board_reset_pin_number(gpio_num_t pin_number) {
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
STATIC socketpool_socket_obj_t *open_socket_handles[CONFIG_LWIP_MAX_SOCKETS];
|
STATIC socketpool_socket_obj_t *open_socket_handles[CONFIG_LWIP_MAX_SOCKETS];
|
||||||
|
|
||||||
void socket_reset(void) {
|
void socket_user_reset(void) {
|
||||||
for (size_t i = 0; i < MP_ARRAY_SIZE(open_socket_handles); i++) {
|
for (size_t i = 0; i < MP_ARRAY_SIZE(open_socket_handles); i++) {
|
||||||
if (open_socket_handles[i]) {
|
if (open_socket_handles[i]) {
|
||||||
if (open_socket_handles[i]->num > 0) {
|
if (open_socket_handles[i]->num > 0) {
|
||||||
|
@ -45,7 +45,7 @@ typedef struct {
|
|||||||
mp_uint_t timeout_ms;
|
mp_uint_t timeout_ms;
|
||||||
} socketpool_socket_obj_t;
|
} socketpool_socket_obj_t;
|
||||||
|
|
||||||
void socket_reset(void);
|
void socket_user_reset(void);
|
||||||
bool register_open_socket(socketpool_socket_obj_t *self);
|
bool register_open_socket(socketpool_socket_obj_t *self);
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_SOCKETPOOL_SOCKET_H
|
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_SOCKETPOOL_SOCKET_H
|
||||||
|
@ -23,3 +23,11 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "shared-bindings/socketpool/__init__.h"
|
||||||
|
|
||||||
|
#include "common-hal/socketpool/Socket.h"
|
||||||
|
|
||||||
|
void socketpool_user_reset(void) {
|
||||||
|
socket_user_reset();
|
||||||
|
}
|
||||||
|
@ -236,6 +236,7 @@ wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t
|
|||||||
if (!common_hal_wifi_radio_get_enabled(self)) {
|
if (!common_hal_wifi_radio_get_enabled(self)) {
|
||||||
mp_raise_RuntimeError(translate("wifi is not enabled"));
|
mp_raise_RuntimeError(translate("wifi is not enabled"));
|
||||||
}
|
}
|
||||||
|
wifi_config_t *config = &self->sta_config;
|
||||||
|
|
||||||
EventBits_t bits;
|
EventBits_t bits;
|
||||||
// can't block since both bits are false after wifi_init
|
// can't block since both bits are false after wifi_init
|
||||||
@ -245,16 +246,31 @@ wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t
|
|||||||
pdTRUE,
|
pdTRUE,
|
||||||
pdTRUE,
|
pdTRUE,
|
||||||
0);
|
0);
|
||||||
if (((bits & WIFI_CONNECTED_BIT) != 0) &&
|
bool connected = ((bits & WIFI_CONNECTED_BIT) != 0) &&
|
||||||
!((bits & WIFI_DISCONNECTED_BIT) != 0)) {
|
!((bits & WIFI_DISCONNECTED_BIT) != 0);
|
||||||
|
if (connected) {
|
||||||
|
if (memcmp(ssid, config->sta.ssid, ssid_len) == 0) {
|
||||||
|
// Already connected to the desired network.
|
||||||
return WIFI_RADIO_ERROR_NONE;
|
return WIFI_RADIO_ERROR_NONE;
|
||||||
|
} else {
|
||||||
|
xEventGroupClearBits(self->event_group_handle, WIFI_DISCONNECTED_BIT);
|
||||||
|
// Trying to switch networks so disconnect first.
|
||||||
|
esp_wifi_disconnect();
|
||||||
|
do {
|
||||||
|
RUN_BACKGROUND_TASKS;
|
||||||
|
bits = xEventGroupWaitBits(self->event_group_handle,
|
||||||
|
WIFI_DISCONNECTED_BIT,
|
||||||
|
pdTRUE,
|
||||||
|
pdTRUE,
|
||||||
|
0);
|
||||||
|
} while ((bits & WIFI_DISCONNECTED_BIT) == 0 && !mp_hal_is_interrupted());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// explicitly clear bits since xEventGroupWaitBits may have timed out
|
// explicitly clear bits since xEventGroupWaitBits may have timed out
|
||||||
xEventGroupClearBits(self->event_group_handle, WIFI_CONNECTED_BIT);
|
xEventGroupClearBits(self->event_group_handle, WIFI_CONNECTED_BIT);
|
||||||
xEventGroupClearBits(self->event_group_handle, WIFI_DISCONNECTED_BIT);
|
xEventGroupClearBits(self->event_group_handle, WIFI_DISCONNECTED_BIT);
|
||||||
set_mode_station(self, true);
|
set_mode_station(self, true);
|
||||||
|
|
||||||
wifi_config_t *config = &self->sta_config;
|
|
||||||
memcpy(&config->sta.ssid, ssid, ssid_len);
|
memcpy(&config->sta.ssid, ssid, ssid_len);
|
||||||
config->sta.ssid[ssid_len] = 0;
|
config->sta.ssid[ssid_len] = 0;
|
||||||
memcpy(&config->sta.password, password, password_len);
|
memcpy(&config->sta.password, password, password_len);
|
||||||
@ -368,6 +384,14 @@ mp_obj_t common_hal_wifi_radio_get_ipv4_subnet_ap(wifi_radio_obj_t *self) {
|
|||||||
return common_hal_ipaddress_new_ipv4address(self->ap_ip_info.netmask.addr);
|
return common_hal_ipaddress_new_ipv4address(self->ap_ip_info.netmask.addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t wifi_radio_get_ipv4_address(wifi_radio_obj_t *self) {
|
||||||
|
if (!esp_netif_is_netif_up(self->netif)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
esp_netif_get_ip_info(self->netif, &self->ip_info);
|
||||||
|
return self->ip_info.ip.addr;
|
||||||
|
}
|
||||||
|
|
||||||
mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self) {
|
mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self) {
|
||||||
if (!esp_netif_is_netif_up(self->netif)) {
|
if (!esp_netif_is_netif_up(self->netif)) {
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
|
@ -42,6 +42,8 @@ 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/workflow.h"
|
||||||
|
|
||||||
static const char *TAG = "wifi";
|
static const char *TAG = "wifi";
|
||||||
|
|
||||||
static void event_handler(void *arg, esp_event_base_t event_base,
|
static void event_handler(void *arg, esp_event_base_t event_base,
|
||||||
@ -106,12 +108,19 @@ static void event_handler(void *arg, esp_event_base_t event_base,
|
|||||||
radio->retries_left = radio->starting_retries;
|
radio->retries_left = radio->starting_retries;
|
||||||
xEventGroupSetBits(radio->event_group_handle, WIFI_CONNECTED_BIT);
|
xEventGroupSetBits(radio->event_group_handle, WIFI_CONNECTED_BIT);
|
||||||
}
|
}
|
||||||
|
supervisor_workflow_request_background();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool wifi_inited, wifi_ever_inited;
|
static bool wifi_inited;
|
||||||
|
static bool wifi_ever_inited;
|
||||||
|
static bool wifi_user_initiated;
|
||||||
|
|
||||||
void common_hal_wifi_init(void) {
|
void common_hal_wifi_init(bool user_initiated) {
|
||||||
|
if (wifi_inited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
wifi_inited = true;
|
wifi_inited = true;
|
||||||
|
wifi_user_initiated = user_initiated;
|
||||||
common_hal_wifi_radio_obj.base.type = &wifi_radio_type;
|
common_hal_wifi_radio_obj.base.type = &wifi_radio_type;
|
||||||
|
|
||||||
if (!wifi_ever_inited) {
|
if (!wifi_ever_inited) {
|
||||||
@ -157,6 +166,12 @@ void common_hal_wifi_init(void) {
|
|||||||
common_hal_wifi_radio_set_enabled(self, true);
|
common_hal_wifi_radio_set_enabled(self, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wifi_user_reset(void) {
|
||||||
|
if (wifi_user_initiated) {
|
||||||
|
wifi_reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wifi_reset(void) {
|
void wifi_reset(void) {
|
||||||
if (!wifi_inited) {
|
if (!wifi_inited) {
|
||||||
return;
|
return;
|
||||||
@ -176,6 +191,7 @@ void wifi_reset(void) {
|
|||||||
esp_netif_destroy(radio->ap_netif);
|
esp_netif_destroy(radio->ap_netif);
|
||||||
radio->ap_netif = NULL;
|
radio->ap_netif = NULL;
|
||||||
wifi_inited = false;
|
wifi_inited = false;
|
||||||
|
supervisor_workflow_request_background();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_address) {
|
void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_address) {
|
||||||
|
@ -282,14 +282,6 @@ void reset_port(void) {
|
|||||||
#if CIRCUITPY_WATCHDOG
|
#if CIRCUITPY_WATCHDOG
|
||||||
watchdog_reset();
|
watchdog_reset();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CIRCUITPY_WIFI
|
|
||||||
wifi_reset();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CIRCUITPY_SOCKETPOOL
|
|
||||||
socket_reset();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_to_bootloader(void) {
|
void reset_to_bootloader(void) {
|
||||||
|
@ -70,7 +70,9 @@ endif
|
|||||||
CIRCUITPY_LTO ?= 0
|
CIRCUITPY_LTO ?= 0
|
||||||
CIRCUITPY_LTO_PARTITION ?= balanced
|
CIRCUITPY_LTO_PARTITION ?= balanced
|
||||||
ifeq ($(CIRCUITPY_LTO),1)
|
ifeq ($(CIRCUITPY_LTO),1)
|
||||||
CFLAGS += -flto -flto-partition=$(CIRCUITPY_LTO_PARTITION)
|
CFLAGS += -flto -flto-partition=$(CIRCUITPY_LTO_PARTITION) -DCIRCUITPY_LTO=1
|
||||||
|
else
|
||||||
|
CFLAGS += -DCIRCUITPY_LTO=0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Produce an object file for translate.c instead of including it in a header.
|
# Produce an object file for translate.c instead of including it in a header.
|
||||||
|
@ -480,6 +480,9 @@ CFLAGS += -DCIRCUITPY_WATCHDOG=$(CIRCUITPY_WATCHDOG)
|
|||||||
CIRCUITPY_WIFI ?= 0
|
CIRCUITPY_WIFI ?= 0
|
||||||
CFLAGS += -DCIRCUITPY_WIFI=$(CIRCUITPY_WIFI)
|
CFLAGS += -DCIRCUITPY_WIFI=$(CIRCUITPY_WIFI)
|
||||||
|
|
||||||
|
CIRCUITPY_WEB_WORKFLOW ?= $(CIRCUITPY_WIFI)
|
||||||
|
CFLAGS += -DCIRCUITPY_WEB_WORKFLOW=$(CIRCUITPY_WEB_WORKFLOW)
|
||||||
|
|
||||||
# tinyusb port tailored configuration
|
# tinyusb port tailored configuration
|
||||||
CIRCUITPY_TUSB_MEM_ALIGN ?= 4
|
CIRCUITPY_TUSB_MEM_ALIGN ?= 4
|
||||||
CFLAGS += -DCIRCUITPY_TUSB_MEM_ALIGN=$(CIRCUITPY_TUSB_MEM_ALIGN)
|
CFLAGS += -DCIRCUITPY_TUSB_MEM_ALIGN=$(CIRCUITPY_TUSB_MEM_ALIGN)
|
||||||
|
@ -69,5 +69,6 @@ void common_hal_displayio_tilegrid_set_tile(displayio_tilegrid_t *self, uint16_t
|
|||||||
|
|
||||||
// Private API for scrolling the TileGrid.
|
// Private API for scrolling the TileGrid.
|
||||||
void common_hal_displayio_tilegrid_set_top_left(displayio_tilegrid_t *self, uint16_t x, uint16_t y);
|
void common_hal_displayio_tilegrid_set_top_left(displayio_tilegrid_t *self, uint16_t x, uint16_t y);
|
||||||
|
void common_hal_displayio_tilegrid_set_all_tiles(displayio_tilegrid_t *self, uint8_t tile_index);
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_TILEGRID_H
|
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_TILEGRID_H
|
||||||
|
@ -27,4 +27,6 @@
|
|||||||
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_SOCKETPOOL___INIT___H
|
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_SOCKETPOOL___INIT___H
|
||||||
#define MICROPY_INCLUDED_SHARED_BINDINGS_SOCKETPOOL___INIT___H
|
#define MICROPY_INCLUDED_SHARED_BINDINGS_SOCKETPOOL___INIT___H
|
||||||
|
|
||||||
|
void socketpool_user_reset(void);
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SOCKETPOOL___INIT___H
|
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SOCKETPOOL___INIT___H
|
||||||
|
@ -38,31 +38,52 @@
|
|||||||
#include "supervisor/shared/translate/translate.h"
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
|
||||||
//| class Terminal:
|
//| class Terminal:
|
||||||
//| """Display a character stream with a TileGrid"""
|
//| """Display a character stream with a TileGrid
|
||||||
//|
|
//|
|
||||||
//| def __init__(self, tilegrid: displayio.TileGrid, font: fontio.BuiltinFont) -> None:
|
//| ASCII control:
|
||||||
|
//| * ``\\r`` - Move cursor to column 1
|
||||||
|
//| * ``\\n`` - Move cursor down a row
|
||||||
|
//| * ``\\b`` - Move cursor left one if possible
|
||||||
|
//|
|
||||||
|
//| OSC control sequences:
|
||||||
|
//| * ``ESC ] 0; <s> ESC \\`` - Set title bar to <s>
|
||||||
|
//| * ``ESC ] ####; <s> ESC \\`` - Ignored
|
||||||
|
//|
|
||||||
|
//| VT100 control sequences:
|
||||||
|
//| * ``ESC [ K`` - Clear the remainder of the line
|
||||||
|
//| * ``ESC [ #### D`` - Move the cursor to the left by ####
|
||||||
|
//| * ``ESC [ 2 J`` - Erase the entire display
|
||||||
|
//| * ``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:
|
||||||
//| """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_tilegrid, ARG_font };
|
enum { ARG_scroll_area, ARG_font, ARG_title_bar };
|
||||||
static const mp_arg_t allowed_args[] = {
|
static const mp_arg_t allowed_args[] = {
|
||||||
{ MP_QSTR_tilegrid, 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_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 *tilegrid = mp_arg_validate_type(args[ARG_tilegrid].u_obj, &displayio_tilegrid_type, MP_QSTR_tilegrid);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
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, tilegrid, font);
|
common_hal_terminalio_terminal_construct(self, scroll_area, font, title_bar);
|
||||||
return MP_OBJ_FROM_PTR(self);
|
return MP_OBJ_FROM_PTR(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 *tilegrid, const fontio_builtinfont_t *font);
|
displayio_tilegrid_t *scroll_area, const fontio_builtinfont_t *font, displayio_tilegrid_t *title_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,
|
||||||
|
@ -439,11 +439,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_set_ipv4_address_obj, 1, wifi_radio
|
|||||||
//| ipv4_address: Optional[ipaddress.IPv4Address]
|
//| ipv4_address: Optional[ipaddress.IPv4Address]
|
||||||
//| """IP v4 Address of the station when connected to an access point. None otherwise."""
|
//| """IP v4 Address of the station when connected to an access point. None otherwise."""
|
||||||
//|
|
//|
|
||||||
STATIC mp_obj_t wifi_radio_get_ipv4_address(mp_obj_t self) {
|
STATIC mp_obj_t _wifi_radio_get_ipv4_address(mp_obj_t self) {
|
||||||
return common_hal_wifi_radio_get_ipv4_address(self);
|
return common_hal_wifi_radio_get_ipv4_address(self);
|
||||||
|
|
||||||
}
|
}
|
||||||
MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_address_obj, wifi_radio_get_ipv4_address);
|
MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_address_obj, _wifi_radio_get_ipv4_address);
|
||||||
|
|
||||||
MP_PROPERTY_GETTER(wifi_radio_ipv4_address_obj,
|
MP_PROPERTY_GETTER(wifi_radio_ipv4_address_obj,
|
||||||
(mp_obj_t)&wifi_radio_get_ipv4_address_obj);
|
(mp_obj_t)&wifi_radio_get_ipv4_address_obj);
|
||||||
|
@ -103,6 +103,7 @@ extern mp_obj_t common_hal_wifi_radio_get_ipv4_gateway(wifi_radio_obj_t *self);
|
|||||||
extern mp_obj_t common_hal_wifi_radio_get_ipv4_gateway_ap(wifi_radio_obj_t *self);
|
extern mp_obj_t common_hal_wifi_radio_get_ipv4_gateway_ap(wifi_radio_obj_t *self);
|
||||||
extern mp_obj_t common_hal_wifi_radio_get_ipv4_subnet(wifi_radio_obj_t *self);
|
extern mp_obj_t common_hal_wifi_radio_get_ipv4_subnet(wifi_radio_obj_t *self);
|
||||||
extern mp_obj_t common_hal_wifi_radio_get_ipv4_subnet_ap(wifi_radio_obj_t *self);
|
extern mp_obj_t common_hal_wifi_radio_get_ipv4_subnet_ap(wifi_radio_obj_t *self);
|
||||||
|
uint32_t wifi_radio_get_ipv4_address(wifi_radio_obj_t *self);
|
||||||
extern mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self);
|
extern mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self);
|
||||||
extern mp_obj_t common_hal_wifi_radio_get_ipv4_address_ap(wifi_radio_obj_t *self);
|
extern mp_obj_t common_hal_wifi_radio_get_ipv4_address_ap(wifi_radio_obj_t *self);
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
// Called when wifi is imported.
|
// Called when wifi is imported.
|
||||||
STATIC mp_obj_t wifi___init__(void) {
|
STATIC mp_obj_t wifi___init__(void) {
|
||||||
common_hal_wifi_init();
|
common_hal_wifi_init(true);
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(wifi___init___obj, wifi___init__);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_0(wifi___init___obj, wifi___init__);
|
||||||
|
@ -31,7 +31,9 @@
|
|||||||
|
|
||||||
extern wifi_radio_obj_t common_hal_wifi_radio_obj;
|
extern wifi_radio_obj_t common_hal_wifi_radio_obj;
|
||||||
|
|
||||||
void common_hal_wifi_init(void);
|
void common_hal_wifi_init(bool user_initiated);
|
||||||
void common_hal_wifi_gc_collect(void);
|
void common_hal_wifi_gc_collect(void);
|
||||||
|
|
||||||
|
void wifi_user_reset(void);
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_WIFI___INIT___H
|
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_WIFI___INIT___H
|
||||||
|
@ -296,6 +296,27 @@ void common_hal_displayio_tilegrid_set_tile(displayio_tilegrid_t *self, uint16_t
|
|||||||
self->partial_change = true;
|
self->partial_change = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void common_hal_displayio_tilegrid_set_all_tiles(displayio_tilegrid_t *self, uint8_t tile_index) {
|
||||||
|
if (tile_index >= self->tiles_in_bitmap) {
|
||||||
|
mp_raise_ValueError(translate("Tile index out of bounds"));
|
||||||
|
}
|
||||||
|
uint8_t *tiles = self->tiles;
|
||||||
|
if (self->inline_tiles) {
|
||||||
|
tiles = (uint8_t *)&self->tiles;
|
||||||
|
}
|
||||||
|
if (tiles == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint16_t x = 0; x < self->width_in_tiles; x++) {
|
||||||
|
for (uint16_t y = 0; y < self->height_in_tiles; y++) {
|
||||||
|
tiles[y * self->width_in_tiles + x] = tile_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self->full_change = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool common_hal_displayio_tilegrid_get_flip_x(displayio_tilegrid_t *self) {
|
bool common_hal_displayio_tilegrid_get_flip_x(displayio_tilegrid_t *self) {
|
||||||
return self->flip_x;
|
return self->flip_x;
|
||||||
}
|
}
|
||||||
|
@ -30,24 +30,28 @@
|
|||||||
#include "shared-bindings/displayio/TileGrid.h"
|
#include "shared-bindings/displayio/TileGrid.h"
|
||||||
#include "shared-bindings/terminalio/Terminal.h"
|
#include "shared-bindings/terminalio/Terminal.h"
|
||||||
|
|
||||||
void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self, displayio_tilegrid_t *tilegrid, const fontio_builtinfont_t *font) {
|
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) {
|
||||||
self->cursor_x = 0;
|
self->cursor_x = 0;
|
||||||
self->cursor_y = 0;
|
self->cursor_y = 0;
|
||||||
self->font = font;
|
self->font = font;
|
||||||
self->tilegrid = tilegrid;
|
self->scroll_area = scroll_area;
|
||||||
|
self->title_bar = title_bar;
|
||||||
|
self->title_x = 0;
|
||||||
|
self->title_y = 0;
|
||||||
self->first_row = 0;
|
self->first_row = 0;
|
||||||
for (uint16_t x = 0; x < self->tilegrid->width_in_tiles; x++) {
|
common_hal_displayio_tilegrid_set_all_tiles(self->scroll_area, 0);
|
||||||
for (uint16_t y = 0; y < self->tilegrid->height_in_tiles; y++) {
|
if (self->title_bar) {
|
||||||
common_hal_displayio_tilegrid_set_tile(self->tilegrid, x, y, 0);
|
common_hal_displayio_tilegrid_set_all_tiles(self->title_bar, 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
common_hal_displayio_tilegrid_set_top_left(self->tilegrid, 0, 1);
|
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, const byte *data, size_t len, int *errcode) {
|
size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, const byte *data, size_t len, int *errcode) {
|
||||||
// Make sure the terminal is initialized before we do anything with it.
|
// Make sure the terminal is initialized before we do anything with it.
|
||||||
if (self->tilegrid == NULL) {
|
if (self->scroll_area == NULL) {
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
const byte *i = data;
|
const byte *i = data;
|
||||||
@ -55,11 +59,34 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
|
|||||||
while (i < data + len) {
|
while (i < data + len) {
|
||||||
unichar c = utf8_get_char(i);
|
unichar c = utf8_get_char(i);
|
||||||
i = utf8_next_char(i);
|
i = utf8_next_char(i);
|
||||||
|
if (self->in_osc_command) {
|
||||||
|
if (c == 0x1b && i[0] == '\\') {
|
||||||
|
self->in_osc_command = false;
|
||||||
|
self->title_x = 0;
|
||||||
|
self->title_y = 0;
|
||||||
|
i += 1;
|
||||||
|
} else if (self->osc_command == 0 && self->title_bar != NULL && self->title_y < self->title_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);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// Always handle ASCII.
|
// Always handle ASCII.
|
||||||
if (c < 128) {
|
if (c < 128) {
|
||||||
if (c >= 0x20 && c <= 0x7e) {
|
if (c >= 0x20 && c <= 0x7e) {
|
||||||
uint8_t tile_index = fontio_builtinfont_get_glyph_index(self->font, c);
|
uint8_t tile_index = fontio_builtinfont_get_glyph_index(self->font, c);
|
||||||
common_hal_displayio_tilegrid_set_tile(self->tilegrid, self->cursor_x, self->cursor_y, tile_index);
|
common_hal_displayio_tilegrid_set_tile(self->scroll_area, self->cursor_x, self->cursor_y, tile_index);
|
||||||
self->cursor_x++;
|
self->cursor_x++;
|
||||||
} else if (c == '\r') {
|
} else if (c == '\r') {
|
||||||
self->cursor_x = 0;
|
self->cursor_x = 0;
|
||||||
@ -71,15 +98,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) {
|
||||||
if (i[0] == '[') {
|
// Handle commands of the form \x1b.####D where . is ignored.
|
||||||
if (i[1] == 'K') {
|
|
||||||
// Clear the rest of the line.
|
|
||||||
for (uint16_t j = self->cursor_x; j < self->tilegrid->width_in_tiles; j++) {
|
|
||||||
common_hal_displayio_tilegrid_set_tile(self->tilegrid, j, self->cursor_y, 0);
|
|
||||||
}
|
|
||||||
i += 2;
|
|
||||||
} else {
|
|
||||||
// Handle commands of the form \x1b[####D
|
|
||||||
uint16_t n = 0;
|
uint16_t n = 0;
|
||||||
uint8_t j = 1;
|
uint8_t j = 1;
|
||||||
for (; j < 6; j++) {
|
for (; j < 6; j++) {
|
||||||
@ -90,6 +109,14 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (i[0] == '[') {
|
||||||
|
if (i[1] == 'K') {
|
||||||
|
// Clear the rest of the line.
|
||||||
|
for (uint16_t k = self->cursor_x; k < self->scroll_area->width_in_tiles; k++) {
|
||||||
|
common_hal_displayio_tilegrid_set_tile(self->scroll_area, k, self->cursor_y, 0);
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
} else {
|
||||||
if (c == 'D') {
|
if (c == 'D') {
|
||||||
if (n > self->cursor_x) {
|
if (n > self->cursor_x) {
|
||||||
self->cursor_x = 0;
|
self->cursor_x = 0;
|
||||||
@ -99,14 +126,10 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
|
|||||||
}
|
}
|
||||||
if (c == 'J') {
|
if (c == 'J') {
|
||||||
if (n == 2) {
|
if (n == 2) {
|
||||||
common_hal_displayio_tilegrid_set_top_left(self->tilegrid, 0, 0);
|
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, 0);
|
||||||
self->cursor_x = self->cursor_y = start_y = 0;
|
self->cursor_x = self->cursor_y = start_y = 0;
|
||||||
n = 0;
|
n = 0;
|
||||||
for (uint16_t x = 0; x < self->tilegrid->width_in_tiles; x++) {
|
common_hal_displayio_tilegrid_set_all_tiles(self->scroll_area, 0);
|
||||||
for (uint16_t y = 0; y < self->tilegrid->height_in_tiles; y++) {
|
|
||||||
common_hal_displayio_tilegrid_set_tile(self->tilegrid, x, y, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c == ';') {
|
if (c == ';') {
|
||||||
@ -126,13 +149,13 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
|
|||||||
if (m > 0) {
|
if (m > 0) {
|
||||||
m--;
|
m--;
|
||||||
}
|
}
|
||||||
if (n >= self->tilegrid->height_in_tiles) {
|
if (n >= self->scroll_area->height_in_tiles) {
|
||||||
n = self->tilegrid->height_in_tiles - 1;
|
n = self->scroll_area->height_in_tiles - 1;
|
||||||
}
|
}
|
||||||
if (m >= self->tilegrid->width_in_tiles) {
|
if (m >= self->scroll_area->width_in_tiles) {
|
||||||
m = self->tilegrid->width_in_tiles - 1;
|
m = self->scroll_area->width_in_tiles - 1;
|
||||||
}
|
}
|
||||||
n = (n + self->tilegrid->top_left_y) % self->tilegrid->height_in_tiles;
|
n = (n + self->scroll_area->top_left_y) % self->scroll_area->height_in_tiles;
|
||||||
self->cursor_x = m;
|
self->cursor_x = m;
|
||||||
self->cursor_y = n;
|
self->cursor_y = n;
|
||||||
start_y = self->cursor_y;
|
start_y = self->cursor_y;
|
||||||
@ -141,30 +164,34 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
|
|||||||
i += j + 1;
|
i += j + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
} else if (i[0] == ']' && c == ';') {
|
||||||
|
self->in_osc_command = true;
|
||||||
|
self->osc_command = n;
|
||||||
|
i += j + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
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) {
|
||||||
common_hal_displayio_tilegrid_set_tile(self->tilegrid, self->cursor_x, self->cursor_y, tile_index);
|
common_hal_displayio_tilegrid_set_tile(self->scroll_area, self->cursor_x, self->cursor_y, tile_index);
|
||||||
self->cursor_x++;
|
self->cursor_x++;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (self->cursor_x >= self->tilegrid->width_in_tiles) {
|
if (self->cursor_x >= self->scroll_area->width_in_tiles) {
|
||||||
self->cursor_y++;
|
self->cursor_y++;
|
||||||
self->cursor_x %= self->tilegrid->width_in_tiles;
|
self->cursor_x %= self->scroll_area->width_in_tiles;
|
||||||
}
|
}
|
||||||
if (self->cursor_y >= self->tilegrid->height_in_tiles) {
|
if (self->cursor_y >= self->scroll_area->height_in_tiles) {
|
||||||
self->cursor_y %= self->tilegrid->height_in_tiles;
|
self->cursor_y %= self->scroll_area->height_in_tiles;
|
||||||
}
|
}
|
||||||
if (self->cursor_y != start_y) {
|
if (self->cursor_y != start_y) {
|
||||||
// clear the new row in case of scroll up
|
// clear the new row in case of scroll up
|
||||||
if (self->cursor_y == self->tilegrid->top_left_y) {
|
if (self->cursor_y == self->scroll_area->top_left_y) {
|
||||||
for (uint16_t j = 0; j < self->tilegrid->width_in_tiles; j++) {
|
for (uint16_t j = 0; j < self->scroll_area->width_in_tiles; j++) {
|
||||||
common_hal_displayio_tilegrid_set_tile(self->tilegrid, j, self->cursor_y, 0);
|
common_hal_displayio_tilegrid_set_tile(self->scroll_area, j, self->cursor_y, 0);
|
||||||
}
|
}
|
||||||
common_hal_displayio_tilegrid_set_top_left(self->tilegrid, 0, (self->cursor_y + self->tilegrid->height_in_tiles + 1) % self->tilegrid->height_in_tiles);
|
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, (self->cursor_y + self->scroll_area->height_in_tiles + 1) % self->scroll_area->height_in_tiles);
|
||||||
}
|
}
|
||||||
start_y = self->cursor_y;
|
start_y = self->cursor_y;
|
||||||
}
|
}
|
||||||
@ -173,5 +200,5 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool common_hal_terminalio_terminal_ready_to_tx(terminalio_terminal_obj_t *self) {
|
bool common_hal_terminalio_terminal_ready_to_tx(terminalio_terminal_obj_t *self) {
|
||||||
return self->tilegrid != NULL;
|
return self->scroll_area != NULL;
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,13 @@ typedef struct {
|
|||||||
const fontio_builtinfont_t *font;
|
const fontio_builtinfont_t *font;
|
||||||
uint16_t cursor_x;
|
uint16_t cursor_x;
|
||||||
uint16_t cursor_y;
|
uint16_t cursor_y;
|
||||||
displayio_tilegrid_t *tilegrid;
|
displayio_tilegrid_t *scroll_area;
|
||||||
|
displayio_tilegrid_t *title_bar;
|
||||||
|
uint16_t title_x;
|
||||||
|
uint16_t title_y;
|
||||||
uint16_t first_row;
|
uint16_t first_row;
|
||||||
|
uint16_t osc_command;
|
||||||
|
bool in_osc_command;
|
||||||
} terminalio_terminal_obj_t;
|
} terminalio_terminal_obj_t;
|
||||||
|
|
||||||
#endif /* SHARED_MODULE_TERMINALIO_TERMINAL_H */
|
#endif /* SHARED_MODULE_TERMINALIO_TERMINAL_H */
|
||||||
|
@ -111,16 +111,28 @@ void background_callback_end_critical_section() {
|
|||||||
CALLBACK_CRITICAL_END;
|
CALLBACK_CRITICAL_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Filter out queued callbacks if they are allocated on the heap.
|
||||||
void background_callback_reset() {
|
void background_callback_reset() {
|
||||||
|
background_callback_t *new_head = NULL;
|
||||||
|
background_callback_t **previous_next = &new_head;
|
||||||
|
background_callback_t *new_tail = NULL;
|
||||||
CALLBACK_CRITICAL_BEGIN;
|
CALLBACK_CRITICAL_BEGIN;
|
||||||
background_callback_t *cb = (background_callback_t *)callback_head;
|
background_callback_t *cb = (background_callback_t *)callback_head;
|
||||||
while (cb) {
|
while (cb) {
|
||||||
background_callback_t *next = cb->next;
|
background_callback_t *next = cb->next;
|
||||||
|
if (!HEAP_PTR((void *)cb)) {
|
||||||
|
*previous_next = cb;
|
||||||
|
previous_next = &cb->next;
|
||||||
|
cb->next = NULL;
|
||||||
|
new_tail = cb;
|
||||||
|
} else {
|
||||||
memset(cb, 0, sizeof(*cb));
|
memset(cb, 0, sizeof(*cb));
|
||||||
|
}
|
||||||
cb = next;
|
cb = next;
|
||||||
}
|
}
|
||||||
callback_head = NULL;
|
callback_head = new_head;
|
||||||
callback_tail = NULL;
|
callback_tail = new_tail;
|
||||||
in_background_callback = false;
|
in_background_callback = false;
|
||||||
CALLBACK_CRITICAL_END;
|
CALLBACK_CRITICAL_END;
|
||||||
}
|
}
|
||||||
|
@ -61,37 +61,26 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) {
|
|||||||
uint8_t scale = 2;
|
uint8_t scale = 2;
|
||||||
|
|
||||||
#if CIRCUITPY_TERMINALIO
|
#if CIRCUITPY_TERMINALIO
|
||||||
displayio_tilegrid_t *grid = &supervisor_terminal_text_grid;
|
displayio_tilegrid_t *scroll_area = &supervisor_terminal_scroll_area_text_grid;
|
||||||
bool tall = height_px > width_px;
|
displayio_tilegrid_t *title_bar = &supervisor_terminal_title_bar_text_grid;
|
||||||
bool reset_tiles = false;
|
bool reset_tiles = false;
|
||||||
#if CIRCUITPY_REPL_LOGO
|
uint16_t width_in_tiles = width_px / scroll_area->tile_width;
|
||||||
uint16_t terminal_width_px = tall ? width_px : width_px - blinka_bitmap.width;
|
|
||||||
uint16_t terminal_height_px = tall ? height_px - blinka_bitmap.height : height_px;
|
|
||||||
#else
|
|
||||||
uint16_t terminal_width_px = width_px;
|
|
||||||
uint16_t terminal_height_px = height_px;
|
|
||||||
#endif
|
|
||||||
uint16_t width_in_tiles = terminal_width_px / grid->tile_width;
|
|
||||||
// determine scale based on h
|
// determine scale based on h
|
||||||
if (width_in_tiles < 80) {
|
if (width_in_tiles < 80) {
|
||||||
scale = 1;
|
scale = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
width_in_tiles = terminal_width_px / (grid->tile_width * scale);
|
width_in_tiles = width_px / (scroll_area->tile_width * scale);
|
||||||
if (width_in_tiles < 1) {
|
if (width_in_tiles < 1) {
|
||||||
width_in_tiles = 1;
|
width_in_tiles = 1;
|
||||||
}
|
}
|
||||||
uint16_t height_in_tiles = terminal_height_px / (grid->tile_height * scale);
|
uint16_t height_in_tiles = height_px / (scroll_area->tile_height * scale);
|
||||||
uint16_t remaining_pixels = tall ? 0 : terminal_height_px % (grid->tile_height * scale);
|
|
||||||
if (height_in_tiles < 1 || remaining_pixels > 0) {
|
|
||||||
height_in_tiles += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t total_tiles = width_in_tiles * height_in_tiles;
|
uint16_t total_tiles = width_in_tiles * height_in_tiles;
|
||||||
|
|
||||||
// check if the terminal tile dimensions are the same
|
// check if the terminal tile dimensions are the same
|
||||||
if ((grid->width_in_tiles != width_in_tiles) ||
|
if ((scroll_area->width_in_tiles != width_in_tiles) ||
|
||||||
(grid->height_in_tiles != height_in_tiles)) {
|
(scroll_area->height_in_tiles != height_in_tiles - 1)) {
|
||||||
reset_tiles = true;
|
reset_tiles = true;
|
||||||
}
|
}
|
||||||
// Reuse the previous allocation if possible
|
// Reuse the previous allocation if possible
|
||||||
@ -114,27 +103,39 @@ 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
|
||||||
grid->y = tall ? blinka_bitmap.height : 0;
|
title_bar->x = blinka_bitmap.width;
|
||||||
grid->x = tall ? 0 : blinka_bitmap.width;
|
// Align the title bar to the bottom of the logo.
|
||||||
|
title_bar->y = blinka_bitmap.height - title_bar->tile_height;
|
||||||
#else
|
#else
|
||||||
grid->y = 0;
|
title_bar->x = 0;
|
||||||
grid->x = 0;
|
title_bar->y = 0;
|
||||||
#endif
|
#endif
|
||||||
grid->top_left_y = 0;
|
title_bar->top_left_y = 0;
|
||||||
if (remaining_pixels > 0) {
|
title_bar->width_in_tiles = width_in_tiles;
|
||||||
grid->y -= (grid->tile_height - remaining_pixels);
|
title_bar->height_in_tiles = 1;
|
||||||
}
|
|
||||||
grid->width_in_tiles = width_in_tiles;
|
|
||||||
grid->height_in_tiles = height_in_tiles;
|
|
||||||
assert(width_in_tiles > 0);
|
assert(width_in_tiles > 0);
|
||||||
assert(height_in_tiles > 0);
|
title_bar->pixel_width = width_in_tiles * title_bar->tile_width;
|
||||||
grid->pixel_width = width_in_tiles * grid->tile_width;
|
title_bar->pixel_height = title_bar->tile_height;
|
||||||
grid->pixel_height = height_in_tiles * grid->tile_height;
|
title_bar->tiles = tiles;
|
||||||
grid->tiles = tiles;
|
title_bar->full_change = true;
|
||||||
|
|
||||||
grid->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;
|
||||||
|
assert(width_in_tiles > 0);
|
||||||
|
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;
|
||||||
|
scroll_area->tiles = tiles + width_in_tiles;
|
||||||
|
scroll_area->full_change = true;
|
||||||
|
|
||||||
common_hal_terminalio_terminal_construct(&supervisor_terminal, grid, &supervisor_terminal_font);
|
common_hal_terminalio_terminal_construct(&supervisor_terminal, scroll_area, &supervisor_terminal_font, title_bar);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -146,18 +147,24 @@ void supervisor_stop_terminal(void) {
|
|||||||
if (tilegrid_tiles != NULL) {
|
if (tilegrid_tiles != NULL) {
|
||||||
free_memory(tilegrid_tiles);
|
free_memory(tilegrid_tiles);
|
||||||
tilegrid_tiles = NULL;
|
tilegrid_tiles = NULL;
|
||||||
supervisor_terminal_text_grid.tiles = NULL;
|
supervisor_terminal_scroll_area_text_grid.tiles = NULL;
|
||||||
supervisor_terminal.tilegrid = NULL;
|
supervisor_terminal_title_bar_text_grid.tiles = NULL;
|
||||||
|
supervisor_terminal.scroll_area = NULL;
|
||||||
|
supervisor_terminal.title_bar = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
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 *title_bar = &supervisor_terminal_title_bar_text_grid;
|
||||||
if (tilegrid_tiles != NULL) {
|
if (tilegrid_tiles != NULL) {
|
||||||
supervisor_terminal_text_grid.tiles = (uint8_t *)tilegrid_tiles->ptr;
|
title_bar->tiles = (uint8_t *)tilegrid_tiles->ptr;
|
||||||
|
scroll_area->tiles = (uint8_t *)tilegrid_tiles->ptr + scroll_area->width_in_tiles;
|
||||||
} else {
|
} else {
|
||||||
supervisor_terminal_text_grid.tiles = NULL;
|
scroll_area->tiles = NULL;
|
||||||
|
title_bar->tiles = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -298,21 +305,21 @@ displayio_tilegrid_t blinka_sprite = {
|
|||||||
|
|
||||||
#if CIRCUITPY_TERMINALIO
|
#if CIRCUITPY_TERMINALIO
|
||||||
#if CIRCUITPY_REPL_LOGO
|
#if CIRCUITPY_REPL_LOGO
|
||||||
mp_obj_t members[] = { &blinka_sprite, &supervisor_terminal_text_grid, };
|
mp_obj_t members[] = { &blinka_sprite, &supervisor_terminal_title_bar_text_grid, &supervisor_terminal_scroll_area_text_grid, };
|
||||||
|
mp_obj_list_t splash_children = {
|
||||||
|
.base = {.type = &mp_type_list },
|
||||||
|
.alloc = 3,
|
||||||
|
.len = 3,
|
||||||
|
.items = members,
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
mp_obj_t members[] = { &supervisor_terminal_title_bar_text_grid, &supervisor_terminal_scroll_area_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,
|
||||||
.len = 2,
|
.len = 2,
|
||||||
.items = members,
|
.items = members,
|
||||||
};
|
};
|
||||||
#else
|
|
||||||
mp_obj_t members[] = { &supervisor_terminal_text_grid, };
|
|
||||||
mp_obj_list_t splash_children = {
|
|
||||||
.base = {.type = &mp_type_list },
|
|
||||||
.alloc = 1,
|
|
||||||
.len = 1,
|
|
||||||
.items = members,
|
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#if CIRCUITPY_REPL_LOGO
|
#if CIRCUITPY_REPL_LOGO
|
||||||
|
@ -43,7 +43,8 @@ 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_text_grid;
|
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;
|
extern terminalio_terminal_obj_t supervisor_terminal;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,7 +45,7 @@ static
|
|||||||
#endif
|
#endif
|
||||||
inline
|
inline
|
||||||
// gcc10 -flto has issues with this being always_inline for debug builds.
|
// gcc10 -flto has issues with this being always_inline for debug builds.
|
||||||
#if CIRCUITPY_DEBUG < 1
|
#if !CIRCUITPY_LTO || CIRCUITPY_DEBUG < 1
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
#endif
|
#endif
|
||||||
const compressed_string_t *translate(const char *original) {
|
const compressed_string_t *translate(const char *original) {
|
||||||
|
92
supervisor/shared/web_workflow/web_workflow.c
Normal file
92
supervisor/shared/web_workflow/web_workflow.c
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Scott Shawcroft 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 <string.h>
|
||||||
|
|
||||||
|
#include "shared-bindings/wifi/Radio.h"
|
||||||
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
#include "supervisor/shared/web_workflow/web_workflow.h"
|
||||||
|
|
||||||
|
#if CIRCUITPY_WIFI
|
||||||
|
#include "shared-bindings/wifi/__init__.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CIRCUITPY_DOTENV
|
||||||
|
#include "shared-module/dotenv/__init__.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static wifi_radio_error_t wifi_status = WIFI_RADIO_ERROR_NONE;
|
||||||
|
|
||||||
|
void supervisor_web_workflow_status(void) {
|
||||||
|
serial_write_compressed(translate("Wi-Fi: "));
|
||||||
|
if (common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj)) {
|
||||||
|
uint32_t ipv4_address = wifi_radio_get_ipv4_address(&common_hal_wifi_radio_obj);
|
||||||
|
if (wifi_status != WIFI_RADIO_ERROR_NONE) {
|
||||||
|
mp_printf(&mp_plat_print, "%d", wifi_status);
|
||||||
|
} else if (ipv4_address == 0) {
|
||||||
|
serial_write_compressed(translate("No IP"));
|
||||||
|
} else {
|
||||||
|
uint8_t *octets = (uint8_t *)&ipv4_address;
|
||||||
|
mp_printf(&mp_plat_print, "%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
serial_write_compressed(translate("off"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void supervisor_start_web_workflow(void) {
|
||||||
|
#if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI
|
||||||
|
char ssid[33];
|
||||||
|
char password[64];
|
||||||
|
mp_int_t ssid_len = 0;
|
||||||
|
mp_int_t password_len = 0;
|
||||||
|
|
||||||
|
#if CIRCUITPY_DOTENV
|
||||||
|
ssid_len = dotenv_get_key("/.env", "CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid) - 1);
|
||||||
|
password_len = dotenv_get_key("/.env", "CIRCUITPY_WIFI_PASSWORD", password, sizeof(password) - 1);
|
||||||
|
#endif
|
||||||
|
if (ssid_len <= 0 || (size_t)ssid_len >= sizeof(ssid) ||
|
||||||
|
password_len <= 0 || (size_t)password_len >= sizeof(password)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
common_hal_wifi_init(false);
|
||||||
|
common_hal_wifi_radio_set_enabled(&common_hal_wifi_radio_obj, true);
|
||||||
|
|
||||||
|
// NUL terminate the strings because dotenv doesn't.
|
||||||
|
ssid[ssid_len] = '\0';
|
||||||
|
password[password_len] = '\0';
|
||||||
|
wifi_status = common_hal_wifi_radio_connect(
|
||||||
|
&common_hal_wifi_radio_obj, (uint8_t *)ssid, ssid_len, (uint8_t *)password, password_len,
|
||||||
|
0, 1, NULL, 0);
|
||||||
|
|
||||||
|
if (wifi_status != WIFI_RADIO_ERROR_NONE) {
|
||||||
|
common_hal_wifi_radio_set_enabled(&common_hal_wifi_radio_obj, false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void supervisor_stop_web_workflow(void) {
|
||||||
|
}
|
35
supervisor/shared/web_workflow/web_workflow.h
Normal file
35
supervisor/shared/web_workflow/web_workflow.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Scott Shawcroft 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
void supervisor_wifi_background(void);
|
||||||
|
void supervisor_wifi_init(void);
|
||||||
|
void supervisor_web_workflow_status(void);
|
||||||
|
void supervisor_start_web_workflow(void);
|
||||||
|
void supervisor_stop_web_workflow(void);
|
@ -26,14 +26,61 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "py/mpconfig.h"
|
#include "py/mpconfig.h"
|
||||||
|
#include "supervisor/background_callback.h"
|
||||||
#include "supervisor/workflow.h"
|
#include "supervisor/workflow.h"
|
||||||
|
#include "supervisor/serial.h"
|
||||||
#include "supervisor/shared/workflow.h"
|
#include "supervisor/shared/workflow.h"
|
||||||
|
|
||||||
|
#if CIRCUITPY_BLEIO
|
||||||
|
#include "shared-bindings/_bleio/__init__.h"
|
||||||
|
#include "supervisor/shared/bluetooth/bluetooth.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CIRCUITPY_USB
|
#if CIRCUITPY_USB
|
||||||
|
#include "supervisor/usb.h"
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CIRCUITPY_WEB_WORKFLOW
|
||||||
|
#include "supervisor/shared/web_workflow/web_workflow.h"
|
||||||
|
#endif
|
||||||
|
static background_callback_t workflow_background_cb;
|
||||||
|
|
||||||
|
static void supervisor_workflow_update_status_bar(void) {
|
||||||
|
// 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
|
||||||
|
// Send string terminator
|
||||||
|
serial_write("\x1b" "\\");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void workflow_background(void *data) {
|
||||||
|
supervisor_workflow_update_status_bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called during a VM reset. Doesn't actually reset things.
|
||||||
void supervisor_workflow_reset(void) {
|
void supervisor_workflow_reset(void) {
|
||||||
|
#if CIRCUITPY_BLEIO
|
||||||
|
supervisor_start_bluetooth();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CIRCUITPY_WEB_WORKFLOW
|
||||||
|
supervisor_start_web_workflow();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
workflow_background_cb.fun = workflow_background;
|
||||||
|
workflow_background_cb.data = NULL;
|
||||||
|
supervisor_workflow_request_background();
|
||||||
|
}
|
||||||
|
|
||||||
|
void supervisor_workflow_request_background(void) {
|
||||||
|
background_callback_add_core(&workflow_background_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true as soon as USB communication with host has started,
|
// Return true as soon as USB communication with host has started,
|
||||||
@ -58,3 +105,25 @@ bool supervisor_workflow_active(void) {
|
|||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void supervisor_workflow_start(void) {
|
||||||
|
// Start USB after giving boot.py a chance to tweak behavior.
|
||||||
|
#if CIRCUITPY_USB
|
||||||
|
// Setup USB connection after heap is available.
|
||||||
|
// It needs the heap to build descriptors.
|
||||||
|
usb_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set up any other serial connection.
|
||||||
|
serial_init();
|
||||||
|
|
||||||
|
#if CIRCUITPY_BLEIO
|
||||||
|
bleio_reset();
|
||||||
|
supervisor_bluetooth_enable_workflow();
|
||||||
|
supervisor_start_bluetooth();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CIRCUITPY_WEB_WORKFLOW
|
||||||
|
supervisor_start_web_workflow();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -146,6 +146,10 @@ ifeq ($(CIRCUITPY_USB),1)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CIRCUITPY_WEB_WORKFLOW),1)
|
||||||
|
SRC_SUPERVISOR += supervisor/shared/web_workflow/web_workflow.c
|
||||||
|
endif
|
||||||
|
|
||||||
SRC_TINYUSB = $(filter lib/tinyusb/%.c, $(SRC_SUPERVISOR))
|
SRC_TINYUSB = $(filter lib/tinyusb/%.c, $(SRC_SUPERVISOR))
|
||||||
$(patsubst %.c,$(BUILD)/%.o,$(SRC_TINYUSB)): CFLAGS += -Wno-missing-prototypes
|
$(patsubst %.c,$(BUILD)/%.o,$(SRC_TINYUSB)): CFLAGS += -Wno-missing-prototypes
|
||||||
|
|
||||||
|
@ -30,3 +30,7 @@ void supervisor_workflow_reset(void);
|
|||||||
|
|
||||||
// True when the user could be actively iterating on their code.
|
// True when the user could be actively iterating on their code.
|
||||||
bool supervisor_workflow_active(void);
|
bool supervisor_workflow_active(void);
|
||||||
|
|
||||||
|
void supervisor_workflow_request_background(void);
|
||||||
|
|
||||||
|
void supervisor_workflow_start(void);
|
||||||
|
@ -139,11 +139,41 @@ displayio_palette_t supervisor_terminal_color = {
|
|||||||
|
|
||||||
c_file.write(
|
c_file.write(
|
||||||
"""\
|
"""\
|
||||||
displayio_tilegrid_t supervisor_terminal_text_grid = {{
|
displayio_tilegrid_t supervisor_terminal_scroll_area_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,
|
||||||
.x = 16,
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.pixel_width = {1},
|
||||||
|
.pixel_height = {2},
|
||||||
|
.bitmap_width_in_tiles = {0},
|
||||||
|
.tiles_in_bitmap = {0},
|
||||||
|
.width_in_tiles = 1,
|
||||||
|
.height_in_tiles = 1,
|
||||||
|
.tile_width = {1},
|
||||||
|
.tile_height = {2},
|
||||||
|
.tiles = NULL,
|
||||||
|
.partial_change = false,
|
||||||
|
.full_change = false,
|
||||||
|
.hidden = false,
|
||||||
|
.hidden_by_parent = false,
|
||||||
|
.moved = false,
|
||||||
|
.inline_tiles = false,
|
||||||
|
.in_group = true
|
||||||
|
}};
|
||||||
|
""".format(
|
||||||
|
len(all_characters), tile_x, tile_y
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
c_file.write(
|
||||||
|
"""\
|
||||||
|
displayio_tilegrid_t supervisor_terminal_title_bar_text_grid = {{
|
||||||
|
.base = {{ .type = &displayio_tilegrid_type }},
|
||||||
|
.bitmap = (displayio_bitmap_t*) &supervisor_terminal_font_bitmap,
|
||||||
|
.pixel_shader = &supervisor_terminal_color,
|
||||||
|
.x = 0,
|
||||||
.y = 0,
|
.y = 0,
|
||||||
.pixel_width = {1},
|
.pixel_width = {1},
|
||||||
.pixel_height = {2},
|
.pixel_height = {2},
|
||||||
@ -228,7 +258,8 @@ terminalio_terminal_obj_t supervisor_terminal = {
|
|||||||
.font = &supervisor_terminal_font,
|
.font = &supervisor_terminal_font,
|
||||||
.cursor_x = 0,
|
.cursor_x = 0,
|
||||||
.cursor_y = 0,
|
.cursor_y = 0,
|
||||||
.tilegrid = NULL
|
.scroll_area = NULL,
|
||||||
|
.title_bar = NULL
|
||||||
};
|
};
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user