merge from main

This commit is contained in:
Dan Halbert 2022-08-04 12:43:23 -04:00
commit d4e8c19b49
85 changed files with 1648 additions and 354 deletions

View File

@ -143,7 +143,7 @@ jobs:
mpy-cross-mac:
runs-on: macos-10.15
runs-on: macos-11
steps:
- name: Dump GitHub context
env:
@ -176,27 +176,25 @@ jobs:
run: make -C mpy-cross -j2
- uses: actions/upload-artifact@v2
with:
name: mpy-cross-macos-catalina
name: mpy-cross-macos-11-x64
path: mpy-cross/mpy-cross
- name: Select SDK for M1 build
run: sudo xcode-select -switch /Applications/Xcode_12.3.app
- name: Build mpy-cross (arm64)
run: make -C mpy-cross -j2 -f Makefile.m1 V=2
- uses: actions/upload-artifact@v2
with:
name: mpy-cross-macos-bigsur-arm64
name: mpy-cross-macos-11-arm64
path: mpy-cross/mpy-cross-arm64
- name: Make universal binary
run: lipo -create -output mpy-cross-macos-universal mpy-cross/mpy-cross mpy-cross/mpy-cross-arm64
- uses: actions/upload-artifact@v2
with:
name: mpy-cross-macos-universal
name: mpy-cross-macos-11-universal
path: mpy-cross-macos-universal
- name: Upload mpy-cross build to S3
run: |
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross-macos-universal s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross-macos-universal-${{ env.CP_VERSION }} --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross-arm64 s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross-macos-bigsur-${{ env.CP_VERSION }}-arm64 --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross-macos-catalina-${{ env.CP_VERSION }} --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross-macos-universal s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross-macos-11-${{ env.CP_VERSION }}-universal --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross-arm64 s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross-macos-11-${{ env.CP_VERSION }}-arm64 --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross-macos-11-${{ env.CP_VERSION }}-x64 --no-progress --region us-east-1
env:
AWS_PAGER: ''
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}

View File

@ -39,6 +39,10 @@ CIRCUITPY_WEB_API_PASSWORD
~~~~~~~~~~~~~~~~~~~~~~~~~~
Password required to make modifications to the board from the Web Workflow.
CIRCUITPY_WEB_API_PORT
~~~~~~~~~~~~~~~~~~~~~~
TCP port number used for the web HTTP API. Defaults to 80 when omitted.
CIRCUITPY_WIFI_PASSWORD
~~~~~~~~~~~~~~~~~~~~~~~
Wi-Fi password used to auto connect to CIRCUITPY_WIFI_SSID.

View File

