merge from main; throw NotImplementedError if CIRCUITPY_USB not set
This commit is contained in:
commit
adf15faa8f
31
.github/workflows/build.yml
vendored
31
.github/workflows/build.yml
vendored
@ -143,7 +143,7 @@ jobs:
|
|||||||
|
|
||||||
|
|
||||||
mpy-cross-mac:
|
mpy-cross-mac:
|
||||||
runs-on: macos-10.15
|
runs-on: macos-11
|
||||||
steps:
|
steps:
|
||||||
- name: Dump GitHub context
|
- name: Dump GitHub context
|
||||||
env:
|
env:
|
||||||
@ -176,27 +176,25 @@ jobs:
|
|||||||
run: make -C mpy-cross -j2
|
run: make -C mpy-cross -j2
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: mpy-cross-macos-catalina
|
name: mpy-cross-macos-11-x64
|
||||||
path: mpy-cross/mpy-cross
|
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)
|
- name: Build mpy-cross (arm64)
|
||||||
run: make -C mpy-cross -j2 -f Makefile.m1 V=2
|
run: make -C mpy-cross -j2 -f Makefile.m1 V=2
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: mpy-cross-macos-bigsur-arm64
|
name: mpy-cross-macos-11-arm64
|
||||||
path: mpy-cross/mpy-cross-arm64
|
path: mpy-cross/mpy-cross-arm64
|
||||||
- name: Make universal binary
|
- name: Make universal binary
|
||||||
run: lipo -create -output mpy-cross-macos-universal mpy-cross/mpy-cross mpy-cross/mpy-cross-arm64
|
run: lipo -create -output mpy-cross-macos-universal mpy-cross/mpy-cross mpy-cross/mpy-cross-arm64
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: mpy-cross-macos-universal
|
name: mpy-cross-macos-11-universal
|
||||||
path: mpy-cross-macos-universal
|
path: mpy-cross-macos-universal
|
||||||
- name: Upload mpy-cross build to S3
|
- name: Upload mpy-cross build to S3
|
||||||
run: |
|
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-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-bigsur-${{ env.CP_VERSION }}-arm64 --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-catalina-${{ env.CP_VERSION }} --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:
|
env:
|
||||||
AWS_PAGER: ''
|
AWS_PAGER: ''
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
@ -287,12 +285,13 @@ jobs:
|
|||||||
fetch-depth: 1
|
fetch-depth: 1
|
||||||
- name: Get CP deps
|
- name: Get CP deps
|
||||||
run: python tools/ci_fetch_deps.py ${{ matrix.board }} ${{ github.sha }}
|
run: python tools/ci_fetch_deps.py ${{ matrix.board }} ${{ github.sha }}
|
||||||
|
- uses: carlosperate/arm-none-eabi-gcc-action@v1
|
||||||
|
with:
|
||||||
|
release: '10-2020-q4'
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install -y gettext
|
sudo apt-get install -y gettext
|
||||||
pip install -r requirements-ci.txt -r requirements-dev.txt
|
pip install -r requirements-ci.txt -r requirements-dev.txt
|
||||||
wget --no-verbose https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
|
|
||||||
sudo tar -C /usr --strip-components=1 -xaf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
|
|
||||||
- name: Versions
|
- name: Versions
|
||||||
run: |
|
run: |
|
||||||
gcc --version
|
gcc --version
|
||||||
@ -382,7 +381,8 @@ jobs:
|
|||||||
if: ${{ needs.test.outputs.boards-espressif != '[]' }}
|
if: ${{ needs.test.outputs.boards-espressif != '[]' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Python 3
|
- name: Set up Python 3
|
||||||
uses: actions/setup-python@v2
|
id: py3
|
||||||
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: "3.x"
|
python-version: "3.x"
|
||||||
- uses: actions/checkout@v2.2.0
|
- uses: actions/checkout@v2.2.0
|
||||||
@ -400,7 +400,7 @@ jobs:
|
|||||||
id: idf-cache
|
id: idf-cache
|
||||||
with:
|
with:
|
||||||
path: ${{ github.workspace }}/.idf_tools
|
path: ${{ github.workspace }}/.idf_tools
|
||||||
key: ${{ runner.os }}-idf-tools-${{ hashFiles('.git/modules/ports/espressif/esp-idf/HEAD') }}-20220404
|
key: ${{ runner.os }}-idf-tools-${{ hashFiles('.git/modules/ports/espressif/esp-idf/HEAD') }}-${{ steps.py3.outputs.python-path }}-20220404
|
||||||
- name: Clone IDF submodules
|
- name: Clone IDF submodules
|
||||||
run: |
|
run: |
|
||||||
(cd $IDF_PATH && git submodule update --init)
|
(cd $IDF_PATH && git submodule update --init)
|
||||||
@ -486,8 +486,9 @@ jobs:
|
|||||||
pip install -r requirements-ci.txt -r requirements-dev.txt
|
pip install -r requirements-ci.txt -r requirements-dev.txt
|
||||||
wget --no-verbose https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz
|
wget --no-verbose https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz
|
||||||
sudo tar -C /usr --strip-components=1 -xaf gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz
|
sudo tar -C /usr --strip-components=1 -xaf gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz
|
||||||
wget --no-verbose https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
|
- uses: carlosperate/arm-none-eabi-gcc-action@v1
|
||||||
sudo tar -C /usr --strip-components=1 -xaf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
|
with:
|
||||||
|
release: '10-2020-q4'
|
||||||
- name: Install mkfs.fat
|
- name: Install mkfs.fat
|
||||||
run: |
|
run: |
|
||||||
wget https://github.com/dosfstools/dosfstools/releases/download/v4.2/dosfstools-4.2.tar.gz
|
wget https://github.com/dosfstools/dosfstools/releases/download/v4.2/dosfstools-4.2.tar.gz
|
||||||
|
2
.github/workflows/create_website_pr.yml
vendored
2
.github/workflows/create_website_pr.yml
vendored
@ -42,5 +42,5 @@ jobs:
|
|||||||
working-directory: tools
|
working-directory: tools
|
||||||
env:
|
env:
|
||||||
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
||||||
ADABOT_GITHUB_ACCESS_TOKEN: ${{ secrets.BLINKA_GITHUB_ACCESS_TOKEN }}
|
ADABOT_GITHUB_ACCESS_TOKEN: ${{ secrets.ADABOT_GITHUB_ACCESS_TOKEN }}
|
||||||
if: github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested')
|
if: github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested')
|
||||||
|
3
.github/workflows/pre-commit.yml
vendored
3
.github/workflows/pre-commit.yml
vendored
@ -14,7 +14,7 @@ concurrency:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre-commit:
|
pre-commit:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2.2.0
|
- uses: actions/checkout@v2.2.0
|
||||||
- name: Set up Python 3
|
- name: Set up Python 3
|
||||||
@ -23,7 +23,6 @@ jobs:
|
|||||||
python-version: "3.x"
|
python-version: "3.x"
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: |
|
run: |
|
||||||
sudo apt-add-repository -y -u ppa:pybricks/ppa
|
|
||||||
sudo apt-get install -y gettext uncrustify
|
sudo apt-get install -y gettext uncrustify
|
||||||
pip3 install black polib pyyaml
|
pip3 install black polib pyyaml
|
||||||
- name: Populate selected submodules
|
- name: Populate selected submodules
|
||||||
|
31
.gitmodules
vendored
31
.gitmodules
vendored
@ -145,8 +145,8 @@
|
|||||||
url = https://github.com/adafruit/Adafruit_CircuitPython_RFM69.git
|
url = https://github.com/adafruit/Adafruit_CircuitPython_RFM69.git
|
||||||
[submodule "ports/espressif/esp-idf"]
|
[submodule "ports/espressif/esp-idf"]
|
||||||
path = ports/espressif/esp-idf
|
path = ports/espressif/esp-idf
|
||||||
url = https://github.com/espressif/esp-idf.git
|
url = https://github.com/adafruit/esp-idf.git
|
||||||
branch = release/v4.4
|
branch = circuitpython8
|
||||||
[submodule "ports/espressif/certificates/nina-fw"]
|
[submodule "ports/espressif/certificates/nina-fw"]
|
||||||
path = ports/espressif/certificates/nina-fw
|
path = ports/espressif/certificates/nina-fw
|
||||||
url = https://github.com/adafruit/nina-fw.git
|
url = https://github.com/adafruit/nina-fw.git
|
||||||
@ -196,6 +196,9 @@
|
|||||||
url = https://github.com/raspberrypi/rpi-firmware.git
|
url = https://github.com/raspberrypi/rpi-firmware.git
|
||||||
branch = master
|
branch = master
|
||||||
shallow = true
|
shallow = true
|
||||||
|
[submodule "lib/adafruit_floppy"]
|
||||||
|
path = lib/adafruit_floppy
|
||||||
|
url = https://github.com/adafruit/Adafruit_Floppy
|
||||||
[submodule "ports/stm/st_driver/cmsis_device_f4"]
|
[submodule "ports/stm/st_driver/cmsis_device_f4"]
|
||||||
path = ports/stm/st_driver/cmsis_device_f4
|
path = ports/stm/st_driver/cmsis_device_f4
|
||||||
url = https://github.com/STMicroelectronics/cmsis_device_f4.git
|
url = https://github.com/STMicroelectronics/cmsis_device_f4.git
|
||||||
@ -283,3 +286,27 @@
|
|||||||
[submodule "frozen/Adafruit_CircuitPython_FakeRequests"]
|
[submodule "frozen/Adafruit_CircuitPython_FakeRequests"]
|
||||||
path = frozen/Adafruit_CircuitPython_FakeRequests
|
path = frozen/Adafruit_CircuitPython_FakeRequests
|
||||||
url = https://github.com/adafruit/Adafruit_CircuitPython_FakeRequests.git
|
url = https://github.com/adafruit/Adafruit_CircuitPython_FakeRequests.git
|
||||||
|
[submodule "frozen/pew-pewpew-lcd"]
|
||||||
|
path = frozen/pew-pewpew-lcd
|
||||||
|
url = https://github.com/pypewpew/pew-pewpew-lcd.git
|
||||||
|
[submodule "frozen/mixgo_cp_lib"]
|
||||||
|
path = frozen/mixgo_cp_lib
|
||||||
|
url = https://github.com/dahanzimin/circuitpython_lib.git
|
||||||
|
[submodule "frozen/Adafruit_CircuitPython_IS31FL3731"]
|
||||||
|
path = frozen/Adafruit_CircuitPython_IS31FL3731
|
||||||
|
url = https://github.com/adafruit/Adafruit_CircuitPython_IS31FL3731.git
|
||||||
|
[submodule "frozen/Adafruit_CircuitPython_Ticks"]
|
||||||
|
path = frozen/Adafruit_CircuitPython_Ticks
|
||||||
|
url = https://github.com/adafruit/Adafruit_CircuitPython_Ticks.git
|
||||||
|
[submodule "frozen/Adafruit_CircuitPython_asyncio"]
|
||||||
|
path = frozen/Adafruit_CircuitPython_asyncio
|
||||||
|
url = https://github.com/adafruit/Adafruit_CircuitPython_asyncio.git
|
||||||
|
[submodule "frozen/circuitpython_ef_music"]
|
||||||
|
path = frozen/circuitpython_ef_music
|
||||||
|
url = https://github.com/elecfreaks/circuitpython_ef_music.git
|
||||||
|
[submodule "frozen/circuitpython_picoed"]
|
||||||
|
path = frozen/circuitpython_picoed
|
||||||
|
url = https://github.com/elecfreaks/circuitpython_picoed.git
|
||||||
|
[submodule "ports/espressif/esp32-camera"]
|
||||||
|
path = ports/espressif/esp32-camera
|
||||||
|
url = https://github.com/adafruit/esp32-camera/
|
||||||
|
@ -9,16 +9,15 @@
|
|||||||
version: 2
|
version: 2
|
||||||
|
|
||||||
build:
|
build:
|
||||||
os: ubuntu-20.04
|
os: ubuntu-20.04
|
||||||
tools:
|
tools:
|
||||||
python: "3"
|
python: "3"
|
||||||
|
jobs:
|
||||||
submodules:
|
post_install:
|
||||||
include:
|
- python tools/ci_fetch_deps.py docs HEAD
|
||||||
- extmod/ulab
|
|
||||||
|
|
||||||
formats:
|
formats:
|
||||||
- pdf
|
- pdf
|
||||||
|
|
||||||
python:
|
python:
|
||||||
install:
|
install:
|
||||||
|
@ -70,7 +70,7 @@ The test suite in the top level `tests` directory. It needs the unix port to ru
|
|||||||
Then you can run the test suite:
|
Then you can run the test suite:
|
||||||
|
|
||||||
cd ../../tests
|
cd ../../tests
|
||||||
./run-tests
|
./run-tests.py
|
||||||
|
|
||||||
A successful run will say something like
|
A successful run will say something like
|
||||||
|
|
||||||
|
76
LICENSE
76
LICENSE
@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2013-2022 Damien P. George
|
Copyright (c) 2013-2022 Damien P. George and others
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -9,77 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in all
|
||||||
all copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
THE SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Unless specified otherwise (see below), the above license and copyright applies
|
|
||||||
to all files in this repository.
|
|
||||||
|
|
||||||
Individual files may include additional copyright holders.
|
|
||||||
|
|
||||||
The various ports of MicroPython may include third-party software that is
|
|
||||||
licensed under different terms. These licenses are summarised in the tree
|
|
||||||
below, please refer to these files and directories for further license and
|
|
||||||
copyright information. Note that (L)GPL-licensed code listed below is only
|
|
||||||
used during the build process and is not part of the compiled source code.
|
|
||||||
|
|
||||||
/ (MIT)
|
|
||||||
/drivers
|
|
||||||
/cc3000 (BSD-3-clause)
|
|
||||||
/cc3100 (BSD-3-clause)
|
|
||||||
/wiznet5k (BSD-3-clause)
|
|
||||||
/lib
|
|
||||||
/asf4 (Apache-2.0)
|
|
||||||
/axtls (BSD-3-clause)
|
|
||||||
/config
|
|
||||||
/scripts
|
|
||||||
/config (GPL-2.0-or-later)
|
|
||||||
/Rules.mak (GPL-2.0)
|
|
||||||
/berkeley-db-1xx (BSD-4-clause)
|
|
||||||
/btstack (See btstack/LICENSE)
|
|
||||||
/cmsis (BSD-3-clause)
|
|
||||||
/crypto-algorithms (NONE)
|
|
||||||
/libhydrogen (ISC)
|
|
||||||
/littlefs (BSD-3-clause)
|
|
||||||
/lwip (BSD-3-clause)
|
|
||||||
/mynewt-nimble (Apache-2.0)
|
|
||||||
/nrfx (BSD-3-clause)
|
|
||||||
/nxp_driver (BSD-3-Clause)
|
|
||||||
/oofatfs (BSD-1-clause)
|
|
||||||
/pico-sdk (BSD-3-clause)
|
|
||||||
/re15 (BSD-3-clause)
|
|
||||||
/stm32lib (BSD-3-clause)
|
|
||||||
/tinytest (BSD-3-clause)
|
|
||||||
/tinyusb (MIT)
|
|
||||||
/uzlib (Zlib)
|
|
||||||
/logo (uses OFL-1.1)
|
|
||||||
/ports
|
|
||||||
/cc3200
|
|
||||||
/hal (BSD-3-clause)
|
|
||||||
/simplelink (BSD-3-clause)
|
|
||||||
/FreeRTOS (GPL-2.0 with FreeRTOS exception)
|
|
||||||
/stm32
|
|
||||||
/usbd*.c (MCD-ST Liberty SW License Agreement V2)
|
|
||||||
/stm32_it.* (MIT + BSD-3-clause)
|
|
||||||
/system_stm32*.c (MIT + BSD-3-clause)
|
|
||||||
/boards
|
|
||||||
/startup_stm32*.s (BSD-3-clause)
|
|
||||||
/*/stm32*.h (BSD-3-clause)
|
|
||||||
/usbdev (MCD-ST Liberty SW License Agreement V2)
|
|
||||||
/usbhost (MCD-ST Liberty SW License Agreement V2)
|
|
||||||
/teensy
|
|
||||||
/core (PJRC.COM)
|
|
||||||
/zephyr
|
|
||||||
/src (Apache-2.0)
|
|
||||||
/tools
|
|
||||||
/dfu.py (LGPL-3.0-only)
|
|
||||||
|
85
LICENSE_MicroPython
Normal file
85
LICENSE_MicroPython
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2013-2022 Damien P. George
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Unless specified otherwise (see below), the above license and copyright applies
|
||||||
|
to all files in this repository.
|
||||||
|
|
||||||
|
Individual files may include additional copyright holders.
|
||||||
|
|
||||||
|
The various ports of MicroPython may include third-party software that is
|
||||||
|
licensed under different terms. These licenses are summarised in the tree
|
||||||
|
below, please refer to these files and directories for further license and
|
||||||
|
copyright information. Note that (L)GPL-licensed code listed below is only
|
||||||
|
used during the build process and is not part of the compiled source code.
|
||||||
|
|
||||||
|
/ (MIT)
|
||||||
|
/drivers
|
||||||
|
/cc3000 (BSD-3-clause)
|
||||||
|
/cc3100 (BSD-3-clause)
|
||||||
|
/wiznet5k (BSD-3-clause)
|
||||||
|
/lib
|
||||||
|
/asf4 (Apache-2.0)
|
||||||
|
/axtls (BSD-3-clause)
|
||||||
|
/config
|
||||||
|
/scripts
|
||||||
|
/config (GPL-2.0-or-later)
|
||||||
|
/Rules.mak (GPL-2.0)
|
||||||
|
/berkeley-db-1xx (BSD-4-clause)
|
||||||
|
/btstack (See btstack/LICENSE)
|
||||||
|
/cmsis (BSD-3-clause)
|
||||||
|
/crypto-algorithms (NONE)
|
||||||
|
/libhydrogen (ISC)
|
||||||
|
/littlefs (BSD-3-clause)
|
||||||
|
/lwip (BSD-3-clause)
|
||||||
|
/mynewt-nimble (Apache-2.0)
|
||||||
|
/nrfx (BSD-3-clause)
|
||||||
|
/nxp_driver (BSD-3-Clause)
|
||||||
|
/oofatfs (BSD-1-clause)
|
||||||
|
/pico-sdk (BSD-3-clause)
|
||||||
|
/re15 (BSD-3-clause)
|
||||||
|
/stm32lib (BSD-3-clause)
|
||||||
|
/tinytest (BSD-3-clause)
|
||||||
|
/tinyusb (MIT)
|
||||||
|
/uzlib (Zlib)
|
||||||
|
/logo (uses OFL-1.1)
|
||||||
|
/ports
|
||||||
|
/cc3200
|
||||||
|
/hal (BSD-3-clause)
|
||||||
|
/simplelink (BSD-3-clause)
|
||||||
|
/FreeRTOS (GPL-2.0 with FreeRTOS exception)
|
||||||
|
/stm32
|
||||||
|
/usbd*.c (MCD-ST Liberty SW License Agreement V2)
|
||||||
|
/stm32_it.* (MIT + BSD-3-clause)
|
||||||
|
/system_stm32*.c (MIT + BSD-3-clause)
|
||||||
|
/boards
|
||||||
|
/startup_stm32*.s (BSD-3-clause)
|
||||||
|
/*/stm32*.h (BSD-3-clause)
|
||||||
|
/usbdev (MCD-ST Liberty SW License Agreement V2)
|
||||||
|
/usbhost (MCD-ST Liberty SW License Agreement V2)
|
||||||
|
/teensy
|
||||||
|
/core (PJRC.COM)
|
||||||
|
/zephyr
|
||||||
|
/src (Apache-2.0)
|
||||||
|
/tools
|
||||||
|
/dfu.py (LGPL-3.0-only)
|
1
Makefile
1
Makefile
@ -61,6 +61,7 @@ TRANSLATE_SOURCES_EXC = -path "ports/*/build-*" \
|
|||||||
|
|
||||||
help:
|
help:
|
||||||
@echo "Please use \`make <target>' where <target> is one of"
|
@echo "Please use \`make <target>' where <target> is one of"
|
||||||
|
@echo " fetch-submodules to fetch dependencies from submodules, run this right after you clone the repo"
|
||||||
@echo " html to make standalone HTML files"
|
@echo " html to make standalone HTML files"
|
||||||
@echo " dirhtml to make HTML files named index.html in directories"
|
@echo " dirhtml to make HTML files named index.html in directories"
|
||||||
@echo " singlehtml to make a single large HTML file"
|
@echo " singlehtml to make a single large HTML file"
|
||||||
|
15
README.rst
15
README.rst
@ -90,9 +90,11 @@ If you'd like to use the term "CircuitPython" and Blinka for your product here i
|
|||||||
* Your product is listed on `circuitpython.org <https://circuitpython.org>`__ (source
|
* Your product is listed on `circuitpython.org <https://circuitpython.org>`__ (source
|
||||||
`here <https://github.com/adafruit/circuitpython-org/>`_). This is to ensure that a user of your
|
`here <https://github.com/adafruit/circuitpython-org/>`_). This is to ensure that a user of your
|
||||||
product can always download the latest version of CircuitPython from the standard place.
|
product can always download the latest version of CircuitPython from the standard place.
|
||||||
* Your product has a user accessible USB plug which appears as a CIRCUITPY drive when plugged in
|
* Your product supports at least one standard "`Workflow <https://docs.circuitpython.org/en/latest/docs/workflows.html>`__" for serial and file access:
|
||||||
AND/OR provides file and serial access over Bluetooth Low Energy. Boards that do not support USB
|
* With a user accessible USB plug which appears as a CIRCUITPY drive when plugged in.
|
||||||
should be clearly marked as BLE-only CircuitPython.
|
* With file and serial access over Bluetooth Low Energy using the BLE Workflow.
|
||||||
|
* With file access over WiFi using the WiFi Workflow with serial access over USB and/or WebSocket.
|
||||||
|
* Boards that do not support the USB Workflow should be clearly marked.
|
||||||
|
|
||||||
If you choose not to meet these requirements, then we ask you call your version of CircuitPython
|
If you choose not to meet these requirements, then we ask you call your version of CircuitPython
|
||||||
something else (for example, SuperDuperPython) and not use the Blinka logo. You can say it is
|
something else (for example, SuperDuperPython) and not use the Blinka logo. You can say it is
|
||||||
@ -120,7 +122,7 @@ Behavior
|
|||||||
make each file independent from each other.
|
make each file independent from each other.
|
||||||
|
|
||||||
- ``boot.py`` runs only once on start up before
|
- ``boot.py`` runs only once on start up before
|
||||||
USB is initialized. This lays the ground work for configuring USB at
|
workflows are initialized. This lays the ground work for configuring USB at
|
||||||
startup rather than it being fixed. Since serial is not available,
|
startup rather than it being fixed. Since serial is not available,
|
||||||
output is written to ``boot_out.txt``.
|
output is written to ``boot_out.txt``.
|
||||||
- ``code.py`` (or ``main.py``) is run after every reload until it
|
- ``code.py`` (or ``main.py``) is run after every reload until it
|
||||||
@ -135,7 +137,10 @@ Behavior
|
|||||||
possible to fix code that causes nasty crashes by making it available through mass storage after
|
possible to fix code that causes nasty crashes by making it available through mass storage after
|
||||||
the crash. A reset (the button) is needed after it's fixed to get back into normal mode.
|
the crash. A reset (the button) is needed after it's fixed to get back into normal mode.
|
||||||
- RGB status LED indicating CircuitPython state.
|
- RGB status LED indicating CircuitPython state.
|
||||||
- Re-runs ``code.py`` or other main file after file system writes over USB mass storage. (Disable with
|
- One green flash - code completed without error.
|
||||||
|
- Two red flashes - code ended due to an exception.
|
||||||
|
- Three yellow flashes - safe mode. May be due to CircuitPython internal error.
|
||||||
|
- Re-runs ``code.py`` or other main file after file system writes by a workflow. (Disable with
|
||||||
``supervisor.disable_autoreload()``)
|
``supervisor.disable_autoreload()``)
|
||||||
- Autoreload is disabled while the REPL is active.
|
- Autoreload is disabled while the REPL is active.
|
||||||
- Main is one of these: ``code.txt``, ``code.py``, ``main.py``,
|
- Main is one of these: ``code.txt``, ``code.py``, ``main.py``,
|
||||||
|
13
conf.py
13
conf.py
@ -52,10 +52,14 @@ subprocess.check_output(["make", "stubs"])
|
|||||||
#modules_support_matrix = shared_bindings_matrix.support_matrix_excluded_boards()
|
#modules_support_matrix = shared_bindings_matrix.support_matrix_excluded_boards()
|
||||||
modules_support_matrix = shared_bindings_matrix.support_matrix_by_board()
|
modules_support_matrix = shared_bindings_matrix.support_matrix_by_board()
|
||||||
modules_support_matrix_reverse = defaultdict(list)
|
modules_support_matrix_reverse = defaultdict(list)
|
||||||
for board, modules in modules_support_matrix.items():
|
for board, matrix_info in modules_support_matrix.items():
|
||||||
for module in modules:
|
for module in matrix_info["modules"]:
|
||||||
modules_support_matrix_reverse[module].append(board)
|
modules_support_matrix_reverse[module].append(board)
|
||||||
modules_support_matrix_reverse = dict((module, sorted(boards)) for module, boards in modules_support_matrix_reverse.items())
|
|
||||||
|
modules_support_matrix_reverse = dict(
|
||||||
|
(module, sorted(boards))
|
||||||
|
for module, boards in modules_support_matrix_reverse.items()
|
||||||
|
)
|
||||||
|
|
||||||
html_context = {
|
html_context = {
|
||||||
'support_matrix': modules_support_matrix,
|
'support_matrix': modules_support_matrix,
|
||||||
@ -83,7 +87,7 @@ extensions = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
templates_path = ['templates']
|
templates_path = ['templates', "docs/templates"]
|
||||||
|
|
||||||
# The suffix of source filenames.
|
# The suffix of source filenames.
|
||||||
source_suffix = {
|
source_suffix = {
|
||||||
@ -195,6 +199,7 @@ exclude_patterns = ["**/build*",
|
|||||||
"ports/cxd56/spresense-exported-sdk",
|
"ports/cxd56/spresense-exported-sdk",
|
||||||
"ports/espressif/certificates",
|
"ports/espressif/certificates",
|
||||||
"ports/espressif/esp-idf",
|
"ports/espressif/esp-idf",
|
||||||
|
"ports/espressif/esp32-camera",
|
||||||
"ports/espressif/.idf_tools",
|
"ports/espressif/.idf_tools",
|
||||||
"ports/espressif/peripherals",
|
"ports/espressif/peripherals",
|
||||||
"ports/litex/hw",
|
"ports/litex/hw",
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 266ea20ed80104c315dcb124b482fa5f9f48cdec
|
Subproject commit 2d292ad4e67890d4b85b027431ba9fef7bf561fd
|
@ -49,6 +49,10 @@
|
|||||||
#include "shared-bindings/_bleio/ScanEntry.h"
|
#include "shared-bindings/_bleio/ScanEntry.h"
|
||||||
#include "shared-bindings/time/__init__.h"
|
#include "shared-bindings/time/__init__.h"
|
||||||
|
|
||||||
|
#if CIRCUITPY_DOTENV
|
||||||
|
#include "shared-module/dotenv/__init__.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))
|
#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))
|
||||||
#define SEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000000) / (RESOLUTION))
|
#define SEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000000) / (RESOLUTION))
|
||||||
#define UNITS_TO_SEC(TIME, RESOLUTION) (((TIME)*(RESOLUTION)) / 1000000)
|
#define UNITS_TO_SEC(TIME, RESOLUTION) (((TIME)*(RESOLUTION)) / 1000000)
|
||||||
@ -278,17 +282,27 @@ char default_ble_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0
|
|||||||
// Get various values and limits set by the adapter.
|
// Get various values and limits set by the adapter.
|
||||||
// Set event mask.
|
// Set event mask.
|
||||||
STATIC void bleio_adapter_hci_init(bleio_adapter_obj_t *self) {
|
STATIC void bleio_adapter_hci_init(bleio_adapter_obj_t *self) {
|
||||||
|
mp_int_t name_len = 0;
|
||||||
|
|
||||||
const size_t len = sizeof(default_ble_name);
|
#if CIRCUITPY_DOTENV
|
||||||
|
char ble_name[32];
|
||||||
|
name_len = dotenv_get_key("/.env", "CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name) - 1);
|
||||||
|
if (name_len > 0) {
|
||||||
|
self->name = mp_obj_new_str(ble_name, (size_t)name_len);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bt_addr_t addr;
|
if (name_len <= 0) {
|
||||||
hci_check_error(hci_read_bd_addr(&addr));
|
name_len = sizeof(default_ble_name);
|
||||||
|
bt_addr_t addr;
|
||||||
|
hci_check_error(hci_read_bd_addr(&addr));
|
||||||
|
|
||||||
default_ble_name[len - 4] = nibble_to_hex_lower[addr.val[1] >> 4 & 0xf];
|
default_ble_name[name_len - 4] = nibble_to_hex_lower[addr.val[1] >> 4 & 0xf];
|
||||||
default_ble_name[len - 3] = nibble_to_hex_lower[addr.val[1] & 0xf];
|
default_ble_name[name_len - 3] = nibble_to_hex_lower[addr.val[1] & 0xf];
|
||||||
default_ble_name[len - 2] = nibble_to_hex_lower[addr.val[0] >> 4 & 0xf];
|
default_ble_name[name_len - 2] = nibble_to_hex_lower[addr.val[0] >> 4 & 0xf];
|
||||||
default_ble_name[len - 1] = nibble_to_hex_lower[addr.val[0] & 0xf];
|
default_ble_name[name_len - 1] = nibble_to_hex_lower[addr.val[0] & 0xf];
|
||||||
self->name = mp_obj_new_str(default_ble_name, len);
|
self->name = mp_obj_new_str(default_ble_name, (uint8_t)name_len);
|
||||||
|
}
|
||||||
|
|
||||||
// Get version information.
|
// Get version information.
|
||||||
if (hci_read_local_version(&self->hci_version, &self->hci_revision, &self->lmp_version,
|
if (hci_read_local_version(&self->hci_version, &self->hci_revision, &self->lmp_version,
|
||||||
|
@ -57,9 +57,9 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self,
|
|||||||
self->value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len);
|
self->value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len);
|
||||||
|
|
||||||
const mp_int_t max_length_max = 512;
|
const mp_int_t max_length_max = 512;
|
||||||
if (max_length < 0 || max_length > max_length_max) {
|
|
||||||
mp_raise_ValueError(translate("max_length must be <= 512"));
|
mp_arg_validate_int_range(max_length, 0, max_length_max, MP_QSTR_max_length);
|
||||||
}
|
|
||||||
self->max_length = max_length;
|
self->max_length = max_length;
|
||||||
self->fixed_length = fixed_length;
|
self->fixed_length = fixed_length;
|
||||||
|
|
||||||
|
@ -57,6 +57,11 @@ bool vm_used_ble;
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
void bleio_user_reset() {
|
||||||
|
// HCI doesn't support the BLE workflow so just do a full reset.
|
||||||
|
bleio_reset();
|
||||||
|
}
|
||||||
|
|
||||||
// Turn off BLE on a reset or reload.
|
// Turn off BLE on a reset or reload.
|
||||||
void bleio_reset() {
|
void bleio_reset() {
|
||||||
// Create a UUID object for all CCCD's.
|
// Create a UUID object for all CCCD's.
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include "shared-bindings/_bleio/Service.h"
|
#include "shared-bindings/_bleio/Service.h"
|
||||||
#include "shared-bindings/_bleio/UUID.h"
|
#include "shared-bindings/_bleio/UUID.h"
|
||||||
#include "supervisor/shared/tick.h"
|
#include "supervisor/shared/tick.h"
|
||||||
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
|
||||||
STATIC uint16_t max_mtu = BT_ATT_DEFAULT_LE_MTU; // 23
|
STATIC uint16_t max_mtu = BT_ATT_DEFAULT_LE_MTU; // 23
|
||||||
STATIC unsigned long timeout = 5000;
|
STATIC unsigned long timeout = 5000;
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
MicroPython & CircuitPython license information
|
# MicroPython & CircuitPython License
|
||||||
===============================================
|
|
||||||
|
|
||||||
The MIT License (MIT)
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2013-2017 Damien P. George, and others
|
Copyright (c) 2013-2022 Damien P. George and others
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -12,13 +11,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in all
|
||||||
all copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
THE SOFTWARE.
|
SOFTWARE.
|
@ -141,7 +141,7 @@ statement will ensure hardware isn't enabled longer than needed.
|
|||||||
Verify your device
|
Verify your device
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
Whenever possible, make sure device you are talking to is the device you expect.
|
Whenever possible, make sure the device you are talking to is the device you expect.
|
||||||
If not, raise a RuntimeError. Beware that I2C addresses can be identical on
|
If not, raise a RuntimeError. Beware that I2C addresses can be identical on
|
||||||
different devices so read registers you know to make sure they match your
|
different devices so read registers you know to make sure they match your
|
||||||
expectation. Validating this upfront will help catch mistakes.
|
expectation. Validating this upfront will help catch mistakes.
|
||||||
@ -202,7 +202,7 @@ interchangeably with the CPython name. This is confusing. Instead, think up a
|
|||||||
new name that is related to the extra functionality you are adding.
|
new name that is related to the extra functionality you are adding.
|
||||||
|
|
||||||
For example, storage mounting and unmounting related functions were moved from
|
For example, storage mounting and unmounting related functions were moved from
|
||||||
``uos`` into a new `storage` module. Terminal related functions were moved into
|
``uos`` into a new `storage` module. Terminal-related functions were moved into
|
||||||
`multiterminal`. These names better match their functionality and do not
|
`multiterminal`. These names better match their functionality and do not
|
||||||
conflict with CPython names. Make sure to check that you don't conflict with
|
conflict with CPython names. Make sure to check that you don't conflict with
|
||||||
CPython libraries too. That way we can port the API to CPython in the future.
|
CPython libraries too. That way we can port the API to CPython in the future.
|
||||||
@ -213,7 +213,7 @@ Example
|
|||||||
When adding extra functionality to CircuitPython to mimic what a normal
|
When adding extra functionality to CircuitPython to mimic what a normal
|
||||||
operating system would do, either copy an existing CPython API (for example file
|
operating system would do, either copy an existing CPython API (for example file
|
||||||
writing) or create a separate module to achieve what you want. For example,
|
writing) or create a separate module to achieve what you want. For example,
|
||||||
mounting and unmount drives is not a part of CPython so it should be done in a
|
mounting and unmounting drives is not a part of CPython so it should be done in a
|
||||||
module, such as a new ``storage`` module, that is only available in CircuitPython.
|
module, such as a new ``storage`` module, that is only available in CircuitPython.
|
||||||
That way when someone moves the code to CPython they know what parts need to be
|
That way when someone moves the code to CPython they know what parts need to be
|
||||||
adapted.
|
adapted.
|
||||||
@ -494,6 +494,45 @@ backticks ``:class:`~adafruit_motor.servo.Servo```. You must also add the refer
|
|||||||
|
|
||||||
"adafruit_motor": ("https://circuitpython.readthedocs.io/projects/motor/en/latest/", None,),
|
"adafruit_motor": ("https://circuitpython.readthedocs.io/projects/motor/en/latest/", None,),
|
||||||
|
|
||||||
|
Use ``adafruit_register`` when possible
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
`Register <https://github.com/adafruit/Adafruit_CircuitPython_Register>`_ is
|
||||||
|
a foundational library that manages packing and unpacking data from I2C device
|
||||||
|
registers. There is also `Register SPI <https://github.com/adafruit/Adafruit_CircuitPython_Register_SPI>`_
|
||||||
|
for SPI devices. When possible, use one of these libraries for unpacking and
|
||||||
|
packing registers. This ensures the packing code is shared amongst all
|
||||||
|
registers (even across drivers). Furthermore, it simplifies device definitions
|
||||||
|
by making them declarative (only data.)
|
||||||
|
|
||||||
|
Values with non-consecutive bits in a register or that represent FIFO endpoints
|
||||||
|
may not map well to existing register classes. In unique cases like these, it is
|
||||||
|
ok to read and write the register directly.
|
||||||
|
|
||||||
|
*Do not* add all registers from a datasheet upfront. Instead, only add the ones
|
||||||
|
necessary for the functionality the driver exposes. Adding them all will lead to
|
||||||
|
unnecessary file size and API clutter. See `this video about outside-in design
|
||||||
|
from @tannewt <https://www.youtube.com/watch?v=3QewiyfBQh8>`_.
|
||||||
|
|
||||||
|
I2C Example
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from adafruit_register import i2c_bit
|
||||||
|
from adafruit_bus_device import i2c_device
|
||||||
|
|
||||||
|
class HelloWorldDevice:
|
||||||
|
"""Device with two bits to control when the words 'hello' and 'world' are lit."""
|
||||||
|
|
||||||
|
hello = i2c_bit.RWBit(0x0, 0x0)
|
||||||
|
"""Bit to indicate if hello is lit."""
|
||||||
|
|
||||||
|
world = i2c_bit.RWBit(0x1, 0x0)
|
||||||
|
"""Bit to indicate if world is lit."""
|
||||||
|
|
||||||
|
def __init__(self, i2c, device_address=0x0):
|
||||||
|
self.i2c_device = i2c_device.I2CDevice(i2c, device_address)
|
||||||
|
|
||||||
Use BusDevice
|
Use BusDevice
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -668,8 +707,24 @@ when using ``const()``, keep in mind these general guide lines:
|
|||||||
|
|
||||||
- Always use via an import, ex: ``from micropython import const``
|
- Always use via an import, ex: ``from micropython import const``
|
||||||
- Limit use to global (module level) variables only.
|
- Limit use to global (module level) variables only.
|
||||||
- If user will not need access to variable, prefix name with a leading
|
- Only used when the user will not need access to variable and prefix name with
|
||||||
underscore, ex: ``_SOME_CONST``.
|
a leading underscore, ex: ``_SOME_CONST``.
|
||||||
|
|
||||||
|
Example
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from adafruit_bus_device import i2c_device
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_DEFAULT_I2C_ADDR = const(0x42)
|
||||||
|
|
||||||
|
class Widget:
|
||||||
|
"""A generic widget."""
|
||||||
|
|
||||||
|
def __init__(self, i2c, address=_DEFAULT_I2C_ADDR):
|
||||||
|
self.i2c_device = i2c_device.I2CDevice(i2c, address)
|
||||||
|
|
||||||
Libraries Examples
|
Libraries Examples
|
||||||
------------------
|
------------------
|
||||||
@ -751,6 +806,16 @@ properties.
|
|||||||
| ``sound_level`` | float | non-unit-specific sound level (monotonic but not actual decibels) |
|
| ``sound_level`` | float | non-unit-specific sound level (monotonic but not actual decibels) |
|
||||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
Driver constant naming
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
When adding variables for constant values for a driver. Do not include the
|
||||||
|
device's name in the variable name. For example, in ``adafruit_fancy123.py``,
|
||||||
|
variables should not start with ``FANCY123_``. Adding this prefix increases RAM
|
||||||
|
usage and .mpy file size because variable names are preserved. User code should
|
||||||
|
refer to these constants as ``adafruit_fancy123.HELLO_WORLD`` for clarity.
|
||||||
|
``adafruit_fancy123.FANCY123_HELLO_WORLD`` would be overly verbose.
|
||||||
|
|
||||||
Adding native modules
|
Adding native modules
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
58
docs/environment.rst
Normal file
58
docs/environment.rst
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
Environment Variables
|
||||||
|
=====================
|
||||||
|
|
||||||
|
CircuitPython 8.0.0 introduces support for environment variables. Environment
|
||||||
|
variables are commonly used to store "secrets" such as Wi-Fi passwords and API
|
||||||
|
keys. This method *does not* make them secure. It only separates them from the
|
||||||
|
code.
|
||||||
|
|
||||||
|
CircuitPython supports these by mimicking the `dotenv <https://github.com/theskumar/python-dotenv>`_
|
||||||
|
CPython library. Other languages such as Javascript, PHP and Ruby also have
|
||||||
|
dotenv libraries.
|
||||||
|
|
||||||
|
These libraries store environment variables in a ``.env`` file. Here is a simple
|
||||||
|
example:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
KEY1='value1'
|
||||||
|
# Comment
|
||||||
|
KEY2='value2
|
||||||
|
is multiple lines'
|
||||||
|
|
||||||
|
CircuitPython uses the ``.env`` at the drive root (no folder) as the environment.
|
||||||
|
User code can access the values from the file using `os.getenv()`. It is
|
||||||
|
recommended to save any values used repeatedly in a variable because `os.getenv()`
|
||||||
|
will parse the ``/.env`` on every access.
|
||||||
|
|
||||||
|
CircuitPython behavior
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
CircuitPython will also read the environment to configure its behavior. Other
|
||||||
|
keys are ignored by CircuitPython. Here are the keys it uses:
|
||||||
|
|
||||||
|
CIRCUITPY_BLE_NAME
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
Default BLE name the board advertises as, including for the BLE workflow.
|
||||||
|
|
||||||
|
CIRCUITPY_RESERVED_PSRAM
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
On boards with Espressif microcontrollers with PSRAM (also called SPIRAM), permanently reserve a portion of PSRAM for use by esp-idf.
|
||||||
|
This storage is removed from the CircuitPython "heap" and is available for allocation by esp-idf routines in the core instead.
|
||||||
|
Generally, only set this to a non-zero value when it is required by a specific core module.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
CIRCUITPY_WIFI_SSID
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
Wi-Fi SSID to auto-connect to even if user code is not running.
|
@ -22,6 +22,8 @@ Full Table of Contents
|
|||||||
supported_ports.rst
|
supported_ports.rst
|
||||||
troubleshooting.rst
|
troubleshooting.rst
|
||||||
drivers.rst
|
drivers.rst
|
||||||
|
workflows
|
||||||
|
environment.rst
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
@ -46,7 +48,7 @@ Full Table of Contents
|
|||||||
../CONTRIBUTING
|
../CONTRIBUTING
|
||||||
../BUILDING
|
../BUILDING
|
||||||
../CODE_OF_CONDUCT
|
../CODE_OF_CONDUCT
|
||||||
../license.rst
|
../docs/LICENSE
|
||||||
../WEBUSB_README
|
../WEBUSB_README
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
|
@ -4,11 +4,18 @@
|
|||||||
All builtin functions and exceptions are described here. They are also
|
All builtin functions and exceptions are described here. They are also
|
||||||
available via ``builtins`` module.
|
available via ``builtins`` module.
|
||||||
|
|
||||||
|
For more information about built-ins, see the following CPython documentation:
|
||||||
|
|
||||||
|
* `Builtin CPython Functions <https://docs.python.org/3/library/functions.html>`_
|
||||||
|
* `Builtin CPython Exceptions <https://docs.python.org/3/library/exceptions.html>`_
|
||||||
|
* `Builtin CPython Constants <https://docs.python.org/3/library/constants.html>`_
|
||||||
|
|
||||||
|
.. note:: Not all of these functions, types, exceptions, and constants are turned
|
||||||
|
on in all CircuitPython ports, for space reasons.
|
||||||
|
|
||||||
Functions and types
|
Functions and types
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Not all of these functions and types are turned on in all CircuitPython ports, for space reasons.
|
|
||||||
|
|
||||||
.. function:: abs()
|
.. function:: abs()
|
||||||
|
|
||||||
.. function:: all()
|
.. function:: all()
|
||||||
@ -160,46 +167,77 @@ Not all of these functions and types are turned on in all CircuitPython ports, f
|
|||||||
Exceptions
|
Exceptions
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
.. exception:: ArithmeticError
|
||||||
|
|
||||||
.. exception:: AssertionError
|
.. exception:: AssertionError
|
||||||
|
|
||||||
.. exception:: AttributeError
|
.. exception:: AttributeError
|
||||||
|
|
||||||
|
.. exception:: BaseException
|
||||||
|
|
||||||
|
.. exception:: BrokenPipeError
|
||||||
|
|
||||||
|
.. exception:: ConnectionError
|
||||||
|
|
||||||
|
.. exception:: EOFError
|
||||||
|
|
||||||
.. exception:: Exception
|
.. exception:: Exception
|
||||||
|
|
||||||
.. exception:: ImportError
|
.. exception:: ImportError
|
||||||
|
|
||||||
|
.. exception:: IndentationError
|
||||||
|
|
||||||
.. exception:: IndexError
|
.. exception:: IndexError
|
||||||
|
|
||||||
.. exception:: KeyboardInterrupt
|
.. exception:: KeyboardInterrupt
|
||||||
|
|
||||||
.. exception:: KeyError
|
.. exception:: KeyError
|
||||||
|
|
||||||
|
.. exception:: LookupError
|
||||||
|
|
||||||
.. exception:: MemoryError
|
.. exception:: MemoryError
|
||||||
|
|
||||||
|
.. exception:: MpyError
|
||||||
|
|
||||||
|
Not a part of the CPython standard library
|
||||||
|
|
||||||
.. exception:: NameError
|
.. exception:: NameError
|
||||||
|
|
||||||
.. exception:: NotImplementedError
|
.. exception:: NotImplementedError
|
||||||
|
|
||||||
.. exception:: OSError
|
.. exception:: OSError
|
||||||
|
|
||||||
|
.. exception:: OverflowError
|
||||||
|
|
||||||
.. exception:: RuntimeError
|
.. exception:: RuntimeError
|
||||||
|
|
||||||
.. exception:: ReloadException
|
.. exception:: ReloadException
|
||||||
|
|
||||||
`ReloadException` is used internally to deal with soft restarts.
|
`ReloadException` is used internally to deal with soft restarts.
|
||||||
|
|
||||||
|
Not a part of the CPython standard library
|
||||||
|
|
||||||
|
.. exception:: StopAsyncIteration
|
||||||
|
|
||||||
.. exception:: StopIteration
|
.. exception:: StopIteration
|
||||||
|
|
||||||
.. exception:: SyntaxError
|
.. exception:: SyntaxError
|
||||||
|
|
||||||
.. exception:: SystemExit
|
.. exception:: SystemExit
|
||||||
|
|
||||||
|see_cpython| :py:class:`cpython:SystemExit`.
|
.. exception:: TimeoutError
|
||||||
|
|
||||||
.. exception:: TypeError
|
.. exception:: TypeError
|
||||||
|
|
||||||
|see_cpython| :py:class:`cpython:TypeError`.
|
.. exception:: UnicodeError
|
||||||
|
|
||||||
.. exception:: ValueError
|
.. exception:: ValueError
|
||||||
|
|
||||||
.. exception:: ZeroDivisionError
|
.. exception:: ZeroDivisionError
|
||||||
|
|
||||||
|
Constants
|
||||||
|
---------
|
||||||
|
|
||||||
|
.. data:: Ellipsis
|
||||||
|
|
||||||
|
.. data:: NotImplemented
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
.. module:: hashlib
|
.. module:: hashlib
|
||||||
:synopsis: hashing algorithms
|
:synopsis: hashing algorithms
|
||||||
|
:noindex:
|
||||||
|
|
||||||
|see_cpython_module| :mod:`cpython:hashlib`.
|
|see_cpython_module| :mod:`cpython:hashlib`.
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
.. module:: zlib
|
.. module:: zlib
|
||||||
:synopsis: zlib decompression
|
:synopsis: zlib decompression
|
||||||
|
:noindex:
|
||||||
|
|
||||||
|see_cpython_module| :mod:`cpython:zlib`.
|
|see_cpython_module| :mod:`cpython:zlib`.
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ Functions
|
|||||||
CPython and is ignored.
|
CPython and is ignored.
|
||||||
|
|
||||||
.. class:: DecompIO(stream, wbits=0, /)
|
.. class:: DecompIO(stream, wbits=0, /)
|
||||||
|
:noindex:
|
||||||
|
|
||||||
Create a ``stream`` wrapper which allows transparent decompression of
|
Create a ``stream`` wrapper which allows transparent decompression of
|
||||||
compressed data in another *stream*. This allows to process compressed
|
compressed data in another *stream*. This allows to process compressed
|
||||||
|
@ -71,7 +71,7 @@ as a natural "TODO" list. An example minimal build list is shown below:
|
|||||||
CIRCUITPY_SDCARDIO = 0
|
CIRCUITPY_SDCARDIO = 0
|
||||||
CIRCUITPY_FRAMEBUFFERIO = 0
|
CIRCUITPY_FRAMEBUFFERIO = 0
|
||||||
CIRCUITPY_FREQUENCYIO = 0
|
CIRCUITPY_FREQUENCYIO = 0
|
||||||
CIRCUITPY_I2CPERIPHERAL = 0
|
CIRCUITPY_I2CTARGET = 0
|
||||||
# Requires SPI, PulseIO (stub ok):
|
# Requires SPI, PulseIO (stub ok):
|
||||||
CIRCUITPY_DISPLAYIO = 0
|
CIRCUITPY_DISPLAYIO = 0
|
||||||
|
|
||||||
@ -79,8 +79,6 @@ as a natural "TODO" list. An example minimal build list is shown below:
|
|||||||
# any port once their prerequisites in common-hal are complete.
|
# any port once their prerequisites in common-hal are complete.
|
||||||
# Requires DigitalIO:
|
# Requires DigitalIO:
|
||||||
CIRCUITPY_BITBANGIO = 0
|
CIRCUITPY_BITBANGIO = 0
|
||||||
# Requires DigitalIO
|
|
||||||
CIRCUITPY_GAMEPADSHIFT = 0
|
|
||||||
# Requires neopixel_write or SPI (dotstar)
|
# Requires neopixel_write or SPI (dotstar)
|
||||||
CIRCUITPY_PIXELBUF = 0
|
CIRCUITPY_PIXELBUF = 0
|
||||||
# Requires OS
|
# Requires OS
|
||||||
|
@ -45,12 +45,10 @@ shared-bindings/audiomp3/__init__.rst shared-bindings/audiomp3/
|
|||||||
shared-bindings/audiopwmio/PWMAudioOut.rst shared-bindings/audiopwmio/#audiopwmio.PWMAudioOut
|
shared-bindings/audiopwmio/PWMAudioOut.rst shared-bindings/audiopwmio/#audiopwmio.PWMAudioOut
|
||||||
shared-bindings/audiopwmio/__init__.rst shared-bindings/audiopwmio/
|
shared-bindings/audiopwmio/__init__.rst shared-bindings/audiopwmio/
|
||||||
shared-bindings/bitbangio/I2C.rst shared-bindings/bitbangio/#bitbangio.I2C
|
shared-bindings/bitbangio/I2C.rst shared-bindings/bitbangio/#bitbangio.I2C
|
||||||
shared-bindings/bitbangio/OneWire.rst shared-bindings/bitbangio/#bitbangio.OneWire
|
|
||||||
shared-bindings/bitbangio/SPI.rst shared-bindings/bitbangio/#bitbangio.SPI
|
shared-bindings/bitbangio/SPI.rst shared-bindings/bitbangio/#bitbangio.SPI
|
||||||
shared-bindings/bitbangio/__init__.rst shared-bindings/bitbangio/
|
shared-bindings/bitbangio/__init__.rst shared-bindings/bitbangio/
|
||||||
shared-bindings/board/__init__.rst shared-bindings/board/
|
shared-bindings/board/__init__.rst shared-bindings/board/
|
||||||
shared-bindings/busio/I2C.rst shared-bindings/busio/#busio.I2C
|
shared-bindings/busio/I2C.rst shared-bindings/busio/#busio.I2C
|
||||||
shared-bindings/busio/OneWire.rst shared-bindings/busio/#busio.OneWire
|
|
||||||
shared-bindings/busio/Parity.rst shared-bindings/busio/#busio.Parity
|
shared-bindings/busio/Parity.rst shared-bindings/busio/#busio.Parity
|
||||||
shared-bindings/busio/SPI.rst shared-bindings/busio/#busio.SPI
|
shared-bindings/busio/SPI.rst shared-bindings/busio/#busio.SPI
|
||||||
shared-bindings/busio/UART.rst shared-bindings/busio/#busio.UART
|
shared-bindings/busio/UART.rst shared-bindings/busio/#busio.UART
|
||||||
@ -82,10 +80,6 @@ shared-bindings/framebufferio/FramebufferDisplay.rst shared-bindings/framebuffer
|
|||||||
shared-bindings/framebufferio/__init__.rst shared-bindings/framebufferio/
|
shared-bindings/framebufferio/__init__.rst shared-bindings/framebufferio/
|
||||||
shared-bindings/frequencyio/FrequencyIn.rst shared-bindings/frequencyio/#frequencyio.FrequencyIn
|
shared-bindings/frequencyio/FrequencyIn.rst shared-bindings/frequencyio/#frequencyio.FrequencyIn
|
||||||
shared-bindings/frequencyio/__init__.rst shared-bindings/frequencyio/
|
shared-bindings/frequencyio/__init__.rst shared-bindings/frequencyio/
|
||||||
shared-bindings/gamepad/GamePad.rst shared-bindings/gamepad/#gamepad.GamePad
|
|
||||||
shared-bindings/gamepad/__init__.rst shared-bindings/gamepad/
|
|
||||||
shared-bindings/gamepadshift/GamePadShift.rst shared-bindings/gamepadshift/#gamepadshift.GamePadShift
|
|
||||||
shared-bindings/gamepadshift/__init__.rst shared-bindings/gamepadshift/
|
|
||||||
shared-bindings/gnss/__init__.rst shared-bindings/gnss/
|
shared-bindings/gnss/__init__.rst shared-bindings/gnss/
|
||||||
shared-bindings/i2cperipheral/__init__.rst shared-bindings/i2cperipheral/
|
shared-bindings/i2cperipheral/__init__.rst shared-bindings/i2cperipheral/
|
||||||
shared-bindings/i2csecondary/__init__.rst shared-bindings/i2csecondary/
|
shared-bindings/i2csecondary/__init__.rst shared-bindings/i2csecondary/
|
||||||
@ -101,6 +95,7 @@ shared-bindings/neopixel_write/__init__.rst shared-bindings/neopixel_write/
|
|||||||
shared-bindings/network/__init__.rst shared-bindings/network/
|
shared-bindings/network/__init__.rst shared-bindings/network/
|
||||||
shared-bindings/nvm/ByteArray.rst shared-bindings/nvm/#nvm.ByteArray
|
shared-bindings/nvm/ByteArray.rst shared-bindings/nvm/#nvm.ByteArray
|
||||||
shared-bindings/nvm/__init__.rst shared-bindings/nvm/
|
shared-bindings/nvm/__init__.rst shared-bindings/nvm/
|
||||||
|
shared-bindings/onewireio/OneWire.rst shared-bindings/onewireio/#onewireio.OneWire
|
||||||
shared-bindings/os/__init__.rst shared-bindings/os/
|
shared-bindings/os/__init__.rst shared-bindings/os/
|
||||||
shared-bindings/protomatter/__init__.rst shared-bindings/protomatter/
|
shared-bindings/protomatter/__init__.rst shared-bindings/protomatter/
|
||||||
shared-bindings/ps2io/Ps2.rst shared-bindings/ps2io/#ps2io.Ps2
|
shared-bindings/ps2io/Ps2.rst shared-bindings/ps2io/#ps2io.Ps2
|
||||||
|
@ -32,7 +32,7 @@ from concurrent.futures import ThreadPoolExecutor
|
|||||||
|
|
||||||
SUPPORTED_PORTS = ['atmel-samd', 'broadcom', 'cxd56', 'espressif', 'litex', 'mimxrt10xx', 'nrf', 'raspberrypi', 'stm']
|
SUPPORTED_PORTS = ['atmel-samd', 'broadcom', 'cxd56', 'espressif', 'litex', 'mimxrt10xx', 'nrf', 'raspberrypi', 'stm']
|
||||||
|
|
||||||
aliases_by_board = {
|
ALIASES_BY_BOARD = {
|
||||||
"circuitplayground_express": [
|
"circuitplayground_express": [
|
||||||
"circuitplayground_express_4h",
|
"circuitplayground_express_4h",
|
||||||
"circuitplayground_express_digikey_pycon2019",
|
"circuitplayground_express_digikey_pycon2019",
|
||||||
@ -40,10 +40,9 @@ aliases_by_board = {
|
|||||||
"pybadge": ["edgebadge"],
|
"pybadge": ["edgebadge"],
|
||||||
"pyportal": ["pyportal_pynt"],
|
"pyportal": ["pyportal_pynt"],
|
||||||
"gemma_m0": ["gemma_m0_pycon2018"],
|
"gemma_m0": ["gemma_m0_pycon2018"],
|
||||||
"pewpew10": ["pewpew13"],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aliases_brand_names = {
|
ALIASES_BRAND_NAMES = {
|
||||||
"circuitplayground_express_4h":
|
"circuitplayground_express_4h":
|
||||||
"Adafruit Circuit Playground Express 4-H",
|
"Adafruit Circuit Playground Express 4-H",
|
||||||
"circuitplayground_express_digikey_pycon2019":
|
"circuitplayground_express_digikey_pycon2019":
|
||||||
@ -54,19 +53,25 @@ aliases_brand_names = {
|
|||||||
"Adafruit PyPortal Pynt",
|
"Adafruit PyPortal Pynt",
|
||||||
"gemma_m0_pycon2018":
|
"gemma_m0_pycon2018":
|
||||||
"Adafruit Gemma M0 PyCon 2018",
|
"Adafruit Gemma M0 PyCon 2018",
|
||||||
"pewpew13":
|
|
||||||
"PewPew 13",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
additional_modules = {
|
ADDITIONAL_MODULES = {
|
||||||
"fontio": "CIRCUITPY_DISPLAYIO",
|
"fontio": "CIRCUITPY_DISPLAYIO",
|
||||||
"terminalio": "CIRCUITPY_DISPLAYIO",
|
"terminalio": "CIRCUITPY_DISPLAYIO",
|
||||||
"adafruit_bus_device": "CIRCUITPY_BUSDEVICE",
|
"adafruit_bus_device": "CIRCUITPY_BUSDEVICE",
|
||||||
"adafruit_pixelbuf": "CIRCUITPY_PIXELBUF"
|
"adafruit_pixelbuf": "CIRCUITPY_PIXELBUF",
|
||||||
|
"usb": "CIRCUITPY_USB_HOST",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FROZEN_EXCLUDES = ["examples", "docs", "tests", "utils", "conf.py", "setup.py"]
|
||||||
|
"""Files and dirs at the root of a frozen directory that should be ignored.
|
||||||
|
This is the same list as in the preprocess_frozen_modules script."""
|
||||||
|
|
||||||
|
repository_urls = {}
|
||||||
|
"""Cache of repository URLs for frozen modules."""
|
||||||
|
|
||||||
def get_circuitpython_root_dir():
|
def get_circuitpython_root_dir():
|
||||||
""" The path to the root './circuitpython' directory
|
""" The path to the root './circuitpython' directory.
|
||||||
"""
|
"""
|
||||||
file_path = pathlib.Path(__file__).resolve()
|
file_path = pathlib.Path(__file__).resolve()
|
||||||
root_dir = file_path.parent.parent
|
root_dir = file_path.parent.parent
|
||||||
@ -74,12 +79,40 @@ def get_circuitpython_root_dir():
|
|||||||
return root_dir
|
return root_dir
|
||||||
|
|
||||||
def get_shared_bindings():
|
def get_shared_bindings():
|
||||||
""" Get a list of modules in shared-bindings based on folder names
|
""" Get a list of modules in shared-bindings based on folder names.
|
||||||
"""
|
"""
|
||||||
shared_bindings_dir = get_circuitpython_root_dir() / "shared-bindings"
|
shared_bindings_dir = get_circuitpython_root_dir() / "shared-bindings"
|
||||||
return [item.name for item in shared_bindings_dir.iterdir()] + ["binascii", "errno", "json", "re", "ulab"]
|
return [item.name for item in shared_bindings_dir.iterdir()] + ["binascii", "errno", "json", "re", "ulab"]
|
||||||
|
|
||||||
|
|
||||||
|
def get_board_mapping():
|
||||||
|
"""
|
||||||
|
Compiles the list of boards from the directories, with aliases and mapping
|
||||||
|
to the port.
|
||||||
|
"""
|
||||||
|
boards = {}
|
||||||
|
for port in SUPPORTED_PORTS:
|
||||||
|
board_path = os.path.join("../ports", port, "boards")
|
||||||
|
for board_path in os.scandir(board_path):
|
||||||
|
if board_path.is_dir():
|
||||||
|
board_files = os.listdir(board_path.path)
|
||||||
|
board_id = board_path.name
|
||||||
|
aliases = ALIASES_BY_BOARD.get(board_path.name, [])
|
||||||
|
boards[board_id] = {
|
||||||
|
"port": port,
|
||||||
|
"download_count": 0,
|
||||||
|
"aliases": aliases,
|
||||||
|
}
|
||||||
|
for alias in aliases:
|
||||||
|
boards[alias] = {
|
||||||
|
"port": port,
|
||||||
|
"download_count": 0,
|
||||||
|
"alias": True,
|
||||||
|
"aliases": [],
|
||||||
|
}
|
||||||
|
return boards
|
||||||
|
|
||||||
|
|
||||||
def read_mpconfig():
|
def read_mpconfig():
|
||||||
""" Open 'circuitpy_mpconfig.mk' and return the contents.
|
""" Open 'circuitpy_mpconfig.mk' and return the contents.
|
||||||
"""
|
"""
|
||||||
@ -104,8 +137,8 @@ def build_module_map():
|
|||||||
full_build = False
|
full_build = False
|
||||||
for module in modules:
|
for module in modules:
|
||||||
full_name = module
|
full_name = module
|
||||||
if module in additional_modules:
|
if module in ADDITIONAL_MODULES:
|
||||||
search_identifier = additional_modules[module]
|
search_identifier = ADDITIONAL_MODULES[module]
|
||||||
else:
|
else:
|
||||||
search_identifier = 'CIRCUITPY_'+module.lstrip("_").upper()
|
search_identifier = 'CIRCUITPY_'+module.lstrip("_").upper()
|
||||||
re_pattern = f"{re.escape(search_identifier)}\s*\??=\s*(.+)"
|
re_pattern = f"{re.escape(search_identifier)}\s*\??=\s*(.+)"
|
||||||
@ -162,6 +195,69 @@ def get_settings_from_makefile(port_dir, board_name):
|
|||||||
|
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
|
def get_repository_url(directory):
|
||||||
|
if directory in repository_urls:
|
||||||
|
return repository_urls[directory]
|
||||||
|
readme = None
|
||||||
|
for readme_path in (
|
||||||
|
os.path.join(directory, "README.rst"),
|
||||||
|
os.path.join(os.path.dirname(directory), "README.rst")
|
||||||
|
):
|
||||||
|
if os.path.exists(readme_path):
|
||||||
|
readme = readme_path
|
||||||
|
break
|
||||||
|
path = None
|
||||||
|
if readme:
|
||||||
|
with open(readme, "r") as fp:
|
||||||
|
for line in fp.readlines():
|
||||||
|
if m := re.match("\s+:target:\s+(http\S+(docs.circuitpython|readthedocs)\S+)\s*", line):
|
||||||
|
path = m.group(1)
|
||||||
|
break
|
||||||
|
if m := re.search("<(http[^>]+)>", line):
|
||||||
|
path = m.group(1)
|
||||||
|
break
|
||||||
|
if path is None:
|
||||||
|
contents = subprocess.run(
|
||||||
|
["git", "remote", "get-url", "origin"],
|
||||||
|
encoding="utf-8",
|
||||||
|
errors="replace",
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
cwd=directory
|
||||||
|
)
|
||||||
|
path = contents.stdout.strip()
|
||||||
|
repository_urls[directory] = path
|
||||||
|
return path
|
||||||
|
|
||||||
|
def frozen_modules_from_dirs(frozen_mpy_dirs, withurl):
|
||||||
|
"""
|
||||||
|
Go through the list of frozen directories and extract the python modules.
|
||||||
|
Paths are of the type:
|
||||||
|
$(TOP)/frozen/Adafruit_CircuitPython_CircuitPlayground
|
||||||
|
$(TOP)/frozen/circuitpython-stage/meowbit
|
||||||
|
Python modules are at the root of the path, and are python files or directories
|
||||||
|
containing python files. Except the ones in the FROZEN_EXCLUDES list.
|
||||||
|
"""
|
||||||
|
frozen_modules = []
|
||||||
|
for frozen_path in filter(lambda x: x, frozen_mpy_dirs.split(" ")):
|
||||||
|
source_dir = get_circuitpython_root_dir() / frozen_path[7:]
|
||||||
|
url_repository = get_repository_url(source_dir)
|
||||||
|
for sub in source_dir.glob("*"):
|
||||||
|
if sub.name in FROZEN_EXCLUDES:
|
||||||
|
continue
|
||||||
|
if sub.name.endswith(".py"):
|
||||||
|
if withurl:
|
||||||
|
frozen_modules.append((sub.name[:-3], url_repository))
|
||||||
|
else:
|
||||||
|
frozen_modules.append(sub.name[:-3])
|
||||||
|
continue
|
||||||
|
if next(sub.glob("**/*.py"), None): # tests if not empty
|
||||||
|
if withurl:
|
||||||
|
frozen_modules.append((sub.name, url_repository))
|
||||||
|
else:
|
||||||
|
frozen_modules.append(sub.name)
|
||||||
|
return frozen_modules
|
||||||
|
|
||||||
def lookup_setting(settings, key, default=''):
|
def lookup_setting(settings, key, default=''):
|
||||||
while True:
|
while True:
|
||||||
value = settings.get(key, default)
|
value = settings.get(key, default)
|
||||||
@ -179,7 +275,7 @@ def all_ports_all_boards(ports=SUPPORTED_PORTS):
|
|||||||
continue
|
continue
|
||||||
yield (port, entry)
|
yield (port, entry)
|
||||||
|
|
||||||
def support_matrix_by_board(use_branded_name=True):
|
def support_matrix_by_board(use_branded_name=True, withurl=True):
|
||||||
""" Compiles a list of the available core modules available for each
|
""" Compiles a list of the available core modules available for each
|
||||||
board.
|
board.
|
||||||
"""
|
"""
|
||||||
@ -207,25 +303,50 @@ def support_matrix_by_board(use_branded_name=True):
|
|||||||
board_modules.append(base[module]['name'])
|
board_modules.append(base[module]['name'])
|
||||||
board_modules.sort()
|
board_modules.sort()
|
||||||
|
|
||||||
|
if "CIRCUITPY_BUILD_EXTENSIONS" in settings:
|
||||||
|
board_extensions = [
|
||||||
|
extension.strip() for extension in
|
||||||
|
settings["CIRCUITPY_BUILD_EXTENSIONS"].split(",")
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
raise OSError(f"Board extensions undefined: {board_name}.")
|
||||||
|
|
||||||
|
frozen_modules = []
|
||||||
|
if "FROZEN_MPY_DIRS" in settings:
|
||||||
|
frozen_modules = frozen_modules_from_dirs(settings["FROZEN_MPY_DIRS"], withurl)
|
||||||
|
if frozen_modules:
|
||||||
|
frozen_modules.sort()
|
||||||
|
|
||||||
# generate alias boards too
|
# generate alias boards too
|
||||||
board_matrix = [(board_name, board_modules)]
|
board_matrix = [(
|
||||||
if entry.name in aliases_by_board:
|
board_name, {
|
||||||
for alias in aliases_by_board[entry.name]:
|
"modules": board_modules,
|
||||||
|
"frozen_libraries": frozen_modules,
|
||||||
|
"extensions": board_extensions,
|
||||||
|
}
|
||||||
|
)]
|
||||||
|
if entry.name in ALIASES_BY_BOARD:
|
||||||
|
for alias in ALIASES_BY_BOARD[entry.name]:
|
||||||
if use_branded_name:
|
if use_branded_name:
|
||||||
if alias in aliases_brand_names:
|
if alias in ALIASES_BRAND_NAMES:
|
||||||
alias = aliases_brand_names[alias]
|
alias = ALIASES_BRAND_NAMES[alias]
|
||||||
else:
|
else:
|
||||||
alias = alias.replace("_"," ").title()
|
alias = alias.replace("_"," ").title()
|
||||||
board_matrix.append( (alias, board_modules) )
|
board_matrix.append((
|
||||||
|
alias, {
|
||||||
|
"modules": board_modules,
|
||||||
|
"frozen_libraries": frozen_modules,
|
||||||
|
"extensions": board_extensions,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
|
||||||
return board_matrix # this is now a list of (board,modules)
|
return board_matrix # this is now a list of (board,modules)
|
||||||
|
|
||||||
executor = ThreadPoolExecutor(max_workers=os.cpu_count())
|
executor = ThreadPoolExecutor(max_workers=os.cpu_count())
|
||||||
mapped_exec = executor.map(support_matrix, all_ports_all_boards())
|
mapped_exec = executor.map(support_matrix, all_ports_all_boards())
|
||||||
# flatmap with comprehensions
|
# flatmap with comprehensions
|
||||||
boards = dict(sorted([board for matrix in mapped_exec for board in matrix]))
|
boards = dict(sorted([board for matrix in mapped_exec for board in matrix], key=lambda x: x[0]))
|
||||||
|
|
||||||
# print(json.dumps(boards, indent=2))
|
|
||||||
return boards
|
return boards
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
17
docs/static/filter.css
vendored
17
docs/static/filter.css
vendored
@ -7,8 +7,21 @@
|
|||||||
right: 10px;
|
right: 10px;
|
||||||
top: 4px;
|
top: 4px;
|
||||||
}
|
}
|
||||||
.support-matrix-table .this_module code,
|
|
||||||
.support-matrix-table .this_module span {
|
.support-matrix-table .reference.external {
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #404040;
|
||||||
|
font-family: "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", Courier, monospace;
|
||||||
|
padding: 2px 5px;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #e1e4e5;
|
||||||
|
font-size: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.support-matrix-table .this_module,
|
||||||
|
.support-matrix-table .this_module.reference.external,
|
||||||
|
.support-matrix-table .this_module * {
|
||||||
background: black;
|
background: black;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
4
docs/static/filter.js
vendored
4
docs/static/filter.js
vendored
@ -44,14 +44,14 @@ $(() => {
|
|||||||
var nvisible = 0;
|
var nvisible = 0;
|
||||||
$(".support-matrix-table tbody tr").each( (index,item) => {
|
$(".support-matrix-table tbody tr").each( (index,item) => {
|
||||||
var name = $(item).find("td:first-child p").html();
|
var name = $(item).find("td:first-child p").html();
|
||||||
var modules = $(item).find("a.reference.internal");
|
var modules = $(item).find("code, a.reference.external");
|
||||||
var matching_all = true;
|
var matching_all = true;
|
||||||
//
|
//
|
||||||
list_search.forEach((sstring) => {
|
list_search.forEach((sstring) => {
|
||||||
var matching = (sstring[0] == "-");
|
var matching = (sstring[0] == "-");
|
||||||
for(var modi = 0; modi < modules.length; ++modi) {
|
for(var modi = 0; modi < modules.length; ++modi) {
|
||||||
module = modules[modi];
|
module = modules[modi];
|
||||||
var mod_name = module.firstChild.firstChild.textContent;
|
var mod_name = module.firstChild.textContent;
|
||||||
if(sstring[0] == "-") {
|
if(sstring[0] == "-") {
|
||||||
if(mod_name.match(sstring.substr(1))) {
|
if(mod_name.match(sstring.substr(1))) {
|
||||||
matching = false;
|
matching = false;
|
||||||
|
430
docs/workflows.md
Normal file
430
docs/workflows.md
Normal file
@ -0,0 +1,430 @@
|
|||||||
|
# Workflows
|
||||||
|
|
||||||
|
Workflows are the process used to 1) manipulate files on the CircuitPython device and 2) interact
|
||||||
|
with the serial connection to CircuitPython. The serial connection is usually used to access the
|
||||||
|
REPL.
|
||||||
|
|
||||||
|
Starting with CircuitPython 3.x we moved to a USB-only workflow. Prior to that, we used the serial
|
||||||
|
connection alone to do the whole workflow. In CircuitPython 7.x, a BLE workflow was added with the
|
||||||
|
advantage of working with mobile devices. CircuitPython 8.x added a web workflow that works over the
|
||||||
|
local network (usually Wi-Fi) and a web browser. Other clients can also use the Web REST API. Boards
|
||||||
|
should clearly document which workflows are supported.
|
||||||
|
|
||||||
|
Code for workflows lives in `supervisor/shared`.
|
||||||
|
|
||||||
|
The workflow APIs are documented here.
|
||||||
|
|
||||||
|
## USB
|
||||||
|
|
||||||
|
These USB interfaces are enabled by default on boards with USB support. They are usable once the
|
||||||
|
device has been plugged into a host.
|
||||||
|
|
||||||
|
### CIRCUITPY drive
|
||||||
|
CircuitPython exposes a standard mass storage (MSC) interface to enable file manipulation over a
|
||||||
|
standard interface. This interface works underneath the file system at the block level so using it
|
||||||
|
excludes other types of workflows from manipulating the file system at the same time.
|
||||||
|
|
||||||
|
### CDC serial
|
||||||
|
CircuitPython exposes one CDC USB interface for CircuitPython serial. This is a standard serial
|
||||||
|
USB interface.
|
||||||
|
|
||||||
|
TODO: Document how it designates itself from the user CDC.
|
||||||
|
|
||||||
|
Setting baudrate 1200 and disconnecting will reboot into a bootloader. (Used by Arduino to trigger
|
||||||
|
a reset into bootloader.)
|
||||||
|
|
||||||
|
## BLE
|
||||||
|
|
||||||
|
The BLE workflow is enabled for nRF boards. By default, to prevent malicious access, it is disabled.
|
||||||
|
To connect to the BLE workflow, press the reset button while the status led blinks blue quickly
|
||||||
|
after the safe mode blinks. The board will restart and broadcast the file transfer service UUID
|
||||||
|
(`0xfebb`) along with the board's [Creation IDs](https://github.com/creationid/creators). This
|
||||||
|
public broadcast is done at a lower transmit level so the devices must be closer. On connection, the
|
||||||
|
device will need to pair and bond. Once bonded, the device will broadcast whenever disconnected
|
||||||
|
using a rotating key rather than a static one. Non-bonded devices won't be able to resolve it. After
|
||||||
|
connection, the central device can discover two default services. One for file transfer and one for
|
||||||
|
CircuitPython specifically that includes serial characteristics.
|
||||||
|
|
||||||
|
To change the default BLE advertising name without (or before) running user code, the desired name
|
||||||
|
can be put in the `/.env` file. The key is `CIRCUITPY_BLE_NAME`. It's limited to approximately
|
||||||
|
30 characters depending on the port's settings and will be truncated if longer.
|
||||||
|
|
||||||
|
### File Transfer API
|
||||||
|
|
||||||
|
CircuitPython uses [an open File Transfer API](https://github.com/adafruit/Adafruit_CircuitPython_BLE_File_Transfer)
|
||||||
|
to enable file system access.
|
||||||
|
|
||||||
|
### CircuitPython Service
|
||||||
|
|
||||||
|
The base UUID for the CircuitPython service is `ADAFXXXX-4369-7263-7569-7450794686e`. The `XXXX` is
|
||||||
|
replaced by the four specific digits below. The service itself is `0001`.
|
||||||
|
|
||||||
|
#### TX - `0002` / RX - `0003`
|
||||||
|
|
||||||
|
These characteristic work just like the Nordic Uart Service (NUS) but have different UUIDs to prevent
|
||||||
|
conflicts with user created NUS services.
|
||||||
|
|
||||||
|
#### Version - `0100`
|
||||||
|
Read-only characteristic that returns the UTF-8 encoded version string.
|
||||||
|
|
||||||
|
## Web
|
||||||
|
|
||||||
|
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 unless overridden by `CIRCUITPY_WEB_API_PORT`. It also enables MDNS.
|
||||||
|
|
||||||
|
Here is an example `/.env`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# To auto-connect to Wi-Fi
|
||||||
|
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
|
||||||
|
hostname of the form `cpy-XXXXXX.local`. The `XXXXXX` is based on network MAC address. The device
|
||||||
|
also provides the MDNS service with service type `_circuitpython` and protocol `_tcp`.
|
||||||
|
|
||||||
|
### HTTP
|
||||||
|
The web server is HTTP 1.1 and may use chunked responses so that it doesn't need to precompute
|
||||||
|
content length.
|
||||||
|
|
||||||
|
The API generally consists of an HTTP method such as GET or PUT and a path. Requests and responses
|
||||||
|
also have headers. Responses will contain a status code and status text such as `404 Not Found`.
|
||||||
|
This API tries to use standard status codes to encode the status of the various operations. The
|
||||||
|
[Mozilla Developer Network HTTP docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP)
|
||||||
|
are a great reference.
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
The examples use `curl`, a common command line program for issuing HTTP requests. The examples below
|
||||||
|
use `circuitpython.local` as the easiest way to work. If you have multiple active devices, you'll
|
||||||
|
want to use the specific `cpy-XXXXXX.local` version.
|
||||||
|
|
||||||
|
The examples also use `passw0rd` as the password placeholder. Replace it with your password before
|
||||||
|
running the example.
|
||||||
|
|
||||||
|
### `/`
|
||||||
|
The root welcome page links to the file system page and also displays other CircuitPython devices
|
||||||
|
found using MDNS service discovery. This allows web browsers to find other devices from one. (All
|
||||||
|
devices will respond to `circuitpython.local` so the device redirected to may vary.)
|
||||||
|
|
||||||
|
### CORS
|
||||||
|
The web server will allow requests from `cpy-XXXXXX.local`, `127.0.0.1`, the device's IP and
|
||||||
|
`code.circuitpython.org`. (`circuitpython.local` requests will be redirected to `cpy-XXXXXX.local`.)
|
||||||
|
|
||||||
|
### 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. 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
|
||||||
|
will respond `401 Unauthorized`.
|
||||||
|
|
||||||
|
#### `/fs/`
|
||||||
|
|
||||||
|
The `/fs/` page will respond with a directory browsing HTML once authenticated. This page is always
|
||||||
|
gzipped. If the `Accept: application/json` header is provided, then the JSON representation of the
|
||||||
|
root will be returned.
|
||||||
|
|
||||||
|
##### OPTIONS
|
||||||
|
When requested with the `OPTIONS` method, the server will respond with CORS related headers. Most
|
||||||
|
aren't needed for API use. They are there for the web browser.
|
||||||
|
|
||||||
|
* `Access-Control-Allow-Methods` - Varies with USB state. `GET, OPTIONS` when USB is active. `GET, OPTIONS, PUT, DELETE, MOVE` otherwise.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -v -u :passw0rd -X OPTIONS -L --location-trusted http://circuitpython.local/fs/
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `/fs/<directory path>/`
|
||||||
|
Directory paths must end with a /. Otherwise, the path is assumed to be a file.
|
||||||
|
|
||||||
|
##### GET
|
||||||
|
Returns a JSON representation of the directory.
|
||||||
|
|
||||||
|
* `200 OK` - Directory exists and JSON returned
|
||||||
|
* `401 Unauthorized` - Incorrect password
|
||||||
|
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
|
||||||
|
* `404 Not Found` - Missing directory
|
||||||
|
|
||||||
|
Returns information about each file in the directory:
|
||||||
|
|
||||||
|
* `name` - File name. No trailing `/` on directory names
|
||||||
|
* `directory` - `true` when a directory. `false` otherwise
|
||||||
|
* `modified_ns` - File modification time in nanoseconds since January 1st, 1970. May not use full resolution
|
||||||
|
* `file_size` - File size in bytes. `0` for directories
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -v -u :passw0rd -H "Accept: application/json" -L --location-trusted http://circuitpython.local/fs/lib/hello/
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "world.txt",
|
||||||
|
"directory": false,
|
||||||
|
"modified_ns": 946934328000000000,
|
||||||
|
"file_size": 12
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
##### PUT
|
||||||
|
Tries to make a directory at the given path. Request body is ignored. The custom `X-Timestamp`
|
||||||
|
header can provide a timestamp in milliseconds since January 1st, 1970 (to match JavaScript's file
|
||||||
|
time resolution) used for the directories modification time. The RTC time will used otherwise.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
* `204 No Content` - Directory exists
|
||||||
|
* `201 Created` - Directory created
|
||||||
|
* `401 Unauthorized` - Incorrect password
|
||||||
|
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
|
||||||
|
* `409 Conflict` - USB is active and preventing file system modification
|
||||||
|
* `404 Not Found` - Missing parent directory
|
||||||
|
* `500 Server Error` - Other, unhandled error
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -v -u :passw0rd -X PUT -L --location-trusted http://circuitpython.local/fs/lib/hello/world/
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Move
|
||||||
|
Moves the directory at the given path to ``X-Destination``. Also known as rename.
|
||||||
|
|
||||||
|
The custom `X-Destination` header stores the destination path of the directory.
|
||||||
|
|
||||||
|
* `201 Created` - Directory renamed
|
||||||
|
* `401 Unauthorized` - Incorrect password
|
||||||
|
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
|
||||||
|
* `404 Not Found` - Source directory not found or destination path is missing
|
||||||
|
* `409 Conflict` - USB is active and preventing file system modification
|
||||||
|
* `412 Precondition Failed` - The destination path is already in use
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -v -u :passw0rd -X MOVE -H "X-Destination: /fs/lib/hello2/" -L --location-trusted http://circuitpython.local/fs/lib/hello/
|
||||||
|
```
|
||||||
|
|
||||||
|
##### DELETE
|
||||||
|
Deletes the directory and all of its contents.
|
||||||
|
|
||||||
|
* `204 No Content` - Directory and its contents deleted
|
||||||
|
* `401 Unauthorized` - Incorrect password
|
||||||
|
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
|
||||||
|
* `404 Not Found` - No directory
|
||||||
|
* `409 Conflict` - USB is active and preventing file system modification
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -v -u :passw0rd -X DELETE -L --location-trusted http://circuitpython.local/fs/lib/hello2/world/
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### `/fs/<file path>`
|
||||||
|
|
||||||
|
##### PUT
|
||||||
|
Stores the provided content to the file path.
|
||||||
|
|
||||||
|
The custom `X-Timestamp` header can provide a timestamp in milliseconds since January 1st, 1970
|
||||||
|
(to match JavaScript's file time resolution) used for the directories modification time. The RTC
|
||||||
|
time will used otherwise.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
* `201 Created` - File created and saved
|
||||||
|
* `204 No Content` - File existed and overwritten
|
||||||
|
* `401 Unauthorized` - Incorrect password
|
||||||
|
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
|
||||||
|
* `404 Not Found` - Missing parent directory
|
||||||
|
* `409 Conflict` - USB is active and preventing file system modification
|
||||||
|
* `413 Payload Too Large` - `Expect` header not sent and file is too large
|
||||||
|
* `417 Expectation Failed` - `Expect` header sent and file is too large
|
||||||
|
* `500 Server Error` - Other, unhandled error
|
||||||
|
|
||||||
|
If the client sends the `Expect` header, the server will reply with `100 Continue` when ok.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
echo "Hello world" >> test.txt
|
||||||
|
curl -v -u :passw0rd -T test.txt -L --location-trusted http://circuitpython.local/fs/lib/hello/world.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
##### GET
|
||||||
|
Returns the raw file contents. `Content-Type` will be set based on extension:
|
||||||
|
|
||||||
|
* `text/plain` - `.py`, `.txt`
|
||||||
|
* `text/javascript` - `.js`
|
||||||
|
* `text/html` - `.html`
|
||||||
|
* `application/json` - `.json`
|
||||||
|
* `application/octet-stream` - Everything else
|
||||||
|
|
||||||
|
Will return:
|
||||||
|
* `200 OK` - File exists and file returned
|
||||||
|
* `401 Unauthorized` - Incorrect password
|
||||||
|
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
|
||||||
|
* `404 Not Found` - Missing file
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -v -u :passw0rd -L --location-trusted http://circuitpython.local/fs/lib/hello/world.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
##### Move
|
||||||
|
Moves the file at the given path to the ``X-Destination``. Also known as rename.
|
||||||
|
|
||||||
|
The custom `X-Destination` header stores the destination path of the file.
|
||||||
|
|
||||||
|
* `201 Created` - File renamed
|
||||||
|
* `401 Unauthorized` - Incorrect password
|
||||||
|
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
|
||||||
|
* `404 Not Found` - Source file not found or destination path is missing
|
||||||
|
* `409 Conflict` - USB is active and preventing file system modification
|
||||||
|
* `412 Precondition Failed` - The destination path is already in use
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -v -u :passw0rd -X MOVE -H "X-Destination: /fs/lib/hello/world2.txt" -L --location-trusted http://circuitpython.local/fs/lib/hello/world.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
##### DELETE
|
||||||
|
Deletes the file.
|
||||||
|
|
||||||
|
|
||||||
|
* `204 No Content` - File existed and deleted
|
||||||
|
* `401 Unauthorized` - Incorrect password
|
||||||
|
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
|
||||||
|
* `404 Not Found` - File not found
|
||||||
|
* `409 Conflict` - USB is active and preventing file system modification
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -v -u :passw0rd -X DELETE -L --location-trusted http://circuitpython.local/fs/lib/hello/world2.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### `/cp/`
|
||||||
|
|
||||||
|
`/cp/` serves basic info about the CircuitPython device and others discovered through MDNS. It is
|
||||||
|
not protected by basic auth in case the device is someone elses.
|
||||||
|
|
||||||
|
Only `GET` requests are supported and will return `405 Method Not Allowed` otherwise.
|
||||||
|
|
||||||
|
#### `/cp/devices.json`
|
||||||
|
|
||||||
|
Returns information about other devices found on the network using MDNS.
|
||||||
|
|
||||||
|
* `total`: Total MDNS response count. May be more than in `devices` if internal limits were hit.
|
||||||
|
* `devices`: List of discovered devices.
|
||||||
|
* `hostname`: MDNS hostname
|
||||||
|
* `instance_name`: MDNS instance name. Defaults to human readable board name.
|
||||||
|
* `port`: Port of CircuitPython Web API
|
||||||
|
* `ip`: IP address
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```sh
|
||||||
|
curl -v -L http://circuitpython.local/cp/devices.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"total": 1,
|
||||||
|
"devices": [
|
||||||
|
{
|
||||||
|
"hostname": "cpy-951032",
|
||||||
|
"instance_name": "Adafruit Feather ESP32-S2 TFT",
|
||||||
|
"port": 80,
|
||||||
|
"ip": "192.168.1.235"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `/cp/serial/`
|
||||||
|
|
||||||
|
|
||||||
|
Serves a basic serial terminal program when a `GET` request is received without the
|
||||||
|
`Upgrade: websocket` header. Otherwise the socket is upgraded to a WebSocket. See WebSockets below for more detail.
|
||||||
|
|
||||||
|
This is an authenticated endpoint in both modes.
|
||||||
|
|
||||||
|
#### `/cp/version.json`
|
||||||
|
|
||||||
|
Returns information about the device.
|
||||||
|
|
||||||
|
* `web_api_version`: Always `1`. This versions the rest of the API and new versions may not be backwards compatible.
|
||||||
|
* `version`: CircuitPython build version.
|
||||||
|
* `build_date`: CircuitPython build date.
|
||||||
|
* `board_name`: Human readable name of the board.
|
||||||
|
* `mcu_name`: Human readable name of the microcontroller.
|
||||||
|
* `board_id`: Board id used in code and on circuitpython.org.
|
||||||
|
* `creator_id`: Creator ID for the board.
|
||||||
|
* `creation_id`: Creation ID for the board, set by the creator.
|
||||||
|
* `hostname`: MDNS hostname.
|
||||||
|
* `port`: Port of CircuitPython Web Service.
|
||||||
|
* `ip`: IP address of the device.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```sh
|
||||||
|
curl -v -L http://circuitpython.local/cp/version.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"web_api_version": 1,
|
||||||
|
"version": "8.0.0-alpha.1-20-ge1d4518a9-dirty",
|
||||||
|
"build_date": "2022-06-24",
|
||||||
|
"board_name": "ESP32-S3-USB-OTG-N8",
|
||||||
|
"mcu_name": "ESP32S3",
|
||||||
|
"board_id": "espressif_esp32s3_usb_otg_n8",
|
||||||
|
"creator_id": 12346,
|
||||||
|
"creation_id": 28683,
|
||||||
|
"hostname": "cpy-f57ce8",
|
||||||
|
"port": 80,
|
||||||
|
"ip": "192.168.1.94"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `/code/`
|
||||||
|
|
||||||
|
The `/code/` page returns a small static html page that will pull in and load the full code editor from
|
||||||
|
[code.circuitpython.org](https://code.circuitpython.org) for a full code editor experience. Because most
|
||||||
|
of the resources reside online instead of the device, an active internet connection is required.
|
||||||
|
|
||||||
|
### Static files
|
||||||
|
|
||||||
|
* `/favicon.ico` - Blinka
|
||||||
|
* `/directory.js` - JavaScript for `/fs/`
|
||||||
|
* `/welcome.js` - JavaScript for `/`
|
||||||
|
|
||||||
|
### WebSocket
|
||||||
|
|
||||||
|
The CircuitPython serial interactions are available over a WebSocket. A WebSocket begins as a
|
||||||
|
special HTTP request that gets upgraded to a WebSocket. Authentication happens before upgrading.
|
||||||
|
|
||||||
|
WebSockets are *not* bare sockets once upgraded. Instead they have their own framing format for data.
|
||||||
|
CircuitPython can handle PING and CLOSE opcodes. All others are treated as TEXT. Data to
|
||||||
|
CircuitPython is expected to be masked UTF-8, as the spec requires. Data from CircuitPython to the
|
||||||
|
client is unmasked. It is also unbuffered so the client will get a variety of frame sizes.
|
||||||
|
|
||||||
|
Only one WebSocket at a time is supported.
|
@ -33,6 +33,8 @@
|
|||||||
#include "shared-bindings/supervisor/__init__.h"
|
#include "shared-bindings/supervisor/__init__.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
|
||||||
#if MICROPY_PY_UASYNCIO
|
#if MICROPY_PY_UASYNCIO
|
||||||
|
|
||||||
// Used when task cannot be guaranteed to be non-NULL.
|
// Used when task cannot be guaranteed to be non-NULL.
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "py/binary.h"
|
#include "py/binary.h"
|
||||||
|
|
||||||
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
|
||||||
static void check_not_unicode(const mp_obj_t arg) {
|
static void check_not_unicode(const mp_obj_t arg) {
|
||||||
#if MICROPY_CPYTHON_COMPAT
|
#if MICROPY_CPYTHON_COMPAT
|
||||||
if (mp_obj_is_str(arg)) {
|
if (mp_obj_is_str(arg)) {
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include "py/objtuple.h"
|
#include "py/objtuple.h"
|
||||||
#include "py/binary.h"
|
#include "py/binary.h"
|
||||||
|
|
||||||
#include "supervisor/shared/translate.h"
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
|
||||||
#if MICROPY_PY_UCTYPES
|
#if MICROPY_PY_UCTYPES
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
|
||||||
#include "supervisor/shared/translate.h"
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
|
||||||
#if MICROPY_PY_UHASHLIB
|
#if MICROPY_PY_UHASHLIB
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "py/objlist.h"
|
#include "py/objlist.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
|
||||||
#include "supervisor/shared/translate.h"
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
|
||||||
#if MICROPY_PY_UHEAPQ
|
#if MICROPY_PY_UHEAPQ
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "py/stream.h"
|
#include "py/stream.h"
|
||||||
|
|
||||||
#include "supervisor/shared/translate.h"
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
|
||||||
#if MICROPY_PY_UJSON
|
#if MICROPY_PY_UJSON
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "py/smallint.h"
|
#include "py/smallint.h"
|
||||||
|
|
||||||
#include "supervisor/shared/translate.h"
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
|
||||||
#if MICROPY_PY_UTIMEQ
|
#if MICROPY_PY_UTIMEQ
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "py/stream.h"
|
#include "py/stream.h"
|
||||||
#include "py/mperrno.h"
|
#include "py/mperrno.h"
|
||||||
|
|
||||||
#include "supervisor/shared/translate.h"
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
|
||||||
#if MICROPY_PY_UZLIB
|
#if MICROPY_PY_UZLIB
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 5d01882c41dbc4115bc94f0b61c093d5a6b812b6
|
Subproject commit 346c936e14c6ea3a8d3d65cb1fa46202dc92999d
|
@ -20,7 +20,7 @@
|
|||||||
#include "extmod/vfs_fat.h"
|
#include "extmod/vfs_fat.h"
|
||||||
#include "shared/timeutils/timeutils.h"
|
#include "shared/timeutils/timeutils.h"
|
||||||
#include "supervisor/filesystem.h"
|
#include "supervisor/filesystem.h"
|
||||||
#include "supervisor/shared/translate.h"
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
|
||||||
#if FF_MAX_SS == FF_MIN_SS
|
#if FF_MAX_SS == FF_MIN_SS
|
||||||
#define SECSIZE(fs) (FF_MIN_SS)
|
#define SECSIZE(fs) (FF_MIN_SS)
|
||||||
@ -30,6 +30,11 @@
|
|||||||
|
|
||||||
#define mp_obj_fat_vfs_t fs_user_mount_t
|
#define mp_obj_fat_vfs_t fs_user_mount_t
|
||||||
|
|
||||||
|
// Factoring this common call saves about 90 bytes.
|
||||||
|
STATIC NORETURN void mp_raise_OSError_fresult(FRESULT res) {
|
||||||
|
mp_raise_OSError(fresult_to_errno_table[res]);
|
||||||
|
}
|
||||||
|
|
||||||
STATIC mp_import_stat_t fat_vfs_import_stat(void *vfs_in, const char *path) {
|
STATIC mp_import_stat_t fat_vfs_import_stat(void *vfs_in, const char *path) {
|
||||||
fs_user_mount_t *vfs = vfs_in;
|
fs_user_mount_t *vfs = vfs_in;
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
@ -64,7 +69,7 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
|||||||
// don't error out if no filesystem, to let mkfs()/mount() create one if wanted
|
// don't error out if no filesystem, to let mkfs()/mount() create one if wanted
|
||||||
vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NO_FILESYSTEM;
|
vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NO_FILESYSTEM;
|
||||||
} else if (res != FR_OK) {
|
} else if (res != FR_OK) {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MP_OBJ_FROM_PTR(vfs);
|
return MP_OBJ_FROM_PTR(vfs);
|
||||||
@ -97,7 +102,7 @@ STATIC mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) {
|
|||||||
res = f_mkfs(&vfs->fatfs, FM_FAT32, 0, working_buf, sizeof(working_buf));
|
res = f_mkfs(&vfs->fatfs, FM_FAT32, 0, working_buf, sizeof(working_buf));
|
||||||
}
|
}
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
@ -172,7 +177,7 @@ STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) {
|
|||||||
iter->is_str = is_str_type;
|
iter->is_str = is_str_type;
|
||||||
FRESULT res = f_opendir(&self->fatfs, &iter->dir, path);
|
FRESULT res = f_opendir(&self->fatfs, &iter->dir, path);
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MP_OBJ_FROM_PTR(iter);
|
return MP_OBJ_FROM_PTR(iter);
|
||||||
@ -188,7 +193,7 @@ STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t vfs_in, mp_obj_t path_in, mp_in
|
|||||||
FRESULT res = f_stat(&self->fatfs, path, &fno);
|
FRESULT res = f_stat(&self->fatfs, path, &fno);
|
||||||
|
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if path is a file or directory
|
// check if path is a file or directory
|
||||||
@ -196,7 +201,7 @@ STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t vfs_in, mp_obj_t path_in, mp_in
|
|||||||
res = f_unlink(&self->fatfs, path);
|
res = f_unlink(&self->fatfs, path);
|
||||||
|
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
} else {
|
} else {
|
||||||
@ -226,7 +231,7 @@ STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_
|
|||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
FRESULT res = f_stat(&self->fatfs, old_path, &fno);
|
FRESULT res = f_stat(&self->fatfs, old_path, &fno);
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
if ((fno.fattrib & AM_DIR) != 0 &&
|
if ((fno.fattrib & AM_DIR) != 0 &&
|
||||||
strlen(new_path) > strlen(old_path) &&
|
strlen(new_path) > strlen(old_path) &&
|
||||||
@ -245,7 +250,7 @@ STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_
|
|||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
} else {
|
} else {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -259,7 +264,7 @@ STATIC mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) {
|
|||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
} else {
|
} else {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir);
|
||||||
@ -273,7 +278,7 @@ STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) {
|
|||||||
FRESULT res = f_chdir(&self->fatfs, path);
|
FRESULT res = f_chdir(&self->fatfs, path);
|
||||||
|
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
@ -286,7 +291,7 @@ STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {
|
|||||||
char buf[MICROPY_ALLOC_PATH_MAX + 1];
|
char buf[MICROPY_ALLOC_PATH_MAX + 1];
|
||||||
FRESULT res = f_getcwd(&self->fatfs, buf, sizeof(buf));
|
FRESULT res = f_getcwd(&self->fatfs, buf, sizeof(buf));
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
return mp_obj_new_str(buf, strlen(buf));
|
return mp_obj_new_str(buf, strlen(buf));
|
||||||
}
|
}
|
||||||
@ -307,7 +312,7 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
|
|||||||
} else {
|
} else {
|
||||||
FRESULT res = f_stat(&self->fatfs, path, &fno);
|
FRESULT res = f_stat(&self->fatfs, path, &fno);
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,7 +362,7 @@ STATIC mp_obj_t fat_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) {
|
|||||||
FATFS *fatfs = &self->fatfs;
|
FATFS *fatfs = &self->fatfs;
|
||||||
FRESULT res = f_getfree(fatfs, &nclst);
|
FRESULT res = f_getfree(fatfs, &nclst);
|
||||||
if (FR_OK != res) {
|
if (FR_OK != res) {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
|
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
|
||||||
@ -395,7 +400,7 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs
|
|||||||
res = f_mkfs(&self->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf));
|
res = f_mkfs(&self->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf));
|
||||||
}
|
}
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
self->blockdev.flags &= ~MP_BLOCKDEV_FLAG_NO_FILESYSTEM;
|
self->blockdev.flags &= ~MP_BLOCKDEV_FLAG_NO_FILESYSTEM;
|
||||||
|
|
||||||
@ -416,7 +421,7 @@ STATIC mp_obj_t vfs_fat_getlabel(mp_obj_t self_in) {
|
|||||||
char working_buf[12];
|
char working_buf[12];
|
||||||
FRESULT res = f_getlabel(&self->fatfs, working_buf, NULL);
|
FRESULT res = f_getlabel(&self->fatfs, working_buf, NULL);
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
return mp_obj_new_str(working_buf, strlen(working_buf));
|
return mp_obj_new_str(working_buf, strlen(working_buf));
|
||||||
}
|
}
|
||||||
@ -431,7 +436,7 @@ STATIC mp_obj_t vfs_fat_setlabel(mp_obj_t self_in, mp_obj_t label_in) {
|
|||||||
if (res == FR_WRITE_PROTECTED) {
|
if (res == FR_WRITE_PROTECTED) {
|
||||||
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Read-only filesystem"));
|
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Read-only filesystem"));
|
||||||
}
|
}
|
||||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
mp_raise_OSError_fresult(res);
|
||||||
}
|
}
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
@ -440,7 +445,7 @@ STATIC const mp_obj_property_t fat_vfs_label_obj = {
|
|||||||
.base.type = &mp_type_property,
|
.base.type = &mp_type_property,
|
||||||
.proxy = {(mp_obj_t)&fat_vfs_getlabel_obj,
|
.proxy = {(mp_obj_t)&fat_vfs_getlabel_obj,
|
||||||
(mp_obj_t)&fat_vfs_setlabel_obj,
|
(mp_obj_t)&fat_vfs_setlabel_obj,
|
||||||
(mp_obj_t)MP_ROM_NONE},
|
MP_ROM_NONE},
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rwxa_count != 1 || plus_count > 1 || bt_count > 1 || bad_mode) {
|
if (rwxa_count != 1 || plus_count > 1 || bt_count > 1 || bad_mode) {
|
||||||
mp_raise_ValueError(translate("Invalid mode"));
|
mp_arg_error_invalid(MP_QSTR_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(vfs != NULL);
|
assert(vfs != NULL);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "py/stream.h"
|
#include "py/stream.h"
|
||||||
#include "extmod/vfs_posix.h"
|
#include "extmod/vfs_posix.h"
|
||||||
#include "supervisor/shared/translate.h"
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
|
||||||
#if (defined(MICROPY_VFS_POSIX) && MICROPY_VFS_POSIX) || (defined(MICROPY_VFS_POSIX_FILE) && MICROPY_VFS_POSIX_FILE)
|
#if (defined(MICROPY_VFS_POSIX) && MICROPY_VFS_POSIX) || (defined(MICROPY_VFS_POSIX_FILE) && MICROPY_VFS_POSIX_FILE)
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit baab505fd4dcc54d8e9d45e6463c68bdc6d100eb
|
Subproject commit f91ffb1a3e77802349f233964e0faed9708a04fe
|
@ -1 +1 @@
|
|||||||
Subproject commit beec03065712cd62f79e839d5cf8f7c9847fc3b1
|
Subproject commit 5c1a51f8ad505e90a6c1b58c4d7926c59dd627d6
|
@ -1 +1 @@
|
|||||||
Subproject commit 859a7d403e4e79ec1c8915c81ba581dbaab8a4ac
|
Subproject commit 810232a6df1c5342b9c89268893025bca2645a0f
|
@ -1 +1 @@
|
|||||||
Subproject commit a8abc3aa8dece6c4d0152b001dfca7d2c279f899
|
Subproject commit 5f6ac407074c61806c9bf0b78987e1c0ed234dd0
|
@ -1 +1 @@
|
|||||||
Subproject commit b04042addd47c2645e139032b02a3b9ddeeb3425
|
Subproject commit f5351add4bfc2aae1ba8f9078f4a734a0893e8ba
|
@ -1 +1 @@
|
|||||||
Subproject commit 938f6bb335ba5e4c56a8062c591ff9f3c18c4297
|
Subproject commit 62113618a07dd4f33310e8454bd59915b376e3cb
|
@ -1 +1 @@
|
|||||||
Subproject commit 8e7e111a9ff39d3f4311caa7babeb451422c759f
|
Subproject commit f7bc753d37b840d0c1dcbdd977a97d1f68fac306
|
@ -1 +1 @@
|
|||||||
Subproject commit df2449815433e05ea0f89c19518ccde7a10a2faa
|
Subproject commit f70254c588e4be37d92960c8067905ac57243aa2
|
@ -1 +1 @@
|
|||||||
Subproject commit 708bb0c82c7b075bd6912c97231aea880b1a1cb8
|
Subproject commit bcd9e5c085081175f2dc1b2ce1eba75cfe4be062
|
@ -1 +1 @@
|
|||||||
Subproject commit 0bd04a235556979bd13a373821a6602445fe132b
|
Subproject commit c82b8138e13f4e3d580081929fb34afdb56f59fc
|
@ -1 +1 @@
|
|||||||
Subproject commit eb6124fdff59b98d7d49dd86072df99c0e97167b
|
Subproject commit 1b39a6990c7d18a1c883b5721f2e49cd5fbfc64e
|
@ -1 +1 @@
|
|||||||
Subproject commit 13775b058422085762874fde8e587f2e9f066855
|
Subproject commit 9cca65bd52f1b0be672fa8c1ea74b278366851a9
|
@ -1 +1 @@
|
|||||||
Subproject commit f6cdec74b64112016c459abe4a5d31a3b34caeb3
|
Subproject commit 3198742a78996db3118e0e4db3d142e37b7f58a1
|
@ -1 +1 @@
|
|||||||
Subproject commit bccbe3da75f42b540b3faebb9d5a2d1ccf5e7147
|
Subproject commit 04608edb68bc72c015de570b6edf6cc598920acc
|
@ -1 +1 @@
|
|||||||
Subproject commit 2fddabcaf0df1763111ed9dbf9e2d4cdb5b0434e
|
Subproject commit 4d68643dcd779e63b4eada09fa84b1ad43c83362
|
@ -1 +1 @@
|
|||||||
Subproject commit 9771c9369c7e251f514eb26abcfcea1e891e6f27
|
Subproject commit 9464b4cad1f252807cd431a39984182bdd7a0cce
|
1
frozen/Adafruit_CircuitPython_IS31FL3731
Submodule
1
frozen/Adafruit_CircuitPython_IS31FL3731
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 8e2069de65e1b2002ca375e9046ba6e608052c87
|
@ -1 +1 @@
|
|||||||
Subproject commit 29816fbe98c012ea0a1b5cae7f07aeae7ebf8b52
|
Subproject commit 80f1d250f4caef3e81760dc7df56bd250210f29b
|
@ -1 +1 @@
|
|||||||
Subproject commit acc4bdd73fdceb74d75cd5a1f261ae157ee32613
|
Subproject commit 0a262391849fa75671c999e9374bf6b160771246
|
@ -1 +1 @@
|
|||||||
Subproject commit 75e9ec62e4fe47a7212a69fb84aa1cfa7848e2b3
|
Subproject commit 87f8b1ddff699b98e7b58d1c969c0c3633661a08
|
@ -1 +1 @@
|
|||||||
Subproject commit 6641509ef43b672a82addf41f02b6466d6c67f01
|
Subproject commit 1107fe1520406c20bc561535d72df9ac6ae4d172
|
@ -1 +1 @@
|
|||||||
Subproject commit fd478fda7adbd254282b8cad5000f06a96760c91
|
Subproject commit b0aca1110b4446bc7952d66233b559256cd4377d
|
@ -1 +1 @@
|
|||||||
Subproject commit a115fc30df1c230c09c8a533ca77f3a4afd9f6c3
|
Subproject commit a4e11ce3a7f5886c706da5778baf1dd653172c94
|
@ -1 +1 @@
|
|||||||
Subproject commit 77ba8eedf89b96c85a6194e5da2061c9d5c20242
|
Subproject commit b9201eb175823b82d56168b0b539847093866090
|
@ -1 +1 @@
|
|||||||
Subproject commit 011acd627fc24342c397fc640b204a798f7b69dd
|
Subproject commit 0af8820605c0858f50f3242fbd1ce3a576bec819
|
@ -1 +1 @@
|
|||||||
Subproject commit c58defd70947531c5a9c37ddcb569f240567a78b
|
Subproject commit 2fc2bfb8f52afc2ec1f31e8d860358547b2f8a9a
|
@ -1 +1 @@
|
|||||||
Subproject commit 742ac7c8fb52bb85d9fd367b60a7f80475d7ed14
|
Subproject commit 6b018cbeb60d6a30088c866a9b1bc46166209735
|
@ -1 +1 @@
|
|||||||
Subproject commit 49ab415d6b601c99979262f9e91c21dcb3a927a7
|
Subproject commit 9c71a86d54015260bd40ad4bc8d0258c930bcc64
|
@ -1 +1 @@
|
|||||||
Subproject commit 270565665ada26fe8d7a99a3cb5941b452444471
|
Subproject commit 9ad59c3bc5e2fdc341779ccbbe2d78560c5d681f
|
@ -1 +1 @@
|
|||||||
Subproject commit 9dd51fecfcbb15cb2a00eeadbd66b36ce0c09ee2
|
Subproject commit ab504a86afb583bbe9008884bc01b33f0654a0dd
|
@ -1 +1 @@
|
|||||||
Subproject commit 79c70a49285be8b6548de3f5ca20aa5ac1fafa22
|
Subproject commit 4a094ea8e0ca902e7c61822060e149d73fa18ce5
|
@ -1 +1 @@
|
|||||||
Subproject commit 272d225365eed46916390cf1f393dd08bc00b7d4
|
Subproject commit 60d9df0ca09b5005ea0c03b94daae854983d79bd
|
@ -1 +1 @@
|
|||||||
Subproject commit fad0f89e760829a76f553ef8459f61001597a846
|
Subproject commit 1156062b06771afd37da54d0b690a84ef611a78b
|
@ -1 +1 @@
|
|||||||
Subproject commit e86f258e43591ce4a04661277e77e9fdf6fec27e
|
Subproject commit 79ff12be057ff5975e52ad273e087d74deb147ab
|
1
frozen/Adafruit_CircuitPython_Ticks
Submodule
1
frozen/Adafruit_CircuitPython_Ticks
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 704cac4af3dccf8e452e69eb8f9f22fe8db26f83
|
1
frozen/Adafruit_CircuitPython_asyncio
Submodule
1
frozen/Adafruit_CircuitPython_asyncio
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 339e037bf6cf30e03fab6fa5b1b9f669821f7685
|
@ -1 +1 @@
|
|||||||
Subproject commit c89c8689161e5b35bfe4fa8355615696e03f0648
|
Subproject commit 73b78e242424b865785d5e66ccef949bdacf7214
|
@ -1 +1 @@
|
|||||||
Subproject commit 3bdd335452ff14a53d1e840de043e3159cb3b829
|
Subproject commit 4124dfbdaadce1966f457d7d6c6984e9832999bf
|
1
frozen/circuitpython_ef_music
Submodule
1
frozen/circuitpython_ef_music
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 6e8eedb1475e2b91f8dea7bceebb20e44d70b171
|
1
frozen/circuitpython_picoed
Submodule
1
frozen/circuitpython_picoed
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 53f15602460329f69fef95498e6b8293aebb513a
|
1
frozen/mixgo_cp_lib
Submodule
1
frozen/mixgo_cp_lib
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit d5e3e809d7aa938b233b49526c55bfd2e314272c
|
1
frozen/pew-pewpew-lcd
Submodule
1
frozen/pew-pewpew-lcd
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 6452f2a78f32cf3b5d07e699f26d25e9c4d10d09
|
1
lib/adafruit_floppy
Submodule
1
lib/adafruit_floppy
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit e36a6127b957ab2f602e031ba3583de9c571582e
|
@ -83,6 +83,8 @@ typedef struct {
|
|||||||
} TINF_TREE;
|
} TINF_TREE;
|
||||||
|
|
||||||
struct uzlib_uncomp {
|
struct uzlib_uncomp {
|
||||||
|
/* Point to the CircuitPython object that owns this decompression stream */
|
||||||
|
void *self;
|
||||||
/* Pointer to the next byte in the input buffer */
|
/* Pointer to the next byte in the input buffer */
|
||||||
const unsigned char *source;
|
const unsigned char *source;
|
||||||
/* Pointer to the next byte past the input buffer (source_limit = source + len) */
|
/* Pointer to the next byte past the input buffer (source_limit = source + len) */
|
||||||
|
1202
locale/ID.po
1202
locale/ID.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1328
locale/cs.po
1328
locale/cs.po
File diff suppressed because it is too large
Load Diff
1359
locale/de_DE.po
1359
locale/de_DE.po
File diff suppressed because it is too large
Load Diff
929
locale/el.po
929
locale/el.po
File diff suppressed because it is too large
Load Diff
1336
locale/en_GB.po
1336
locale/en_GB.po
File diff suppressed because it is too large
Load Diff
1323
locale/es.po
1323
locale/es.po
File diff suppressed because it is too large
Load Diff
1109
locale/fil.po
1109
locale/fil.po
File diff suppressed because it is too large
Load Diff
1470
locale/fr.po
1470
locale/fr.po
File diff suppressed because it is too large
Load Diff
929
locale/hi.po
929
locale/hi.po
File diff suppressed because it is too large
Load Diff
1137
locale/it_IT.po
1137
locale/it_IT.po
File diff suppressed because it is too large
Load Diff
1213
locale/ja.po
1213
locale/ja.po
File diff suppressed because it is too large
Load Diff
966
locale/ko.po
966
locale/ko.po
File diff suppressed because it is too large
Load Diff
1275
locale/nl.po
1275
locale/nl.po
File diff suppressed because it is too large
Load Diff
1179
locale/pl.po
1179
locale/pl.po
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user