@ -72,7 +72,7 @@ Read-only characteristic that returns the UTF-8 encoded version string.
The web workflow is depends on adding Wi-Fi credentials into the `/.env` file. The keys are
`CIRCUITPY_WIFI_SSID` and `CIRCUITPY_WIFI_PASSWORD`. Once these are defined, CircuitPython will
automatically connect to the network and start the webserver used for the workflow. The webserver
is on port 80. It also enables MDNS.
is on port 80 unless overridden by `CIRCUITPY_WEB_API_PORT`. It also enables MDNS.
Here is an example `/.env`:
@ -82,7 +82,10 @@ CIRCUITPY_WIFI_SSID='scottswifi'
CIRCUITPY_WIFI_PASSWORD='secretpassword'
# To enable modifying files from the web. Change this too!
# Leave the User field blank in the browser.
CIRCUITPY_WEB_API_PASSWORD='passw0rd'
CIRCUITPY_WEB_API_PORT=80
```
MDNS is used to resolve [`circuitpython.local`](http://circuitpython.local) to a device specific
@ -119,7 +122,7 @@ The web server will allow requests from `cpy-XXXXXX.local`, `127.0.0.1`, the dev
### File REST API
All file system related APIs are protected by HTTP basic authentication. It is *NOT* secure but will
hopefully prevent some griefing in shared settings. The password is sent unencrypted so do not reuse
a password with something important.
a password with something important. The user field is left blank.
The password is taken from `/.env` with the key `CIRCUITPY_WEB_API_PASSWORD`. If this is unset, the
server will respond with `403 Forbidden`. When a password is set, but not provided in a request, it

View File

@ -971,10 +971,6 @@ msgstr "Gagal terhubung: kesalahan internal"
msgid "Failed to connect: timeout"
msgstr "Gagal terhubung: habis waktu"
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr ""
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr "Gagal mengurai file MP3"
@ -1564,7 +1560,7 @@ msgstr "Hanya 8 atau 16 bit mono dengan "
msgid "Only IPv4 addresses supported"
msgstr "Hanya alamat IPv4 yang didukung"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Hanysa socket IPv4 yang didukung"
@ -1636,7 +1632,7 @@ msgstr "Waktu habis"
msgid "Out of memory"
msgstr "Kehabisan memori"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr "Kehabisan socket"
@ -3791,11 +3787,20 @@ msgstr ""
msgid "pow() with 3 arguments requires integers"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"

View File

@ -958,10 +958,6 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr ""
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr ""
@ -1548,7 +1544,7 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -1616,7 +1612,7 @@ msgstr ""
msgid "Out of memory"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr ""
@ -3759,11 +3755,20 @@ msgstr ""
msgid "pow() with 3 arguments requires integers"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"

View File

@ -969,10 +969,6 @@ msgstr "Připojení se nezdařilo: interní chyba"
msgid "Failed to connect: timeout"
msgstr "Nepodařilo se připojit: časový limit"
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr "Chyba inicializace WiFi"
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr "Soubor MP3 se nepodařilo analyzovat"
@ -1564,7 +1560,7 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr "Pouze IPv4 adresy podporovány"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Pouze IPv4 sokety podporovány"
@ -1632,7 +1628,7 @@ msgstr ""
msgid "Out of memory"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr ""
@ -3777,11 +3773,20 @@ msgstr ""
msgid "pow() with 3 arguments requires integers"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"
@ -4333,6 +4338,9 @@ msgstr ""
msgid "zi must be of shape (n_section, 2)"
msgstr ""
#~ msgid "Failed to init wifi"
#~ msgstr "Chyba inicializace WiFi"
#~ msgid "%q must be a tuple of length 2"
#~ msgstr "%q musí být n-tice délky 2"

View File

@ -976,10 +976,6 @@ msgstr "Verbindung fehlgeschlagen: interner Fehler"
msgid "Failed to connect: timeout"
msgstr "Verbindung nicht erfolgreich: timeout"
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr "Wifi Initialisierung ist fehlgeschlagen"
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr "MP3-Datei konnte nicht analysiert werden"
@ -1579,7 +1575,7 @@ msgstr "Nur 8 oder 16 bit mono mit "
msgid "Only IPv4 addresses supported"
msgstr "Nur IPv4-Adressen werden unterstützt"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Nur IPv4-Sockets werden unterstützt"
@ -1651,7 +1647,7 @@ msgstr "Zeit für Vorgang abgelaufen"
msgid "Out of memory"
msgstr "Kein Speicher mehr verfügbar"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr "Keine Sockets mehr verfügbar"
@ -3854,11 +3850,20 @@ msgstr "pow() drittes Argument darf nicht 0 sein"
msgid "pow() with 3 arguments requires integers"
msgstr "pow() mit 3 Argumenten erfordert Integer"
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"
@ -4415,6 +4420,9 @@ msgstr "zi muss eine Gleitkommazahl sein"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi muss die Form (n_section, 2) haben"
#~ msgid "Failed to init wifi"
#~ msgstr "Wifi Initialisierung ist fehlgeschlagen"
#~ msgid "input must be a tensor of rank 2"
#~ msgstr "Eingabe muss ein Tensor von Rang 2 sein"

View File

@ -958,10 +958,6 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr ""
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr ""
@ -1548,7 +1544,7 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -1616,7 +1612,7 @@ msgstr ""
msgid "Out of memory"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr ""
@ -3759,11 +3755,20 @@ msgstr ""
msgid "pow() with 3 arguments requires integers"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"

View File

@ -972,10 +972,6 @@ msgstr "Failed to connect: internal error"
msgid "Failed to connect: timeout"
msgstr "Failed to connect: timeout"
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr "Failed to init WiFi"
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr "Failed to parse MP3 file"
@ -1565,7 +1561,7 @@ msgstr "Only 8 or 16 bit mono with "
msgid "Only IPv4 addresses supported"
msgstr "Only IPv4 addresses supported"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Only IPv4 sockets supported"
@ -1636,7 +1632,7 @@ msgstr "Operation timed out"
msgid "Out of memory"
msgstr "Out of memory"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr "Out of sockets"
@ -3796,11 +3792,20 @@ msgstr "pow() 3rd argument cannot be 0"
msgid "pow() with 3 arguments requires integers"
msgstr "pow() with 3 arguments requires integers"
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"
@ -4354,6 +4359,9 @@ msgstr "zi must be of float type"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi must be of shape (n_section, 2)"
#~ msgid "Failed to init wifi"
#~ msgstr "Failed to init WiFi"
#~ msgid "input must be a tensor of rank 2"
#~ msgstr "input must be a tensor of rank 2"

View File

@ -979,10 +979,6 @@ msgstr "Error al conectar: error interno"
msgid "Failed to connect: timeout"
msgstr "Error al conectar: tiempo de espera agotado"
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr "Fallo al inicializar wifi"
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr "Error al analizar el archivo MP3"
@ -1585,7 +1581,7 @@ msgstr "Solo mono de 8 ó 16 bit con "
msgid "Only IPv4 addresses supported"
msgstr "Solo hay capacidad para direcciones IPv4"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Solo se admiten sockets IPv4"
@ -1657,7 +1653,7 @@ msgstr "Tiempo de espera agotado"
msgid "Out of memory"
msgstr "Memoria agotada"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr "Se acabaron los enchufes"
@ -3840,11 +3836,20 @@ msgstr "el 3er argumento de pow() no puede ser 0"
msgid "pow() with 3 arguments requires integers"
msgstr "pow() con 3 argumentos requiere enteros"
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"
@ -4399,6 +4404,9 @@ msgstr "zi debe ser de tipo flotante"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi debe ser una forma (n_section,2)"
#~ msgid "Failed to init wifi"
#~ msgstr "Fallo al inicializar wifi"
#~ msgid "input must be a tensor of rank 2"
#~ msgstr "Entrada tiene que ser un tensor de rango 2"

View File

@ -969,10 +969,6 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr ""
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr ""
@ -1564,7 +1560,7 @@ msgstr "Tanging 8 o 16 na bit mono na may "
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -1632,7 +1628,7 @@ msgstr ""
msgid "Out of memory"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr ""
@ -3798,11 +3794,20 @@ msgstr "pow() 3rd argument ay hindi maaring 0"
msgid "pow() with 3 arguments requires integers"
msgstr "pow() na may 3 argumento kailangan ng integers"
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"

View File

@ -993,10 +993,6 @@ msgstr "Impossible de se connecter : erreur interne"
msgid "Failed to connect: timeout"
msgstr "Impossible de se connecter: délai dépassé"
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr "Echec de l'initialisation du Wifi"
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr "Impossible d'analyser le fichier MP3"
@ -1608,7 +1604,7 @@ msgstr "Uniquement 8 ou 16 bit mono avec "
msgid "Only IPv4 addresses supported"
msgstr "Seulement les adresses IPv4 sont supportées"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Seulement les sockets IPv4 sont supportés"
@ -1680,7 +1676,7 @@ msgstr "Timeout de l'opération"
msgid "Out of memory"
msgstr "Hors de mémoire"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr "Plus de sockets"
@ -3885,11 +3881,20 @@ msgstr "le 3e argument de pow() ne peut être 0"
msgid "pow() with 3 arguments requires integers"
msgstr "pow() avec 3 arguments nécessite des entiers"
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr "presser le bouton SW38 au démarrage.\n"
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"
@ -4444,6 +4449,9 @@ msgstr "zi doit être de type float"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi doit être de forme (n_section, 2)"
#~ msgid "Failed to init wifi"
#~ msgstr "Echec de l'initialisation du Wifi"
#~ msgid "input must be a tensor of rank 2"
#~ msgstr "l'entrée doit être un tenseur de rang 2"

View File

@ -958,10 +958,6 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr ""
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr ""
@ -1548,7 +1544,7 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -1616,7 +1612,7 @@ msgstr ""
msgid "Out of memory"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr ""
@ -3759,11 +3755,20 @@ msgstr ""
msgid "pow() with 3 arguments requires integers"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"

View File

@ -974,10 +974,6 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr ""
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr ""
@ -1571,7 +1567,7 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -1639,7 +1635,7 @@ msgstr ""
msgid "Out of memory"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr ""
@ -3811,11 +3807,20 @@ msgstr "il terzo argomento di pow() non può essere 0"
msgid "pow() with 3 arguments requires integers"
msgstr "pow() con 3 argomenti richiede interi"
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"

View File

@ -967,10 +967,6 @@ msgstr "接続失敗: 内部エラー"
msgid "Failed to connect: timeout"
msgstr "接続失敗: タイムアウト"
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr ""
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr "MP3ファイルのパーズに失敗"
@ -1561,7 +1557,7 @@ msgstr "8または16ビットの "
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -1629,7 +1625,7 @@ msgstr ""
msgid "Out of memory"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr ""
@ -3780,11 +3776,20 @@ msgstr "pow()の3つ目の引数は0にできません"
msgid "pow() with 3 arguments requires integers"
msgstr "pow()の第3引数には整数が必要"
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"

View File

@ -961,10 +961,6 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr ""
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr ""
@ -1551,7 +1547,7 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -1619,7 +1615,7 @@ msgstr ""
msgid "Out of memory"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr ""
@ -3763,11 +3759,20 @@ msgstr ""
msgid "pow() with 3 arguments requires integers"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"

View File

@ -966,10 +966,6 @@ msgstr "Verbinding mislukt: interne fout"
msgid "Failed to connect: timeout"
msgstr "Verbinding mislukt: timeout"
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr "Kon WiFi niet initialiseren"
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr "Mislukt om MP3 bestand te ontleden"
@ -1561,7 +1557,7 @@ msgstr "Alleen 8 of 16 bit mono met "
msgid "Only IPv4 addresses supported"
msgstr "Alleen IPv4 adressen worden ondersteund"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Alleen IPv4-sockets ondersteund"
@ -1633,7 +1629,7 @@ msgstr ""
msgid "Out of memory"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr "Geen sockets meer beschikbaar"
@ -3796,11 +3792,20 @@ msgstr "derde argument van pow() mag geen 0 zijn"
msgid "pow() with 3 arguments requires integers"
msgstr "pow() met 3 argumenten vereist integers"
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"
@ -4354,6 +4359,9 @@ msgstr "zi moet van type float zijn"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi moet vorm (n_section, 2) hebben"
#~ msgid "Failed to init wifi"
#~ msgstr "Kon WiFi niet initialiseren"
#~ msgid "input must be a tensor of rank 2"
#~ msgstr "invoer moet een tensor van rang 2 zijn"

View File

@ -967,10 +967,6 @@ msgstr "Nie udało się połączyć: błąd wewnętrzny"
msgid "Failed to connect: timeout"
msgstr "Nie udało się połączyć: upłynął limit czasu"
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr ""
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr "Nie można przeanalizować pliku MP3"
@ -1559,7 +1555,7 @@ msgstr "Tylko 8 lub 16 bitów mono z "
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -1627,7 +1623,7 @@ msgstr ""
msgid "Out of memory"
msgstr "Brak pamięci"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr ""
@ -3772,11 +3768,20 @@ msgstr "trzeci argument pow() nie może być 0"
msgid "pow() with 3 arguments requires integers"
msgstr "trzyargumentowe pow() wymaga liczb całkowitych"
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"

View File

@ -985,10 +985,6 @@ msgstr "Falha ao conectar: erro interno"
msgid "Failed to connect: timeout"
msgstr "Falha ao conectar: tempo limite"
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr "Houve uma falha ao iniciar o wifi"
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr "Falha ao analisar o arquivo MP3"
@ -1590,7 +1586,7 @@ msgstr "Apenas mono com 8 ou 16 bits com "
msgid "Only IPv4 addresses supported"
msgstr "Somente os endereços IPv4 são suportados"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Apenas soquetes IPv4 são suportados"
@ -1662,7 +1658,7 @@ msgstr "A operação expirou"
msgid "Out of memory"
msgstr "Sem memória"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr "Sem soquetes"
@ -3862,11 +3858,20 @@ msgstr "O terceiro argumento pow() não pode ser 0"
msgid "pow() with 3 arguments requires integers"
msgstr "o pow() com 3 argumentos requer números inteiros"
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr "pressionando o botão SW38 na inicialização.\n"
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"
@ -4420,6 +4425,9 @@ msgstr "zi deve ser de um tipo float"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi deve estar na forma (n_section, 2)"
#~ msgid "Failed to init wifi"
#~ msgstr "Houve uma falha ao iniciar o wifi"
#~ msgid "input must be a tensor of rank 2"
#~ msgstr "a entrada dos dados deve ser um tensor de nível 2"

View File

@ -983,10 +983,6 @@ msgstr "Не удалось подключиться: внутренняя ош
msgid "Failed to connect: timeout"
msgstr "Не удалось подключиться: тайм-аут"
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr "Не удалось инициировать wifi"
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr "Не удалось распарсить файл MP3"
@ -1588,7 +1584,7 @@ msgstr "Только 8- или 16-битное моно с "
msgid "Only IPv4 addresses supported"
msgstr "Поддерживаются только адреса IPv4"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Поддерживаются только сокеты IPv4"
@ -1658,7 +1654,7 @@ msgstr ""
msgid "Out of memory"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr ""
@ -3808,11 +3804,20 @@ msgstr ""
msgid "pow() with 3 arguments requires integers"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"
@ -4364,6 +4369,9 @@ msgstr "zi должно быть типа float"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi должен иметь форму (n_section, 2)"
#~ msgid "Failed to init wifi"
#~ msgstr "Не удалось инициировать wifi"
#~ msgid "%q must be a tuple of length 2"
#~ msgstr "%q должен быть кортежем длинной 2"

View File

@ -972,10 +972,6 @@ msgstr "Det gick inte att ansluta: internt fel"
msgid "Failed to connect: timeout"
msgstr "Det gick inte att ansluta: timeout"
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr "Kunde inte initiera WiFi"
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr "Det gick inte att tolka MP3-filen"
@ -1571,7 +1567,7 @@ msgstr "Endast 8 eller 16 bitars mono med "
msgid "Only IPv4 addresses supported"
msgstr "Endast IPv4-adresser stöds"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Endast IPv4-socket stöds"
@ -1642,7 +1638,7 @@ msgstr "Åtgärden orsakade timeout"
msgid "Out of memory"
msgstr "Slut på minne"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr "Slut på sockets"
@ -3821,11 +3817,20 @@ msgstr "pow() 3: e argument kan inte vara 0"
msgid "pow() with 3 arguments requires integers"
msgstr "pow() med 3 argument kräver heltal"
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr "genom att trycka på SW38-knappen vid start.\n"
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"
@ -4379,6 +4384,9 @@ msgstr "zi måste vara av typ float"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi måste vara i formen (n_section, 2)"
#~ msgid "Failed to init wifi"
#~ msgstr "Kunde inte initiera WiFi"
#~ msgid "input must be a tensor of rank 2"
#~ msgstr "indata måste vara en tensor av rank 2"

View File

@ -975,10 +975,6 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr ""
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr ""
@ -1565,7 +1561,7 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -1633,7 +1629,7 @@ msgstr ""
msgid "Out of memory"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr ""
@ -3779,11 +3775,20 @@ msgstr ""
msgid "pow() with 3 arguments requires integers"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"

View File

@ -981,10 +981,6 @@ msgstr "Liánjiē shībài: Nèibù cuòwù"
msgid "Failed to connect: timeout"
msgstr "Liánjiē shībài: Chāoshí"
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to init wifi"
msgstr "Wúfǎ chūshǐhuà wifi"
#: shared-module/audiomp3/MP3Decoder.c
msgid "Failed to parse MP3 file"
msgstr "Wúfǎ jiěxī MP3 wénjiàn"
@ -1584,7 +1580,7 @@ msgstr "Zhǐyǒu 8 huò 16 wèi dānwèi "
msgid "Only IPv4 addresses supported"
msgstr "Jǐn zhīchí IPv4 dìzhǐ"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "jǐn zhī chí IPv4 tào jiē zì"
@ -1656,7 +1652,7 @@ msgstr "cāo zuò yǐ fēn shí"
msgid "Out of memory"
msgstr "nèi cún bù zú"
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr "tào jiē zì wài"
@ -3830,11 +3826,20 @@ msgstr "pow() 3 cān shǔ bùnéng wéi 0"
msgid "pow() with 3 arguments requires integers"
msgstr "pow() yǒu 3 cānshù xūyào zhěngshù"
#: ports/espressif/boards/adafruit_qtpy_esp32_pico/mpconfigboard.h
msgid "pressing BOOT button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "pressing SW38 button at start up.\n"
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "pressing VOLUME button at start up.\n"
msgstr ""
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
#: supervisor/shared/safe_mode.c
msgid "pressing boot button at start up.\n"
@ -4391,6 +4396,9 @@ msgstr "zi bìxū wèi fú diǎn xíng"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi bìxū jùyǒu xíngzhuàng (n_section,2)"
#~ msgid "Failed to init wifi"
#~ msgstr "Wúfǎ chūshǐhuà wifi"
#~ msgid "input must be a tensor of rank 2"
#~ msgstr "shū rù bì xū shì děng jí 2 de zhāng liàng"

4
main.c
View File

@ -57,6 +57,7 @@
#include "supervisor/shared/stack.h"
#include "supervisor/shared/status_leds.h"
#include "supervisor/shared/tick.h"
#include "supervisor/shared/title_bar.h"
#include "supervisor/shared/traceback.h"
#include "supervisor/shared/translate/translate.h"
#include "supervisor/shared/workflow.h"
@ -822,7 +823,9 @@ STATIC int run_repl(bool first_run) {
status_led_deinit();
#endif
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
supervisor_title_bar_suspend();
exit_code = pyexec_raw_repl();
supervisor_title_bar_resume();
} else {
exit_code = pyexec_friendly_repl();
}
@ -914,6 +917,7 @@ int __attribute__((used)) main(void) {
run_boot_py(safe_mode);
supervisor_workflow_start();
supervisor_title_bar_start();
// Boot script is finished, so now go into REPL or run code.py.
int exit_code = PYEXEC_FORCED_EXIT;

View File

@ -7,4 +7,4 @@ BUILD=build-arm64
include mpy-cross.mk
# Because mpy-cross.mk unconditionally overwrites CC for Darwin, we must set it BELOW the inclusion
CC := $(shell xcrun --sdk macosx11.1 --find clang) -isysroot $(shell xcrun --sdk macosx11.1 --show-sdk-path) -target arm64-apple-macos11
CC := $(shell xcrun --find clang) -isysroot $(shell xcrun --show-sdk-path) -target arm64-apple-macos11

View File

@ -33,8 +33,6 @@
#include "shared-module/displayio/mipi_constants.h"
#include "supervisor/shared/board.h"
displayio_fourwire_obj_t board_display_obj;
#define DELAY 0x80
uint8_t display_init_sequence[] = {

View File

@ -123,8 +123,8 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
// The maximum frequency divisor gives a clock rate of around 48MHz/2/255
// but set_baudrate does not diagnose this problem. (This is not the
// exact cutoff, but no frequency well under 100kHz is available)
if (frequency < 95000 &&
i2c_m_sync_set_baudrate(&self->i2c_desc, 0, frequency / 1000) != ERR_NONE) {
if ((frequency < 95000) ||
(i2c_m_sync_set_baudrate(&self->i2c_desc, 0, frequency / 1000) != ERR_NONE)) {
reset_pin_number(sda->number);
reset_pin_number(scl->number);
common_hal_busio_i2c_deinit(self);

View File

@ -6,7 +6,7 @@ set(ENV{IDF_PATH} ${CMAKE_SOURCE_DIR}/esp-idf)
# The component list here determines what options we get in menuconfig and what the ninja file
# can build.
set(COMPONENTS esptool_py soc driver log main esp-tls mbedtls mdns esp_event esp_adc_cal esp_netif esp_wifi lwip wpa_supplicant freertos bt)
set(COMPONENTS esptool_py soc driver log main esp-tls mbedtls mdns esp_event esp_adc_cal esp_netif esp_wifi lwip wpa_supplicant freertos bt usb)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(circuitpython)

View File

@ -98,6 +98,8 @@ INC += \
-isystem esp-idf/components/bt/host/nimble/port/include \
-isystem esp-idf/components/driver/include \
-isystem esp-idf/components/driver/$(IDF_TARGET)/include \
-isystem esp-idf/components/efuse/include \
-isystem esp-idf/components/efuse/$(IDF_TARGET)/include \
-isystem esp-idf/components/$(IDF_TARGET)/include \
-isystem esp-idf/components/esp_adc_cal/include \
-isystem esp-idf/components/esp_common/include \

View File

@ -47,3 +47,19 @@ void reset_board(void) {
void board_deinit(void) {
}
bool espressif_board_reset_pin_number(gpio_num_t pin_number) {
// Pull LED down on reset rather than the default up
if (pin_number == 13) {
gpio_config_t cfg = {
.pin_bit_mask = BIT64(pin_number),
.mode = GPIO_MODE_DISABLE,
.pull_up_en = false,
.pull_down_en = true,
.intr_type = GPIO_INTR_DISABLE,
};
gpio_config(&cfg);
return true;
}
return false;
}

View File

@ -10,9 +10,6 @@ LONGINT_IMPL = MPZ
# so increase it to 32.
CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32
CIRCUITPY_STATUS_BAR = 0
CIRCUITPY_WEB_WORKFLOW = 0
CIRCUITPY_ESP_FLASH_MODE = dio
CIRCUITPY_ESP_FLASH_FREQ = 40m
CIRCUITPY_ESP_FLASH_SIZE = 8MB

View File

@ -16,4 +16,4 @@ CIRCUITPY_ESP_FLASH_MODE = qio
CIRCUITPY_ESP_FLASH_FREQ = 40m
CIRCUITPY_ESP_FLASH_SIZE = 4MB
CIRCUITPY_PS2IO = 0
OPTIMIZATION_FLAGS = -Os

View File

@ -0,0 +1,52 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 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 "supervisor/board.h"
#include "mpconfigboard.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "components/driver/include/driver/gpio.h"
#include "components/hal/include/hal/gpio_hal.h"
#include "common-hal/microcontroller/Pin.h"
void board_init(void) {
reset_board();
}
bool board_requests_safe_mode(void) {
return false;
}
void reset_board(void) {
// Turn on NeoPixel power by default.
gpio_set_direction(8, GPIO_MODE_DEF_OUTPUT);
gpio_set_level(8, true);
}
void board_deinit(void) {
// Turn off NeoPixel
gpio_set_direction(8, GPIO_MODE_DEF_OUTPUT);
gpio_set_level(8, false);
}

View File

@ -0,0 +1,49 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#define MICROPY_HW_BOARD_NAME "Adafruit QT Py ESP32 PICO"
#define MICROPY_HW_MCU_NAME "ESP32"
#define MICROPY_HW_NEOPIXEL (&pin_GPIO5)
#define CIRCUITPY_BOARD_I2C (2)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO33, .sda = &pin_GPIO4}, \
{.scl = &pin_GPIO19, .sda = &pin_GPIO22}}
#define CIRCUITPY_BOARD_SPI (1)
#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO14, .mosi = &pin_GPIO13, .miso = &pin_GPIO12}}
#define CIRCUITPY_BOARD_UART (1)
#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO32, .rx = &pin_GPIO7}}
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)
// Explanation of how a user got into safe mode
#define BOARD_USER_SAFE_MODE_ACTION translate("pressing BOOT button at start up.\n")
// UART pins attached to the USB-serial converter chip
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3)

View File

@ -0,0 +1,15 @@
CIRCUITPY_CREATOR_ID = 0x0000239A
CIRCUITPY_CREATION_ID = 0x00320003
IDF_TARGET = esp32
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = MPZ
# The default queue depth of 16 overflows on release builds,
# so increase it to 32.
CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32
CIRCUITPY_ESP_FLASH_MODE = dio
CIRCUITPY_ESP_FLASH_FREQ = 40m
CIRCUITPY_ESP_FLASH_SIZE = 8MB

View File

@ -0,0 +1,63 @@
#include "shared-bindings/board/__init__.h"
CIRCUITPY_BOARD_BUS_SINGLETON(stemma_i2c, i2c, 1)
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
{ MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO32) },
{ MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO32) },
{ MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO32) },
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_D35), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_D36), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_D37), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_SCL1), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_D40), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_SDA1), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_D41), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_stemma_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -0,0 +1,52 @@
#
# Partition Table
#
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="esp-idf-config/partitions-8MB-no-uf2.csv"
CONFIG_PARTITION_TABLE_FILENAME="esp-idf-config/partitions-8MB-no-uf2.csv"
# end of Partition Table
#
# SPI RAM config
#
# CONFIG_SPIRAM_TYPE_AUTO is not set
CONFIG_SPIRAM_TYPE_ESPPSRAM16=y
# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set
CONFIG_SPIRAM_SIZE=2097152
CONFIG_SPIRAM_SPEED_40M=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_BOOT_INIT=y
CONFIG_SPIRAM_IGNORE_NOTFOUND=y
CONFIG_SPIRAM_USE_MEMMAP=y
# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set
# CONFIG_SPIRAM_USE_MALLOC is not set
CONFIG_SPIRAM_MEMTEST=y
# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set
# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set
CONFIG_SPIRAM_CACHE_WORKAROUND=y
#
# SPI RAM config
#
CONFIG_ESP32_SPIRAM_SUPPORT=y
# CONFIG_SPIRAM_TYPE_AUTO is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set
### # Uncomment to send log output to TX/RX pins on Feather ESP32V2
### #
### # ESP System Settings
### #
### CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
### # CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set
### CONFIG_ESP_CONSOLE_UART_CUSTOM=y
### # CONFIG_ESP_CONSOLE_NONE is not set
### CONFIG_ESP_CONSOLE_UART=y
### CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_0=y
### # CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_1 is not set
### CONFIG_ESP_CONSOLE_UART_NUM=0
### CONFIG_ESP_CONSOLE_UART_TX_GPIO=8
### CONFIG_ESP_CONSOLE_UART_RX_GPIO=7
### CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200
### # CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 is not set
### # end of ESP System Settings

View File

@ -30,6 +30,14 @@ CONFIG_PARTITION_TABLE_FILENAME="esp-idf-config/partitions-4MB-no-uf2.csv"
#
# Component config
#
#
#
# PHY
#
CONFIG_ESP_PHY_ENABLE_USB=y
# end of PHY
#
# ESP System Settings
#

View File

@ -1,3 +1,9 @@
#
# PHY
#
CONFIG_ESP_PHY_ENABLE_USB=y
# end of PHY
#
# LWIP
#

View File

@ -0,0 +1,138 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 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 "supervisor/board.h"
#include "mpconfigboard.h"
#include "shared-bindings/busio/SPI.h"
#include "shared-bindings/displayio/FourWire.h"
#include "shared-module/displayio/__init__.h"
#include "shared-module/displayio/mipi_constants.h"
#include "common-hal/microcontroller/Pin.h"
#define DELAY 0x80
// ILI9341 init sequence from:
// https://github.com/hardkernel/ODROID-GO-MicroPython/blob/loboris/odroid_go/utils/lcd/lcd.py#L55
uint8_t display_init_sequence[] = {
0x0f, 3, 0x03, 0x80, 0x02, // RDDSDR
0xcf, 3, 0x00, 0xcf, 0x30, // PWCRTLB
0xed, 4, 0x64, 0x03, 0x12, 0x81, // PWRONCTRL
0xe8, 3, 0x85, 0x00, 0x78, // DTCTRLA
0xcb, 5, 0x39, 0x2c, 0x00, 0x34, 0x02, // PWCTRLA
0xf7, 1, 0x20, // PRCTRL
0xea, 2, 0x00, 0x00, // DTCTRLB
0xc0, 1, 0x1b, // PWCTRL1
0xc1, 1, 0x12, // PWCTRL2
0xc5, 2, 0x3e, 0x3c, // VMCTRL1
0xc7, 1, 0x91, // VMCTRL2
0x36, 1, 0xa8, // MADCTL
0x3a, 1, 0x55, // PIXSET
0xb1, 2, 0x00, 0x1b, // FRMCTR1
0xb6, 3, 0x0a, 0xa2, 0x27, // DISCTRL
0xf6, 2, 0x01, 0x30, // INTFACE
0xf2, 1, 0x00, // ENA3G
0x26, 1, 0x01, // GAMSET
0xe0, 15, 0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1, 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00, // PGAMCTRL
0xe1, 15, 0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, 0xc1, 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f, // NGAMCTRL
0x11, 0 | DELAY, 10, // SLPOUT
0x29, 0 | DELAY, 100, // DISPON
};
void board_init(void) {
busio_spi_obj_t *spi = &displays[0].fourwire_bus.inline_bus;
common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO23, NULL, false);
common_hal_busio_spi_never_reset(spi);
displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus;
bus->base.type = &displayio_fourwire_type;
common_hal_displayio_fourwire_construct(bus,
spi,
&pin_GPIO21, // TFT_DC Command or data
&pin_GPIO5, // TFT_CS Chip select
NULL, // TFT_RST Reset
40000000, // Baudrate
0, // Polarity
0); // Phase
displayio_display_obj_t *display = &displays[0].display;
display->base.type = &displayio_display_type;
common_hal_displayio_display_construct(display,
bus,
320, // Width (after rotation)
240, // Height (after rotation)
0, // column start
0, // row start
0, // rotation
16, // Color depth
false, // grayscale
false, // pixels in byte share row. only used for depth < 8
1, // bytes per cell. Only valid for depths < 8
false, // reverse_pixels_in_byte. Only valid for depths < 8
true, // reverse_pixels_in_word
MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
display_init_sequence,
sizeof(display_init_sequence),
&pin_GPIO14, // backlight pin
NO_BRIGHTNESS_COMMAND,
1.0f, // brightness (ignored)
true, // auto_brightness
false, // single_byte_bounds
false, // data_as_commands
true, // auto_refresh
60, // native_frames_per_second
true, // backlight_on_high
false, // SH1107_addressing
50000); // backlight pwm frequency
}
bool board_requests_safe_mode(void) {
return false;
}
void reset_board(void) {
}
void board_deinit(void) {
}
bool espressif_board_reset_pin_number(gpio_num_t pin_number) {
// Pull LED down on reset rather than the default up
if (pin_number == 2) {
gpio_config_t cfg = {
.pin_bit_mask = BIT64(pin_number),
.mode = GPIO_MODE_DISABLE,
.pull_up_en = false,
.pull_down_en = true,
.intr_type = GPIO_INTR_DISABLE,
};
gpio_config(&cfg);
return true;
}
return false;
}

View File

@ -0,0 +1,42 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#define MICROPY_HW_BOARD_NAME "Hardkernel Odroid Go"
#define MICROPY_HW_MCU_NAME "ESP32"
#define MICROPY_HW_LED_STATUS (&pin_GPIO2)
#define CIRCUITPY_BOARD_SPI (1)
#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO18, .mosi = &pin_GPIO23, .miso = &pin_GPIO19}}
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)
// Explanation of how a user got into safe mode
#define BOARD_USER_SAFE_MODE_ACTION translate("pressing VOLUME button at start up.\n")
// UART pins attached to the USB-serial converter chip
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3)

View File

@ -0,0 +1,15 @@
CIRCUITPY_CREATOR_ID = 0x0D10D000
CIRCUITPY_CREATION_ID = 0x00320060
IDF_TARGET = esp32
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = MPZ
# The default queue depth of 16 overflows on release builds,
# so increase it to 32.
CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32
CIRCUITPY_ESP_FLASH_MODE = dio
CIRCUITPY_ESP_FLASH_FREQ = 40m
CIRCUITPY_ESP_FLASH_SIZE = 16MB

View File

@ -0,0 +1,57 @@
#include "shared-bindings/board/__init__.h"
// Pin names from: https://wiki.odroid.com/odroid_go/odroid_go
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
// Left side
{ MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_GPIO36) },
{ MP_ROM_QSTR(MP_QSTR_BTN_START), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_BTN_AXIS_X), MP_ROM_PTR(&pin_GPIO34) },
{ MP_ROM_QSTR(MP_QSTR_BTN_AXIS_Y), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_BTN_A), MP_ROM_PTR(&pin_GPIO32) },
{ MP_ROM_QSTR(MP_QSTR_BTN_B), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_SPEAKER_IN_M), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_SPEAKER_IN_P), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_BTN_SELECT), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_BACKLIGHT_PWM), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_EXT3), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_BTN_MENU), MP_ROM_PTR(&pin_GPIO13) },
// Right side.
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_EXT8), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_EXT7), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_EXT2), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_EXT5), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_BTN_VOLUME), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_EXT4), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -0,0 +1,54 @@
#
# Partition Table
#
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="esp-idf-config/partitions-16MB-no-uf2.csv"
CONFIG_PARTITION_TABLE_FILENAME="esp-idf-config/partitions-16MB-no-uf2.csv"
# end of Partition Table
CONFIG_ESP_INT_WDT_TIMEOUT_MS=3000
#
# SPI RAM config
#
# CONFIG_SPIRAM_TYPE_AUTO is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set
CONFIG_SPIRAM_TYPE_ESPPSRAM32=y
# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set
CONFIG_SPIRAM_SIZE=4194304
CONFIG_SPIRAM_SPEED_40M=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_BOOT_INIT=y
CONFIG_SPIRAM_IGNORE_NOTFOUND=y
CONFIG_SPIRAM_USE_MEMMAP=y
# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set
# CONFIG_SPIRAM_USE_MALLOC is not set
CONFIG_SPIRAM_MEMTEST=y
# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set
# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set
CONFIG_SPIRAM_CACHE_WORKAROUND=y
#
# SPI RAM config
#
CONFIG_ESP32_SPIRAM_SUPPORT=y
# CONFIG_SPIRAM_TYPE_AUTO is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set
### # Uncomment to send log output to TX/RX pins on Feather ESP32V2
### #
### # ESP System Settings
### #
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
### # CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set
CONFIG_ESP_CONSOLE_UART_CUSTOM=y
### # CONFIG_ESP_CONSOLE_NONE is not set
CONFIG_ESP_CONSOLE_UART=y
CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_0=y
### # CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_1 is not set
CONFIG_ESP_CONSOLE_UART_NUM=0
CONFIG_ESP_CONSOLE_UART_TX_GPIO=12
CONFIG_ESP_CONSOLE_UART_RX_GPIO=15
CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200
### # CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 is not set
### # end of ESP System Settings

View File

@ -1,3 +1,9 @@
#
# PHY
#
CONFIG_ESP_PHY_ENABLE_USB=y
# end of PHY
#
# LWIP
#

View File

@ -0,0 +1,26 @@
#include "shared-bindings/microcontroller/Pin.h"
#include "supervisor/board.h"
#include "components/driver/include/driver/gpio.h"
void board_init(void) {
// Debug UART
#ifdef DEBUG
common_hal_never_reset_pin(&pin_GPIO20);
common_hal_never_reset_pin(&pin_GPIO21);
#endif
}
bool board_requests_safe_mode(void) {
return false;
}
bool espressif_board_reset_pin_number(gpio_num_t pin_number) {
return false;
}
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -0,0 +1,14 @@
#define MICROPY_HW_BOARD_NAME "Seeed Studio XIAO ESP32C3"
#define MICROPY_HW_MCU_NAME "ESP32-C3FN4"
#define DEFAULT_I2C_BUS_SCL (&pin_GPIO7)
#define DEFAULT_I2C_BUS_SDA (&pin_GPIO6)
#define DEFAULT_SPI_BUS_SCK (&pin_GPIO8)
#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO10)
#define DEFAULT_SPI_BUS_MISO (&pin_GPIO9)
#define DEFAULT_UART_BUS_RX (&pin_GPIO20)
#define DEFAULT_UART_BUS_TX (&pin_GPIO21)
#define CIRCUITPY_ESP_USB_SERIAL_JTAG (1)

View File

@ -0,0 +1,10 @@
CIRCUITPY_CREATOR_ID = 0x000C2886
CIRCUITPY_CREATION_ID = 0x00C30001
IDF_TARGET = esp32c3
INTERNAL_FLASH_FILESYSTEM = 1
CIRCUITPY_ESP_FLASH_MODE = qio
CIRCUITPY_ESP_FLASH_FREQ = 80m
CIRCUITPY_ESP_FLASH_SIZE = 4MB

View File

@ -0,0 +1,43 @@
#include "shared-bindings/board/__init__.h"
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO20) },
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO20) },
{ MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -0,0 +1,5 @@
#
# LWIP
#
CONFIG_LWIP_LOCAL_HOSTNAME="seeed-xiao-esp32c3"
# end of LWIP

View File

@ -27,7 +27,7 @@
#include "py/runtime.h"
#include "supervisor/esp_port.h"
#include "supervisor/port.h"
#include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/microcontroller/__init__.h"
@ -90,11 +90,7 @@ STATIC void gpio_interrupt(void *arg) {
gpio_ll_intr_disable(&GPIO, 32 + i);
}
}
BaseType_t high_task_wakeup;
vTaskNotifyGiveFromISR(circuitpython_task, &high_task_wakeup);
if (high_task_wakeup) {
portYIELD_FROM_ISR();
}
port_wake_main_task_from_isr();
}
bool alarm_pin_pinalarm_woke_this_cycle(void) {

View File

@ -27,7 +27,7 @@
#include "esp_sleep.h"
#include "py/runtime.h"
#include "supervisor/esp_port.h"
#include "supervisor/port.h"
#include "components/esp_timer/include/esp_timer.h"
@ -66,7 +66,7 @@ STATIC bool woke_up = false;
STATIC void timer_callback(void *arg) {
(void)arg;
woke_up = true;
xTaskNotifyGive(circuitpython_task);
port_wake_main_task();
}
bool alarm_time_timealarm_woke_this_cycle(void) {

View File

@ -30,7 +30,7 @@
#include "esp_sleep.h"
#include "peripherals/touch.h"
#include "supervisor/esp_port.h"
#include "supervisor/port.h"
static uint16_t touch_channel_mask;
static volatile bool woke_up = false;
@ -86,11 +86,7 @@ mp_obj_t alarm_touch_touchalarm_create_wakeup_alarm(void) {
STATIC void touch_interrupt(void *arg) {
(void)arg;
woke_up = true;
BaseType_t task_wakeup;
vTaskNotifyGiveFromISR(circuitpython_task, &task_wakeup);
if (task_wakeup) {
portYIELD_FROM_ISR();
}
port_wake_main_task_from_isr();
}
void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms) {

View File

@ -204,5 +204,9 @@ mp_obj_t common_hal_mdns_server_find(mdns_server_obj_t *self, const char *servic
}
void common_hal_mdns_server_advertise_service(mdns_server_obj_t *self, const char *service_type, const char *protocol, mp_int_t port) {
mdns_service_add(NULL, service_type, protocol, port, NULL, 0);
if (mdns_service_exists(service_type, protocol, NULL)) {
mdns_service_port_set(service_type, protocol, port);
} else {
mdns_service_add(NULL, service_type, protocol, port, NULL, 0);
}
}

View File

@ -46,19 +46,7 @@ static const uint64_t pin_mask_reset_forbidden =
// Never ever reset serial pins for bootloader and possibly USB-serial converter.
GPIO_SEL_1 | // TXD0
GPIO_SEL_3 | // RXD0
// Never ever reset pins used to communicate with SPI flash and PSRAM.
GPIO_SEL_6 | // CLK
/////////TEMP
GPIO_SEL_7 | // SD0
GPIO_SEL_8 | // SD1
////////END TEMP
GPIO_SEL_9 | // (PSRAM) SD2
GPIO_SEL_10 | // (PSRAM) SD3
GPIO_SEL_11 | // CMD
GPIO_SEL_16 | // SPIHD
GPIO_SEL_17 | // SPIDO
GPIO_SEL_18 | // SPIWP
GPIO_SEL_23 | // SPIDI
// SPI flash and PSRAM pins are protected at runtime in supervisor/port.c.
#endif // ESP32
#if defined(CONFIG_IDF_TARGET_ESP32C3)

View File

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

View File

@ -0,0 +1,9 @@
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
# bootloader.bin,, 0x1000, 32K
# partition table,, 0x8000, 4K
nvs, data, nvs, 0x9000, 20K,
otadata, data, ota, 0xe000, 8K,
ota_0, 0, ota_0, 0x10000, 2048K,
ota_1, 0, ota_1, 0x210000, 2048K,
user_fs, data, fat, 0x410000, 12224K,
1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 # bootloader.bin,, 0x1000, 32K
4 # partition table,, 0x8000, 4K
5 nvs, data, nvs, 0x9000, 20K,
6 otadata, data, ota, 0xe000, 8K,
7 ota_0, 0, ota_0, 0x10000, 2048K,
8 ota_1, 0, ota_1, 0x210000, 2048K,
9 user_fs, data, fat, 0x410000, 12224K,

View File

@ -0,0 +1,18 @@
#
# Serial flasher config
#
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_ESPTOOLPY_FLASHSIZE="16MB"
CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
# end of Serial flasher config
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="esp-idf-config/partitions-16MB-no-uf2.csv"
#
# Partition Table
#
CONFIG_PARTITION_TABLE_FILENAME="esp-idf-config/partitions-16MB-no-uf2.csv"
# end of Partition Table

View File

@ -30,7 +30,6 @@
#include "supervisor/board.h"
#include "supervisor/port.h"
#include "py/runtime.h"
#include "supervisor/esp_port.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@ -82,11 +81,19 @@
#include "soc/cache_memory.h"
#endif
#include "soc/efuse_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "esp_debug_helpers.h"
#include "bootloader_flash_config.h"
#include "esp_efuse.h"
#include "esp_ipc.h"
#include "esp_rom_efuse.h"
#ifdef CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/efuse.h"
#endif
#ifdef CONFIG_SPIRAM
#include "esp32/spiram.h"
@ -135,6 +142,93 @@ STATIC void tick_timer_cb(void *arg) {
void sleep_timer_cb(void *arg);
// The ESP-IDF determines these pins at runtime so we do too. This code is based on:
// https://github.com/espressif/esp-idf/blob/6d85d53ceec30c818a92c2fff8f5437d21c4720f/components/esp_hw_support/port/esp32/spiram_psram.c#L810
// IO-pins for PSRAM.
// WARNING: PSRAM shares all but the CS and CLK pins with the flash, so these defines
// hardcode the flash pins as well, making this code incompatible with either a setup
// that has the flash on non-standard pins or ESP32s with built-in flash.
#define PSRAM_SPIQ_SD0_IO 7
#define PSRAM_SPID_SD1_IO 8
#define PSRAM_SPIWP_SD3_IO 10
#define PSRAM_SPIHD_SD2_IO 9
#define FLASH_HSPI_CLK_IO 14
#define FLASH_HSPI_CS_IO 15
#define PSRAM_HSPI_SPIQ_SD0_IO 12
#define PSRAM_HSPI_SPID_SD1_IO 13
#define PSRAM_HSPI_SPIWP_SD3_IO 2
#define PSRAM_HSPI_SPIHD_SD2_IO 4
// PSRAM clock and cs IO should be configured based on hardware design.
// For ESP32-WROVER or ESP32-WROVER-B module, the clock IO is IO17, the cs IO is IO16,
// they are the default value for these two configs.
#define D0WD_PSRAM_CLK_IO CONFIG_D0WD_PSRAM_CLK_IO // Default value is 17
#define D0WD_PSRAM_CS_IO CONFIG_D0WD_PSRAM_CS_IO // Default value is 16
#define D2WD_PSRAM_CLK_IO CONFIG_D2WD_PSRAM_CLK_IO // Default value is 9
#define D2WD_PSRAM_CS_IO CONFIG_D2WD_PSRAM_CS_IO // Default value is 10
// There is no reason to change the pin of an embedded psram.
// So define the number of pin directly, instead of configurable.
#define D0WDR2_V3_PSRAM_CLK_IO 6
#define D0WDR2_V3_PSRAM_CS_IO 16
// For ESP32-PICO chip, the psram share clock with flash. The flash clock pin is fixed, which is IO6.
#define PICO_PSRAM_CLK_IO 6
#define PICO_PSRAM_CS_IO CONFIG_PICO_PSRAM_CS_IO // Default value is 10
#define PICO_V3_02_PSRAM_CLK_IO 10
#define PICO_V3_02_PSRAM_CS_IO 9
static void _never_reset_spi_ram_flash(void) {
#if defined(CONFIG_IDF_TARGET_ESP32)
uint32_t pkg_ver = esp_efuse_get_pkg_ver();
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
never_reset_pin_number(D2WD_PSRAM_CLK_IO);
never_reset_pin_number(D2WD_PSRAM_CS_IO);
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4 && esp_efuse_get_chip_ver() >= 3) {
// This chip is ESP32-PICO-V3 and doesn't have PSRAM.
} else if ((pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) || (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4)) {
never_reset_pin_number(PICO_PSRAM_CLK_IO);
never_reset_pin_number(PICO_PSRAM_CS_IO);
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302) {
never_reset_pin_number(PICO_V3_02_PSRAM_CLK_IO);
never_reset_pin_number(PICO_V3_02_PSRAM_CS_IO);
} else if ((pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6) || (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ5)) {
never_reset_pin_number(D0WD_PSRAM_CLK_IO);
never_reset_pin_number(D0WD_PSRAM_CS_IO);
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D0WDR2V3) {
never_reset_pin_number(D0WDR2_V3_PSRAM_CLK_IO);
never_reset_pin_number(D0WDR2_V3_PSRAM_CS_IO);
}
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) {
never_reset_pin_number(SPI_IOMUX_PIN_NUM_CLK);
never_reset_pin_number(SPI_IOMUX_PIN_NUM_CS);
never_reset_pin_number(PSRAM_SPIQ_SD0_IO);
never_reset_pin_number(PSRAM_SPID_SD1_IO);
never_reset_pin_number(PSRAM_SPIWP_SD3_IO);
never_reset_pin_number(PSRAM_SPIHD_SD2_IO);
} else if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI) {
never_reset_pin_number(FLASH_HSPI_CLK_IO);
never_reset_pin_number(FLASH_HSPI_CS_IO);
never_reset_pin_number(PSRAM_HSPI_SPIQ_SD0_IO);
never_reset_pin_number(PSRAM_HSPI_SPID_SD1_IO);
never_reset_pin_number(PSRAM_HSPI_SPIWP_SD3_IO);
never_reset_pin_number(PSRAM_HSPI_SPIHD_SD2_IO);
} else {
never_reset_pin_number(EFUSE_SPICONFIG_RET_SPICLK(spiconfig));
never_reset_pin_number(EFUSE_SPICONFIG_RET_SPICS0(spiconfig));
never_reset_pin_number(EFUSE_SPICONFIG_RET_SPIQ(spiconfig));
never_reset_pin_number(EFUSE_SPICONFIG_RET_SPID(spiconfig));
never_reset_pin_number(EFUSE_SPICONFIG_RET_SPIHD(spiconfig));
never_reset_pin_number(bootloader_flash_get_wp_pin());
}
#endif
}
safe_mode_t port_init(void) {
esp_timer_create_args_t args;
args.callback = &tick_timer_cb;
@ -215,6 +309,8 @@ safe_mode_t port_init(void) {
}
#endif
_never_reset_spi_ram_flash();
if (heap == NULL) {
size_t heap_total = heap_caps_get_total_size(MALLOC_CAP_8BIT);
heap_size = MIN(heap_caps_get_largest_free_block(MALLOC_CAP_8BIT), heap_total / 2);
@ -390,6 +486,14 @@ void port_wake_main_task() {
xTaskNotifyGive(circuitpython_task);
}
void port_wake_main_task_from_isr() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
vTaskNotifyGiveFromISR(circuitpython_task, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken == pdTRUE) {
portYIELD_FROM_ISR();
}
}
void sleep_timer_cb(void *arg) {
port_wake_main_task();
}

View File

@ -27,7 +27,6 @@
#include "py/runtime.h"
#include "supervisor/usb.h"
#include "supervisor/esp_port.h"
#include "supervisor/port.h"
#include "shared/runtime/interrupt_char.h"
#include "shared/readline/readline.h"

View File

@ -28,19 +28,46 @@
#include "py/ringbuf.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "usb_serial_jtag.h"
#include "supervisor/port.h"
#include "supervisor/usb_serial_jtag.h"
#include "hal/usb_serial_jtag_ll.h"
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
#include "supervisor/esp_port.h"
#define USB_SERIAL_JTAG_BUF_SIZE (64)
STATIC ringbuf_t ringbuf;
STATIC uint8_t buf[128];
STATIC bool connected;
STATIC volatile bool connected;
#if CIRCUITPY_ESP_USB_SERIAL_JTAG && !CONFIG_ESP_PHY_ENABLE_USB
#error "CONFIG_ESP_PHY_ENABLE_USB must be enabled in sdkconfig"
#endif
// Make sure the recv interrupt is disabled during this. Otherwise, it could reorder data if it
// interrupts itself.
static void _copy_out_of_fifo(void) {
size_t req_len = ringbuf_num_empty(&ringbuf);
if (req_len == 0) {
// Disable the interrupt so that CircuitPython can run and process the ringbuf. It will
// re-enable the interrupt once the ringbuf is empty.
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
}
if (req_len > USB_SERIAL_JTAG_BUF_SIZE) {
req_len = USB_SERIAL_JTAG_BUF_SIZE;
}
uint8_t rx_buf[USB_SERIAL_JTAG_BUF_SIZE];
size_t len = usb_serial_jtag_ll_read_rxfifo(rx_buf, req_len);
for (size_t i = 0; i < len; ++i) {
if (rx_buf[i] == mp_interrupt_char) {
mp_sched_keyboard_interrupt();
} else {
ringbuf_put(&ringbuf, rx_buf[i]);
}
}
}
static void usb_serial_jtag_isr_handler(void *arg) {
uint32_t flags = usb_serial_jtag_ll_get_intsts_mask();
@ -49,40 +76,27 @@ static void usb_serial_jtag_isr_handler(void *arg) {
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SOF);
}
if (flags & USB_SERIAL_JTAG_INTR_TOKEN_REC_IN_EP1) {
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_TOKEN_REC_IN_EP1);
connected = true;
}
if (flags & USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT) {
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
size_t req_len = ringbuf_num_empty(&ringbuf);
if (req_len > USB_SERIAL_JTAG_BUF_SIZE) {
req_len = USB_SERIAL_JTAG_BUF_SIZE;
}
uint8_t rx_buf[USB_SERIAL_JTAG_BUF_SIZE];
size_t len = usb_serial_jtag_ll_read_rxfifo(rx_buf, req_len);
for (size_t i = 0; i < len; ++i) {
if (rx_buf[i] == mp_interrupt_char) {
mp_sched_keyboard_interrupt();
} else {
ringbuf_put(&ringbuf, rx_buf[i]);
}
}
vTaskNotifyGiveFromISR(circuitpython_task, NULL);
_copy_out_of_fifo();
port_wake_main_task_from_isr();
}
}
void usb_serial_jtag_init(void) {
ringbuf_init(&ringbuf, buf, sizeof(buf));
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SOF | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SOF | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
ringbuf_init(&ringbuf, buf, sizeof(buf) - 1);
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SOF | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT | USB_SERIAL_JTAG_INTR_TOKEN_REC_IN_EP1);
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SOF | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT | USB_SERIAL_JTAG_INTR_TOKEN_REC_IN_EP1);
ESP_ERROR_CHECK(esp_intr_alloc(ETS_USB_SERIAL_JTAG_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1,
usb_serial_jtag_isr_handler, NULL, NULL));
}
bool usb_serial_jtag_connected(void) {
// Make connected sticky. Otherwise we'll be disconnected every time the SOF
// index is 0. (It's only ~15 bits so it wraps around frequently.)
if (connected) {
return true;
}
connected = USB_SERIAL_JTAG.fram_num.sof_frame_index > 0;
return connected;
}
@ -90,22 +104,38 @@ char usb_serial_jtag_read_char(void) {
if (ringbuf_num_filled(&ringbuf) == 0) {
return -1;
}
return ringbuf_get(&ringbuf);
char c = ringbuf_get(&ringbuf);
// Maybe re-enable the recv interrupt if we've emptied the ringbuf.
if (ringbuf_num_filled(&ringbuf) == 0) {
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
_copy_out_of_fifo();
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
}
return c;
}
bool usb_serial_jtag_bytes_available(void) {
return ringbuf_num_filled(&ringbuf);
return ringbuf_num_filled(&ringbuf) > 0;
}
void usb_serial_jtag_write(const char *text, uint32_t length) {
if (USB_SERIAL_JTAG.fram_num.sof_frame_index > 0) {
size_t total_written = 0;
uint32_t start_time = supervisor_ticks_ms32();
// Time out after 5 milliseconds in case usb isn't actually reading CDC.
while (total_written < length && start_time - supervisor_ticks_ms32() < 5) {
total_written += usb_serial_jtag_ll_write_txfifo((const uint8_t *)(text + total_written), length - total_written);
RUN_BACKGROUND_TASKS;
}
usb_serial_jtag_ll_txfifo_flush();
if (!usb_serial_jtag_connected()) {
return;
}
size_t total_written = 0;
while (total_written < length) {
uint32_t start_time = supervisor_ticks_ms32();
// Wait until we can write to the FIFO again. If it takes too long, then
// assume we're disconnected.
while (!usb_serial_jtag_ll_txfifo_writable()) {
uint32_t now = supervisor_ticks_ms32();
if (now - start_time > 200) {
connected = false;
return;
}
}
total_written += usb_serial_jtag_ll_write_txfifo((const uint8_t *)(text + total_written), length - total_written);
RUN_BACKGROUND_TASKS;
}
usb_serial_jtag_ll_txfifo_flush();
}

View File

@ -22,6 +22,7 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_SW_A), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_GPIO18) },

View File

@ -161,6 +161,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mdns_server_find_obj, 1, _mdns_server_find);
//| def advertise_service(self, *, service_type: str, protocol: str, port: int) -> None:
//| """Respond to queries for the given service with the given port.
//|
//| ``service_type`` and ``protocol`` can only occur on one port. Any call after the first
//| will update the entry's port.
//|
//| :param str service_type: The service type such as "_http"
//| :param str protocol: The service protocol such as "_tcp"
//| :param int port: The port used by the service"""

View File

@ -177,6 +177,17 @@ int readline_process_char(int c) {
vstr_cut_tail_bytes(rl.line, rl.line->len - rl.cursor_pos);
// set redraw parameters
redraw_from_cursor = true;
#endif
} else if (c == CHAR_CTRL_L) {
// CTRL-L is clear screen / redraw. This specific sequence is used
// (instead of a slightly more minimal sequence) for compatibility
// with the built-in Terminal class
mp_hal_stdout_tx_str("\x1b[;H\x1b[2J");
mp_hal_stdout_tx_str(rl.prompt);
mp_hal_stdout_tx_strn(rl.line->buf + rl.orig_line_len, rl.cursor_pos - rl.orig_line_len);
// set redraw parameters
redraw_from_cursor = true;
#if MICROPY_REPL_EMACS_KEYS
} else if (c == CHAR_CTRL_N) {
// CTRL-N is go to next line in history
goto down_arrow_key;

View File

@ -35,6 +35,7 @@
#define CHAR_CTRL_E (5)
#define CHAR_CTRL_F (6)
#define CHAR_CTRL_K (11)
#define CHAR_CTRL_L (12)
#define CHAR_CTRL_N (14)
#define CHAR_CTRL_P (16)
#define CHAR_CTRL_U (21)

View File

@ -99,8 +99,14 @@ void port_background_task(void);
void port_start_background_task(void);
void port_finish_background_task(void);
// Some ports need special handling to wake the main task from an interrupt
// context or other task. The port must implement the necessary code in this
// function. A default weak implementation is provided that does nothing.
// Some ports need special handling to wake the main task from another task. The
// port must implement the necessary code in this function. A default weak
// implementation is provided that does nothing.
void port_wake_main_task(void);
// Some ports need special handling to wake the main task from an interrupt
// context. The port must implement the necessary code in this function. A
// default weak implementation is provided that does nothing.
void port_wake_main_task_from_isr(void);
#endif // MICROPY_INCLUDED_SUPERVISOR_PORT_H

View File

@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
* 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
@ -24,12 +24,10 @@
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESPRESSIF_SUPERVISOR_PORT_H
#define MICROPY_INCLUDED_ESPRESSIF_SUPERVISOR_PORT_H
#include "supervisor/port.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
MP_WEAK void port_wake_main_task(void) {
}
extern TaskHandle_t circuitpython_task;
#endif // MICROPY_INCLUDED_ESPRESSIF_SUPERVISOR_PORT_H
MP_WEAK void port_wake_main_task_from_isr(void) {
}

View File

@ -207,10 +207,17 @@ char serial_read(void) {
#if CIRCUITPY_WEB_WORKFLOW
if (websocket_available()) {
return websocket_read_char();
char c = websocket_read_char();
if (c != -1) {
return c;
}
}
#endif
if (port_serial_bytes_available() > 0) {
return port_serial_read();
}
#if CIRCUITPY_USB_CDC
if (!usb_cdc_console_enabled()) {
return -1;
@ -220,9 +227,6 @@ char serial_read(void) {
return (char)tud_cdc_read_char();
#endif
if (port_serial_bytes_available() > 0) {
return port_serial_read();
}
return -1;
}

View File

@ -0,0 +1,106 @@
/*
* 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 <stdbool.h>
#include "genhdr/mpversion.h"
#include "py/mpconfig.h"
#include "supervisor/background_callback.h"
#include "supervisor/serial.h"
#include "supervisor/shared/title_bar.h"
#if CIRCUITPY_WEB_WORKFLOW
#include "supervisor/shared/web_workflow/web_workflow.h"
#endif
static background_callback_t title_bar_background_cb;
static bool _forced_dirty = false;
static bool _suspended = false;
static void title_bar_background(void *data) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
if (_suspended) {
return;
}
bool dirty = _forced_dirty;
#if CIRCUITPY_WEB_WORKFLOW
dirty = dirty || supervisor_web_workflow_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" "\\");
}
void supervisor_title_bar_start(void) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
title_bar_background_cb.fun = title_bar_background;
title_bar_background_cb.data = NULL;
supervisor_title_bar_request_update(true);
}
void supervisor_title_bar_request_update(bool force_dirty) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
if (force_dirty) {
_forced_dirty = true;
}
background_callback_add_core(&title_bar_background_cb);
}
void supervisor_title_bar_suspend(void) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
_suspended = true;
}
void supervisor_title_bar_resume(void) {
#if !CIRCUITPY_STATUS_BAR
return;
#endif
_suspended = false;
supervisor_title_bar_request_update(false);
}

View File

@ -0,0 +1,34 @@
/*
* 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_title_bar_start(void);
void supervisor_title_bar_suspend(void);
void supervisor_title_bar_resume(void);
void supervisor_title_bar_request_update(bool force_dirty);

View File

@ -4,11 +4,13 @@
<title></title>
<meta charset="UTF-8">
<script src="/directory.js" defer=true></script>
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet" href="http://circuitpython.org/assets/css/webworkflow-8.css">
</head>
<body>
<h1><a href="/"><img src="/favicon.ico"/></a>&nbsp;<span id="path"></span></h1>
<div id="usbwarning" style="display: none;">🛈 USB is using the storage. Only allowing reads. See <a href="https://learn.adafruit.com/circuitpython-essentials/circuitpython-storage">the CircuitPython Essentials: Storage guide</a> for details.</div>
<template id="row"><tr><td></td><td></td><td><a></a></td><td></td><td><button class="delete">🗑️</button></td></tr></template>
<template id="row"><tr><td></td><td></td><td><a></a></td><td></td><td><button class="delete">🗑️</button></td><td><a class="edit_link" href="">Edit</a></td></tr></template>
<table>
<thead><tr><th>Type</th><th>Size</th><th>Path</th><th>Modified</th><th></th></tr></thead>
<tbody></tbody>

View File

@ -63,6 +63,7 @@ async function refresh_list() {
var icon = "⬇";
var file_path = current_path + f.name;
let api_url = new URL("/fs" + file_path, url_base);
let edit_url = "/edit/#" + file_path;
if (f.directory) {
file_path = "#" + file_path + "/";
api_url += "/";
@ -91,6 +92,9 @@ async function refresh_list() {
delete_button.disabled = !editable;
delete_button.onclick = del;
edit_url = new URL(edit_url, url_base);
let edit_link = clone.querySelector(".edit_link");
edit_link.href = edit_url
new_children.push(clone);
}

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Code Edit</title>
<link rel="stylesheet" href="http://circuitpython.org/assets/css/webworkflow-8.css">
<link rel="stylesheet" href="/style.css">
</head>
<body>
<button id="save_btn">Save</button>
<p id="output_text">Loading</p>
<textarea id="code_textarea"></textarea>
<script src="/edit.js" defer=true></script>
</body>
</html>

View File

@ -0,0 +1,47 @@
let $editor = document.querySelector("#code_textarea");
let filename = location.hash.substring(1);
let $output_text = document.querySelector("#output_text");
fetch(`/fs/${filename}`)
.then(function (response) {
$output_text.innerText = `Loading Status: ${response.status}`;
return response.status === 200 ? response.text() : "";
})
.then(function (data) {
$editor.value = data;
});
function save() {
$output_text.innerText = "Saving..."
const requestOptions = {
method: 'PUT',
body: $editor.value
};
fetch(`/fs/${filename}`, requestOptions)
.then(function (response) {
$output_text.innerText = `Saving Status: ${response.status}`;
return response.text();
})
.then(function (data) {
console.log("after fetch: " + data);
});
}
document.querySelector("#save_btn").onclick = function () {
console.log("Click Save!");
save();
}
let isCtrl = false;
document.onkeyup=function(e){
if(e.keyCode === 17) isCtrl=false;
}
document.onkeydown=function(e){
if(e.keyCode === 17) isCtrl=true;
if(e.keyCode === 83 && isCtrl === true) {
//ctrl-s pressed
save();
return false;
}
}

View File

@ -5,6 +5,8 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="/serial.js" defer=true></script>
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet" href="http://circuitpython.org/assets/css/webworkflow-8.css">
</head>
<body style="flex-direction: column; display: flex; height: 100%; width: 100%; margin: 0; font-size: 1rem;">
<div style="flex: auto; display: flex; overflow: auto; flex-direction: column;">

View File

@ -63,10 +63,12 @@ input.addEventListener("beforeinput", function(e) {
input.value = "";
input.focus();
e.preventDefault();
} else if (e.inputType == "insertText") {
} else if (e.inputType == "insertText" || e.inputType == "insertFromPaste") {
ws.send(e.data);
} else if (e.inputType == "deleteContentBackward") {
ws.send("\b");
} else {
console.log(e);
}
});

View File

@ -0,0 +1,19 @@
body {
max-width: 960px;
margin: 20px auto;
font-size: 18px;
font-family: "Proxima Nova", Verdana, sans-serif;
line-height: 20.7px;
}
/* for edit.html */
#code_textarea {
width: 90%;
height: 600px;
}
#output_text {
margin: 0;
font-size: 0.7em;
}

View File

@ -5,17 +5,29 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="/welcome.js" defer=true></script>
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet" href="http://circuitpython.org/assets/css/webworkflow-8.css">
</head>
<body>
<h1><a href="/"><img src="/favicon.ico"/></a>&nbsp;Welcome!</h1>
Welcome to CircuitPython's Web API. Go to the <a href="/fs/">file browser</a> to work with files in the CIRCUITPY drive. Go to the <a href="/cp/serial/">serial terminal</a> to see code output and interact with the REPL. Make sure you've set <code>CIRCUITPY_WEB_API_PASSWORD='somepassword'</code> in <code>/.env</code>. Provide the password when the browser prompts for it. Leave the username blank.
<h2>Device Info</h2>
Board: <a id="board"></a><br>
Version: <span id="version"></span><br>
Hostname: <a id="hostname"></a><br>
IP: <a id="ip"></a>
<h2>Other Devices</h2>
Here are other CircuitPython devices on your network:
<p>Welcome to CircuitPython's Web API. Go to the <a href="/fs/">file browser</a> to work with files in the CIRCUITPY drive. Go to the <a href="/cp/serial/">serial terminal</a> to see code output and interact with the REPL. Make sure you've set <code>CIRCUITPY_WEB_API_PASSWORD='somepassword'</code> in <code>/.env</code>. Provide the password when the browser prompts for it. <strong>Leave the username blank.</strong></p>
<h2>Device Info:</h2>
<dl>
<dt>Board:</dt>
<dd><a id="board"></a></dd>
<dt>Version:</dt>
<dd><span id="version"></span></dd>
<dt>Hostname:</dt>
<dd><a id="hostname"></a></dd>
<dt>IP:</dt>
<dd><a id="ip"></a></dd>
</dl>
<h2>Here are other CircuitPython devices on your network:</h2>
<ul id="devices">
</ul>
</body>

View File

@ -44,7 +44,7 @@ async function find_devices() {
li.appendChild(a);
var port = "";
if (device.port != 80) {
port = ":" + version_info.port;
port = ":" + device.port;
}
var server;
if (mdns_works) {

View File

@ -95,9 +95,15 @@ typedef struct {
char websocket_key[24 + 1];
} _request;
static wifi_radio_error_t wifi_status = WIFI_RADIO_ERROR_NONE;
static wifi_radio_error_t _wifi_status = WIFI_RADIO_ERROR_NONE;
// Store last status state to compute dirty.
static bool _last_enabled = false;
static uint32_t _last_ip = 0;
static wifi_radio_error_t _last_wifi_status = WIFI_RADIO_ERROR_NONE;
static mdns_server_obj_t mdns;
static uint32_t web_api_port = 80;
static socketpool_socketpool_obj_t pool;
static socketpool_socket_obj_t listening;
@ -107,6 +113,7 @@ static _request active_request;
static char _api_password[64];
// Store the encoded IP so we don't duplicate work.
static uint32_t _encoded_ip = 0;
static char _our_ip_encoded[4 * 4];
@ -169,26 +176,45 @@ static bool _base64_in_place(char *buf, size_t in_len, size_t out_len) {
return true;
}
STATIC void _update_encoded_ip(void) {
uint32_t ipv4_address = 0;
if (common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj)) {
ipv4_address = wifi_radio_get_ipv4_address(&common_hal_wifi_radio_obj);
}
if (_encoded_ip != ipv4_address) {
uint8_t *octets = (uint8_t *)&ipv4_address;
snprintf(_our_ip_encoded, sizeof(_our_ip_encoded), "%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3]);
_encoded_ip = ipv4_address;
}
}
bool supervisor_web_workflow_status_dirty(void) {
return common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) != _last_enabled ||
_encoded_ip != _last_ip ||
_last_wifi_status != _wifi_status;
}
void supervisor_web_workflow_status(void) {
serial_write_compressed(translate("Wi-Fi: "));
if (common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj)) {
_last_enabled = common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj);
if (_last_enabled) {
uint32_t ipv4_address = wifi_radio_get_ipv4_address(&common_hal_wifi_radio_obj);
if (wifi_status == WIFI_RADIO_ERROR_AUTH_EXPIRE ||
wifi_status == WIFI_RADIO_ERROR_AUTH_FAIL) {
_last_wifi_status = _wifi_status;
if (_wifi_status == WIFI_RADIO_ERROR_AUTH_EXPIRE ||
_wifi_status == WIFI_RADIO_ERROR_AUTH_FAIL) {
serial_write_compressed(translate("Authentication failure"));
} else if (wifi_status != WIFI_RADIO_ERROR_NONE) {
mp_printf(&mp_plat_print, "%d", wifi_status);
} else if (_wifi_status != WIFI_RADIO_ERROR_NONE) {
mp_printf(&mp_plat_print, "%d", _wifi_status);
} else if (ipv4_address == 0) {
_last_ip = 0;
serial_write_compressed(translate("No IP"));
} else {
if (_encoded_ip != ipv4_address) {
uint8_t *octets = (uint8_t *)&ipv4_address;
snprintf(_our_ip_encoded, sizeof(_our_ip_encoded), "%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3]);
_encoded_ip = ipv4_address;
}
_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 {
@ -199,11 +225,6 @@ void supervisor_web_workflow_status(void) {
void supervisor_start_web_workflow(void) {
#if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI
if (common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) &&
wifi_radio_get_ipv4_address(&common_hal_wifi_radio_obj) != 0) {
// Already started.
return;
}
char ssid[33];
char password[64];
@ -218,8 +239,10 @@ void supervisor_start_web_workflow(void) {
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);
if (!common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj)) {
common_hal_wifi_init(false);
common_hal_wifi_radio_set_enabled(&common_hal_wifi_radio_obj, true);
}
// TODO: Do our own scan so that we can find the channel we want before calling connect.
// Otherwise, connect will do a full slow scan to pick the best AP.
@ -227,30 +250,59 @@ void supervisor_start_web_workflow(void) {
// NUL terminate the strings because dotenv doesn't.
ssid[ssid_len] = '\0';
password[password_len] = '\0';
wifi_status = common_hal_wifi_radio_connect(
// We can all connect again because it will return early if we're already connected to the
// network. If we are connected to a different network, then it will disconnect before
// attempting to connect to the given network.
_wifi_status = common_hal_wifi_radio_connect(
&common_hal_wifi_radio_obj, (uint8_t *)ssid, ssid_len, (uint8_t *)password, password_len,
0, 0.1, NULL, 0);
if (wifi_status != WIFI_RADIO_ERROR_NONE) {
if (_wifi_status != WIFI_RADIO_ERROR_NONE) {
common_hal_wifi_radio_set_enabled(&common_hal_wifi_radio_obj, false);
return;
}
mdns_server_construct(&mdns, true);
common_hal_mdns_server_set_instance_name(&mdns, MICROPY_HW_BOARD_NAME);
common_hal_mdns_server_advertise_service(&mdns, "_circuitpython", "_tcp", 80);
char port_encoded[6];
size_t port_len = 0;
size_t new_port = web_api_port;
#if CIRCUITPY_DOTENV
port_len = dotenv_get_key("/.env", "CIRCUITPY_WEB_API_PORT", port_encoded, sizeof(port_encoded) - 1);
#endif
if (0 < port_len && port_len < sizeof(port_encoded)) {
port_encoded[port_len] = '\0';
new_port = strtoul(port_encoded, NULL, 10);
}
pool.base.type = &socketpool_socketpool_type;
common_hal_socketpool_socketpool_construct(&pool, &common_hal_wifi_radio_obj);
bool first_start = mdns.base.type != &mdns_server_type;
bool port_changed = new_port != web_api_port;
ESP_LOGI(TAG, "Starting web workflow");
listening.base.type = &socketpool_socket_type;
socketpool_socket(&pool, SOCKETPOOL_AF_INET, SOCKETPOOL_SOCK_STREAM, &listening);
common_hal_socketpool_socket_settimeout(&listening, 0);
// Bind to any ip.
// TODO: Make this port .env configurable.
common_hal_socketpool_socket_bind(&listening, "", 0, 80);
common_hal_socketpool_socket_listen(&listening, 1);
if (first_start) {
ESP_LOGI(TAG, "Starting web workflow");
mdns_server_construct(&mdns, true);
mdns.base.type = &mdns_server_type;
common_hal_mdns_server_set_instance_name(&mdns, MICROPY_HW_BOARD_NAME);
pool.base.type = &socketpool_socketpool_type;
common_hal_socketpool_socketpool_construct(&pool, &common_hal_wifi_radio_obj);
listening.base.type = &socketpool_socket_type;
active.base.type = &socketpool_socket_type;
active.num = -1;
active.connected = false;
websocket_init();
}
if (port_changed) {
common_hal_socketpool_socket_close(&listening);
}
if (first_start || port_changed) {
web_api_port = new_port;
common_hal_mdns_server_advertise_service(&mdns, "_circuitpython", "_tcp", web_api_port);
socketpool_socket(&pool, SOCKETPOOL_AF_INET, SOCKETPOOL_SOCK_STREAM, &listening);
common_hal_socketpool_socket_settimeout(&listening, 0);
// Bind to any ip.
common_hal_socketpool_socket_bind(&listening, "", 0, web_api_port);
common_hal_socketpool_socket_listen(&listening, 1);
}
mp_int_t api_password_len = dotenv_get_key("/.env", "CIRCUITPY_WEB_API_PASSWORD", _api_password + 1, sizeof(_api_password) - 2);
if (api_password_len > 0) {
@ -259,15 +311,7 @@ void supervisor_start_web_workflow(void) {
_base64_in_place(_api_password, api_password_len + 1, sizeof(_api_password));
}
active.base.type = &socketpool_socket_type;
active.num = -1;
active.connected = false;
websocket_init();
// TODO:
// GET /cp/serial.txt
// - Most recent 1k of serial output.
// GET /edit/
// - Super basic editor
#endif
@ -283,6 +327,10 @@ static void _send_raw(socketpool_socket_obj_t *socket, const uint8_t *buf, int l
}
}
STATIC void _print_raw(void *env, const char *str, size_t len) {
_send_raw((socketpool_socket_obj_t *)env, (const uint8_t *)str, (size_t)len);
}
static void _send_str(socketpool_socket_obj_t *socket, const char *str) {
_send_raw(socket, (const uint8_t *)str, strlen(str));
}
@ -301,14 +349,19 @@ static void _send_strs(socketpool_socket_obj_t *socket, ...) {
}
static void _send_chunk(socketpool_socket_obj_t *socket, const char *chunk) {
char encoded_len[sizeof(size_t) * 2 + 1];
int len = snprintf(encoded_len, sizeof(encoded_len), "%X", strlen(chunk));
_send_raw(socket, (const uint8_t *)encoded_len, len);
_send_raw(socket, (const uint8_t *)"\r\n", 2);
mp_print_t _socket_print = {socket, _print_raw};
mp_printf(&_socket_print, "%X\r\n", strlen(chunk));
_send_raw(socket, (const uint8_t *)chunk, strlen(chunk));
_send_raw(socket, (const uint8_t *)"\r\n", 2);
}
STATIC void _print_chunk(void *env, const char *str, size_t len) {
mp_print_t _socket_print = {env, _print_raw};
mp_printf(&_socket_print, "%X\r\n", len);
_send_raw((socketpool_socket_obj_t *)env, (const uint8_t *)str, len);
_send_raw((socketpool_socket_obj_t *)env, (const uint8_t *)"\r\n", 2);
}
// A bit of a misnomer because it sends all arguments as one chunk.
// The last argument must be NULL! Otherwise, it won't stop.
static void _send_chunks(socketpool_socket_obj_t *socket, ...) {
@ -326,9 +379,9 @@ static void _send_chunks(socketpool_socket_obj_t *socket, ...) {
}
va_end(strs_to_count);
char encoded_len[sizeof(size_t) * 2 + 1];
snprintf(encoded_len, sizeof(encoded_len), "%X", chunk_len);
_send_strs(socket, encoded_len, "\r\n", NULL);
mp_print_t _socket_print = {socket, _print_raw};
mp_printf(&_socket_print, "%X\r\n", chunk_len);
str = va_arg(strs_to_send, const char *);
while (str != NULL) {
@ -373,6 +426,7 @@ static bool _origin_ok(const char *origin) {
return true;
}
_update_encoded_ip();
end = origin + strlen(http) + strlen(_our_ip_encoded);
if (strncmp(origin + strlen(http), _our_ip_encoded, strlen(_our_ip_encoded)) == 0 &&
(end[0] == '\0' || end[0] == ':')) {
@ -438,7 +492,7 @@ static void _reply_access_control(socketpool_socket_obj_t *socket, _request *req
"HTTP/1.1 204 No Content\r\n",
"Content-Length: 0\r\n",
"Access-Control-Expose-Headers: Access-Control-Allow-Methods\r\n",
"Access-Control-Allow-Headers: X-Timestamp, Content-Type\r\n",
"Access-Control-Allow-Headers: X-Timestamp, Content-Type, Authorization\r\n",
"Access-Control-Allow-Methods:GET, OPTIONS", NULL);
if (!_usb_active()) {
_send_str(socket, ", PUT, DELETE");
@ -531,7 +585,12 @@ static void _reply_redirect(socketpool_socket_obj_t *socket, _request *request,
_send_str(socket, "http");
}
_send_strs(socket, "://", hostname, ".local", path, "\r\n", NULL);
_send_strs(socket, "://", hostname, ".local", NULL);
if (web_api_port != 80) {
mp_print_t _socket_print = {socket, _print_raw};
mp_printf(&_socket_print, ":%d", web_api_port);
}
_send_strs(socket, path, "\r\n", NULL);
_cors_header(socket, request);
_send_str(socket, "\r\n");
}
@ -540,6 +599,7 @@ static void _reply_directory_json(socketpool_socket_obj_t *socket, _request *req
socketpool_socket_send(socket, (const uint8_t *)OK_JSON, strlen(OK_JSON));
_cors_header(socket, request);
_send_str(socket, "\r\n");
mp_print_t _socket_print = {socket, _print_chunk};
_send_chunk(socket, "[");
bool first = true;
@ -560,24 +620,24 @@ static void _reply_directory_json(socketpool_socket_obj_t *socket, _request *req
}
// We use nanoseconds past Jan 1, 1970 for consistency with BLE API and
// LittleFS.
_send_chunk(socket, ", \"modified_ns\": ");
_send_chunk(socket, ", ");
uint64_t truncated_time = timeutils_mktime(1980 + (file_info.fdate >> 9),
uint32_t truncated_time = timeutils_mktime(1980 + (file_info.fdate >> 9),
(file_info.fdate >> 5) & 0xf,
file_info.fdate & 0x1f,
file_info.ftime >> 11,
(file_info.ftime >> 5) & 0x1f,
(file_info.ftime & 0x1f) * 2) * 1000000000ULL;
(file_info.ftime & 0x1f) * 2);
char encoded_number[32];
snprintf(encoded_number, sizeof(encoded_number), "%lld", truncated_time);
_send_chunks(socket, encoded_number, ", \"file_size\": ", NULL);
// Manually append zeros to make the time nanoseconds. Support for printing 64 bit numbers
// varies across chipsets.
mp_printf(&_socket_print, "\"modified_ns\": %lu000000000, ", truncated_time);
size_t file_size = 0;
if ((file_info.fattrib & AM_DIR) == 0) {
file_size = file_info.fsize;
}
snprintf(encoded_number, sizeof(encoded_number), "%d", file_size);
_send_chunks(socket, encoded_number, "}", NULL);
mp_printf(&_socket_print, "\"file_size\": %d }", file_size);
first = false;
res = f_readdir(dir, &file_info);
}
@ -587,12 +647,10 @@ static void _reply_directory_json(socketpool_socket_obj_t *socket, _request *req
static void _reply_with_file(socketpool_socket_obj_t *socket, _request *request, const char *filename, FIL *active_file) {
uint32_t total_length = f_size(active_file);
char encoded_len[10];
snprintf(encoded_len, sizeof(encoded_len), "%d", total_length);
_send_strs(socket,
"HTTP/1.1 200 OK\r\n",
"Content-Length: ", encoded_len, "\r\n", NULL);
_send_str(socket, "HTTP/1.1 200 OK\r\n");
mp_print_t _socket_print = {socket, _print_raw};
mp_printf(&_socket_print, "Content-Length: %d\r\n", total_length);
// TODO: Make this a table to save space.
if (_endswith(filename, ".txt") || _endswith(filename, ".py")) {
_send_str(socket, "Content-Type: text/plain\r\n");
@ -640,27 +698,23 @@ static void _reply_with_devices_json(socketpool_socket_obj_t *socket, _request *
socketpool_socket_send(socket, (const uint8_t *)OK_JSON, strlen(OK_JSON));
_cors_header(socket, request);
_send_str(socket, "\r\n");
char total_encoded[4];
snprintf(total_encoded, sizeof(total_encoded), "%d", total_results);
_send_chunks(socket, "{\"total\": ", total_encoded, ", \"devices\": [", NULL);
mp_print_t _socket_print = {socket, _print_chunk};
mp_printf(&_socket_print, "{\"total\": %d, \"devices\": [", total_results);
for (size_t i = 0; i < count; i++) {
if (i > 0) {
_send_chunk(socket, ",");
}
const char *hostname = common_hal_mdns_remoteservice_get_hostname(&found_devices[i]);
const char *instance_name = common_hal_mdns_remoteservice_get_instance_name(&found_devices[i]);
char port_encoded[4];
int port = common_hal_mdns_remoteservice_get_port(&found_devices[i]);
snprintf(port_encoded, sizeof(port_encoded), "%d", port);
char ip_encoded[4 * 4];
uint32_t ipv4_address = mdns_remoteservice_get_ipv4_address(&found_devices[i]);
uint8_t *octets = (uint8_t *)&ipv4_address;
snprintf(ip_encoded, sizeof(ip_encoded), "%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3]);
_send_chunks(socket,
"{\"hostname\": \"", hostname, "\", ",
"\"instance_name\": \"", instance_name, "\", ",
"\"port\": ", port_encoded, ", ",
"\"ip\": \"", ip_encoded, "\"}", NULL);
mp_printf(&_socket_print,
"{\"hostname\": \"%s\", "
"\"instance_name\": \"%s\", "
"\"port\": %d, "
"\"ip\": \"%d.%d.%d.%d\"}", hostname, instance_name, port, octets[0], octets[1], octets[2], octets[3]);
common_hal_mdns_remoteservice_deinit(&found_devices[i]);
}
_send_chunk(socket, "]}");
@ -672,24 +726,23 @@ static void _reply_with_version_json(socketpool_socket_obj_t *socket, _request *
_send_str(socket, OK_JSON);
_cors_header(socket, request);
_send_str(socket, "\r\n");
char encoded_creator_id[11]; // 2 ** 32 is 10 decimal digits plus one for \0
snprintf(encoded_creator_id, sizeof(encoded_creator_id), "%u", CIRCUITPY_CREATOR_ID);
char encoded_creation_id[11]; // 2 ** 32 is 10 decimal digits plus one for \0
snprintf(encoded_creation_id, sizeof(encoded_creation_id), "%u", CIRCUITPY_CREATION_ID);
mp_print_t _socket_print = {socket, _print_chunk};
const char *hostname = common_hal_mdns_server_get_hostname(&mdns);
_send_chunks(socket,
"{\"web_api_version\": 1, ",
"\"version\": \"", MICROPY_GIT_TAG, "\", ",
"\"build_date\": \"", MICROPY_BUILD_DATE, "\", ",
"\"board_name\": \"", MICROPY_HW_BOARD_NAME, "\", ",
"\"mcu_name\": \"", MICROPY_HW_MCU_NAME, "\", ",
"\"board_id\": \"", CIRCUITPY_BOARD_ID, "\", ",
"\"creator_id\": ", encoded_creator_id, ", ",
"\"creation_id\": ", encoded_creation_id, ", ",
"\"hostname\": \"", hostname, "\", ",
"\"port\": 80, ",
"\"ip\": \"", _our_ip_encoded,
"\"}", NULL);
_update_encoded_ip();
// Note: this leverages the fact that C concats consecutive string literals together.
mp_printf(&_socket_print,
"{\"web_api_version\": 1, "
"\"version\": \"" MICROPY_GIT_TAG "\", "
"\"build_date\": \"" MICROPY_BUILD_DATE "\", "
"\"board_name\": \"" MICROPY_HW_BOARD_NAME "\", "
"\"mcu_name\": \"" MICROPY_HW_MCU_NAME "\", "
"\"board_id\": \"" CIRCUITPY_BOARD_ID "\", "
"\"creator_id\": %u, "
"\"creation_id\": %u, "
"\"hostname\": \"%s\", "
"\"port\": %d, "
"\"ip\": \"%s\"}", CIRCUITPY_CREATOR_ID, CIRCUITPY_CREATION_ID, hostname, web_api_port, _our_ip_encoded);
// Empty chunk signals the end of the response.
_send_chunk(socket, "");
}
@ -861,6 +914,9 @@ STATIC_FILE(directory_html);
STATIC_FILE(directory_js);
STATIC_FILE(welcome_html);
STATIC_FILE(welcome_js);
STATIC_FILE(edit_html);
STATIC_FILE(edit_js);
STATIC_FILE(style_css);
STATIC_FILE(serial_html);
STATIC_FILE(serial_js);
STATIC_FILE(blinka_16x16_ico);
@ -1031,6 +1087,16 @@ static bool _reply(socketpool_socket_obj_t *socket, _request *request) {
}
}
}
} else if (strcmp(request->path, "/edit/") == 0) {
if (!request->authenticated) {
if (_api_password[0] != '\0') {
_reply_unauthorized(socket, request);
} else {
_reply_forbidden(socket, request);
}
} else {
_REPLY_STATIC(socket, request, edit_html);
}
} else if (strncmp(request->path, "/cp/", 4) == 0) {
const char *path = request->path + 3;
if (strcasecmp(request->method, "OPTIONS") == 0) {
@ -1070,6 +1136,10 @@ static bool _reply(socketpool_socket_obj_t *socket, _request *request) {
_REPLY_STATIC(socket, request, welcome_js);
} else if (strcmp(request->path, "/serial.js") == 0) {
_REPLY_STATIC(socket, request, serial_js);
} else if (strcmp(request->path, "/edit.js") == 0) {
_REPLY_STATIC(socket, request, edit_js);
} else if (strcmp(request->path, "/style.css") == 0) {
_REPLY_STATIC(socket, request, style_css);
} else if (strcmp(request->path, "/favicon.ico") == 0) {
// TODO: Autogenerate this based on the blinka bitmap and change the
// palette based on MAC address.
@ -1179,7 +1249,12 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
request->authenticated = strncmp(request->header_value, prefix, strlen(prefix)) == 0 &&
strcmp(_api_password, request->header_value + strlen(prefix)) == 0;
} else if (strcasecmp(request->header_key, "Host") == 0) {
request->redirect = strcmp(request->header_value, "circuitpython.local") == 0;
// Do a prefix check so that port is ignored. Length must be the same or the
// header ends in :.
const char *cp_local = "circuitpython.local";
request->redirect = strncmp(request->header_value, cp_local, strlen(cp_local)) == 0 &&
(strlen(request->header_value) == strlen(cp_local) ||
request->header_value[strlen(cp_local)] == ':');
} else if (strcasecmp(request->header_key, "Content-Length") == 0) {
request->content_length = strtoul(request->header_value, NULL, 10);
} else if (strcasecmp(request->header_key, "Expect") == 0) {

View File

@ -31,6 +31,7 @@
// This background function should be called repeatedly. It cannot be done based
// on events.
void supervisor_web_workflow_background(void);
bool supervisor_web_workflow_status_dirty(void);
void supervisor_web_workflow_status(void);
void supervisor_start_web_workflow(void);
void supervisor_stop_web_workflow(void);

View File

@ -26,6 +26,8 @@
#include "supervisor/shared/web_workflow/websocket.h"
#include "supervisor/shared/title_bar.h"
// TODO: Remove ESP specific stuff. For now, it is useful as we refine the server.
#include "esp_log.h"
@ -59,6 +61,9 @@ void websocket_handoff(socketpool_socket_obj_t *socket) {
// Mark the original socket object as closed without telling the lower level.
socket->connected = false;
socket->num = -1;
// Send the title bar for the new client.
supervisor_title_bar_request_update(true);
}
bool websocket_connected(void) {
@ -94,7 +99,7 @@ static void _read_next_frame_header(void) {
}
if (cp_serial.frame_index == 1 && _read_byte(&h)) {
cp_serial.frame_index++;
uint8_t len = h & 0xf;
uint8_t len = h & 0x7f;
cp_serial.masked = (h >> 7) == 1;
if (len <= 125) {
cp_serial.payload_remaining = len;
@ -194,7 +199,9 @@ bool websocket_available(void) {
char websocket_read_char(void) {
uint8_t c;
_read_next_payload_byte(&c);
if (!_read_next_payload_byte(&c)) {
c = -1;
}
return c;
}
@ -215,13 +222,20 @@ static void _websocket_send(_websocket *ws, const char *text, size_t len) {
}
frame_header[1] = payload_len;
_send_raw(&ws->socket, (const uint8_t *)frame_header, 2);
uint8_t extended_len[4];
if (payload_len == 126) {
_send_raw(&ws->socket, (const uint8_t *)&len, 2);
extended_len[0] = (len >> 8) & 0xff;
extended_len[1] = len & 0xff;
_send_raw(&ws->socket, extended_len, 2);
} else if (payload_len == 127) {
uint32_t zero = 0;
// 64 bits where top four bytes are zero.
_send_raw(&ws->socket, (const uint8_t *)&zero, 4);
_send_raw(&ws->socket, (const uint8_t *)&len, 4);
extended_len[0] = (len >> 24) & 0xff;
extended_len[1] = (len >> 16) & 0xff;
extended_len[2] = (len >> 8) & 0xff;
extended_len[3] = len & 0xff;
_send_raw(&ws->socket, extended_len, 4);
}
_send_raw(&ws->socket, (const uint8_t *)text, len);
char copy[len];

View File

@ -46,27 +46,7 @@
#endif
static background_callback_t workflow_background_cb;
#if CIRCUITPY_STATUS_BAR
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" "\\");
}
#endif
static void workflow_background(void *data) {
#if CIRCUITPY_STATUS_BAR
supervisor_workflow_update_status_bar();
#endif
#if CIRCUITPY_WEB_WORKFLOW
supervisor_web_workflow_background();
#endif

View File

@ -8,12 +8,14 @@ SRC_SUPERVISOR = \
supervisor/shared/lock.c \
supervisor/shared/memory.c \
supervisor/shared/micropython.c \
supervisor/shared/port.c \
supervisor/shared/reload.c \
supervisor/shared/safe_mode.c \
supervisor/shared/serial.c \
supervisor/shared/stack.c \
supervisor/shared/status_leds.c \
supervisor/shared/tick.c \
supervisor/shared/title_bar.c \
supervisor/shared/traceback.c \
supervisor/shared/translate/translate.c \
supervisor/shared/workflow.c

View File

@ -29,7 +29,9 @@ for f in args.files:
if f.name.endswith(".html"):
uncompressed = minify_html.minify(uncompressed.decode("utf-8")).encode("utf-8")
elif f.name.endswith(".js"):
uncompressed = jsmin.jsmin(uncompressed.decode("utf-8")).encode("utf-8")
uncompressed = jsmin.jsmin(uncompressed.decode("utf-8"), quote_chars="'\"`").encode(
"utf-8"
)
compressed = gzip.compress(uncompressed)
clen = len(compressed)
compressed = ", ".join([hex(x) for x in compressed])