Compare commits
64 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e494ca4b51 | ||
|
25f09479fc | ||
|
378a727ed0 | ||
|
74833ad35f | ||
|
652860ad2d | ||
|
8f6b5e885c | ||
|
44c398d186 | ||
|
1d39be4954 | ||
|
6d6089f4c2 | ||
|
ef4993a7a6 | ||
|
17955ba5e2 | ||
|
1ef1301346 | ||
|
934534c9ee | ||
|
83fcdba9c4 | ||
|
3d49d180d1 | ||
|
3201c16d3b | ||
|
8b97d8f13a | ||
|
d8b1df380e | ||
|
c605b8e068 | ||
|
89c412e7f6 | ||
|
3a2decba00 | ||
|
da50901576 | ||
|
8f9122af50 | ||
|
47dbf9ef3e | ||
|
fb9e4cf306 | ||
|
57c52c758e | ||
|
cae4eea42b | ||
|
3474f6b1f9 | ||
|
2c26e87854 | ||
|
67b85dc2e0 | ||
|
173cc4bd5f | ||
|
43ad85dca5 | ||
|
ef726bb87a | ||
|
a367d562ab | ||
|
252f14e992 | ||
|
97f75ad517 | ||
|
655f0c0eec | ||
|
702485dae8 | ||
|
e643e2e561 | ||
|
93055e728e | ||
|
b6494919a9 | ||
|
e43ddc0e17 | ||
|
919295039d | ||
|
45e141c6f8 | ||
|
fbfd436ea9 | ||
|
8794cd4f81 | ||
|
507677b20a | ||
|
1dd24b6ccd | ||
|
5d8c798256 | ||
|
cdf7acf340 | ||
|
975f992e40 | ||
|
68a25eb04f | ||
|
659f2d5bd8 | ||
|
9a38a6c46a | ||
|
b3b7eb9802 | ||
|
c06e631862 | ||
|
1d07447580 | ||
|
f66fc25d95 | ||
|
01be02dd00 | ||
|
223cf44ec3 | ||
|
eee48f57c2 | ||
|
f601af0a93 | ||
|
71cc5551f2 | ||
|
a1387b72f5 |
@ -1,7 +0,0 @@
|
||||
#define MICROPY_HW_BOARD_NAME "BLOK"
|
||||
USB_PRODUCT = "BLOK"
|
||||
uint32_t THI = (*(uint32_t *)FUSES_HOT_TEMP_VAL_INT_ADDR & FUSES_HOT_TEMP_VAL_INT_Msk) >> FUSES_HOT_TEMP_VAL_INT_Pos;
|
||||
float TH = THI + convert_dec_to_frac(THD);
|
||||
print(binascii.b2a_base64(b"fo"))
|
||||
# again, neither will "there" or "wither", since they have "the"
|
||||
i1Qb$TE"rl
|
@ -1,28 +0,0 @@
|
||||
ans
|
||||
ure
|
||||
clen
|
||||
ser
|
||||
endianess
|
||||
pris
|
||||
synopsys
|
||||
reenable
|
||||
dout
|
||||
inout
|
||||
wel
|
||||
iput
|
||||
hsi
|
||||
astroid
|
||||
busses
|
||||
cyphertext
|
||||
dum
|
||||
deque
|
||||
deques
|
||||
extint
|
||||
shs
|
||||
pass-thru
|
||||
numer
|
||||
arithmetics
|
||||
ftbfs
|
||||
straightaway
|
||||
ftbs
|
||||
ftb
|
10
.codespellrc
10
.codespellrc
@ -1,10 +0,0 @@
|
||||
# See: https://github.com/codespell-project/codespell#using-a-config-file
|
||||
[codespell]
|
||||
# In the event of a false positive, add the problematic word, in all lowercase, to 'ignore-words.txt' (one word per line).
|
||||
# Or copy & paste the whole problematic line to 'exclude-file.txt'
|
||||
ignore-words = .codespell/ignore-words.txt
|
||||
exclude-file = .codespell/exclude-file.txt
|
||||
check-filenames =
|
||||
check-hidden =
|
||||
count =
|
||||
skip = .cproject,.git,./lib,./locale,ACKNOWLEDGEMENTS
|
@ -1,31 +0,0 @@
|
||||
Build CircuitPython in a Github-Devcontainer
|
||||
============================================
|
||||
|
||||
To build CircuitPython within a Github-Devcontainer, you need to perform
|
||||
the following steps.
|
||||
|
||||
1. checkout the code to a devcontainer
|
||||
|
||||
- click on the green "<> Code"-button
|
||||
- select the Codespaces-tab
|
||||
- choose "+ new with options..." from the "..."-menu
|
||||
- in the following screen select the branch and then
|
||||
- select ".devcontainer/cortex-m/devcontainer.json" instead
|
||||
of "Default Codespaces configuration"
|
||||
- update region as necessary
|
||||
- finally, click on the green "Create codespace" button
|
||||
|
||||
2. Your codespace is created. Cloning the images is quite fast, but
|
||||
preparing it for CircuitPython-development takes about 10 minutes.
|
||||
Note that this is a one-time task.
|
||||
|
||||
3. During creation, you can run the command
|
||||
`tail -f /workspaces/.codespaces/.persistedshare/creation.log`
|
||||
to see what is going on.
|
||||
|
||||
4. To actually build CircuitPython, run
|
||||
|
||||
cd ports/raspberrypi
|
||||
make -j $(nproc) BOARD=whatever TRANSLATION=xx_XX
|
||||
|
||||
This takes about 2m40s.
|
@ -1,23 +0,0 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||
// README at: https://github.com/devcontainers/templates/tree/main/src/universal
|
||||
{
|
||||
"name": "CircuitPython Cortex-M Build-Environment (base: Default Linux Universal)",
|
||||
"image": "mcr.microsoft.com/devcontainers/universal:2-linux",
|
||||
"postCreateCommand": ".devcontainer/cortex-m/on-create.sh",
|
||||
"remoteEnv": { "PATH": "/workspaces/gcc-arm-none-eabi/bin:${containerEnv:PATH}" }
|
||||
|
||||
// Features to add to the dev container. More info: https://containers.dev/features.
|
||||
// "features": {},
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
// "postCreateCommand": "uname -a",
|
||||
|
||||
// Configure tool-specific properties.
|
||||
// "customizations": {},
|
||||
|
||||
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
||||
// "remoteUser": "root"
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
#!/bin/bash
|
||||
# -----------------------------------------------------------------------------
|
||||
# on-create.sh: postCreateCommand-hook for devcontainer.json (Cortex-M build)
|
||||
#
|
||||
# Author: Bernhard Bablok
|
||||
#
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
echo -e "[on-create.sh] downloading and installing gcc-arm-non-eabi toolchain"
|
||||
cd /workspaces
|
||||
wget -qO gcc-arm-none-eabi.tar.bz2 https://adafru.it/Pid
|
||||
tar -xjf gcc-arm-none-eabi.tar.bz2
|
||||
ln -s gcc-arm-none-eabi-10-2020-q4-major gcc-arm-none-eabi
|
||||
rm -f /workspaces/gcc-arm-none-eabi.tar.bz2
|
||||
export PATH=/workspaces/gcc-arm-none-eabi/bin:$PATH
|
||||
|
||||
# add repository and install tools
|
||||
echo -e "[on-create.sh] adding pybricks/ppa"
|
||||
sudo add-apt-repository -y ppa:pybricks/ppa
|
||||
echo -e "[on-create.sh] installing uncrustify and mtools"
|
||||
sudo apt-get -y install uncrustify mtools
|
||||
|
||||
# dosfstools >= 4.2 needed, standard repo only has 4.1
|
||||
echo -e "[on-create.sh] downloading and installing dosfstools"
|
||||
wget https://github.com/dosfstools/dosfstools/releases/download/v4.2/dosfstools-4.2.tar.gz
|
||||
tar -xzf dosfstools-4.2.tar.gz
|
||||
cd dosfstools-4.2/
|
||||
./configure
|
||||
make -j $(nproc)
|
||||
sudo make install
|
||||
cd /workspaces
|
||||
rm -fr /workspaces/dosfstools-4.2 /workspaces/dosfstools-4.2.tar.gz
|
||||
|
||||
# prepare source-code tree
|
||||
cd /workspaces/circuitpython/
|
||||
echo -e "[on-create.sh] fetching submodules"
|
||||
make fetch-all-submodules
|
||||
echo -e "[on-create.sh] fetching tags"
|
||||
git fetch --tags --recurse-submodules=no --shallow-since="2021-07-01" https://github.com/adafruit/circuitpython HEAD
|
||||
|
||||
# additional python requirements
|
||||
echo -e "[on-create.sh] pip-installing requirements"
|
||||
pip install --upgrade -r requirements-dev.txt
|
||||
pip install --upgrade -r requirements-doc.txt
|
||||
|
||||
# add pre-commit
|
||||
echo -e "[on-create.sh] installing pre-commit"
|
||||
pre-commit install
|
||||
|
||||
# create cross-compiler
|
||||
echo -e "[on-create.sh] building mpy-cross"
|
||||
make -j $(nproc) -C mpy-cross # time: about 36 sec
|
||||
|
||||
# that's it!
|
||||
echo -e "[on-create.sh] setup complete"
|
||||
|
||||
#commands to actually build CP:
|
||||
#cd ports/raspberrypi
|
||||
#time make -j $(nproc) BOARD=pimoroni_tufty2040 TRANSLATION=de_DE
|
@ -1,56 +0,0 @@
|
||||
# all: Fix various spelling mistakes found by codespell 2.2.6.
|
||||
cf490a70917a1b2d38ba9b58e763e0837d0f7ca7
|
||||
|
||||
# all: Fix spelling mistakes based on codespell check.
|
||||
b1229efbd1509654dec6053865ab828d769e29db
|
||||
|
||||
# top: Update Python formatting to black "2023 stable style".
|
||||
8b2748269244304854b3462cb8902952b4dcb892
|
||||
|
||||
# all: Reformat remaining C code that doesn't have a space after a comma.
|
||||
5b700b0af90591d6b1a2c087bb8de6b7f1bfdd2d
|
||||
|
||||
# ports: Reformat more C and Python source code.
|
||||
5c32111fa0e31e451b0f1666bdf926be2fdfd82c
|
||||
|
||||
# all: Update Python formatting to latest Black version 22.1.0.
|
||||
ab2923dfa1174dc177f0a90cb00a7e4ff87958d2
|
||||
|
||||
# all: Update Python formatting to latest Black version 21.12b0.
|
||||
3770fab33449a5dadf8eb06edfae0767e75320a6
|
||||
|
||||
# tools/gen-cpydiff.py: Fix formatting of doc strings for new Black.
|
||||
0f78c36c5aa458a954eed39a46942209107a553e
|
||||
|
||||
# tests/run-tests.py: Reformat with Black.
|
||||
2a38d7103672580882fb621a5b76e8d26805d593
|
||||
|
||||
# all: Update Python code to conform to latest black formatting.
|
||||
06659077a81b85882254cf0953c33b27614e018e
|
||||
|
||||
# tools/uncrustify: Enable more opts to remove space between func and '('.
|
||||
77ed6f69ac35c1663a5633a8ee1d8a2446542204
|
||||
|
||||
# tools/codeformat.py: Include extmod/{btstack,nimble} in code formatting.
|
||||
026fda605e03113d6e753290d65fed774418bc53
|
||||
|
||||
# all: Format code to add space after C++-style comment start.
|
||||
84fa3312cfa7d2237d4b56952f2cd6e3591210c4
|
||||
|
||||
# tests: Format all Python code with black, except tests in basics subdir.
|
||||
3dc324d3f1312e40d3a8ed87e7244966bb756f26
|
||||
|
||||
# all: Remove spaces inside and around parenthesis.
|
||||
1a3e386c67e03a79eb768cb6e9f6777e002d6660
|
||||
|
||||
# all: Remove spaces between nested paren and inside function arg paren.
|
||||
feb25775851ba0c04b8d1013716f442258879d9c
|
||||
|
||||
# all: Reformat C and Python source code with tools/codeformat.py.
|
||||
69661f3343bedf86e514337cff63d96cc42f8859
|
||||
|
||||
# stm32/usbdev: Convert files to unix line endings.
|
||||
abde0fa2267f9062b28c3c015d7662a550125cc6
|
||||
|
||||
# all: Remove trailing spaces, per coding conventions.
|
||||
761e4c7ff62896c7d8f8c3dfc3cc98a4cc4f2f6f
|
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -11,7 +11,6 @@
|
||||
*.bat text eol=crlf
|
||||
|
||||
# These are binary so should never be modified by git.
|
||||
*.a binary
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.dxf binary
|
||||
|
54
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
54
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: 'bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- Thanks! for testing out CircuitPython. Now that you have got a problem...
|
||||
you can file a bug report for it. Feel free to modify the below format to better
|
||||
suit your issue. :) -->
|
||||
|
||||
**Firmware**
|
||||
|
||||
<!-- Include the version of CircuitPython you're running. You can see it in the
|
||||
`boot_out.txt` file, as well as in the REPL. -->
|
||||
|
||||
```python
|
||||
Adafruit CircuitPython 6.2.0-beta.2 on 2021-03-01; Raspberry Pi Pico with rp2040
|
||||
```
|
||||
|
||||
**Code/REPL**
|
||||
|
||||
<!-- Include your code that reproduces the bug here. Try to distill down to the
|
||||
minimum possible to reproduce. -->
|
||||
|
||||
```python
|
||||
import busio, bitbangio
|
||||
i2c = bitbangio.I2C(board.GP1, board.GP0)
|
||||
```
|
||||
|
||||
**Behavior**
|
||||
|
||||
<!-- What happens when you run the code above? Include any error messages. -->
|
||||
|
||||
```python
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
TimeoutError: Clock stretch too long
|
||||
```
|
||||
|
||||
**Description**
|
||||
|
||||
<!-- Optionally, describe the issue in more detail. Here are some examples: -->
|
||||
|
||||
- Error while using i2c...
|
||||
- Only happens when...
|
||||
- might be related to #4291...
|
||||
|
||||
**Additional Info**
|
||||
|
||||
<!-- Optionally, add any other information like hardware connection, scope output etc.
|
||||
If you have already done some debugging, mention it here. -->
|
63
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
63
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -1,63 +0,0 @@
|
||||
name: 🐞 Bug Report
|
||||
description: Create a bug report to help us improve
|
||||
labels:
|
||||
- bug
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >-
|
||||
Thanks for testing out CircuitPython! Now that you have encountered a
|
||||
bug... you can file a report for it.
|
||||
- type: textarea
|
||||
id: firmware
|
||||
attributes:
|
||||
label: CircuitPython version
|
||||
description: >-
|
||||
Include the version of CircuitPython you're running. You can see it in
|
||||
the `boot_out.txt` file, as well as in the `REPL`.
|
||||
placeholder: Adafruit CircuitPython 6.2.0 on 2021-03-01; Raspberry Pi Pico with rp2040
|
||||
render: python
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: code
|
||||
attributes:
|
||||
label: Code/REPL
|
||||
description: This is automatically rendered as Python, so no need for backticks.
|
||||
placeholder: |
|
||||
import busio, bitbangio
|
||||
i2c = bitbangio.I2C(board.GP1, board.GP0)
|
||||
render: python
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: behavior
|
||||
attributes:
|
||||
label: Behavior
|
||||
description: What happens when you run the code above? Include error messages (if any).
|
||||
placeholder: |
|
||||
```python
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
TimeoutError: Clock stretch too long
|
||||
```
|
||||
On-board led pulses red.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: Optionally, describe the bug in more detail.
|
||||
placeholder: |
|
||||
- Error while using i2c...
|
||||
- Only happens when...
|
||||
- might be related to #4291...
|
||||
- type: textarea
|
||||
id: more-info
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: >-
|
||||
Optionally, add any other information like hardware connection, scope
|
||||
output etc. If you have already done some debugging, mention it here.
|
||||
placeholder: Removing [this](url) line resolves the issue.
|
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,7 +1,7 @@
|
||||
contact_links:
|
||||
- name: 🔗 Adafruit Forum
|
||||
- name: Adafruit Forum
|
||||
url: https://forums.adafruit.com/
|
||||
about: Official Adafruit technical support forum. Good for getting help on getting a project working.
|
||||
- name: 🔗 Adafruit Discord
|
||||
- name: Adafruit Discord
|
||||
url: https://adafru.it/discord
|
||||
about: Unofficial chat with many helpful folks and normally prompt replies.
|
||||
|
4
.github/ISSUE_TEMPLATE/feature_request.md
vendored
4
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 🚀 Feature Request
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: 'enhancement'
|
||||
@ -7,5 +7,5 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- We keep adding new features and enhancements to CircuitPython 🚀
|
||||
<!-- We are always adding new features and enhancements to CircuitPython 🚀
|
||||
and would love ❤ to see what new challenge you have got for us... 🙂 -->
|
||||
|
59
.github/actions/deps/external/action.yml
vendored
59
.github/actions/deps/external/action.yml
vendored
@ -1,59 +0,0 @@
|
||||
name: Fetch external deps
|
||||
|
||||
inputs:
|
||||
action:
|
||||
required: false
|
||||
default: restore
|
||||
type: choice
|
||||
options:
|
||||
- cache
|
||||
- restore
|
||||
|
||||
port:
|
||||
required: false
|
||||
default: none
|
||||
type: string
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
# arm
|
||||
- name: Get arm toolchain
|
||||
if: >-
|
||||
inputs.port != 'none' &&
|
||||
inputs.port != 'litex' &&
|
||||
inputs.port != 'espressif'
|
||||
uses: carlosperate/arm-none-eabi-gcc-action@v1
|
||||
with:
|
||||
release: '13.2.Rel1'
|
||||
|
||||
# espressif
|
||||
- name: Get espressif toolchain
|
||||
if: inputs.port == 'espressif'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ninja-build
|
||||
shell: bash
|
||||
- name: Install IDF tools
|
||||
if: inputs.port == 'espressif'
|
||||
run: |
|
||||
$IDF_PATH/install.sh
|
||||
rm -rf $IDF_TOOLS_PATH/dist
|
||||
shell: bash
|
||||
- name: Set environment
|
||||
if: inputs.port == 'espressif'
|
||||
run: |
|
||||
source $IDF_PATH/export.sh
|
||||
echo >> $GITHUB_ENV "IDF_PYTHON_ENV_PATH=$IDF_PYTHON_ENV_PATH"
|
||||
echo >> $GITHUB_PATH "$PATH"
|
||||
shell: bash
|
||||
|
||||
# common
|
||||
- name: Cache python dependencies
|
||||
if: inputs.port != 'espressif'
|
||||
uses: ./.github/actions/deps/python
|
||||
with:
|
||||
action: ${{ inputs.action }}
|
||||
- name: Install python dependencies
|
||||
run: pip install -r requirements-dev.txt
|
||||
shell: bash
|
36
.github/actions/deps/ports/action.yml
vendored
36
.github/actions/deps/ports/action.yml
vendored
@ -1,36 +0,0 @@
|
||||
name: Fetch port deps
|
||||
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
outputs:
|
||||
port:
|
||||
value: ${{ steps.board-to-port.outputs.port }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Board to port
|
||||
id: board-to-port
|
||||
run: |
|
||||
PORT=$(find ports/*/boards/ -type d -name ${{ inputs.board }} | sed 's/^ports\///g;s/\/boards.*//g')
|
||||
if [ -z $PORT ]; then (exit 1); else echo >> $GITHUB_OUTPUT "port=$PORT"; fi
|
||||
shell: bash
|
||||
|
||||
- name: Set up broadcom
|
||||
if: steps.board-to-port.outputs.port == 'broadcom'
|
||||
uses: ./.github/actions/deps/ports/broadcom
|
||||
|
||||
- name: Set up espressif
|
||||
if: steps.board-to-port.outputs.port == 'espressif'
|
||||
uses: ./.github/actions/deps/ports/espressif
|
||||
|
||||
- name: Set up litex
|
||||
if: steps.board-to-port.outputs.port == 'litex'
|
||||
uses: ./.github/actions/deps/ports/litex
|
||||
|
||||
- name: Set up nrf
|
||||
if: steps.board-to-port.outputs.port == 'nrf'
|
||||
uses: ./.github/actions/deps/ports/nrf
|
22
.github/actions/deps/ports/broadcom/action.yml
vendored
22
.github/actions/deps/ports/broadcom/action.yml
vendored
@ -1,22 +0,0 @@
|
||||
name: Fetch broadcom port deps
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Get broadcom toolchain
|
||||
run: |
|
||||
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 apt-get update
|
||||
sudo apt-get install -y mtools
|
||||
shell: bash
|
||||
- name: Install mkfs.fat
|
||||
run: |
|
||||
wget https://github.com/dosfstools/dosfstools/releases/download/v4.2/dosfstools-4.2.tar.gz
|
||||
tar -xaf dosfstools-4.2.tar.gz
|
||||
cd dosfstools-4.2
|
||||
./configure
|
||||
make -j 2
|
||||
cd src
|
||||
echo >> $GITHUB_PATH $(pwd)
|
||||
shell: bash
|
36
.github/actions/deps/ports/espressif/action.yml
vendored
36
.github/actions/deps/ports/espressif/action.yml
vendored
@ -1,36 +0,0 @@
|
||||
name: Fetch espressif port deps
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Set IDF env
|
||||
run: |
|
||||
echo >> $GITHUB_ENV "IDF_PATH=$GITHUB_WORKSPACE/ports/espressif/esp-idf"
|
||||
echo >> $GITHUB_ENV "IDF_TOOLS_PATH=$GITHUB_WORKSPACE/.idf_tools"
|
||||
shell: bash
|
||||
|
||||
- name: Get IDF commit
|
||||
id: idf-commit
|
||||
run: |
|
||||
COMMIT=$(git submodule status ports/espressif/esp-idf | grep -o -P '(?<=^-).*(?= )')
|
||||
echo "$COMMIT"
|
||||
echo "commit=$COMMIT" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Cache IDF submodules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
.git/modules/ports/espressif/esp-idf
|
||||
ports/espressif/esp-idf
|
||||
key: submodules-idf-${{ steps.idf-commit.outputs.commit }}
|
||||
|
||||
- name: Cache IDF tools
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.IDF_TOOLS_PATH }}
|
||||
key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-idf-${{ steps.idf-commit.outputs.commit }}
|
||||
|
||||
- name: Initialize IDF submodules
|
||||
run: git submodule update --init --depth=1 --recursive $IDF_PATH
|
||||
shell: bash
|
10
.github/actions/deps/ports/litex/action.yml
vendored
10
.github/actions/deps/ports/litex/action.yml
vendored
@ -1,10 +0,0 @@
|
||||
name: Fetch litex port deps
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Get litex toolchain
|
||||
run: |
|
||||
wget https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-centos6.tar.gz
|
||||
sudo tar -C /usr --strip-components=1 -xaf riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-centos6.tar.gz
|
||||
shell: bash
|
17
.github/actions/deps/ports/nrf/action.yml
vendored
17
.github/actions/deps/ports/nrf/action.yml
vendored
@ -1,17 +0,0 @@
|
||||
name: Fetch nrf port deps
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Get nrfutil 7+
|
||||
run: |
|
||||
wget https://developer.nordicsemi.com/.pc-tools/nrfutil/x64-linux/nrfutil
|
||||
chmod +x nrfutil
|
||||
./nrfutil install nrf5sdk-tools
|
||||
mkdir -p $HOME/.local/bin
|
||||
mv nrfutil $HOME/.local/bin
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
- name: Print nrfutil version
|
||||
run: nrfutil -V
|
||||
shell: bash
|
42
.github/actions/deps/python/action.yml
vendored
42
.github/actions/deps/python/action.yml
vendored
@ -1,42 +0,0 @@
|
||||
name: Fetch python deps
|
||||
|
||||
inputs:
|
||||
action:
|
||||
description: The cache action to use
|
||||
required: false
|
||||
default: restore
|
||||
type: choice
|
||||
options:
|
||||
- cache
|
||||
- restore
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Cache python dependencies
|
||||
id: cache-python-deps
|
||||
if: inputs.action == 'cache'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .cp_tools
|
||||
key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-cp-${{ hashFiles('requirements-dev.txt') }}
|
||||
|
||||
- name: Restore python dependencies
|
||||
id: restore-python-deps
|
||||
if: inputs.action == 'restore'
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: .cp_tools
|
||||
key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-cp-${{ hashFiles('requirements-dev.txt') }}
|
||||
|
||||
- name: Set up venv
|
||||
if: inputs.action == 'cache' && !steps.cache-python-deps.outputs.cache-hit
|
||||
run: python -m venv .cp_tools
|
||||
shell: bash
|
||||
|
||||
- name: Activate venv
|
||||
if: inputs.action == 'cache' || (inputs.action == 'restore' && steps.restore-python-deps.outputs.cache-hit)
|
||||
run: |
|
||||
source .cp_tools/bin/activate
|
||||
echo >> $GITHUB_PATH "$PATH"
|
||||
shell: bash
|
87
.github/actions/deps/submodules/action.yml
vendored
87
.github/actions/deps/submodules/action.yml
vendored
@ -1,87 +0,0 @@
|
||||
name: 'Fetch Submodules'
|
||||
|
||||
inputs:
|
||||
target:
|
||||
description: 'The target for ci_fetch_deps'
|
||||
required: false
|
||||
type: string
|
||||
|
||||
submodules:
|
||||
description: 'The submodules to cache'
|
||||
required: false
|
||||
default: '["extmod/ulab", "lib/", "tools/"]'
|
||||
type: string
|
||||
|
||||
action:
|
||||
description: 'The cache action to use'
|
||||
required: false
|
||||
default: 'restore'
|
||||
type: choice
|
||||
options:
|
||||
- cache
|
||||
- restore
|
||||
|
||||
version:
|
||||
description: 'Whether to generate CP version'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
outputs:
|
||||
frozen:
|
||||
description: 'Whether frozen submodules were fetched'
|
||||
value: ${{ steps.cp-deps.outputs.frozen_tags }}
|
||||
|
||||
version:
|
||||
description: 'The CP version'
|
||||
value: ${{ steps.cp-version.outputs.cp-version }}
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Create submodule status
|
||||
id: create-submodule-status
|
||||
run: |
|
||||
git submodule status ${{ join(fromJSON(inputs.submodules), ' ') }} >> submodule_status
|
||||
echo $(cut -d ' ' -f 2 submodule_status) | echo "submodules=[\"$(sed "s/ /\", \"/g")\"]" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Cache submodules
|
||||
if: ${{ inputs.action == 'cache' }}
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ".git/modules/\n${{ join(fromJSON(steps.create-submodule-status.outputs.submodules), '\n') }}"
|
||||
key: submodules-common-${{ hashFiles('submodule_status') }}
|
||||
enableCrossOsArchive: true
|
||||
|
||||
- name: Restore submodules
|
||||
if: ${{ inputs.action == 'restore' }}
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: ".git/modules/\n${{ join(fromJSON(steps.create-submodule-status.outputs.submodules), '\n') }}"
|
||||
key: submodules-common-${{ hashFiles('submodule_status') }}
|
||||
enableCrossOsArchive: true
|
||||
|
||||
- name: Remove submodule status
|
||||
run: rm submodule_status
|
||||
shell: bash
|
||||
|
||||
- name: CircuitPython dependencies
|
||||
id: cp-deps
|
||||
run: python tools/ci_fetch_deps.py ${{ inputs.target || matrix.board || github.job }}
|
||||
shell: bash
|
||||
|
||||
- name: CircuitPython version
|
||||
id: cp-version
|
||||
if: ${{ inputs.version == 'true' }}
|
||||
run: |
|
||||
echo "::group::Fetch history and tags"
|
||||
git fetch --no-recurse-submodules --shallow-since="2021-07-01" --tags https://github.com/adafruit/circuitpython HEAD
|
||||
git fetch --no-recurse-submodules --shallow-since="2021-07-01" origin $GITHUB_SHA
|
||||
git repack -d
|
||||
echo "::endgroup::"
|
||||
CP_VERSION=$(tools/describe)
|
||||
echo "$CP_VERSION"
|
||||
echo "CP_VERSION=$CP_VERSION" >> $GITHUB_ENV
|
||||
echo "cp-version=$CP_VERSION" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
42
.github/actions/mpy_cross/action.yml
vendored
42
.github/actions/mpy_cross/action.yml
vendored
@ -1,42 +0,0 @@
|
||||
name: Set up mpy-cross
|
||||
|
||||
inputs:
|
||||
download:
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
cp-version:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Download mpy-cross
|
||||
id: download-mpy-cross
|
||||
if: inputs.download == 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mpy-cross
|
||||
path: mpy-cross/build
|
||||
|
||||
- name: Make mpy-cross executable
|
||||
if: inputs.download == 'true' && steps.download-mpy-cross.outcome == 'success'
|
||||
run: sudo chmod +x mpy-cross/build/mpy-cross
|
||||
shell: bash
|
||||
|
||||
- name: Build mpy-cross
|
||||
if: inputs.download == 'false' || steps.download-mpy-cross.outcome == 'failure'
|
||||
run: make -C mpy-cross -j2
|
||||
shell: bash
|
||||
env:
|
||||
CP_VERSION: ${{ inputs.cp-version }}
|
||||
|
||||
- name: Upload mpy-cross
|
||||
if: inputs.download == 'false' || steps.download-mpy-cross.outcome == 'failure'
|
||||
continue-on-error: true
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mpy-cross
|
||||
path: mpy-cross/build/mpy-cross
|
33
.github/actions/upload_aws/action.yml
vendored
33
.github/actions/upload_aws/action.yml
vendored
@ -1,33 +0,0 @@
|
||||
name: Upload to AWS S3
|
||||
|
||||
inputs:
|
||||
source:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
destination:
|
||||
required: false
|
||||
type: string
|
||||
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: true
|
||||
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Upload to S3
|
||||
if: >-
|
||||
(github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository_owner == 'adafruit') ||
|
||||
(github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
|
||||
run: >-
|
||||
[ -z "$AWS_ACCESS_KEY_ID" ] ||
|
||||
aws s3 cp ${{ inputs.source }} s3://adafruit-circuit-python/bin/${{ inputs.destination }}
|
||||
${{ endsWith(inputs.source, '/') && '--recursive' || '' }} --no-progress --region us-east-1
|
||||
env:
|
||||
AWS_PAGER: ''
|
||||
AWS_ACCESS_KEY_ID: ${{ inputs.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ inputs.AWS_SECRET_ACCESS_KEY }}
|
||||
shell: bash
|
87
.github/workflows/build-boards.yml
vendored
87
.github/workflows/build-boards.yml
vendored
@ -1,87 +0,0 @@
|
||||
name: Build boards
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
boards:
|
||||
required: true
|
||||
type: string
|
||||
cp-version:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: false
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
board:
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
CP_VERSION: ${{ inputs.cp-version }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
board: ${{ fromJSON(inputs.boards) }}
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: false
|
||||
fetch-depth: 1
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
- name: Set up port
|
||||
id: set-up-port
|
||||
uses: ./.github/actions/deps/ports
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
- name: Set up submodules
|
||||
id: set-up-submodules
|
||||
uses: ./.github/actions/deps/submodules
|
||||
- name: Set up external
|
||||
uses: ./.github/actions/deps/external
|
||||
with:
|
||||
port: ${{ steps.set-up-port.outputs.port }}
|
||||
- name: Set up mpy-cross
|
||||
if: steps.set-up-submodules.outputs.frozen == 'True'
|
||||
uses: ./.github/actions/mpy_cross
|
||||
with:
|
||||
cp-version: ${{ inputs.cp-version }}
|
||||
|
||||
- name: Versions
|
||||
run: |
|
||||
gcc --version
|
||||
python3 --version
|
||||
cmake --version || true
|
||||
ninja --version || true
|
||||
aarch64-none-elf-gcc --version || true
|
||||
arm-none-eabi-gcc --version || true
|
||||
xtensa-esp32-elf-gcc --version || true
|
||||
riscv32-esp-elf-gcc --version || true
|
||||
riscv64-unknown-elf-gcc --version || true
|
||||
mkfs.fat --version || true
|
||||
|
||||
- name: Set up build failure matcher
|
||||
run: echo "::add-matcher::$GITHUB_WORKSPACE/.github/workflows/match-build-fail.json"
|
||||
- name: Build board
|
||||
run: python3 -u build_release_files.py
|
||||
working-directory: tools
|
||||
env:
|
||||
BOARDS: ${{ matrix.board }}
|
||||
PULL: ${{ github.event.number }}
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ matrix.board }}
|
||||
path: bin/${{ matrix.board }}
|
||||
- name: Upload to S3
|
||||
uses: ./.github/actions/upload_aws
|
||||
with:
|
||||
source: bin/
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
74
.github/workflows/build-mpy-cross.yml
vendored
74
.github/workflows/build-mpy-cross.yml
vendored
@ -1,74 +0,0 @@
|
||||
name: Build mpy-cross
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
cp-version:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: false
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
mpy-cross: ["static", "static-aarch64", "static-mingw", "static-raspbian"]
|
||||
env:
|
||||
CP_VERSION: ${{ inputs.cp-version }}
|
||||
EX_static-mingw: static.exe
|
||||
OS_static: linux-amd64
|
||||
OS_static-aarch64: linux-aarch64
|
||||
OS_static-mingw: windows
|
||||
OS_static-raspbian: linux-raspbian
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: false
|
||||
fetch-depth: 1
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
- name: Set up submodules
|
||||
uses: ./.github/actions/deps/submodules
|
||||
with:
|
||||
target: mpy-cross
|
||||
|
||||
- name: Install toolchain (aarch64)
|
||||
if: matrix.mpy-cross == 'static-aarch64'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gcc-aarch64-linux-gnu
|
||||
- name: Install toolchain (mingw)
|
||||
if: matrix.mpy-cross == 'static-mingw'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y mingw-w64
|
||||
|
||||
- name: Build mpy-cross.${{ matrix.mpy-cross }}
|
||||
run: make -C mpy-cross -j2 -f Makefile.${{ matrix.mpy-cross }}
|
||||
|
||||
- name: Set output
|
||||
run: |
|
||||
echo >> $GITHUB_ENV "EX=${{ env[format('EX_{0}', matrix.mpy-cross)] || matrix.mpy-cross }}"
|
||||
echo >> $GITHUB_ENV "OS=${{ env[format('OS_{0}', matrix.mpy-cross)] }}"
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mpy-cross.${{ env.EX }}
|
||||
path: mpy-cross/build-${{ matrix.mpy-cross }}/mpy-cross.${{ env.EX }}
|
||||
- name: Upload to S3
|
||||
uses: ./.github/actions/upload_aws
|
||||
with:
|
||||
source: mpy-cross/build-${{ matrix.mpy-cross }}/mpy-cross.${{ env.EX }}
|
||||
destination: mpy-cross/${{ env.OS }}/mpy-cross-${{ env.OS }}-${{ env.CP_VERSION }}.${{ env.EX }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
756
.github/workflows/build.yml
vendored
756
.github/workflows/build.yml
vendored
@ -9,115 +9,142 @@ on:
|
||||
pull_request:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
check_suite:
|
||||
types: [rerequested]
|
||||
|
||||
jobs:
|
||||
scheduler:
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
docs: ${{ steps.set-matrix.outputs.docs }}
|
||||
ports: ${{ steps.set-matrix.outputs.ports }}
|
||||
windows: ${{ steps.set-matrix.outputs.windows }}
|
||||
cp-version: ${{ steps.set-up-submodules.outputs.version }}
|
||||
test:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v3
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v2.2.0
|
||||
with:
|
||||
submodules: false
|
||||
fetch-depth: 1
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v4
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
||||
- name: CircuitPython version
|
||||
run: |
|
||||
git describe --dirty --tags
|
||||
echo >>$GITHUB_ENV CP_VERSION=$(git describe --dirty --tags)
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.x
|
||||
- name: Duplicate USB VID/PID check
|
||||
python-version: 3.8
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y eatmydata
|
||||
sudo eatmydata apt-get install -y gettext librsvg2-bin mingw-w64 latexmk texlive-fonts-recommended texlive-latex-recommended texlive-latex-extra
|
||||
pip install -r requirements-dev.txt
|
||||
- name: Versions
|
||||
run: |
|
||||
gcc --version
|
||||
python3 --version
|
||||
- name: New boards check
|
||||
run: python3 -u ci_new_boards_check.py
|
||||
working-directory: tools
|
||||
- name: Duplicate USB VID/PID Check
|
||||
run: python3 -u -m tools.ci_check_duplicate_usb_vid_pid
|
||||
- name: Set up submodules
|
||||
id: set-up-submodules
|
||||
uses: ./.github/actions/deps/submodules
|
||||
- name: Build and Validate Stubs
|
||||
run: make check-stubs -j2
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
action: cache
|
||||
version: true
|
||||
- name: Set up external
|
||||
uses: ./.github/actions/deps/external
|
||||
name: stubs
|
||||
path: circuitpython-stubs*
|
||||
- name: Test Documentation Build (HTML)
|
||||
run: sphinx-build -E -W -b html -D version=${{ env.CP_VERSION }} -D release=${{ env.CP_VERSION }} . _build/html
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
action: cache
|
||||
- name: Set up mpy-cross
|
||||
uses: ./.github/actions/mpy_cross
|
||||
name: docs
|
||||
path: _build/html
|
||||
- name: Test Documentation Build (LaTeX/PDF)
|
||||
run: |
|
||||
make latexpdf
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
cp-version: ${{ steps.set-up-submodules.outputs.version }}
|
||||
download: false
|
||||
- name: Get last commit with checks
|
||||
id: get-last-commit-with-checks
|
||||
if: github.event_name == 'pull_request'
|
||||
working-directory: tools
|
||||
run: python3 -u ci_changes_per_commit.py
|
||||
name: docs
|
||||
path: _build/latex
|
||||
- name: Build mpy-cross
|
||||
run: make -C mpy-cross -j2
|
||||
- name: Build unix port
|
||||
run: |
|
||||
make -C ports/unix deplibs -j2
|
||||
make -C ports/unix -j2
|
||||
make -C ports/unix coverage -j2
|
||||
- name: Test all
|
||||
run: MICROPY_CPYTHON3=python3.8 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1
|
||||
working-directory: tests
|
||||
- name: Print failure info
|
||||
run: |
|
||||
shopt -s nullglob;
|
||||
for exp in *.exp;
|
||||
do testbase=$(basename $exp .exp);
|
||||
echo -e "\nFAILURE $testbase";
|
||||
diff -u $testbase.exp $testbase.out;
|
||||
done
|
||||
working-directory: tests
|
||||
if: failure()
|
||||
- name: Native Tests
|
||||
run: MICROPY_CPYTHON3=python3.8 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --emit native
|
||||
working-directory: tests
|
||||
- name: mpy Tests
|
||||
run: MICROPY_CPYTHON3=python3.8 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --via-mpy -d basics float
|
||||
working-directory: tests
|
||||
- name: Build mpy-cross.static-raspbian
|
||||
run: make -C mpy-cross -j2 -f Makefile.static-raspbian
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: mpy-cross.static-raspbian
|
||||
path: mpy-cross/mpy-cross.static-raspbian
|
||||
- name: Build mpy-cross.static
|
||||
run: make -C mpy-cross -j2 -f Makefile.static
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: mpy-cross.static-amd64-linux
|
||||
path: mpy-cross/mpy-cross.static
|
||||
- name: Build mpy-cross.static-mingw
|
||||
run: make -C mpy-cross -j2 -f Makefile.static-mingw
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: mpy-cross.static-x64-windows
|
||||
path: mpy-cross/mpy-cross.static.exe
|
||||
- name: Upload stubs and mpy-cross builds to S3
|
||||
run: |
|
||||
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross.static-raspbian s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross.static-raspbian-${{ env.CP_VERSION }} --no-progress --region us-east-1
|
||||
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross.static s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross.static-amd64-linux-${{ env.CP_VERSION }} --no-progress --region us-east-1
|
||||
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross.static.exe s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross.static-x64-windows-${{ env.CP_VERSION }}.exe --no-progress --region us-east-1
|
||||
zip -9r circuitpython-stubs.zip circuitpython-stubs
|
||||
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp circuitpython-stubs.zip s3://adafruit-circuit-python/bin/stubs/circuitpython-stubs-${{ env.CP_VERSION }}.zip --no-progress --region us-east-1
|
||||
env:
|
||||
REPO: ${{ github.repository }}
|
||||
PULL: ${{ github.event.number }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
EXCLUDE_COMMIT: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Set head sha (pull)
|
||||
if: github.event_name == 'pull_request'
|
||||
run: echo "HEAD_SHA=${{ github.event.pull_request.head.sha }}" >> $GITHUB_ENV
|
||||
- name: Set base sha (pull)
|
||||
if: github.event_name == 'pull_request'
|
||||
run: git cat-file -e $SHA && echo "BASE_SHA=$SHA" >> $GITHUB_ENV || true
|
||||
env:
|
||||
SHA: ${{ steps.get-last-commit-with-checks.outputs.commit_sha || github.event.pull_request.base.sha }}
|
||||
- name: Set head sha (push)
|
||||
if: github.event_name == 'push'
|
||||
run: echo "HEAD_SHA=${{ github.event.after }}" >> $GITHUB_ENV
|
||||
- name: Set base sha (push)
|
||||
if: github.event_name == 'push'
|
||||
run: git cat-file -e $SHA && echo "BASE_SHA=$SHA" >> $GITHUB_ENV || true
|
||||
env:
|
||||
SHA: ${{ github.event.before }}
|
||||
- name: Set matrix
|
||||
id: set-matrix
|
||||
run: python3 -u ci_set_matrix.py
|
||||
working-directory: tools
|
||||
env:
|
||||
LAST_FAILED_JOBS: ${{ steps.get-last-commit-with-checks.outputs.check_runs }}
|
||||
AWS_PAGER: ''
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
if: github.event_name == 'push' || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
|
||||
|
||||
tests:
|
||||
needs: scheduler
|
||||
uses: ./.github/workflows/run-tests.yml
|
||||
with:
|
||||
cp-version: ${{ needs.scheduler.outputs.cp-version }}
|
||||
|
||||
mpy-cross:
|
||||
needs: scheduler
|
||||
if: needs.scheduler.outputs.ports != '{}'
|
||||
uses: ./.github/workflows/build-mpy-cross.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
cp-version: ${{ needs.scheduler.outputs.cp-version }}
|
||||
|
||||
mpy-cross-mac:
|
||||
runs-on: macos-11
|
||||
needs: scheduler
|
||||
if: needs.scheduler.outputs.ports != '{}'
|
||||
env:
|
||||
CP_VERSION: ${{ needs.scheduler.outputs.cp-version }}
|
||||
runs-on: macos-10.15
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v2.2.0
|
||||
with:
|
||||
submodules: false
|
||||
fetch-depth: 1
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
- name: Set up submodules
|
||||
uses: ./.github/actions/deps/submodules
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
||||
- name: CircuitPython version
|
||||
run: |
|
||||
git describe --dirty --tags
|
||||
echo >>$GITHUB_ENV CP_VERSION=$(git describe --dirty --tags)
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install gettext
|
||||
echo >>$GITHUB_PATH /usr/local/opt/gettext/bin
|
||||
- name: Versions
|
||||
run: |
|
||||
gcc --version
|
||||
@ -125,172 +152,403 @@ jobs:
|
||||
msgfmt --version
|
||||
- name: Build mpy-cross
|
||||
run: make -C mpy-cross -j2
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: mpy-cross-macos-11-x64
|
||||
path: mpy-cross/build/mpy-cross
|
||||
- name: Build mpy-cross (arm64)
|
||||
run: make -C mpy-cross -j2 -f Makefile.m1 V=2
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mpy-cross-macos-11-arm64
|
||||
path: mpy-cross/build-arm64/mpy-cross-arm64
|
||||
- name: Make universal binary
|
||||
run: lipo -create -output mpy-cross-macos-universal mpy-cross/build/mpy-cross mpy-cross/build-arm64/mpy-cross-arm64
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mpy-cross-macos-11-universal
|
||||
path: mpy-cross-macos-universal
|
||||
- name: Upload to S3
|
||||
if: >-
|
||||
(github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository_owner == 'adafruit') ||
|
||||
(github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
|
||||
name: mpy-cross-macos-catalina
|
||||
path: mpy-cross/mpy-cross
|
||||
- name: Upload mpy-cross build to S3
|
||||
run: |
|
||||
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross-macos-universal s3://adafruit-circuit-python/bin/mpy-cross/macos-11/mpy-cross-macos-11-${{ env.CP_VERSION }}-universal --no-progress --region us-east-1
|
||||
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/build-arm64/mpy-cross-arm64 s3://adafruit-circuit-python/bin/mpy-cross/macos-11/mpy-cross-macos-11-${{ env.CP_VERSION }}-arm64 --no-progress --region us-east-1
|
||||
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/build/mpy-cross s3://adafruit-circuit-python/bin/mpy-cross/macos-11/mpy-cross-macos-11-${{ env.CP_VERSION }}-x64 --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
|
||||
env:
|
||||
AWS_PAGER: ''
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
if: github.event_name == 'push' || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
|
||||
|
||||
docs:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: scheduler
|
||||
if: needs.scheduler.outputs.docs == 'True'
|
||||
env:
|
||||
CP_VERSION: ${{ needs.scheduler.outputs.cp-version }}
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: false
|
||||
fetch-depth: 1
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
- name: Set up submodules
|
||||
uses: ./.github/actions/deps/submodules
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y latexmk librsvg2-bin texlive-fonts-recommended texlive-latex-recommended texlive-latex-extra
|
||||
pip install -r requirements-doc.txt
|
||||
- name: Build and Validate Stubs
|
||||
run: make check-stubs -j2
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: stubs
|
||||
path: circuitpython-stubs/dist/*
|
||||
- name: Test Documentation Build (HTML)
|
||||
run: sphinx-build -E -W -b html -D version=${{ env.CP_VERSION }} -D release=${{ env.CP_VERSION }} . _build/html
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docs
|
||||
path: _build/html
|
||||
- name: Test Documentation Build (LaTeX/PDF)
|
||||
run: |
|
||||
make latexpdf
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docs
|
||||
path: _build/latex
|
||||
- name: Upload to S3
|
||||
uses: ./.github/actions/upload_aws
|
||||
with:
|
||||
source: circuitpython-stubs/dist/*.tar.gz
|
||||
destination: stubs/circuitpython-stubs-${{ env.CP_VERSION }}.tar.gz
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
- name: Upload stubs to PyPi
|
||||
if: github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested')
|
||||
env:
|
||||
TWINE_USERNAME: ${{ secrets.pypi_username }}
|
||||
TWINE_PASSWORD: ${{ secrets.pypi_password }}
|
||||
run: |
|
||||
# python -m build was run by 'make stubs'
|
||||
[ -z "$TWINE_USERNAME" ] || echo "Uploading dev release to PyPi"
|
||||
[ -z "$TWINE_USERNAME" ] || twine upload circuitpython-stubs/dist/*
|
||||
|
||||
windows:
|
||||
runs-on: windows-2022
|
||||
needs: scheduler
|
||||
if: needs.scheduler.outputs.windows == 'True'
|
||||
env:
|
||||
CP_VERSION: ${{ needs.scheduler.outputs.cp-version }}
|
||||
defaults:
|
||||
run:
|
||||
# We define a custom shell script here, although `msys2.cmd` does neither exist nor is it available in the PATH yet
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
# We want to change the configuration of the git command that actions/checkout will be using
|
||||
# (since it is not possible to set autocrlf through the action yet, see actions/checkout#226).
|
||||
- run: git config --global core.autocrlf input
|
||||
shell: bash
|
||||
- name: Check python coding (cmd)
|
||||
run: python -c "import sys, locale; print(sys.getdefaultencoding(), locale.getpreferredencoding(False))"
|
||||
shell: cmd
|
||||
# We use a JS Action, which calls the system terminal or other custom terminals directly, if required
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
install: base-devel git wget unzip gcc python-pip
|
||||
# The goal of this was to test how things worked when the default file encoding (locale.getpreferedencoding())
|
||||
# was not UTF-8. However, msys2 python does use utf-8 as the preferred file encoding, and using actions/setup-python
|
||||
# python3.8 gave a broken build, so we're not really testing what we wanted to test.
|
||||
# However, commandline length limits are being tested so that does some good.
|
||||
- name: Check python coding (msys2)
|
||||
run: |
|
||||
locale -v
|
||||
which python; python --version
|
||||
python -c "import sys, locale; print(sys.getdefaultencoding(), locale.getpreferredencoding(False))"
|
||||
which python3; python3 --version
|
||||
python3 -c "import sys, locale; print(sys.getdefaultencoding(), locale.getpreferredencoding(False))"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
wget --no-verbose -O gcc-arm.zip https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.zip
|
||||
unzip -q -d /tmp gcc-arm.zip
|
||||
tar -C /tmp/gcc-arm-none-* -cf - . | tar -C /usr/local -xf -
|
||||
pip install wheel
|
||||
# requirements_dev.txt doesn't install on windows. (with msys2 python)
|
||||
# instead, pick a subset for what we want to do
|
||||
pip install cascadetoml jinja2 typer click intelhex
|
||||
# check that installed packages work....?
|
||||
which python; python --version; python -c "import cascadetoml"
|
||||
which python3; python3 --version; python3 -c "import cascadetoml"
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: false
|
||||
fetch-depth: 1
|
||||
- name: Set up submodules
|
||||
uses: ./.github/actions/deps/submodules
|
||||
- name: build mpy-cross
|
||||
run: make -j2 -C mpy-cross
|
||||
- name: build rp2040
|
||||
run: make -j2 -C ports/raspberrypi BOARD=adafruit_feather_rp2040 TRANSLATION=de_DE
|
||||
- name: build samd21
|
||||
run: make -j2 -C ports/atmel-samd BOARD=feather_m0_express TRANSLATION=zh_Latn_pinyin
|
||||
- name: build samd51
|
||||
run: make -j2 -C ports/atmel-samd BOARD=feather_m4_express TRANSLATION=es
|
||||
- name: build nrf
|
||||
run: make -j2 -C ports/nrf BOARD=feather_nrf52840_express TRANSLATION=fr
|
||||
- name: build stm
|
||||
run: make -j2 -C ports/stm BOARD=feather_stm32f405_express TRANSLATION=pt_BR
|
||||
# I gave up trying to do esp builds on windows when I saw
|
||||
# ERROR: Platform MINGW64_NT-10.0-17763-x86_64 appears to be unsupported
|
||||
# https://github.com/espressif/esp-idf/issues/7062
|
||||
|
||||
ports:
|
||||
needs: [scheduler, mpy-cross, tests]
|
||||
if: needs.scheduler.outputs.ports != '{}'
|
||||
uses: ./.github/workflows/build-boards.yml
|
||||
secrets: inherit
|
||||
build-arm:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: test
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
port: ${{ fromJSON(needs.scheduler.outputs.ports).ports }}
|
||||
with:
|
||||
boards: ${{ toJSON(fromJSON(needs.scheduler.outputs.ports)[matrix.port]) }}
|
||||
cp-version: ${{ needs.scheduler.outputs.cp-version }}
|
||||
board:
|
||||
- "8086_commander"
|
||||
- "ADM_B_NRF52840_1"
|
||||
- "TG-Watch"
|
||||
- "adafruit_feather_rp2040"
|
||||
- "adafruit_itsybitsy_rp2040"
|
||||
- "adafruit_neokey_trinkey_m0"
|
||||
- "adafruit_proxlight_trinkey_m0"
|
||||
- "adafruit_qt2040_trinkey"
|
||||
- "adafruit_qtpy_rp2040"
|
||||
- "adafruit_rotary_trinkey_m0"
|
||||
- "adafruit_slide_trinkey_m0"
|
||||
- "aloriumtech_evo_m51"
|
||||
- "aramcon2_badge"
|
||||
- "aramcon_badge_2019"
|
||||
- "arduino_mkr1300"
|
||||
- "arduino_mkrzero"
|
||||
- "arduino_nano_33_ble"
|
||||
- "arduino_nano_33_iot"
|
||||
- "arduino_nano_rp2040_connect"
|
||||
- "arduino_zero"
|
||||
- "bast_pro_mini_m0"
|
||||
- "bastble"
|
||||
- "bdmicro_vina_d21"
|
||||
- "bdmicro_vina_d51"
|
||||
- "bdmicro_vina_d51_pcb7"
|
||||
- "bless_dev_board_multi_sensor"
|
||||
- "blm_badge"
|
||||
- "capablerobot_usbhub"
|
||||
- "catwan_usbstick"
|
||||
- "circuitbrains_basic_m0"
|
||||
- "circuitbrains_deluxe_m4"
|
||||
- "circuitplayground_bluefruit"
|
||||
- "circuitplayground_express"
|
||||
- "circuitplayground_express_crickit"
|
||||
- "circuitplayground_express_displayio"
|
||||
- "clue_nrf52840_express"
|
||||
- "cp32-m4"
|
||||
- "cp_sapling_m0"
|
||||
- "cp_sapling_m0_spiflash"
|
||||
- "datalore_ip_m4"
|
||||
- "datum_distance"
|
||||
- "datum_imu"
|
||||
- "datum_light"
|
||||
- "datum_weather"
|
||||
- "dynalora_usb"
|
||||
- "dynossat_edu_eps"
|
||||
- "dynossat_edu_obc"
|
||||
- "electronut_labs_blip"
|
||||
- "electronut_labs_papyr"
|
||||
- "escornabot_makech"
|
||||
- "espruino_pico"
|
||||
- "espruino_wifi"
|
||||
- "feather_bluefruit_sense"
|
||||
- "feather_m0_adalogger"
|
||||
- "feather_m0_basic"
|
||||
- "feather_m0_express"
|
||||
- "feather_m0_express_crickit"
|
||||
- "feather_m0_rfm69"
|
||||
- "feather_m0_rfm9x"
|
||||
- "feather_m0_supersized"
|
||||
- "feather_m4_can"
|
||||
- "feather_m4_express"
|
||||
- "feather_m7_1011"
|
||||
- "feather_mimxrt1011"
|
||||
- "feather_mimxrt1062"
|
||||
- "feather_nrf52840_express"
|
||||
- "feather_radiofruit_zigbee"
|
||||
- "feather_stm32f405_express"
|
||||
- "fluff_m0"
|
||||
- "gemma_m0"
|
||||
- "grandcentral_m4_express"
|
||||
- "hallowing_m0_express"
|
||||
- "hallowing_m4_express"
|
||||
- "hiibot_bluefi"
|
||||
- "huntercat_nfc"
|
||||
- "ikigaisense_vita"
|
||||
- "imxrt1010_evk"
|
||||
- "imxrt1020_evk"
|
||||
- "imxrt1060_evk"
|
||||
- "itsybitsy_m0_express"
|
||||
- "itsybitsy_m4_express"
|
||||
- "itsybitsy_nrf52840_express"
|
||||
- "kicksat-sprite"
|
||||
- "loc_ber_m4_base_board"
|
||||
- "makerdiary_m60_keyboard"
|
||||
- "makerdiary_nrf52840_m2_devkit"
|
||||
- "makerdiary_nrf52840_mdk"
|
||||
- "makerdiary_nrf52840_mdk_usb_dongle"
|
||||
- "matrixportal_m4"
|
||||
- "meowbit_v121"
|
||||
- "meowmeow"
|
||||
- "metro_m0_express"
|
||||
- "metro_m4_airlift_lite"
|
||||
- "metro_m4_express"
|
||||
- "metro_m7_1011"
|
||||
- "metro_nrf52840_express"
|
||||
- "mini_sam_m4"
|
||||
- "monster_m4sk"
|
||||
- "ndgarage_ndbit6"
|
||||
- "ndgarage_ndbit6_v2"
|
||||
- "neopixel_trinkey_m0"
|
||||
- "nfc_copy_cat"
|
||||
- "nice_nano"
|
||||
- "nucleo_f746zg"
|
||||
- "nucleo_f767zi"
|
||||
- "nucleo_h743zi_2"
|
||||
- "ohs2020_badge"
|
||||
- "openbook_m4"
|
||||
- "openmv_h7"
|
||||
- "particle_argon"
|
||||
- "particle_boron"
|
||||
- "particle_xenon"
|
||||
- "pca10056"
|
||||
- "pca10059"
|
||||
- "pca10100"
|
||||
- "pewpew10"
|
||||
- "pewpew_m4"
|
||||
- "picoplanet"
|
||||
- "pimoroni_keybow2040"
|
||||
- "pimoroni_picolipo_16mb"
|
||||
- "pimoroni_picolipo_4mb"
|
||||
- "pimoroni_picosystem"
|
||||
- "pimoroni_tiny2040"
|
||||
- "pirkey_m0"
|
||||
- "pitaya_go"
|
||||
- "pyb_nano_v2"
|
||||
- "pybadge"
|
||||
- "pybadge_airlift"
|
||||
- "pyboard_v11"
|
||||
- "pycubed"
|
||||
- "pycubed_mram"
|
||||
- "pygamer"
|
||||
- "pygamer_advance"
|
||||
- "pyportal"
|
||||
- "pyportal_titano"
|
||||
- "pyruler"
|
||||
- "qtpy_m0"
|
||||
- "qtpy_m0_haxpress"
|
||||
- "raspberry_pi_pico"
|
||||
- "raytac_mdbt50q-db-40"
|
||||
- "robohatmm1_m4"
|
||||
- "sam32"
|
||||
- "same54_xplained"
|
||||
- "seeeduino_wio_terminal"
|
||||
- "seeeduino_xiao"
|
||||
- "serpente"
|
||||
- "shirtty"
|
||||
- "silicognition-m4-shim"
|
||||
- "simmel"
|
||||
- "snekboard"
|
||||
- "sparkfun_lumidrive"
|
||||
- "sparkfun_micromod_rp2040"
|
||||
- "sparkfun_nrf52840_micromod"
|
||||
- "sparkfun_nrf52840_mini"
|
||||
- "sparkfun_pro_micro_rp2040"
|
||||
- "sparkfun_qwiic_micro_no_flash"
|
||||
- "sparkfun_qwiic_micro_with_flash"
|
||||
- "sparkfun_redboard_turbo"
|
||||
- "sparkfun_samd21_dev"
|
||||
- "sparkfun_samd21_mini"
|
||||
- "sparkfun_samd51_thing_plus"
|
||||
- "sparkfun_thing_plus_rp2040"
|
||||
- "spresense"
|
||||
- "stackrduino_m0_pro"
|
||||
- "stm32f411ce_blackpill"
|
||||
- "stm32f411ce_blackpill_with_flash"
|
||||
- "stm32f411ve_discovery"
|
||||
- "stm32f412zg_discovery"
|
||||
- "stm32f4_discovery"
|
||||
- "stm32f746g_discovery"
|
||||
- "stringcar_m0_express"
|
||||
- "teensy40"
|
||||
- "teensy41"
|
||||
- "teknikio_bluebird"
|
||||
- "thunderpack_v11"
|
||||
- "thunderpack_v12"
|
||||
- "tinkeringtech_scoutmakes_azul"
|
||||
- "trellis_m4_express"
|
||||
- "trinket_m0"
|
||||
- "trinket_m0_haxpress"
|
||||
- "uartlogger2"
|
||||
- "uchip"
|
||||
- "ugame10"
|
||||
- "winterbloom_big_honking_button"
|
||||
- "winterbloom_sol"
|
||||
- "xinabox_cc03"
|
||||
- "xinabox_cs11"
|
||||
|
||||
steps:
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.8
|
||||
- uses: actions/checkout@v2.2.0
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo apt-get install -y gettext
|
||||
pip install -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
|
||||
run: |
|
||||
gcc --version
|
||||
arm-none-eabi-gcc --version
|
||||
python3 --version
|
||||
- name: mpy-cross
|
||||
run: make -C mpy-cross -j2
|
||||
- name: build
|
||||
run: python3 -u build_release_files.py
|
||||
working-directory: tools
|
||||
env:
|
||||
BOARDS: ${{ matrix.board }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ matrix.board }}
|
||||
path: bin/${{ matrix.board }}
|
||||
- name: Upload to S3
|
||||
run: "[ -z \"$AWS_ACCESS_KEY_ID\" ] || aws s3 cp bin/ s3://adafruit-circuit-python/bin/ --recursive --no-progress --region us-east-1"
|
||||
env:
|
||||
AWS_PAGER: ''
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
if: github.event_name == 'push' || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
|
||||
|
||||
build-riscv:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: test
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
board:
|
||||
- "fomu"
|
||||
|
||||
steps:
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.8
|
||||
- uses: actions/checkout@v2.2.0
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo apt-get install -y gettext
|
||||
pip install requests sh click setuptools awscli
|
||||
wget https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-centos6.tar.gz
|
||||
sudo tar -C /usr --strip-components=1 -xaf riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-centos6.tar.gz
|
||||
- name: Versions
|
||||
run: |
|
||||
gcc --version
|
||||
riscv64-unknown-elf-gcc --version
|
||||
python3 --version
|
||||
- name: mpy-cross
|
||||
run: make -C mpy-cross -j2
|
||||
- name: build
|
||||
run: python3 -u build_release_files.py
|
||||
working-directory: tools
|
||||
env:
|
||||
BOARDS: ${{ matrix.board }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ matrix.board }}
|
||||
path: bin/${{ matrix.board }}
|
||||
- name: Upload to S3
|
||||
run: "[ -z \"$AWS_ACCESS_KEY_ID\" ] || aws s3 cp bin/ s3://adafruit-circuit-python/bin/ --recursive --no-progress --region us-east-1"
|
||||
env:
|
||||
AWS_PAGER: ''
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
if: github.event_name == 'push' || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
|
||||
build-xtensa:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: test
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
board:
|
||||
- "adafruit_feather_esp32s2_nopsram"
|
||||
- "adafruit_feather_esp32s2_tftback_nopsram"
|
||||
- "adafruit_funhouse"
|
||||
- "adafruit_magtag_2.9_grayscale"
|
||||
- "adafruit_metro_esp32s2"
|
||||
- "artisense_rd00"
|
||||
- "electroniccats_bastwifi"
|
||||
- "espressif_kaluga_1"
|
||||
- "espressif_saola_1_wroom"
|
||||
- "espressif_saola_1_wrover"
|
||||
- "franzininho_wifi_wroom"
|
||||
- "franzininho_wifi_wrover"
|
||||
- "lilygo_ttgo_t8_s2_st7789"
|
||||
- "microdev_micro_s2"
|
||||
- "muselab_nanoesp32_s2"
|
||||
- "targett_module_clip_wroom"
|
||||
- "targett_module_clip_wrover"
|
||||
- "unexpectedmaker_feathers2"
|
||||
- "unexpectedmaker_feathers2_prerelease"
|
||||
- "unexpectedmaker_tinys2"
|
||||
|
||||
steps:
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.8
|
||||
- uses: actions/checkout@v2.2.0
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
||||
- name: CircuitPython version
|
||||
run: git describe --dirty --tags
|
||||
- uses: actions/cache@v2
|
||||
name: Fetch IDF tool cache
|
||||
id: idf-cache
|
||||
with:
|
||||
path: ${{ github.workspace }}/.idf_tools
|
||||
key: ${{ runner.os }}-idf-tools-${{ hashFiles('.git/modules/ports/esp32s2/esp-idf/HEAD') }}-20210518
|
||||
- name: Clone IDF submodules
|
||||
run: |
|
||||
(cd $IDF_PATH && git submodule update --init)
|
||||
env:
|
||||
IDF_PATH: ${{ github.workspace }}/ports/esp32s2/esp-idf
|
||||
- name: Install IDF tools
|
||||
run: |
|
||||
$IDF_PATH/tools/idf_tools.py --non-interactive install required
|
||||
$IDF_PATH/tools/idf_tools.py --non-interactive install cmake
|
||||
$IDF_PATH/tools/idf_tools.py --non-interactive install-python-env
|
||||
rm -rf $IDF_TOOLS_PATH/dist
|
||||
env:
|
||||
IDF_PATH: ${{ github.workspace }}/ports/esp32s2/esp-idf
|
||||
IDF_TOOLS_PATH: ${{ github.workspace }}/.idf_tools
|
||||
- name: Install CircuitPython deps
|
||||
run: |
|
||||
source $IDF_PATH/export.sh
|
||||
pip install -r requirements-dev.txt
|
||||
sudo apt-get install -y gettext ninja-build
|
||||
env:
|
||||
IDF_PATH: ${{ github.workspace }}/ports/esp32s2/esp-idf
|
||||
IDF_TOOLS_PATH: ${{ github.workspace }}/.idf_tools
|
||||
- name: Versions
|
||||
run: |
|
||||
source $IDF_PATH/export.sh
|
||||
gcc --version
|
||||
xtensa-esp32s2-elf-gcc --version
|
||||
python3 --version
|
||||
ninja --version
|
||||
cmake --version
|
||||
shell: bash
|
||||
env:
|
||||
IDF_PATH: ${{ github.workspace }}/ports/esp32s2/esp-idf
|
||||
IDF_TOOLS_PATH: ${{ github.workspace }}/.idf_tools
|
||||
- name: mpy-cross
|
||||
run: make -C mpy-cross -j2
|
||||
- name: build
|
||||
run: |
|
||||
source $IDF_PATH/export.sh
|
||||
python3 -u build_release_files.py
|
||||
working-directory: tools
|
||||
shell: bash
|
||||
env:
|
||||
IDF_PATH: ${{ github.workspace }}/ports/esp32s2/esp-idf
|
||||
IDF_TOOLS_PATH: ${{ github.workspace }}/.idf_tools
|
||||
BOARDS: ${{ matrix.board }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ matrix.board }}
|
||||
path: bin/${{ matrix.board }}
|
||||
- name: Upload to S3
|
||||
run: "[ -z \"$AWS_ACCESS_KEY_ID\" ] || aws s3 cp bin/ s3://adafruit-circuit-python/bin/ --recursive --no-progress --region us-east-1"
|
||||
env:
|
||||
AWS_PAGER: ''
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
if: github.event_name == 'push' || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
|
||||
|
43
.github/workflows/create-website-pr.yml
vendored
43
.github/workflows/create-website-pr.yml
vendored
@ -1,43 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Update CircuitPython.org
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
website:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: false
|
||||
fetch-depth: 1
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
- name: Set up submodules
|
||||
uses: ./.github/actions/deps/submodules
|
||||
with:
|
||||
version: true
|
||||
- name: Set up external
|
||||
uses: ./.github/actions/deps/external
|
||||
- name: Versions
|
||||
run: |
|
||||
gcc --version
|
||||
python3 --version
|
||||
- name: Website
|
||||
run: python3 build_board_info.py
|
||||
working-directory: tools
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
||||
ADABOT_GITHUB_ACCESS_TOKEN: ${{ secrets.ADABOT_GITHUB_ACCESS_TOKEN }}
|
43
.github/workflows/create_website_pr.yml
vendored
Normal file
43
.github/workflows/create_website_pr.yml
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Update CircuitPython.org
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
website:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v2.2.0
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install deps
|
||||
run: |
|
||||
pip install -r requirements-dev.txt
|
||||
- name: Versions
|
||||
run: |
|
||||
gcc --version
|
||||
python3 --version
|
||||
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
|
||||
- name: CircuitPython version
|
||||
run: git describe --dirty --tags
|
||||
- name: Website
|
||||
run: python3 build_board_info.py
|
||||
working-directory: tools
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
||||
ADABOT_GITHUB_ACCESS_TOKEN: ${{ secrets.BLINKA_GITHUB_ACCESS_TOKEN }}
|
||||
if: github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested')
|
90
.github/workflows/custom-board-build.yml
vendored
90
.github/workflows/custom-board-build.yml
vendored
@ -1,90 +0,0 @@
|
||||
name: Custom board build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
board:
|
||||
description: 'Board: Found in ports/*/boards/[board_id]'
|
||||
required: true
|
||||
type: string
|
||||
version:
|
||||
description: 'Version: Can be a tag or a commit (>=8.1.0)'
|
||||
required: false
|
||||
default: latest
|
||||
type: string
|
||||
language:
|
||||
description: 'Language: Found in locale/[language].po'
|
||||
required: false
|
||||
default: en_US
|
||||
type: string
|
||||
flags:
|
||||
description: 'Flags: Build flags (e.g. CIRCUITPY_WIFI=1)'
|
||||
required: false
|
||||
type: string
|
||||
debug:
|
||||
description: 'Make a debug build'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
run-name: ${{ inputs.board }}-${{ inputs.language }}-${{ inputs.version }}${{ inputs.flags != '' && '-custom' || '' }}${{ inputs.debug && '-debug' || '' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Set up repository
|
||||
run: |
|
||||
git clone --filter=tree:0 https://github.com/adafruit/circuitpython.git $GITHUB_WORKSPACE
|
||||
git checkout ${{ inputs.version == 'latest' && 'HEAD' || inputs.version }}
|
||||
- name: Set up identifier
|
||||
if: inputs.debug || inputs.flags != ''
|
||||
run: |
|
||||
> custom-build && git add custom-build
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
- name: Set up port
|
||||
id: set-up-port
|
||||
uses: ./.github/actions/deps/ports
|
||||
with:
|
||||
board: ${{ inputs.board }}
|
||||
- name: Set up submodules
|
||||
id: set-up-submodules
|
||||
uses: ./.github/actions/deps/submodules
|
||||
with:
|
||||
action: cache
|
||||
target: ${{ inputs.board }}
|
||||
- name: Set up external
|
||||
uses: ./.github/actions/deps/external
|
||||
with:
|
||||
action: cache
|
||||
port: ${{ steps.set-up-port.outputs.port }}
|
||||
- name: Set up mpy-cross
|
||||
if: steps.set-up-submodules.outputs.frozen == 'True'
|
||||
uses: ./.github/actions/mpy_cross
|
||||
with:
|
||||
cp-version: ${{ steps.set-up-submodules.outputs.version }}
|
||||
download: false
|
||||
- name: Versions
|
||||
run: |
|
||||
tools/describe
|
||||
gcc --version
|
||||
python3 --version
|
||||
cmake --version || true
|
||||
ninja --version || true
|
||||
aarch64-none-elf-gcc --version || true
|
||||
arm-none-eabi-gcc --version || true
|
||||
xtensa-esp32-elf-gcc --version || true
|
||||
riscv32-esp-elf-gcc --version || true
|
||||
riscv64-unknown-elf-gcc --version || true
|
||||
mkfs.fat --version || true
|
||||
- name: Build board
|
||||
run: make -j2 ${{ inputs.flags }} BOARD=${{ inputs.board }} DEBUG=${{ inputs.debug && '1' || '0' }} TRANSLATION=${{ inputs.language }}
|
||||
working-directory: ports/${{ steps.set-up-port.outputs.port }}
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ inputs.board }}-${{ inputs.language }}-${{ inputs.version }}${{ inputs.flags != '' && '-custom' || '' }}${{ inputs.debug && '-debug' || '' }}
|
||||
path: ports/${{ steps.set-up-port.outputs.port }}/build-${{ inputs.board }}/firmware.*
|
14
.github/workflows/match-build-fail.json
vendored
14
.github/workflows/match-build-fail.json
vendored
@ -1,14 +0,0 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"severity": "error",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(Build .+ and \\x1b\\[31mfailed\\x1b\\[0m)$",
|
||||
"message": 1
|
||||
}
|
||||
],
|
||||
"owner": "build-failed"
|
||||
}
|
||||
]
|
||||
}
|
18
.github/workflows/notify-on-issue-label.yml
vendored
18
.github/workflows/notify-on-issue-label.yml
vendored
@ -1,18 +0,0 @@
|
||||
name: Notify users based on issue labels
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
jobs:
|
||||
notify:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- uses: tekktrik/issue-labeled-ping@v1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
user: v923z
|
||||
label: ulab
|
||||
message: Heads up {user} - the "{label}" label was applied to this issue.
|
48
.github/workflows/pre-commit.yml
vendored
48
.github/workflows/pre-commit.yml
vendored
@ -5,42 +5,26 @@
|
||||
name: pre-commit
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
push:
|
||||
|
||||
jobs:
|
||||
pre-commit:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: false
|
||||
fetch-depth: 1
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
- name: Set up submodules
|
||||
uses: ./.github/actions/deps/submodules
|
||||
- name: Set up external
|
||||
uses: ./.github/actions/deps/external
|
||||
- name: Install dependencies
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/setup-python@v1
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gettext uncrustify
|
||||
- name: Run pre-commit
|
||||
uses: pre-commit/action@v3.0.0
|
||||
- name: Make patch
|
||||
if: failure()
|
||||
run: git diff > ~/pre-commit.patch
|
||||
- name: Upload patch
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
sudo apt-add-repository -y -u ppa:pybricks/ppa
|
||||
sudo apt-get install -y black gettext uncrustify
|
||||
pip3 install -r requirements-dev.txt
|
||||
- name: Populate selected submodules
|
||||
run: git submodule update --init extmod/ulab
|
||||
- name: Set PY
|
||||
run: echo >>$GITHUB_ENV PY="$(python -c 'import hashlib, sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')"
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
name: patch
|
||||
path: ~/pre-commit.patch
|
||||
path: ~/.cache/pre-commit
|
||||
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- uses: pre-commit/action@v1.1.0
|
||||
|
66
.github/workflows/run-tests.yml
vendored
66
.github/workflows/run-tests.yml
vendored
@ -1,66 +0,0 @@
|
||||
name: Run tests
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
cp-version:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
run:
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
test: [all, mpy, native, native_mpy]
|
||||
env:
|
||||
CP_VERSION: ${{ inputs.cp-version }}
|
||||
MICROPY_CPYTHON3: python3.8
|
||||
MICROPY_MICROPYTHON: ../ports/unix/build-coverage/micropython
|
||||
TEST_all:
|
||||
TEST_mpy: --via-mpy -d basics float micropython
|
||||
TEST_native: --emit native
|
||||
TEST_native_mpy: --via-mpy --emit native -d basics float micropython
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: false
|
||||
fetch-depth: 1
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Set up submodules
|
||||
uses: ./.github/actions/deps/submodules
|
||||
with:
|
||||
target: tests
|
||||
- name: Set up external
|
||||
if: matrix.test == 'all'
|
||||
uses: ./.github/actions/deps/external
|
||||
- name: Set up mpy-cross
|
||||
uses: ./.github/actions/mpy_cross
|
||||
with:
|
||||
cp-version: ${{ inputs.cp-version }}
|
||||
- name: Build unix port
|
||||
run: make -C ports/unix VARIANT=coverage -j2
|
||||
- name: Run tests
|
||||
run: ./run-tests.py -j2 ${{ env[format('TEST_{0}', matrix.test)] }}
|
||||
working-directory: tests
|
||||
- name: Print failure info
|
||||
run: ./run-tests.py -j2 --print-failures
|
||||
if: failure()
|
||||
working-directory: tests
|
||||
- name: Build native modules
|
||||
if: matrix.test == 'all'
|
||||
run: |
|
||||
make -C examples/natmod/features1
|
||||
make -C examples/natmod/features2
|
||||
make -C examples/natmod/heapq
|
||||
make -C examples/natmod/random
|
||||
make -C examples/natmod/re
|
||||
- name: Test native modules
|
||||
if: matrix.test == 'all'
|
||||
run: ./run-natmodtests.py extmod/{heapq*,re*,zlib*}.py
|
||||
working-directory: tests
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -9,7 +9,6 @@
|
||||
!atmel-samd/asf/**/*.a
|
||||
*.elf
|
||||
*.bin
|
||||
!*.toml.bin
|
||||
*.map
|
||||
*.hex
|
||||
*.dis
|
||||
@ -29,17 +28,16 @@ dist/
|
||||
######################
|
||||
*.swp
|
||||
|
||||
# Build directories
|
||||
# Build directory
|
||||
######################
|
||||
build/
|
||||
bin/
|
||||
circuitpython-stubs/
|
||||
test-stubs/
|
||||
build-*/
|
||||
|
||||
# Test failure outputs
|
||||
######################
|
||||
tests/results/*
|
||||
tests/*.exp
|
||||
tests/*.out
|
||||
|
||||
# Python cache files
|
||||
######################
|
||||
|
209
.gitmodules
vendored
209
.gitmodules
vendored
@ -4,13 +4,17 @@
|
||||
|
||||
[submodule "lib/axtls"]
|
||||
path = lib/axtls
|
||||
url = https://github.com/micropython/axtls.git
|
||||
url = https://github.com/pfalcon/axtls
|
||||
branch = micropython
|
||||
[submodule "lib/libffi"]
|
||||
path = lib/libffi
|
||||
url = https://github.com/atgreen/libffi
|
||||
[submodule "lib/berkeley-db-1.xx"]
|
||||
path = lib/berkeley-db-1.xx
|
||||
url = https://github.com/pfalcon/berkeley-db-1.xx
|
||||
[submodule "lib/uzlib"]
|
||||
path = lib/uzlib
|
||||
url = https://github.com/pfalcon/uzlib
|
||||
[submodule "tools/uf2"]
|
||||
path = tools/uf2
|
||||
url = https://github.com/Microsoft/uf2.git
|
||||
@ -33,6 +37,9 @@
|
||||
path = ports/atmel-samd/asf4
|
||||
url = https://github.com/adafruit/asf4.git
|
||||
branch = circuitpython
|
||||
[submodule "tools/usb_descriptor"]
|
||||
path = tools/usb_descriptor
|
||||
url = https://github.com/adafruit/usb_descriptor.git
|
||||
[submodule "lib/nrfutil"]
|
||||
path = lib/nrfutil
|
||||
url = https://github.com/adafruit/nRF52_nrfutil
|
||||
@ -100,7 +107,7 @@
|
||||
url = https://github.com/adafruit/Adafruit_MP3
|
||||
[submodule "ports/mimxrt10xx/sdk"]
|
||||
path = ports/mimxrt10xx/sdk
|
||||
url = https://github.com/nxp-mcuxpresso/mcux-sdk.git
|
||||
url = https://github.com/adafruit/MIMXRT10xx_SDK
|
||||
[submodule "frozen/Adafruit_CircuitPython_Register"]
|
||||
path = frozen/Adafruit_CircuitPython_Register
|
||||
url = https://github.com/adafruit/Adafruit_CircuitPython_Register.git
|
||||
@ -113,6 +120,9 @@
|
||||
[submodule "frozen/Adafruit_CircuitPython_Requests"]
|
||||
path = frozen/Adafruit_CircuitPython_Requests
|
||||
url = https://github.com/adafruit/Adafruit_CircuitPython_Requests
|
||||
[submodule "ports/stm/st_driver"]
|
||||
path = ports/stm/st_driver
|
||||
url = https://github.com/hathach/st_driver.git
|
||||
[submodule "lib/protomatter"]
|
||||
path = lib/protomatter
|
||||
url = https://github.com/adafruit/Adafruit_Protomatter
|
||||
@ -140,17 +150,12 @@
|
||||
[submodule "frozen/Adafruit_CircuitPython_RFM69"]
|
||||
path = frozen/Adafruit_CircuitPython_RFM69
|
||||
url = https://github.com/adafruit/Adafruit_CircuitPython_RFM69.git
|
||||
[submodule "ports/espressif/esp-idf"]
|
||||
path = ports/espressif/esp-idf
|
||||
[submodule "ports/esp32s2/esp-idf"]
|
||||
path = ports/esp32s2/esp-idf
|
||||
url = https://github.com/adafruit/esp-idf.git
|
||||
branch = circuitpython-v5.1
|
||||
[submodule "ports/espressif/esp-protocols"]
|
||||
path = ports/espressif/esp-protocols
|
||||
url = https://github.com/espressif/esp-protocols.git
|
||||
[submodule "ports/espressif/esp-camera"]
|
||||
path = ports/espressif/esp-camera
|
||||
url = https://github.com/adafruit/esp32-camera.git
|
||||
branch = circuitpython
|
||||
[submodule "ports/esp32s2/certificates/nina-fw"]
|
||||
path = ports/esp32s2/certificates/nina-fw
|
||||
url = https://github.com/adafruit/nina-fw.git
|
||||
[submodule "frozen/Adafruit_CircuitPython_ST7789"]
|
||||
path = frozen/Adafruit_CircuitPython_ST7789
|
||||
url = https://github.com/adafruit/Adafruit_CircuitPython_ST7789
|
||||
@ -171,7 +176,7 @@
|
||||
url = https://github.com/adafruit/Adafruit_CircuitPython_SimpleMath
|
||||
[submodule "ports/raspberrypi/sdk"]
|
||||
path = ports/raspberrypi/sdk
|
||||
url = https://github.com/raspberrypi/pico-sdk.git
|
||||
url = https://github.com/adafruit/pico-sdk.git
|
||||
[submodule "data/nvm.toml"]
|
||||
path = data/nvm.toml
|
||||
url = https://github.com/adafruit/nvm.toml.git
|
||||
@ -179,181 +184,3 @@
|
||||
[submodule "frozen/Adafruit_CircuitPython_MIDI"]
|
||||
path = frozen/Adafruit_CircuitPython_MIDI
|
||||
url = https://github.com/adafruit/Adafruit_CircuitPython_MIDI
|
||||
[submodule "frozen/Adafruit_CircuitPython_SimpleIO"]
|
||||
path = frozen/Adafruit_CircuitPython_SimpleIO
|
||||
url = https://github.com/adafruit/adafruit_circuitpython_simpleio
|
||||
[submodule "lib/quirc"]
|
||||
path = lib/quirc
|
||||
url = https://github.com/adafruit/quirc.git
|
||||
[submodule "frozen/Adafruit_CircuitPython_APDS9960"]
|
||||
path = frozen/Adafruit_CircuitPython_APDS9960
|
||||
url = https://github.com/adafruit/Adafruit_CircuitPython_APDS9960
|
||||
[submodule "rpi-firmware"]
|
||||
path = ports/broadcom/firmware
|
||||
url = https://github.com/raspberrypi/rpi-firmware.git
|
||||
branch = master
|
||||
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"]
|
||||
path = ports/stm/st_driver/cmsis_device_f4
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_f4.git
|
||||
[submodule "ports/stm/st_driver/cmsis_device_f0"]
|
||||
path = ports/stm/st_driver/cmsis_device_f0
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_f0.git
|
||||
[submodule "ports/stm/st_driver/stm32f0xx_hal_driver"]
|
||||
path = ports/stm/st_driver/stm32f0xx_hal_driver
|
||||
url = https://github.com/STMicroelectronics/stm32f0xx_hal_driver.git
|
||||
[submodule "ports/stm/st_driver/cmsis_device_f1"]
|
||||
path = ports/stm/st_driver/cmsis_device_f1
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_f1.git
|
||||
[submodule "ports/stm/st_driver/stm32f1xx_hal_driver"]
|
||||
path = ports/stm/st_driver/stm32f1xx_hal_driver
|
||||
url = https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git
|
||||
[submodule "ports/stm/st_driver/cmsis_device_f2"]
|
||||
path = ports/stm/st_driver/cmsis_device_f2
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_f2.git
|
||||
[submodule "ports/stm/st_driver/stm32f2xx_hal_driver"]
|
||||
path = ports/stm/st_driver/stm32f2xx_hal_driver
|
||||
url = https://github.com/STMicroelectronics/stm32f2xx_hal_driver.git
|
||||
[submodule "ports/stm/st_driver/cmsis_device_f3"]
|
||||
path = ports/stm/st_driver/cmsis_device_f3
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_f3.git
|
||||
[submodule "ports/stm/st_driver/stm32f3xx_hal_driver"]
|
||||
path = ports/stm/st_driver/stm32f3xx_hal_driver
|
||||
url = https://github.com/STMicroelectronics/stm32f3xx_hal_driver.git
|
||||
[submodule "ports/stm/st_driver/cmsis_device_f7"]
|
||||
path = ports/stm/st_driver/cmsis_device_f7
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_f7.git
|
||||
[submodule "ports/stm/st_driver/stm32f7xx_hal_driver"]
|
||||
path = ports/stm/st_driver/stm32f7xx_hal_driver
|
||||
url = https://github.com/STMicroelectronics/stm32f7xx_hal_driver.git
|
||||
[submodule "ports/stm/st_driver/cmsis_device_h7"]
|
||||
path = ports/stm/st_driver/cmsis_device_h7
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_h7.git
|
||||
[submodule "ports/stm/st_driver/stm32h7xx_hal_driver"]
|
||||
path = ports/stm/st_driver/stm32h7xx_hal_driver
|
||||
url = https://github.com/STMicroelectronics/stm32h7xx_hal_driver.git
|
||||
[submodule "ports/stm/st_driver/cmsis_device_l0"]
|
||||
path = ports/stm/st_driver/cmsis_device_l0
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_l0.git
|
||||
[submodule "ports/stm/st_driver/stm32l0xx_hal_driver"]
|
||||
path = ports/stm/st_driver/stm32l0xx_hal_driver
|
||||
url = https://github.com/STMicroelectronics/stm32l0xx_hal_driver.git
|
||||
[submodule "ports/stm/st_driver/cmsis_device_l1"]
|
||||
path = ports/stm/st_driver/cmsis_device_l1
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_l1.git
|
||||
[submodule "ports/stm/st_driver/stm32l1xx_hal_driver"]
|
||||
path = ports/stm/st_driver/stm32l1xx_hal_driver
|
||||
url = https://github.com/STMicroelectronics/stm32l1xx_hal_driver.git
|
||||
[submodule "ports/stm/st_driver/cmsis_device_l4"]
|
||||
path = ports/stm/st_driver/cmsis_device_l4
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_l4.git
|
||||
[submodule "ports/stm/st_driver/stm32l4xx_hal_driver"]
|
||||
path = ports/stm/st_driver/stm32l4xx_hal_driver
|
||||
url = https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git
|
||||
[submodule "ports/stm/st_driver/cmsis_device_g0"]
|
||||
path = ports/stm/st_driver/cmsis_device_g0
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_g0.git
|
||||
[submodule "ports/stm/st_driver/stm32g0xx_hal_driver"]
|
||||
path = ports/stm/st_driver/stm32g0xx_hal_driver
|
||||
url = https://github.com/STMicroelectronics/stm32g0xx_hal_driver.git
|
||||
[submodule "ports/stm/st_driver/cmsis_device_g4"]
|
||||
path = ports/stm/st_driver/cmsis_device_g4
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_g4.git
|
||||
[submodule "ports/stm/st_driver/stm32g4xx_hal_driver"]
|
||||
path = ports/stm/st_driver/stm32g4xx_hal_driver
|
||||
url = https://github.com/STMicroelectronics/stm32g4xx_hal_driver.git
|
||||
[submodule "ports/stm/st_driver/cmsis_device_l5"]
|
||||
path = ports/stm/st_driver/cmsis_device_l5
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_l5.git
|
||||
[submodule "ports/stm/st_driver/stm32l5xx_hal_driver"]
|
||||
path = ports/stm/st_driver/stm32l5xx_hal_driver
|
||||
url = https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git
|
||||
[submodule "ports/stm/st_driver/CMSIS_5"]
|
||||
path = ports/stm/st_driver/CMSIS_5
|
||||
url = https://github.com/ARM-software/CMSIS_5.git
|
||||
[submodule "ports/stm/st_driver/stm32f4xx_hal_driver"]
|
||||
path = ports/stm/st_driver/stm32f4xx_hal_driver
|
||||
url = https://github.com/adafruit/stm32f4xx_hal_driver.git
|
||||
[submodule "frozen/Adafruit_CircuitPython_PortalBase"]
|
||||
path = frozen/Adafruit_CircuitPython_PortalBase
|
||||
url = https://github.com/adafruit/Adafruit_CircuitPython_PortalBase.git
|
||||
[submodule "frozen/Adafruit_CircuitPython_FakeRequests"]
|
||||
path = frozen/Adafruit_CircuitPython_FakeRequests
|
||||
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/raspberrypi/lib/cyw43-driver"]
|
||||
path = ports/raspberrypi/lib/cyw43-driver
|
||||
url = https://github.com/georgerobotics/cyw43-driver.git
|
||||
[submodule "ports/raspberrypi/lib/lwip"]
|
||||
path = ports/raspberrypi/lib/lwip
|
||||
url = https://github.com/adafruit/lwip.git
|
||||
branch = circuitpython8
|
||||
[submodule "lib/mbedtls"]
|
||||
path = lib/mbedtls
|
||||
url = https://github.com/ARMmbed/mbedtls.git
|
||||
[submodule "frozen/Adafruit_CircuitPython_UC8151D"]
|
||||
path = frozen/Adafruit_CircuitPython_UC8151D
|
||||
url = https://github.com/adafruit/Adafruit_CircuitPython_UC8151D
|
||||
[submodule "frozen/Adafruit_CircuitPython_SSD1680"]
|
||||
path = frozen/Adafruit_CircuitPython_SSD1680
|
||||
url = https://github.com/adafruit/Adafruit_CircuitPython_SSD1680
|
||||
[submodule "ports/broadcom/peripherals"]
|
||||
path = ports/broadcom/peripherals
|
||||
url = https://github.com/adafruit/broadcom-peripherals.git
|
||||
branch = main-build
|
||||
[submodule "ports/silabs/gecko_sdk"]
|
||||
path = ports/silabs/gecko_sdk
|
||||
url = https://github.com/SiliconLabs/gecko_sdk.git
|
||||
branch = v4.2.1
|
||||
[submodule "ports/silabs/tools/slc_cli_linux"]
|
||||
path = ports/silabs/tools/slc_cli_linux
|
||||
url = https://github.com/SiliconLabs/circuitpython_slc_cli_linux
|
||||
[submodule "ports/raspberrypi/lib/PicoDVI"]
|
||||
path = ports/raspberrypi/lib/PicoDVI
|
||||
url = https://github.com/circuitpython/PicoDVI.git
|
||||
branch = circuitpython
|
||||
[submodule "frozen/circuitpython-pcf85063a"]
|
||||
path = frozen/circuitpython-pcf85063a
|
||||
url = https://github.com/bablokb/circuitpython-pcf85063a
|
||||
[submodule "frozen/Adafruit_CircuitPython_Wave"]
|
||||
path = frozen/Adafruit_CircuitPython_Wave
|
||||
url = https://github.com/adafruit/Adafruit_CircuitPython_Wave.git
|
||||
[submodule "ports/raspberrypi/lib/Pico-PIO-USB"]
|
||||
path = ports/raspberrypi/lib/Pico-PIO-USB
|
||||
url = https://github.com/sekigon-gonnoc/Pico-PIO-USB.git
|
||||
branch = main
|
||||
[submodule "lib/micropython-lib"]
|
||||
path = lib/micropython-lib
|
||||
url = https://github.com/micropython/micropython-lib.git
|
||||
[submodule "lib/certificates"]
|
||||
path = lib/certificates
|
||||
url = https://github.com/adafruit/certificates
|
||||
[submodule "lib/tlsf"]
|
||||
path = lib/tlsf
|
||||
url = https://github.com/espressif/tlsf.git
|
||||
[submodule "frozen/CircuitPython_AXP313A"]
|
||||
path = frozen/CircuitPython_AXP313A
|
||||
url = https://github.com/bill88t/CircuitPython_AXP313A
|
||||
|
@ -4,26 +4,13 @@
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.0.1
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: check-yaml
|
||||
- id: end-of-file-fixer
|
||||
exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*)'
|
||||
exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|ports/esp32s2/esp-idf-config/.*|ports/esp32s2/boards/.*/sdkconfig)'
|
||||
- id: trailing-whitespace
|
||||
exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|lib/mbedtls_errors/generate_errors.diff)'
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v2.2.4
|
||||
hooks:
|
||||
- id: codespell
|
||||
args: [-w]
|
||||
exclude: |
|
||||
(?x)^(
|
||||
locale/|
|
||||
lib/|
|
||||
tests/unicode/data/utf-8_invalid.txt|
|
||||
tests/extmod/data/qr.pgm|
|
||||
tests/basics/bytearray_byte_operations.py
|
||||
)
|
||||
exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*)'
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: translations
|
||||
|
@ -8,17 +8,14 @@
|
||||
|
||||
version: 2
|
||||
|
||||
build:
|
||||
os: ubuntu-20.04
|
||||
tools:
|
||||
python: "3"
|
||||
jobs:
|
||||
post_install:
|
||||
- python tools/ci_fetch_deps.py docs
|
||||
submodules:
|
||||
include:
|
||||
- extmod/ulab
|
||||
|
||||
formats:
|
||||
- pdf
|
||||
- pdf
|
||||
|
||||
python:
|
||||
version: 3
|
||||
install:
|
||||
- requirements: requirements-doc.txt
|
||||
- requirements: docs/requirements.txt
|
||||
|
@ -762,6 +762,7 @@ today. The names appear in order of pledging.
|
||||
1642 Udine
|
||||
1643 Simon Critchley
|
||||
1644 Sven Haiges, Germany
|
||||
1645 Yi Qing Sim
|
||||
1646 "silicium" ("silicium_one", if "silicium" is busy)
|
||||
1648 Andy O'Malia, @andyomalia
|
||||
1650 RedCamelApps.com
|
||||
|
33
BUILDING.md
33
BUILDING.md
@ -15,7 +15,7 @@ https://learn.adafruit.com/building-circuitpython/
|
||||
|
||||
## Setup
|
||||
|
||||
Please ensure you set up your build environment appropriately, as per the guide. You will need:
|
||||
Please ensure you setup your build environment appropriately, as per the guide. You will need:
|
||||
|
||||
* Linux: https://learn.adafruit.com/building-circuitpython/linux
|
||||
* MacOS: https://learn.adafruit.com/building-circuitpython/macos
|
||||
@ -25,21 +25,8 @@ Please ensure you set up your build environment appropriately, as per the guide.
|
||||
|
||||
This project has a bunch of git submodules. You will need to update them regularly.
|
||||
|
||||
In the root folder of the CircuitPython repository, execute the following:
|
||||
|
||||
make fetch-all-submodules
|
||||
|
||||
Or, in the ports directory for the particular port you are building, do:
|
||||
|
||||
make fetch-port-submodules
|
||||
|
||||
### Required Python Packages
|
||||
|
||||
Failing to install these will prevent from properly building.
|
||||
|
||||
pip3 install -r requirements-dev.txt
|
||||
|
||||
If you run into an error installing minify_html, you may need to install `rust`.
|
||||
git submodule sync
|
||||
git submodule update --init
|
||||
|
||||
### mpy-cross
|
||||
|
||||
@ -48,7 +35,7 @@ To compile (or recompile) mpy-cross:
|
||||
|
||||
make -C mpy-cross
|
||||
|
||||
## Building
|
||||
# Building
|
||||
|
||||
There a number of ports of CircuitPython! To build for your board, change to the appropriate ports directory and build.
|
||||
|
||||
@ -64,7 +51,7 @@ If you aren't sure what boards exist, have a peek in the boards subdirectory of
|
||||
If you have a fast computer with many cores, consider adding `-j` to your build flags, such as `-j17` on
|
||||
a 6-core 12-thread machine.
|
||||
|
||||
## Testing
|
||||
# Testing
|
||||
|
||||
If you are working on changes to the core language, you might find it useful to run the test suite.
|
||||
The test suite in the top level `tests` directory. It needs the unix port to run.
|
||||
@ -76,7 +63,7 @@ The test suite in the top level `tests` directory. It needs the unix port to ru
|
||||
Then you can run the test suite:
|
||||
|
||||
cd ../../tests
|
||||
./run-tests.py
|
||||
./run-tests
|
||||
|
||||
A successful run will say something like
|
||||
|
||||
@ -84,7 +71,7 @@ A successful run will say something like
|
||||
676 tests passed
|
||||
30 tests skipped: buffered_writer builtin_help builtin_range_binop class_delattr_setattr cmd_parsetree extra_coverage framebuf1 framebuf16 framebuf2 framebuf4 framebuf8 framebuf_subclass mpy_invalid namedtuple_asdict non_compliant resource_stream schedule sys_getsizeof urandom_extra ure_groups ure_span ure_sub ure_sub_unmatched vfs_basic vfs_fat_fileio1 vfs_fat_fileio2 vfs_fat_more vfs_fat_oldproto vfs_fat_ramdisk vfs_userfs
|
||||
|
||||
## Debugging
|
||||
# Debugging
|
||||
|
||||
The easiest way to debug CircuitPython on hardware is with a JLink device, JLinkGDBServer, and an appropriate GDB.
|
||||
Instructions can be found at https://learn.adafruit.com/debugging-the-samd21-with-gdb
|
||||
@ -99,7 +86,7 @@ Example:
|
||||
If your port/build includes `arm-none-eabi-gdb-py`, consider using it instead, as it can be used for better register
|
||||
debugging with https://github.com/bnahill/PyCortexMDebug
|
||||
|
||||
## Code Quality Checks
|
||||
# Code Quality Checks
|
||||
|
||||
We apply code quality checks using pre-commit. Install pre-commit once per system with
|
||||
|
||||
@ -107,13 +94,13 @@ We apply code quality checks using pre-commit. Install pre-commit once per syst
|
||||
|
||||
Activate it once per git clone with
|
||||
|
||||
pre-commit install
|
||||
pre-commit --install
|
||||
|
||||
Pre-commit also requires some additional programs to be installed through your package manager:
|
||||
|
||||
* Standard Unix tools such as make, find, etc
|
||||
* The gettext package, any modern version
|
||||
* uncrustify version 0.71 (0.72 is also tested and OK; 0.75 is not OK)
|
||||
* uncrustify version 0.71 (0.72 is also tested)
|
||||
|
||||
Each time you create a git commit, the pre-commit quality checks will be run. You can also run them e.g., with `pre-commit run foo.c` or `pre-commit run --all` to run on all files whether modified or not.
|
||||
|
||||
|
@ -123,7 +123,7 @@ accordingly.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 1.4, available at
|
||||
<https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>,
|
||||
and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html).
|
||||
|
@ -38,9 +38,9 @@ For SAMD21 debugging workflow tips check out [this learn guide](https://learn.ad
|
||||
Scott Shawcroft ([@tannewt](https://github.com/tannewt)) is the lead developer of CircuitPython
|
||||
and is sponsored by [Adafruit Industries LLC](https://adafruit.com). Scott is usually available
|
||||
during US West Coast working hours. Dan Halbert ([@dhalbert](https://github.com/dhalbert)) and
|
||||
Jeff Epler ([@jepler](https://github.com/jepler)) are also sponsored by [Adafruit Industries
|
||||
LLC](https://adafruit.com) and are usually available during US daytime hours including some
|
||||
weekends.
|
||||
Kattni Rembor ([@kattni](https://github.com/kattni)) are also sponsored by [Adafruit Industries
|
||||
LLC](https://adafruit.com) and are usually available during US East Coast daytime hours including
|
||||
some weekends.
|
||||
|
||||
They are all reachable on [Discord](https://adafru.it/discord), GitHub issues and the [Adafruit
|
||||
support forum](https://forums.adafruit.com/viewforum.php?f=60).
|
||||
|
6
LICENSE
6
LICENSE
@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2023 Damien P. George
|
||||
Copyright (c) 2013, 2014 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
|
||||
@ -17,5 +17,5 @@ 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.
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
@ -1,85 +0,0 @@
|
||||
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 +0,0 @@
|
||||
recursive-include . *.pyi
|
54
Makefile
54
Makefile
@ -7,7 +7,7 @@
|
||||
|
||||
# You can set these variables from the command line.
|
||||
PYTHON = python3
|
||||
SPHINXOPTS = -W --keep-going
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
# path to build the generated docs
|
||||
@ -40,7 +40,7 @@ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(BASEOPTS)
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(BASEOPTS)
|
||||
|
||||
TRANSLATE_SOURCES = extmod lib main.c ports/atmel-samd ports/cxd56 ports/espressif ports/mimxrt10xx ports/nrf ports/raspberrypi ports/stm py shared-bindings shared-module supervisor
|
||||
TRANSLATE_SOURCES = extmod lib main.c ports/atmel-samd ports/cxd56 ports/esp32s2 ports/mimxrt10xx ports/nrf ports/raspberrypi ports/stm py shared-bindings shared-module supervisor
|
||||
# Paths to exclude from TRANSLATE_SOURCES
|
||||
# Each must be preceded by "-path"; if any wildcards, enclose in quotes.
|
||||
# Separate by "-o" (Find's "or" operand)
|
||||
@ -48,14 +48,12 @@ TRANSLATE_SOURCES_EXC = -path "ports/*/build-*" \
|
||||
-o -path "ports/*/build" \
|
||||
-o -path ports/atmel-samd/asf4 \
|
||||
-o -path ports/cxd56/spresense-exported-sdk \
|
||||
-o -path ports/espressif/esp-idf \
|
||||
-o -path ports/esp32s2/esp-idf \
|
||||
-o -path ports/mimxrt10xx/sdk \
|
||||
-o -path ports/raspberrypi/sdk \
|
||||
-o -path ports/stm/st_driver \
|
||||
-o -path lib/tinyusb \
|
||||
-o -path lib/lwip \
|
||||
-o -path extmod/ulab/circuitpython \
|
||||
-o -path extmod/ulab/micropython \
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext stubs
|
||||
|
||||
@ -83,15 +81,13 @@ help:
|
||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
@echo " fetch-all-submodules to fetch submodules for all ports"
|
||||
@echo " remove-all-submodules remove all submodules, including files and .git/ data"
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
rm -rf autoapi
|
||||
rm -rf $(STUBDIR) $(DISTDIR) *.egg-info
|
||||
|
||||
html:
|
||||
html: stubs
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
@ -226,9 +222,8 @@ pseudoxml:
|
||||
.PHONY: all-source
|
||||
all-source:
|
||||
|
||||
TRANSLATE_COMMAND=find $(TRANSLATE_SOURCES) -type d \( $(TRANSLATE_SOURCES_EXC) \) -prune -o -type f \( -iname "*.c" -o -iname "*.h" \) -print | (LC_ALL=C sort) | xgettext -x locale/synthetic.pot -f- -L C -s --add-location=file --keyword=MP_ERROR_TEXT -o - | sed -e '/"POT-Creation-Date: /d'
|
||||
locale/circuitpython.pot: all-source
|
||||
$(TRANSLATE_COMMAND) > $@
|
||||
find $(TRANSLATE_SOURCES) -type d \( $(TRANSLATE_SOURCES_EXC) \) -prune -o -type f \( -iname "*.c" -o -iname "*.h" \) -print | (LC_ALL=C sort) | xgettext -f- -L C -s --add-location=file --keyword=translate -o - | sed -e '/"POT-Creation-Date: /d' > $@
|
||||
|
||||
# Historically, `make translate` updated the .pot file and ran msgmerge.
|
||||
# However, this was a frequent source of merge conflicts. Weblate can perform
|
||||
@ -253,27 +248,20 @@ merge-translate:
|
||||
|
||||
.PHONY: check-translate
|
||||
check-translate:
|
||||
$(TRANSLATE_COMMAND) > locale/circuitpython.pot.tmp
|
||||
find $(TRANSLATE_SOURCES) -type d \( $(TRANSLATE_SOURCES_EXC) \) -prune -o -type f \( -iname "*.c" -o -iname "*.h" \) -print | (LC_ALL=C sort) | xgettext -f- -L C -s --add-location=file --keyword=translate -o circuitpython.pot.tmp -p locale
|
||||
$(PYTHON) tools/check_translations.py locale/circuitpython.pot.tmp locale/circuitpython.pot; status=$$?; rm -f locale/circuitpython.pot.tmp; exit $$status
|
||||
|
||||
.PHONY: stubs
|
||||
stubs:
|
||||
@rm -rf circuitpython-stubs
|
||||
@mkdir circuitpython-stubs
|
||||
@mkdir -p circuitpython-stubs
|
||||
@$(PYTHON) tools/extract_pyi.py shared-bindings/ $(STUBDIR)
|
||||
@$(PYTHON) tools/extract_pyi.py extmod/ulab/code/ $(STUBDIR)/ulab
|
||||
@$(PYTHON) tools/extract_pyi.py ports/atmel-samd/bindings $(STUBDIR)
|
||||
@$(PYTHON) tools/extract_pyi.py ports/espressif/bindings $(STUBDIR)
|
||||
@$(PYTHON) tools/extract_pyi.py ports/raspberrypi/bindings $(STUBDIR)
|
||||
@cp setup.py-stubs circuitpython-stubs/setup.py
|
||||
@cp README.rst-stubs circuitpython-stubs/README.rst
|
||||
@cp MANIFEST.in-stubs circuitpython-stubs/MANIFEST.in
|
||||
@$(PYTHON) -m build circuitpython-stubs
|
||||
@$(PYTHON) setup.py -q sdist
|
||||
|
||||
.PHONY: check-stubs
|
||||
check-stubs: stubs
|
||||
@(cd $(STUBDIR) && set -- */__init__.pyi && mypy "$${@%/*}")
|
||||
@tools/test-stubs.sh
|
||||
MYPYPATH=$(STUBDIR) mypy --strict $(STUBDIR)
|
||||
|
||||
update-frozen-libraries:
|
||||
@echo "Updating all frozen libraries to latest tagged version."
|
||||
@ -287,8 +275,8 @@ samd21:
|
||||
samd51:
|
||||
$(MAKE) -C ports/atmel-samd BOARD=feather_m4_express
|
||||
|
||||
espressif:
|
||||
$(MAKE) -C ports/espressif BOARD=espressif_saola_1_wroom
|
||||
esp32s2:
|
||||
$(MAKE) -C ports/esp32s2 BOARD=espressif_saola_1_wroom
|
||||
|
||||
litex:
|
||||
$(MAKE) -C ports/litex BOARD=fomu
|
||||
@ -302,7 +290,7 @@ nrf:
|
||||
stm:
|
||||
$(MAKE) -C ports/stm BOARD=feather_stm32f405_express
|
||||
|
||||
clean-one-of-each: clean-samd21 clean-samd51 clean-espressif clean-litex clean-mimxrt10xx clean-nrf clean-stm
|
||||
clean-one-of-each: clean-samd21 clean-samd51 clean-esp32s2 clean-litex clean-mimxrt10xx clean-nrf clean-stm
|
||||
|
||||
clean-samd21:
|
||||
$(MAKE) -C ports/atmel-samd BOARD=trinket_m0 clean
|
||||
@ -310,8 +298,8 @@ clean-samd21:
|
||||
clean-samd51:
|
||||
$(MAKE) -C ports/atmel-samd BOARD=feather_m4_express clean
|
||||
|
||||
clean-espressif:
|
||||
$(MAKE) -C ports/espressif BOARD=espressif_saola_1_wroom clean
|
||||
clean-esp32s2:
|
||||
$(MAKE) -C ports/esp32s2 BOARD=espressif_saola_1_wroom clean
|
||||
|
||||
clean-litex:
|
||||
$(MAKE) -C ports/litex BOARD=fomu clean
|
||||
@ -324,17 +312,3 @@ clean-nrf:
|
||||
|
||||
clean-stm:
|
||||
$(MAKE) -C ports/stm BOARD=feather_stm32f405_express clean
|
||||
|
||||
|
||||
.PHONY: fetch-all-submodules
|
||||
fetch-all-submodules:
|
||||
$(PYTHON) tools/ci_fetch_deps.py all
|
||||
|
||||
.PHONY: remove-all-submodules
|
||||
remove-all-submodules:
|
||||
git submodule deinit -f --all
|
||||
rm -rf .git/modules/*
|
||||
|
||||
.PHONY: fetch-tags
|
||||
fetch-tags:
|
||||
git fetch --tags --recurse-submodules=no --shallow-since="2023-02-01" https://github.com/adafruit/circuitpython HEAD
|
||||
|
119
README.rst
119
README.rst
@ -14,30 +14,25 @@ CircuitPython
|
||||
computers called microcontrollers. Microcontrollers are the brains of many electronics including a
|
||||
wide variety of development boards used to build hobby projects and prototypes. CircuitPython in
|
||||
electronics is one of the best ways to learn to code because it connects code to reality. Simply
|
||||
install CircuitPython on a supported USB board usually via drag and drop and then edit a ``code.py``
|
||||
file on the CIRCUITPY drive. The code will automatically reload. No software installs are needed
|
||||
besides a text editor (we recommend `Mu <https://codewith.mu/>`_ for beginners.)
|
||||
install CircuitPython on a supported board via drag and drop and then edit a ``code.py`` file on
|
||||
the CIRCUITPY drive. The code will automatically reload. No software installs are needed besides a
|
||||
text editor (we recommend `Mu <https://codewith.mu/>`_ for beginners.)
|
||||
|
||||
Starting with CircuitPython 7.0.0, some boards may only be connectable over Bluetooth Low Energy
|
||||
(BLE). Those boards provide serial and file access over BLE instead of USB using open protocols.
|
||||
(Some boards may use both USB and BLE.) BLE access can be done from a variety of apps including
|
||||
`code.circuitpython.org <https://code.circuitpython.org>`_.
|
||||
|
||||
CircuitPython features unified Python core APIs and a growing list of 300+ device libraries and
|
||||
CircuitPython features unified Python core APIs and a growing list of 150+ device libraries and
|
||||
drivers that work with it. These libraries also work on single board computers with regular
|
||||
Python via the `Adafruit Blinka Library <https://github.com/adafruit/Adafruit_Blinka>`_.
|
||||
|
||||
CircuitPython is based on `MicroPython <https://micropython.org>`_. See
|
||||
`below <#differences-from-micropython>`_ for differences. Most, but not all, CircuitPython
|
||||
development is sponsored by `Adafruit <https://adafruit.com>`_ and is available on their educational
|
||||
development boards. Please support both MicroPython and Adafruit.
|
||||
`below <#differences-from-micropython>`_ for differences. CircuitPython development is sponsored by
|
||||
`Adafruit <https://adafruit.com>`_ and is available on their educational development boards. Please
|
||||
support both MicroPython and Adafruit.
|
||||
|
||||
Get CircuitPython
|
||||
------------------
|
||||
|
||||
Official binaries for all supported boards are available through
|
||||
`circuitpython.org/downloads <https://circuitpython.org/downloads>`_. The site includes stable, unstable and
|
||||
continuous builds. Full release notes are available through
|
||||
continuous builds. Full release notes and assets are available through
|
||||
`GitHub releases <https://github.com/adafruit/circuitpython/releases>`_ as well.
|
||||
|
||||
Documentation
|
||||
@ -56,6 +51,10 @@ Specifically useful documentation when starting out:
|
||||
- `CircuitPython Essentials <https://learn.adafruit.com/circuitpython-essentials>`__
|
||||
- `Example Code <https://github.com/adafruit/Adafruit_Learning_System_Guides/tree/master/CircuitPython_Essentials>`__
|
||||
|
||||
Code Search
|
||||
------------
|
||||
GitHub doesn't currently support code search on forks. Therefore, CircuitPython doesn't have code search through GitHub because it is a fork of MicroPython. Luckily, `SourceGraph <https://sourcegraph.com/github.com/adafruit/circuitpython>`_ has free code search for public repos like CircuitPython. So, visit `sourcegraph.com/github.com/adafruit/circuitpython <https://sourcegraph.com/github.com/adafruit/circuitpython>`_ to search the CircuitPython codebase online.
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
@ -80,19 +79,13 @@ common set of requirements.
|
||||
|
||||
If you'd like to use the term "CircuitPython" and Blinka for your product here is what we ask:
|
||||
|
||||
- Your product is supported by the primary
|
||||
* Your product is supported by the primary
|
||||
`"adafruit/circuitpython" <https://github.com/adafruit/circuitpython>`_ repo. This way we can
|
||||
update any custom code as we update the CircuitPython internals.
|
||||
- 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
|
||||
product can always download the latest version of CircuitPython from the standard place.
|
||||
- Your product supports at least one standard "`Workflow <https://docs.circuitpython.org/en/latest/docs/workflows.html>`__" for serial and file access:
|
||||
|
||||
- With a user accessible USB plug which appears as a CIRCUITPY drive when plugged in.
|
||||
- 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.
|
||||
* Your product has a user accessible USB plug which appears as a CIRCUITPY drive when plugged in.
|
||||
|
||||
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
|
||||
@ -105,11 +98,10 @@ Differences from `MicroPython <https://github.com/micropython/micropython>`__
|
||||
|
||||
CircuitPython:
|
||||
|
||||
- Supports native USB on most boards and BLE otherwise, allowing file editing without special tools.
|
||||
- Supports native USB on all boards, allowing file editing without special tools.
|
||||
- Floats (aka decimals) are enabled for all builds.
|
||||
- Error messages are translated into 10+ languages.
|
||||
- Concurrency within Python is not well supported. Interrupts and threading are disabled.
|
||||
async/await keywords are available on some boards for cooperative multitasking. Some concurrency
|
||||
- Does not support concurrency within Python (including interrupts and threading). Some concurrency
|
||||
is achieved with native modules for tasks that require it such as audio file playback.
|
||||
|
||||
Behavior
|
||||
@ -118,51 +110,37 @@ Behavior
|
||||
- The order that files are run and the state that is shared between
|
||||
them. CircuitPython's goal is to clarify the role of each file and
|
||||
make each file independent from each other.
|
||||
|
||||
- ``boot.py`` runs only once on start up before
|
||||
workflows are initialized. This lays the ground work for configuring USB at
|
||||
startup rather than it being fixed. Since serial is not available,
|
||||
output is written to ``boot_out.txt``.
|
||||
- ``code.py`` (or ``main.py``) is run after every reload until it
|
||||
finishes or is interrupted. After it is done running, the vm and
|
||||
hardware is reinitialized. **This means you cannot read state from**
|
||||
``code.py`` **in the REPL anymore, as the REPL is a fresh vm.** CircuitPython's goal for this
|
||||
change includes reducing confusion about pins and memory being used.
|
||||
- After the main code is finished the REPL can be entered by pressing any key.
|
||||
- If the file ``repl.py`` exists, it is executed before the REPL Prompt is shown
|
||||
- In safe mode this functionality is disabled, to ensure the REPL Prompt can always be reached
|
||||
- Autoreload state will be maintained across reload.
|
||||
|
||||
- Adds a safe mode that does not run user code after a hard crash or brown out. This makes it
|
||||
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.
|
||||
- Safe mode may be handled programmatically by providing a ``safemode.py``.
|
||||
``safemode.py`` is run if the board has reset due to entering safe mode, unless the safe mode
|
||||
initiated by the user by pressing button(s).
|
||||
USB is not available so nothing can be printed.
|
||||
``safemode.py`` can determine why the safe mode occurred
|
||||
using ``supervisor.runtime.safe_mode_reason``, and take appropriate action. For instance,
|
||||
if a hard crash occurred, ``safemode.py`` may do a ``microcontroller.reset()``
|
||||
to automatically restart despite the crash.
|
||||
If the battery is low, but is being charged, ``safemode.py`` may put the board in deep sleep
|
||||
for a while. Or it may simply reset, and have ``code.py`` check the voltage and do the sleep.
|
||||
- RGB status LED indicating CircuitPython state.
|
||||
- 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
|
||||
- ``boot.py`` (or ``settings.py``) runs only once on start up before
|
||||
USB is initialized. This lays the ground work for configuring USB at
|
||||
startup rather than it being fixed. Since serial is not available,
|
||||
output is written to ``boot_out.txt``.
|
||||
- ``code.py`` (or ``main.py``) is run after every reload until it
|
||||
finishes or is interrupted. After it is done running, the vm and
|
||||
hardware is reinitialized. **This means you cannot read state from**
|
||||
``code.py`` **in the REPL anymore, as the REPL is a fresh vm.** CircuitPython's goal for this
|
||||
change includes reducing confusion about pins and memory being used.
|
||||
- After the main code is finished the REPL can be entered by pressing any key.
|
||||
- Autoreload state will be maintained across reload.
|
||||
- Adds a safe mode that does not run user code after a hard crash or
|
||||
brown out. The hope is that this will make it easier 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.
|
||||
- RGB status LED indicating CircuitPython state, and errors through a sequence of colored flashes.
|
||||
- Re-runs ``code.py`` or other main file after file system writes over USB mass storage. (Disable with
|
||||
``supervisor.disable_autoreload()``)
|
||||
- Autoreload is disabled while the REPL is active.
|
||||
- ``code.py`` may also be named ``code.txt``, ``main.py``, or ``main.txt``.
|
||||
- ``boot.py`` may also be named ``boot.txt``.
|
||||
- ``safemode.py`` may also be named ``safemode.txt``.
|
||||
- Main is one of these: ``code.txt``, ``code.py``, ``main.py``,
|
||||
``main.txt``
|
||||
- Boot is one of these: ``settings.txt``, ``settings.py``, ``boot.py``,
|
||||
``boot.txt``
|
||||
|
||||
API
|
||||
~~~
|
||||
|
||||
- Unified hardware APIs. Documented on
|
||||
`ReadTheDocs <https://circuitpython.readthedocs.io/en/latest/shared-bindings/index.html>`_.
|
||||
- API docs are Python stubs within the C files in ``shared-bindings``.
|
||||
- API docs are rST within the C files in ``shared-bindings``.
|
||||
- No ``machine`` API.
|
||||
|
||||
Modules
|
||||
@ -221,19 +199,19 @@ amongst ports including CircuitPython:
|
||||
Ports
|
||||
~~~~~
|
||||
|
||||
Ports include the code unique to a microcontroller line.
|
||||
Ports include the code unique to a microcontroller line and also
|
||||
variations based on the board.
|
||||
|
||||
================ ============================================================
|
||||
Supported Support status
|
||||
================ ============================================================
|
||||
atmel-samd ``SAMD21`` stable | ``SAMD51`` stable
|
||||
cxd56 stable
|
||||
espressif ``ESP32`` beta | ``ESP32-C3`` beta | ``ESP32-S2`` stable | ``ESP32-S3`` beta
|
||||
esp32s2 beta
|
||||
litex alpha
|
||||
mimxrt10xx alpha
|
||||
nrf stable
|
||||
raspberrypi stable
|
||||
silabs (efr32) alpha
|
||||
raspberrypi beta
|
||||
stm ``F4`` stable | ``others`` beta
|
||||
unix alpha
|
||||
================ ============================================================
|
||||
@ -242,13 +220,8 @@ unix alpha
|
||||
- ``beta`` Being actively improved but may be missing functionality and have bugs.
|
||||
- ``alpha`` Will have bugs and missing functionality.
|
||||
|
||||
Boards
|
||||
~~~~~~
|
||||
|
||||
- Each ``port`` has a ``boards`` directory containing boards
|
||||
which belong to a specific microcontroller line.
|
||||
- A list of native modules supported by a particular board can be found
|
||||
`here <https://circuitpython.readthedocs.io/en/latest/shared-bindings/support_matrix.html>`__.
|
||||
The remaining port directories not listed above are in the repo to maintain compatibility with the
|
||||
`MicroPython <https://github.com/micropython/micropython>`__ parent project.
|
||||
|
||||
`Back to Top <#circuitpython>`__
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
CircuitPython
|
||||
=============
|
||||
|
||||
.. image:: https://s3.amazonaws.com/adafruit-circuit-python/CircuitPython_Repo_header_logo.png
|
||||
|
||||
|Build Status| |Doc Status| |License| |Discord| |Weblate|
|
||||
|
||||
`circuitpython.org <https://circuitpython.org>`__ \| `Get CircuitPython <#get-circuitpython>`__ \|
|
||||
`Documentation <#documentation>`__ \| `Contributing <#contributing>`__ \|
|
||||
`Branding <#branding>`__ \| `Differences from Micropython <#differences-from-micropython>`__ \|
|
||||
`Project Structure <#project-structure>`__
|
||||
|
||||
**CircuitPython** is a *beginner friendly*, open source version of Python for tiny, inexpensive
|
||||
computers called microcontrollers.
|
||||
|
||||
This package contains the "stubs", or type definitions for CircuitPython. With some advanced
|
||||
editors and other tools, this information can be identify TypeErrors, AttributeErrors, and other
|
||||
problems before you deploy your code to a device and can even help autocomplete your code.
|
||||
|
||||
.. |Build Status| image:: https://github.com/adafruit/circuitpython/workflows/Build%20CI/badge.svg
|
||||
:target: https://github.com/adafruit/circuitpython/actions?query=branch%3Amain
|
||||
.. |Doc Status| image:: https://readthedocs.org/projects/circuitpython/badge/?version=latest
|
||||
:target: http://circuitpython.readthedocs.io/
|
||||
.. |Discord| image:: https://img.shields.io/discord/327254708534116352.svg
|
||||
:target: https://adafru.it/discord
|
||||
.. |License| image:: https://img.shields.io/badge/License-MIT-brightgreen.svg
|
||||
:target: https://choosealicense.com/licenses/mit/
|
||||
.. |Weblate| image:: https://hosted.weblate.org/widgets/circuitpython/-/svg-badge.svg
|
||||
:target: https://hosted.weblate.org/engage/circuitpython/?utm_source=widget
|
@ -6,7 +6,7 @@ SPDX-License-Identifier: MIT
|
||||
|
||||
# WebUSB Serial Support
|
||||
|
||||
To date, this has only been tested on one port (espressif), on one board (espressif_kaluga_1).
|
||||
To date, this has only been tested on one port (esp32s2), on one board (espressif_kaluga_1).
|
||||
|
||||
## What it does
|
||||
|
||||
@ -62,4 +62,33 @@ The tinyusb examples already include a "WebUSB serial" example.
|
||||
Basically, this feature was ported into CircuitPython by pulling code snippets out of the
|
||||
tinyusb example, and putting them where they best belonged in the CircuitPython codebase.
|
||||
|
||||
### TODO: This needs to be reworked for dynamic USB descriptors.
|
||||
There was one complication:
|
||||
|
||||
tinyusb uses C preprocessor macros to define things like USB descriptors.
|
||||
|
||||
CircuitPython uses a Python program (tools/gen_usb_descriptor.py) to create USB descriptors (etc.)
|
||||
using "helper objects" from another repo (adafruit_usb_descriptor). This means some of the example
|
||||
code had to be adapted to the new programing model, and gen_usb_descriptor gained new command-line
|
||||
options to control the generated code.
|
||||
|
||||
The generated files go into the "build" directory, look for autogen_usb_descriptor.c and
|
||||
genhdr/autogen_usb_descriptor.h.
|
||||
|
||||
|
||||
Also worth pointing out - the re-use of the CDC connect/disconnect mechanism is not actually part
|
||||
of the WebUSB standard, it's more of "common idiom". We make use of it here because we need to know
|
||||
when we should be paying attention to the WebUSB serial interface, and when we should ignore it..
|
||||
|
||||
## Possible future work areas
|
||||
|
||||
The current code uses the existing Python infrastructure to create the Interface descriptor, but
|
||||
simply outputs the code snippets from the original tinyusb demo code to create the WEBUSB_URL,
|
||||
BOS, and MS_OS_20 descriptors. I suppose additional work could be done to add these to the
|
||||
adafruit_usb_descriptor project, and then gen_usb_descriptor.py could be modified to make use
|
||||
of them.
|
||||
|
||||
Program gen_usb_descriptor.py creates objects for most interface types, regardless of whether or
|
||||
not they are actually enabled. This increases the size of a generated string table. I made the
|
||||
new vendor-interface-related code not do this (because some of the ARM platforms would no longer
|
||||
build), but I did not go back and do this for the other interface types (CDC, MIDI, HID, etc.)
|
||||
Some FLASH savings are probably possible if this is done.
|
||||
|
111
conf.py
111
conf.py
@ -24,15 +24,11 @@ import subprocess
|
||||
import sys
|
||||
import urllib.parse
|
||||
import time
|
||||
import pathlib
|
||||
from collections import defaultdict
|
||||
|
||||
import recommonmark
|
||||
from sphinx.transforms import SphinxTransform
|
||||
from docutils import nodes
|
||||
from sphinx import addnodes
|
||||
from sphinx.ext import intersphinx
|
||||
|
||||
tools_describe = str(pathlib.Path(__file__).parent / "tools/describe")
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
@ -52,19 +48,9 @@ subprocess.check_output(["make", "stubs"])
|
||||
|
||||
#modules_support_matrix = shared_bindings_matrix.support_matrix_excluded_boards()
|
||||
modules_support_matrix = shared_bindings_matrix.support_matrix_by_board()
|
||||
modules_support_matrix_reverse = defaultdict(list)
|
||||
for board, matrix_info in modules_support_matrix.items():
|
||||
for module in matrix_info["modules"]:
|
||||
modules_support_matrix_reverse[module].append(board)
|
||||
|
||||
modules_support_matrix_reverse = dict(
|
||||
(module, sorted(boards))
|
||||
for module, boards in modules_support_matrix_reverse.items()
|
||||
)
|
||||
|
||||
html_context = {
|
||||
'support_matrix': modules_support_matrix,
|
||||
'support_matrix_reverse': modules_support_matrix_reverse
|
||||
'support_matrix': modules_support_matrix
|
||||
}
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
@ -78,18 +64,16 @@ needs_sphinx = '1.3'
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.doctest',
|
||||
"sphinxcontrib.jquery",
|
||||
'sphinxcontrib.rsvgconverter',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx_search.extension',
|
||||
'rstjinja',
|
||||
'myst_parser',
|
||||
'recommonmark',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['templates', "docs/templates"]
|
||||
templates_path = ['templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = {
|
||||
@ -102,16 +86,13 @@ extensions.append('autoapi.extension')
|
||||
autoapi_type = 'python'
|
||||
# Uncomment this if debugging autoapi
|
||||
autoapi_keep_files = True
|
||||
autoapi_dirs = [os.path.join('circuitpython-stubs', x) for x in os.listdir('circuitpython-stubs') if os.path.exists(os.path.join("circuitpython-stubs", x, "__init__.pyi"))]
|
||||
print("autoapi_dirs", autoapi_dirs)
|
||||
autoapi_dirs = [os.path.join('circuitpython-stubs', x) for x in os.listdir('circuitpython-stubs')]
|
||||
autoapi_add_toctree_entry = False
|
||||
autoapi_options = ['members', 'undoc-members', 'private-members', 'show-inheritance', 'special-members', 'show-module-summary']
|
||||
autoapi_template_dir = 'docs/autoapi/templates'
|
||||
autoapi_python_class_content = "both"
|
||||
autoapi_python_use_implicit_namespaces = True
|
||||
autoapi_root = "shared-bindings"
|
||||
def autoapi_prepare_jinja_env(jinja_env):
|
||||
jinja_env.globals['support_matrix_reverse'] = modules_support_matrix_reverse
|
||||
|
||||
redirects_file = 'docs/redirects.txt'
|
||||
|
||||
@ -138,7 +119,7 @@ copyright = f'2014-{current_date.tm_year}, MicroPython & CircuitPython contribut
|
||||
|
||||
final_version = ""
|
||||
git_describe = subprocess.run(
|
||||
[tools_describe],
|
||||
["git", "describe", "--dirty", "--tags"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
encoding="utf-8"
|
||||
@ -173,7 +154,6 @@ exclude_patterns = ["**/build*",
|
||||
".env",
|
||||
".venv",
|
||||
".direnv",
|
||||
".devcontainer/Readme.md",
|
||||
"data",
|
||||
"docs/autoapi",
|
||||
"docs/README.md",
|
||||
@ -196,16 +176,12 @@ exclude_patterns = ["**/build*",
|
||||
"ports/atmel-samd/peripherals",
|
||||
"ports/atmel-samd/QTouch",
|
||||
"ports/atmel-samd/tools",
|
||||
"ports/broadcom/firmware",
|
||||
"ports/broadcom/peripherals",
|
||||
"ports/cxd56/mkspk",
|
||||
"ports/cxd56/spresense-exported-sdk",
|
||||
"ports/espressif/certificates",
|
||||
"ports/espressif/esp-idf",
|
||||
"ports/espressif/esp-camera",
|
||||
"ports/espressif/esp-protocols",
|
||||
"ports/espressif/.idf_tools",
|
||||
"ports/espressif/peripherals",
|
||||
"ports/esp32s2/certificates",
|
||||
"ports/esp32s2/esp-idf",
|
||||
"ports/esp32s2/.idf_tools",
|
||||
"ports/esp32s2/peripherals",
|
||||
"ports/litex/hw",
|
||||
"ports/minimal",
|
||||
"ports/mimxrt10xx/peripherals",
|
||||
@ -217,22 +193,17 @@ exclude_patterns = ["**/build*",
|
||||
"ports/nrf/peripherals",
|
||||
"ports/nrf/usb",
|
||||
"ports/raspberrypi/sdk",
|
||||
"ports/raspberrypi/lib",
|
||||
"ports/silabs/gecko_sdk",
|
||||
"ports/silabs/tools",
|
||||
"ports/stm/st_driver",
|
||||
"ports/stm/packages",
|
||||
"ports/stm/peripherals",
|
||||
"ports/stm/ref",
|
||||
"ports/unix",
|
||||
"py",
|
||||
"shared/*",
|
||||
"shared-bindings/util.*",
|
||||
"shared-module",
|
||||
"supervisor",
|
||||
"tests",
|
||||
"test-stubs",
|
||||
"tools",
|
||||
"circuitpython-stubs/README.rst"]
|
||||
"tools"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
@ -267,9 +238,19 @@ rst_epilog = """
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
|
||||
# on_rtd is whether we are on readthedocs.org
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
try:
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
|
||||
except:
|
||||
html_theme = 'default'
|
||||
html_theme_path = ['.']
|
||||
else:
|
||||
html_theme_path = ['.']
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@ -362,23 +343,15 @@ latex_elements = {
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
# Include 3 levels of headers in PDF ToC
|
||||
'preamble': r'''
|
||||
\setcounter{tocdepth}{2}
|
||||
\hbadness=99999
|
||||
\hfuzz=20pt
|
||||
\usepackage{pdflscape}
|
||||
''',
|
||||
'preamble': '\setcounter{tocdepth}{2}',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
("docs/pdf", 'CircuitPython.tex', 'CircuitPython Documentation',
|
||||
(master_doc, 'CircuitPython.tex', 'CircuitPython Documentation',
|
||||
'CircuitPython Contributors', 'manual'),
|
||||
# Uncomment this if you want to build a PDF of the board -> module support matrix.
|
||||
# ("shared-bindings/support_matrix", 'SupportMatrix.tex', 'Board Support Matrix',
|
||||
# 'CircuitPython Contributors', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@ -440,10 +413,9 @@ texinfo_documents = [
|
||||
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {"python": ('https://docs.python.org/3/', None),
|
||||
"register": ('https://circuitpython.readthedocs.io/projects/register/en/latest/', None),
|
||||
"mcp2515": ('https://circuitpython.readthedocs.io/projects/mcp2515/en/latest/', None),
|
||||
"typing": ('https://circuitpython.readthedocs.io/projects/adafruit-circuitpython-typing/en/latest/', None)}
|
||||
intersphinx_mapping = {"cpython": ('https://docs.python.org/3/', None),
|
||||
"bus_device": ('https://circuitpython.readthedocs.io/projects/busdevice/en/latest/', None),
|
||||
"register": ('https://circuitpython.readthedocs.io/projects/register/en/latest/', None)}
|
||||
|
||||
# Adapted from sphinxcontrib-redirects
|
||||
from sphinx.builders import html as builders
|
||||
@ -485,26 +457,6 @@ def generate_redirects(app):
|
||||
with open(redirected_filename, 'w') as f:
|
||||
f.write(TEMPLATE % urllib.parse.quote(to_path, '#/'))
|
||||
|
||||
def adafruit_typing_workaround(app, env, node, contnode):
|
||||
# Sphinx marks a requesting node that uses circuitpython-typing
|
||||
# as looking for a "class" definition, but unfortunately
|
||||
# Sphinx doesn't recognize TypeAlias based types usefully from
|
||||
# the typing library.
|
||||
# (see: https://github.com/sphinx-doc/sphinx/issues/8934)
|
||||
# Instead, it categorizes these types as "data".
|
||||
# (see: python -m sphinx.ext.intersphinx \
|
||||
# https://docs.circuitpython.org/projects/adafruit-circuitpython-typing/en/latest/objects.inv)
|
||||
# This workaround traps missing references, checks if
|
||||
# they are likely to be in the circuitpython_typing package,
|
||||
# and changes the requesting type from "class" to "data" if
|
||||
# needed, and re-tries the reference resolver.
|
||||
ref = node.get("reftarget", None)
|
||||
if ref and ref.startswith("circuitpython_typing."):
|
||||
dtype = node.get("reftype", None)
|
||||
if dtype != "data":
|
||||
node.attributes.update({"reftype": "data"})
|
||||
return intersphinx.missing_reference(app, env, node, contnode)
|
||||
|
||||
|
||||
class CoreModuleTransform(SphinxTransform):
|
||||
default_priority = 870
|
||||
@ -537,9 +489,6 @@ class CoreModuleTransform(SphinxTransform):
|
||||
|
||||
def setup(app):
|
||||
app.add_css_file("customstyle.css")
|
||||
app.add_css_file("filter.css")
|
||||
app.add_js_file("filter.js")
|
||||
app.add_config_value('redirects_file', 'redirects', 'env')
|
||||
app.connect('builder-inited', generate_redirects)
|
||||
app.connect('missing-reference', adafruit_typing_workaround)
|
||||
app.add_transform(CoreModuleTransform)
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit d17b999f46fd148ac192ad692b8a4639f81add38
|
||||
Subproject commit e5b149599d14a8841167fe552846ca36925b87a0
|
@ -49,10 +49,6 @@
|
||||
#include "shared-bindings/_bleio/ScanEntry.h"
|
||||
#include "shared-bindings/time/__init__.h"
|
||||
|
||||
#if CIRCUITPY_OS_GETENV
|
||||
#include "shared-bindings/os/__init__.h"
|
||||
#endif
|
||||
|
||||
#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))
|
||||
#define SEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000000) / (RESOLUTION))
|
||||
#define UNITS_TO_SEC(TIME, RESOLUTION) (((TIME)*(RESOLUTION)) / 1000000)
|
||||
@ -82,23 +78,28 @@ STATIC void add_generic_services(bleio_adapter_obj_t *adapter) {
|
||||
|
||||
// Generic Access Service setup.
|
||||
|
||||
bleio_uuid_obj_t *generic_access_service_uuid = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type);
|
||||
bleio_uuid_obj_t *generic_access_service_uuid = m_new_obj(bleio_uuid_obj_t);
|
||||
generic_access_service_uuid->base.type = &bleio_uuid_type;
|
||||
common_hal_bleio_uuid_construct(generic_access_service_uuid, 0x1800, NULL);
|
||||
|
||||
bleio_uuid_obj_t *device_name_characteristic_uuid = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type);
|
||||
bleio_uuid_obj_t *device_name_characteristic_uuid = m_new_obj(bleio_uuid_obj_t);
|
||||
device_name_characteristic_uuid->base.type = &bleio_uuid_type;
|
||||
common_hal_bleio_uuid_construct(device_name_characteristic_uuid, 0x2A00, NULL);
|
||||
|
||||
bleio_uuid_obj_t *appearance_characteristic_uuid = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type);
|
||||
bleio_uuid_obj_t *appearance_characteristic_uuid = m_new_obj(bleio_uuid_obj_t);
|
||||
appearance_characteristic_uuid->base.type = &bleio_uuid_type;
|
||||
common_hal_bleio_uuid_construct(appearance_characteristic_uuid, 0x2A01, NULL);
|
||||
|
||||
// Not implemented:
|
||||
// Peripheral Preferred Connection Parameters
|
||||
// Central Address Resolution
|
||||
|
||||
bleio_service_obj_t *generic_access_service = mp_obj_malloc(bleio_service_obj_t, &bleio_service_type);
|
||||
bleio_service_obj_t *generic_access_service = m_new_obj(bleio_service_obj_t);
|
||||
generic_access_service->base.type = &bleio_service_type;
|
||||
common_hal_bleio_service_construct(generic_access_service, generic_access_service_uuid, false);
|
||||
|
||||
adapter->device_name_characteristic = mp_obj_malloc(bleio_characteristic_obj_t, &bleio_characteristic_type);
|
||||
adapter->device_name_characteristic = m_new_obj(bleio_characteristic_obj_t);
|
||||
adapter->device_name_characteristic->base.type = &bleio_characteristic_type;
|
||||
|
||||
char generic_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 'n', 'n', 'n', 'n' };
|
||||
mp_buffer_info_t generic_name_bufinfo = {
|
||||
@ -117,8 +118,7 @@ STATIC void add_generic_services(bleio_adapter_obj_t *adapter) {
|
||||
SECURITY_MODE_NO_ACCESS,
|
||||
248, // max length, from Bluetooth spec
|
||||
false, // not fixed length
|
||||
&generic_name_bufinfo,
|
||||
NULL
|
||||
&generic_name_bufinfo
|
||||
);
|
||||
|
||||
uint16_t zero_16 = 0;
|
||||
@ -127,7 +127,8 @@ STATIC void add_generic_services(bleio_adapter_obj_t *adapter) {
|
||||
.len = sizeof(zero_16),
|
||||
};
|
||||
|
||||
adapter->appearance_characteristic = mp_obj_malloc(bleio_characteristic_obj_t, &bleio_characteristic_type);
|
||||
adapter->appearance_characteristic = m_new_obj(bleio_characteristic_obj_t);
|
||||
adapter->appearance_characteristic->base.type = &bleio_characteristic_type;
|
||||
|
||||
common_hal_bleio_characteristic_construct(
|
||||
adapter->appearance_characteristic,
|
||||
@ -139,22 +140,25 @@ STATIC void add_generic_services(bleio_adapter_obj_t *adapter) {
|
||||
SECURITY_MODE_NO_ACCESS,
|
||||
2, // max length, from Bluetooth spec
|
||||
true, // fixed length
|
||||
&zero_16_value,
|
||||
NULL
|
||||
&zero_16_value
|
||||
);
|
||||
|
||||
// Generic Attribute Service setup.
|
||||
|
||||
bleio_uuid_obj_t *generic_attribute_service_uuid = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type);
|
||||
bleio_uuid_obj_t *generic_attribute_service_uuid = m_new_obj(bleio_uuid_obj_t);
|
||||
generic_attribute_service_uuid->base.type = &bleio_uuid_type;
|
||||
common_hal_bleio_uuid_construct(generic_attribute_service_uuid, 0x1801, NULL);
|
||||
|
||||
bleio_uuid_obj_t *service_changed_characteristic_uuid = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type);
|
||||
bleio_uuid_obj_t *service_changed_characteristic_uuid = m_new_obj(bleio_uuid_obj_t);
|
||||
service_changed_characteristic_uuid->base.type = &bleio_uuid_type;
|
||||
common_hal_bleio_uuid_construct(service_changed_characteristic_uuid, 0x2A05, NULL);
|
||||
|
||||
bleio_service_obj_t *generic_attribute_service = mp_obj_malloc(bleio_service_obj_t, &bleio_service_type);
|
||||
bleio_service_obj_t *generic_attribute_service = m_new_obj(bleio_service_obj_t);
|
||||
generic_attribute_service->base.type = &bleio_service_type;
|
||||
common_hal_bleio_service_construct(generic_attribute_service, generic_attribute_service_uuid, false);
|
||||
|
||||
adapter->service_changed_characteristic = mp_obj_malloc(bleio_characteristic_obj_t, &bleio_characteristic_type);
|
||||
adapter->service_changed_characteristic = m_new_obj(bleio_characteristic_obj_t);
|
||||
adapter->service_changed_characteristic->base.type = &bleio_characteristic_type;
|
||||
|
||||
uint32_t zero_32 = 0;
|
||||
mp_buffer_info_t zero_32_value = {
|
||||
@ -172,15 +176,14 @@ STATIC void add_generic_services(bleio_adapter_obj_t *adapter) {
|
||||
SECURITY_MODE_NO_ACCESS,
|
||||
4, // max length, from Bluetooth spec
|
||||
true, // fixed length
|
||||
&zero_32_value,
|
||||
NULL
|
||||
&zero_32_value
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
STATIC void check_enabled(bleio_adapter_obj_t *adapter) {
|
||||
if (!common_hal_bleio_adapter_get_enabled(adapter)) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Adapter not enabled"));
|
||||
mp_raise_bleio_BluetoothError(translate("Adapter not enabled"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,43 +275,33 @@ 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.
|
||||
// Set event mask.
|
||||
STATIC void bleio_adapter_hci_init(bleio_adapter_obj_t *self) {
|
||||
mp_int_t name_len = 0;
|
||||
|
||||
#if CIRCUITPY_OS_GETENV
|
||||
mp_obj_t name = common_hal_os_getenv("CIRCUITPY_BLE_NAME", mp_const_none);
|
||||
if (name != mp_const_none) {
|
||||
mp_arg_validate_type_string(name, MP_QSTR_CIRCUITPY_BLE_NAME);
|
||||
self->name = name;
|
||||
}
|
||||
#endif
|
||||
const size_t len = sizeof(default_ble_name);
|
||||
|
||||
if (!self->name) {
|
||||
name_len = sizeof(default_ble_name);
|
||||
bt_addr_t addr;
|
||||
hci_check_error(hci_read_bd_addr(&addr));
|
||||
bt_addr_t addr;
|
||||
hci_check_error(hci_read_bd_addr(&addr));
|
||||
|
||||
default_ble_name[name_len - 4] = nibble_to_hex_lower[addr.val[1] >> 4 & 0xf];
|
||||
default_ble_name[name_len - 3] = nibble_to_hex_lower[addr.val[1] & 0xf];
|
||||
default_ble_name[name_len - 2] = nibble_to_hex_lower[addr.val[0] >> 4 & 0xf];
|
||||
default_ble_name[name_len - 1] = nibble_to_hex_lower[addr.val[0] & 0xf];
|
||||
self->name = mp_obj_new_str(default_ble_name, (uint8_t)name_len);
|
||||
}
|
||||
default_ble_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[len - 2] = nibble_to_hex_lower[addr.val[0] >> 4 & 0xf];
|
||||
default_ble_name[len - 1] = nibble_to_hex_lower[addr.val[0] & 0xf];
|
||||
self->name = mp_obj_new_str(default_ble_name, len);
|
||||
|
||||
// Get version information.
|
||||
if (hci_read_local_version(&self->hci_version, &self->hci_revision, &self->lmp_version,
|
||||
&self->manufacturer, &self->lmp_subversion) != HCI_OK) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Could not read HCI version"));
|
||||
mp_raise_bleio_BluetoothError(translate("Could not read HCI version"));
|
||||
}
|
||||
// Get supported features.
|
||||
if (hci_le_read_local_supported_features(self->features) != HCI_OK) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Could not read BLE features"));
|
||||
mp_raise_bleio_BluetoothError(translate("Could not read BLE features"));
|
||||
}
|
||||
|
||||
// Enabled desired events.
|
||||
// Most importantly, includes:
|
||||
// BT_EVT_MASK_LE_META_EVENT BT_EVT_BIT(61)
|
||||
if (hci_set_event_mask(0x3FFFFFFFFFFFFFFF) != HCI_OK) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Could not set event mask"));
|
||||
mp_raise_bleio_BluetoothError(translate("Could not set event mask"));
|
||||
}
|
||||
// The default events for LE are:
|
||||
// BT_EVT_MASK_LE_CONN_COMPLETE, BT_EVT_MASK_LE_ADVERTISING_REPORT,
|
||||
@ -329,7 +322,7 @@ STATIC void bleio_adapter_hci_init(bleio_adapter_obj_t *self) {
|
||||
uint16_t acl_max_num;
|
||||
uint16_t sco_max_num;
|
||||
if (hci_read_buffer_size(&acl_max_len, &sco_max_len, &acl_max_num, &sco_max_num) != HCI_OK) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Could not read BLE buffer info"));
|
||||
mp_raise_bleio_BluetoothError(translate("Could not read BLE buffer info"));
|
||||
}
|
||||
self->max_acl_buffer_len = acl_max_len;
|
||||
self->max_acl_num_buffers = acl_max_num;
|
||||
@ -339,7 +332,7 @@ STATIC void bleio_adapter_hci_init(bleio_adapter_obj_t *self) {
|
||||
if (BT_FEAT_LE_EXT_ADV(self->features)) {
|
||||
uint16_t max_adv_data_len;
|
||||
if (hci_le_read_maximum_advertising_data_length(&max_adv_data_len) != HCI_OK) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Could not get max advertising length"));
|
||||
mp_raise_bleio_BluetoothError(translate("Could not get max advertising length"));
|
||||
}
|
||||
self->max_adv_data_len = max_adv_data_len;
|
||||
} else {
|
||||
@ -406,7 +399,8 @@ bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *s
|
||||
bt_addr_t addr;
|
||||
hci_check_error(hci_read_bd_addr(&addr));
|
||||
|
||||
bleio_address_obj_t *address = mp_obj_malloc(bleio_address_obj_t, &bleio_address_type);
|
||||
bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t);
|
||||
address->base.type = &bleio_address_type;
|
||||
|
||||
common_hal_bleio_address_construct(address, addr.val, BT_ADDR_LE_PUBLIC);
|
||||
return address;
|
||||
@ -472,14 +466,14 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t
|
||||
|
||||
if (self->scan_results != NULL) {
|
||||
if (!shared_module_bleio_scanresults_get_done(self->scan_results)) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Scan already in progress. Stop with stop_scan."));
|
||||
mp_raise_bleio_BluetoothError(translate("Scan already in progess. Stop with stop_scan."));
|
||||
}
|
||||
self->scan_results = NULL;
|
||||
}
|
||||
self->scan_results = shared_module_bleio_new_scanresults(buffer_size, prefixes, prefix_length, minimum_rssi);
|
||||
|
||||
// size_t max_packet_size = extended ? BLE_GAP_SCAN_BUFFER_EXTENDED_MAX_SUPPORTED : BLE_GAP_SCAN_BUFFER_MAX;
|
||||
// uint8_t *raw_data = m_malloc(sizeof(ble_data_t) + max_packet_size);
|
||||
// uint8_t *raw_data = m_malloc(sizeof(ble_data_t) + max_packet_size, false);
|
||||
// ble_data_t * sd_data = (ble_data_t *) raw_data;
|
||||
// self->scan_results->common_hal_data = sd_data;
|
||||
// sd_data->len = max_packet_size;
|
||||
@ -601,7 +595,7 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre
|
||||
|
||||
// uint16_t conn_handle = event_info.conn_handle;
|
||||
// if (conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||
// mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Failed to connect: timeout"));
|
||||
// mp_raise_bleio_BluetoothError(translate("Failed to connect: timeout"));
|
||||
// }
|
||||
|
||||
// // Negotiate for better PHY, larger MTU and data lengths since we are the central. These are
|
||||
@ -622,14 +616,14 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre
|
||||
// }
|
||||
// }
|
||||
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Failed to connect: internal error"));
|
||||
mp_raise_bleio_BluetoothError(translate("Failed to connect: internal error"));
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC void check_data_fit(size_t data_len, bool connectable) {
|
||||
if (data_len > MAX_ADVERTISEMENT_SIZE) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Data too large for advertisement packet"));
|
||||
mp_raise_ValueError(translate("Data too large for advertisement packet"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -651,11 +645,7 @@ STATIC void check_data_fit(size_t data_len, bool connectable) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
|
||||
bool connectable, bool anonymous, uint32_t timeout, float interval,
|
||||
const uint8_t *advertising_data, uint16_t advertising_data_len,
|
||||
const uint8_t *scan_response_data, uint16_t scan_response_data_len,
|
||||
mp_int_t tx_power, const bleio_address_obj_t *directed_to) {
|
||||
uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, uint32_t timeout, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len) {
|
||||
check_enabled(self);
|
||||
|
||||
if (self->now_advertising) {
|
||||
@ -669,24 +659,15 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
|
||||
}
|
||||
}
|
||||
|
||||
// Peer address, for directed advertising
|
||||
bt_addr_le_t peer_addr = { 0 };
|
||||
|
||||
// Copy peer address, if supplied.
|
||||
if (directed_to) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
if (mp_get_buffer(directed_to->bytes, &bufinfo, MP_BUFFER_READ)) {
|
||||
peer_addr.type = directed_to->type;
|
||||
memcpy(&peer_addr.a.val, bufinfo.buf, sizeof(peer_addr.a.val));
|
||||
}
|
||||
}
|
||||
// Peer address, which we don't use (no directed advertising).
|
||||
bt_addr_le_t empty_addr = { 0 };
|
||||
|
||||
bool extended =
|
||||
advertising_data_len > self->max_adv_data_len || scan_response_data_len > self->max_adv_data_len;
|
||||
|
||||
if (extended) {
|
||||
if (!BT_FEAT_LE_EXT_ADV(self->features)) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Data length needs extended advertising, but this adapter does not support it"));
|
||||
mp_raise_bleio_BluetoothError(translate("Data length needs extended advertising, but this adapter does not support it"));
|
||||
}
|
||||
|
||||
uint16_t props = 0;
|
||||
@ -708,7 +689,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
|
||||
interval_units, // max interval
|
||||
0b111, // channel map: channels 37, 38, 39
|
||||
anonymous ? BT_ADDR_LE_RANDOM : BT_ADDR_LE_PUBLIC,
|
||||
&peer_addr, // peer_addr,
|
||||
&empty_addr, // peer_addr,
|
||||
0x00, // filter policy: no filter
|
||||
DEFAULT_TX_POWER,
|
||||
BT_HCI_LE_EXT_SCAN_PHY_1M, // Secondary PHY to use
|
||||
@ -758,7 +739,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
|
||||
interval_units, // max interval
|
||||
adv_type,
|
||||
anonymous ? BT_ADDR_LE_RANDOM : BT_ADDR_LE_PUBLIC,
|
||||
&peer_addr,
|
||||
&empty_addr,
|
||||
0b111, // channel map: channels 37, 38, 39
|
||||
0x00 // filter policy: no filter
|
||||
));
|
||||
@ -788,11 +769,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
|
||||
bool connectable, bool anonymous, uint32_t timeout, mp_float_t interval,
|
||||
mp_buffer_info_t *advertising_data_bufinfo,
|
||||
mp_buffer_info_t *scan_response_data_bufinfo,
|
||||
mp_int_t tx_power, const bleio_address_obj_t *directed_to) {
|
||||
void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, uint32_t timeout, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo) {
|
||||
check_enabled(self);
|
||||
|
||||
// interval value has already been validated.
|
||||
@ -801,7 +778,7 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
|
||||
check_data_fit(scan_response_data_bufinfo->len, connectable);
|
||||
|
||||
if (advertising_data_bufinfo->len > MAX_ADVERTISEMENT_SIZE && scan_response_data_bufinfo->len > 0) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Extended advertisements with scan response not supported."));
|
||||
mp_raise_bleio_BluetoothError(translate("Extended advertisements with scan response not supported."));
|
||||
}
|
||||
|
||||
// Anonymous mode requires a timeout so that we don't continue to broadcast
|
||||
@ -811,25 +788,20 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
|
||||
timeout = MAX_ANONYMOUS_ADV_TIMEOUT_SECS;
|
||||
} else {
|
||||
if (timeout > MAX_LIMITED_DISCOVERABLE_ADV_TIMEOUT_SECS) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Timeout is too long: Maximum timeout length is %d seconds"),
|
||||
mp_raise_bleio_BluetoothError(translate("Timeout is too long: Maximum timeout length is %d seconds"),
|
||||
MAX_LIMITED_DISCOVERABLE_ADV_TIMEOUT_SECS);
|
||||
}
|
||||
}
|
||||
|
||||
if (tx_power != 0) {
|
||||
mp_raise_NotImplementedError(MP_ERROR_TEXT("Only tx_power=0 supported"));
|
||||
}
|
||||
|
||||
const uint32_t result = _common_hal_bleio_adapter_start_advertising(
|
||||
self, connectable, anonymous, timeout, interval,
|
||||
advertising_data_bufinfo->buf,
|
||||
advertising_data_bufinfo->len,
|
||||
scan_response_data_bufinfo->buf,
|
||||
scan_response_data_bufinfo->len,
|
||||
tx_power, directed_to);
|
||||
scan_response_data_bufinfo->len);
|
||||
|
||||
if (result) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Already advertising"));
|
||||
mp_raise_bleio_BluetoothError(translate("Already advertising"));
|
||||
}
|
||||
self->circuitpython_advertising = false;
|
||||
}
|
||||
@ -914,10 +886,10 @@ uint16_t bleio_adapter_add_attribute(bleio_adapter_obj_t *adapter, mp_obj_t *att
|
||||
uint16_t handle = (uint16_t)adapter->attributes->len;
|
||||
mp_obj_list_append(adapter->attributes, attribute);
|
||||
|
||||
if (mp_obj_is_type(attribute, &bleio_service_type)) {
|
||||
if (MP_OBJ_IS_TYPE(attribute, &bleio_service_type)) {
|
||||
adapter->last_added_service_handle = handle;
|
||||
}
|
||||
if (mp_obj_is_type(attribute, &bleio_characteristic_type)) {
|
||||
if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) {
|
||||
adapter->last_added_characteristic_handle = handle;
|
||||
}
|
||||
|
||||
@ -941,8 +913,8 @@ uint16_t bleio_adapter_max_attribute_handle(bleio_adapter_obj_t *adapter) {
|
||||
|
||||
|
||||
void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter) {
|
||||
gc_collect_root((void **)adapter, sizeof(bleio_adapter_obj_t) / (sizeof(size_t)));
|
||||
gc_collect_root((void **)bleio_connections, sizeof(bleio_connections) / (sizeof(size_t)));
|
||||
gc_collect_root((void **)adapter, sizeof(bleio_adapter_obj_t) / sizeof(size_t));
|
||||
gc_collect_root((void **)bleio_connections, sizeof(bleio_connections) / sizeof(size_t));
|
||||
}
|
||||
|
||||
void bleio_adapter_reset(bleio_adapter_obj_t *adapter) {
|
||||
|
@ -65,7 +65,7 @@ typedef struct _bleio_adapter_obj_t {
|
||||
uint16_t manufacturer;
|
||||
uint16_t lmp_subversion;
|
||||
|
||||
// Used to monitor advertising timeout for legacy advertising.
|
||||
// Used to monitor advertising timeout for legacy avertising.
|
||||
uint64_t advertising_start_ticks;
|
||||
uint64_t advertising_timeout_msecs; // If zero, do not check.
|
||||
|
||||
|
@ -33,17 +33,17 @@
|
||||
|
||||
|
||||
bleio_uuid_obj_t *bleio_attribute_get_uuid(mp_obj_t *attribute) {
|
||||
if (mp_obj_is_type(attribute, &bleio_characteristic_type)) {
|
||||
if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) {
|
||||
bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute);
|
||||
return characteristic->uuid;
|
||||
}
|
||||
if (mp_obj_is_type(attribute, &bleio_descriptor_type)) {
|
||||
if (MP_OBJ_IS_TYPE(attribute, &bleio_descriptor_type)) {
|
||||
bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute);
|
||||
return descriptor->uuid;
|
||||
}
|
||||
if (mp_obj_is_type(attribute, &bleio_service_type)) {
|
||||
if (MP_OBJ_IS_TYPE(attribute, &bleio_service_type)) {
|
||||
bleio_service_obj_t *service = MP_OBJ_TO_PTR(attribute);
|
||||
return service->uuid;
|
||||
}
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("Invalid BLE attribute"));
|
||||
mp_raise_RuntimeError(translate("Invalid BLE attribute"));
|
||||
}
|
||||
|
@ -41,7 +41,7 @@
|
||||
#define CCCD_INDICATE 0x2
|
||||
|
||||
|
||||
void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo, const char *user_description) {
|
||||
void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) {
|
||||
self->service = service;
|
||||
self->uuid = uuid;
|
||||
self->decl_handle = BLE_GATT_HANDLE_INVALID;
|
||||
@ -57,16 +57,16 @@ 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);
|
||||
|
||||
const mp_int_t max_length_max = 512;
|
||||
|
||||
mp_arg_validate_int_range(max_length, 0, max_length_max, MP_QSTR_max_length);
|
||||
|
||||
if (max_length < 0 || max_length > max_length_max) {
|
||||
mp_raise_ValueError(translate("max_length must be <= 512"));
|
||||
}
|
||||
self->max_length = max_length;
|
||||
self->fixed_length = fixed_length;
|
||||
|
||||
if (service->is_remote) {
|
||||
self->handle = handle;
|
||||
} else {
|
||||
common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo, user_description);
|
||||
common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,10 +78,6 @@ bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_character
|
||||
return self->service;
|
||||
}
|
||||
|
||||
size_t common_hal_bleio_characteristic_get_max_length(bleio_characteristic_obj_t *self) {
|
||||
return self->max_length;
|
||||
}
|
||||
|
||||
size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t *buf, size_t len) {
|
||||
// Do GATT operations only if this characteristic has been added to a registered service.
|
||||
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||
@ -108,10 +104,10 @@ size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *sel
|
||||
|
||||
void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
|
||||
if (self->fixed_length && bufinfo->len != self->max_length) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Value length != required fixed length"));
|
||||
mp_raise_ValueError(translate("Value length != required fixed length"));
|
||||
}
|
||||
if (bufinfo->len > self->max_length) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Value length > max_length"));
|
||||
mp_raise_ValueError(translate("Value length > max_length"));
|
||||
}
|
||||
|
||||
// Do GATT operations only if this characteristic has been added to a registered service.
|
||||
@ -125,7 +121,7 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self,
|
||||
} else if (self->props & CHAR_PROP_WRITE_NO_RESPONSE) {
|
||||
// att_write_cmd(conn_handle, self->handle, bufinfo->buff, bufinfo->len);
|
||||
} else {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Characteristic not writable"));
|
||||
mp_raise_bleio_BluetoothError(translate("Characteristic not writable"));
|
||||
}
|
||||
} else {
|
||||
// Always write the value locally even if no connections are active.
|
||||
@ -168,7 +164,7 @@ bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties
|
||||
void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor) {
|
||||
if (self->handle != common_hal_bleio_adapter_obj.last_added_characteristic_handle) {
|
||||
mp_raise_bleio_BluetoothError(
|
||||
MP_ERROR_TEXT("Descriptor can only be added to most recently added characteristic"));
|
||||
translate("Descriptor can only be added to most recently added characteristic"));
|
||||
}
|
||||
|
||||
descriptor->handle = bleio_adapter_add_attribute(&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(descriptor));
|
||||
@ -181,11 +177,11 @@ void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *
|
||||
|
||||
void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) {
|
||||
if (self->cccd == NULL) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("No CCCD for this Characteristic"));
|
||||
mp_raise_bleio_BluetoothError(translate("No CCCD for this Characteristic"));
|
||||
}
|
||||
|
||||
if (!common_hal_bleio_service_get_is_remote(self->service)) {
|
||||
mp_raise_bleio_RoleError(MP_ERROR_TEXT("Can't set CCCD on local Characteristic"));
|
||||
mp_raise_bleio_RoleError(translate("Can't set CCCD on local Characteristic"));
|
||||
}
|
||||
|
||||
const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
||||
@ -199,7 +195,7 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self,
|
||||
(void)cccd_value;
|
||||
// uint8_t rsp[sizeof(bt_att_error_rsp)];
|
||||
// if (att_write_req(conn_handle, self->cccd->handle, &cccd_value, sizeof(cccd_value)) == 0) {
|
||||
// mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Could not write CCCD"));
|
||||
// mp_raise_bleio_BluetoothError(translate("Could not write CCCD"));
|
||||
// }
|
||||
}
|
||||
|
||||
@ -213,9 +209,9 @@ bool bleio_characteristic_set_local_value(bleio_characteristic_obj_t *self, mp_b
|
||||
|
||||
self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
|
||||
|
||||
if (mp_obj_is_type(self->observer, &bleio_characteristic_buffer_type)) {
|
||||
if (MP_OBJ_IS_TYPE(self->observer, &bleio_characteristic_buffer_type)) {
|
||||
bleio_characteristic_buffer_update(MP_OBJ_FROM_PTR(self->observer), bufinfo);
|
||||
} else if (mp_obj_is_type(self->observer, &bleio_packet_buffer_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(self->observer, &bleio_packet_buffer_type)) {
|
||||
bleio_packet_buffer_update(MP_OBJ_FROM_PTR(self->observer), bufinfo);
|
||||
} else {
|
||||
return false;
|
||||
|
@ -27,13 +27,12 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shared/runtime/interrupt_char.h"
|
||||
#include "lib/utils/interrupt_char.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
#include "shared-bindings/_bleio/__init__.h"
|
||||
#include "shared-bindings/_bleio/Connection.h"
|
||||
#include "shared-bindings/_bleio/CharacteristicBuffer.h"
|
||||
#include "supervisor/shared/tick.h"
|
||||
#include "common-hal/_bleio/CharacteristicBuffer.h"
|
||||
|
||||
@ -55,7 +54,8 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe
|
||||
self->characteristic = characteristic;
|
||||
self->timeout_ms = timeout * 1000;
|
||||
// This is a macro.
|
||||
ringbuf_alloc(&self->ringbuf, buffer_size);
|
||||
// true means long-lived, so it won't be moved.
|
||||
ringbuf_alloc(&self->ringbuf, buffer_size, true);
|
||||
|
||||
bleio_characteristic_set_observer(characteristic, self);
|
||||
}
|
||||
@ -92,7 +92,6 @@ bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer
|
||||
void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) {
|
||||
if (!common_hal_bleio_characteristic_buffer_deinited(self)) {
|
||||
bleio_characteristic_clear_observer(self->characteristic);
|
||||
ringbuf_deinit(&self->ringbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shared/runtime/interrupt_char.h"
|
||||
#include "lib/utils/interrupt_char.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/objlist.h"
|
||||
#include "py/objstr.h"
|
||||
@ -453,7 +453,8 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
||||
// for (size_t i = 0; i < response->count; ++i) {
|
||||
// ble_gattc_service_t *gattc_service = &response->services[i];
|
||||
|
||||
// bleio_service_obj_t *service = mp_obj_malloc(bleio_service_obj_t, &bleio_service_type);
|
||||
// bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t);
|
||||
// service->base.type = &bleio_service_type;
|
||||
|
||||
// // Initialize several fields at once.
|
||||
// bleio_service_from_connection(service, bleio_connection_new_from_internal(connection));
|
||||
@ -465,7 +466,8 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
||||
|
||||
// if (gattc_service->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
|
||||
// // Known service UUID.
|
||||
// bleio_uuid_obj_t *uuid = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type);
|
||||
// bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t);
|
||||
// uuid->base.type = &bleio_uuid_type;
|
||||
// bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid);
|
||||
// service->uuid = uuid;
|
||||
// } else {
|
||||
@ -489,14 +491,15 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
||||
// for (size_t i = 0; i < response->count; ++i) {
|
||||
// ble_gattc_char_t *gattc_char = &response->chars[i];
|
||||
|
||||
// bleio_characteristic_obj_t *characteristic =
|
||||
// mp_obj_malloc(bleio_characteristic_obj_t, &bleio_characteristic_type);
|
||||
// bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t);
|
||||
// characteristic->base.type = &bleio_characteristic_type;
|
||||
|
||||
// bleio_uuid_obj_t *uuid = NULL;
|
||||
|
||||
// if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
|
||||
// // Known characteristic UUID.
|
||||
// uuid = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type);
|
||||
// uuid = m_new_obj(bleio_uuid_obj_t);
|
||||
// uuid->base.type = &bleio_uuid_type;
|
||||
// bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid);
|
||||
// } else {
|
||||
// // The discovery response contained a 128-bit UUID that has not yet been registered with the
|
||||
@ -512,7 +515,7 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
||||
// (gattc_char->char_props.write ? CHAR_PROP_WRITE : 0) |
|
||||
// (gattc_char->char_props.write_wo_resp ? CHAR_PROP_WRITE_NO_RESPONSE : 0);
|
||||
|
||||
// // Call common_hal_bleio_characteristic_construct() to initialize some fields and set up evt handler.
|
||||
// // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler.
|
||||
// common_hal_bleio_characteristic_construct(
|
||||
// characteristic, m_char_discovery_service, gattc_char->handle_value, uuid,
|
||||
// props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
|
||||
@ -554,13 +557,15 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
||||
// break;
|
||||
// }
|
||||
|
||||
// bleio_descriptor_obj_t *descriptor = mp_obj_malloc(bleio_descriptor_obj_t, &bleio_descriptor_type);
|
||||
// bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t);
|
||||
// descriptor->base.type = &bleio_descriptor_type;
|
||||
|
||||
// bleio_uuid_obj_t *uuid = NULL;
|
||||
|
||||
// if (gattc_desc->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
|
||||
// // Known descriptor UUID.
|
||||
// uuid = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type);
|
||||
// uuid = m_new_obj(bleio_uuid_obj_t);
|
||||
// uuid->base.type = &bleio_uuid_type;
|
||||
// bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_desc->uuid);
|
||||
// } else {
|
||||
// // The discovery response contained a 128-bit UUID that has not yet been registered with the
|
||||
@ -639,8 +644,8 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
||||
// mp_obj_t iterable = mp_getiter(service_uuids_whitelist, &iter_buf);
|
||||
// mp_obj_t uuid_obj;
|
||||
// while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
// if (!mp_obj_is_type(uuid_obj, &bleio_uuid_type)) {
|
||||
// mp_raise_TypeError(MP_ERROR_TEXT("non-UUID found in service_uuids_whitelist"));
|
||||
// if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
|
||||
// mp_raise_TypeError(translate("non-UUID found in service_uuids_whitelist"));
|
||||
// }
|
||||
// bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj);
|
||||
|
||||
@ -745,7 +750,8 @@ mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *interna
|
||||
if (internal->connection_obj != mp_const_none) {
|
||||
return internal->connection_obj;
|
||||
}
|
||||
bleio_connection_obj_t *connection = mp_obj_malloc(bleio_connection_obj_t, &bleio_connection_type);
|
||||
bleio_connection_obj_t *connection = m_new_obj(bleio_connection_obj_t);
|
||||
connection->base.type = &bleio_connection_type;
|
||||
connection->connection = internal;
|
||||
internal->connection_obj = connection;
|
||||
|
||||
|
@ -85,6 +85,5 @@ typedef struct {
|
||||
uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self);
|
||||
mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *connection);
|
||||
bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle);
|
||||
void bleio_connection_clear(bleio_connection_internal_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CONNECTION_H
|
||||
|
@ -43,7 +43,7 @@ void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_c
|
||||
|
||||
const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
|
||||
if (max_length < 0 || max_length > max_length_max) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("max_length must be 0-%d when fixed_length is %s"),
|
||||
mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"),
|
||||
max_length_max, fixed_length ? "True" : "False");
|
||||
}
|
||||
self->max_length = max_length;
|
||||
@ -85,10 +85,10 @@ size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8
|
||||
|
||||
void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo) {
|
||||
if (self->fixed_length && bufinfo->len != self->max_length) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Value length != required fixed length"));
|
||||
mp_raise_ValueError(translate("Value length != required fixed length"));
|
||||
}
|
||||
if (bufinfo->len > self->max_length) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Value length > max_length"));
|
||||
mp_raise_ValueError(translate("Value length > max_length"));
|
||||
}
|
||||
|
||||
self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shared/runtime/interrupt_char.h"
|
||||
#include "lib/utils/interrupt_char.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
@ -37,13 +37,13 @@
|
||||
#include "supervisor/shared/tick.h"
|
||||
|
||||
STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, uint8_t *data, uint16_t len) {
|
||||
if (len + sizeof(uint16_t) > ringbuf_size(&self->ringbuf)) {
|
||||
if (len + sizeof(uint16_t) > ringbuf_capacity(&self->ringbuf)) {
|
||||
// This shouldn't happen.
|
||||
return;
|
||||
}
|
||||
// Push all the data onto the ring buffer.
|
||||
// Make room for the new value by dropping the oldest packets first.
|
||||
while (ringbuf_size(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) {
|
||||
while (ringbuf_capacity(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) {
|
||||
uint16_t packet_length;
|
||||
ringbuf_get_n(&self->ringbuf, (uint8_t *)&packet_length, sizeof(uint16_t));
|
||||
for (uint16_t i = 0; i < packet_length; i++) {
|
||||
@ -81,7 +81,7 @@ void bleio_packet_buffer_update(bleio_packet_buffer_obj_t *self, mp_buffer_info_
|
||||
|
||||
void common_hal_bleio_packet_buffer_construct(
|
||||
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
|
||||
size_t buffer_size, size_t max_packet_size) {
|
||||
size_t buffer_size) {
|
||||
|
||||
self->characteristic = characteristic;
|
||||
self->client = self->characteristic->service->is_remote;
|
||||
@ -101,8 +101,8 @@ void common_hal_bleio_packet_buffer_construct(
|
||||
}
|
||||
|
||||
if (incoming) {
|
||||
if (!ringbuf_alloc(&self->ringbuf, buffer_size * (sizeof(uint16_t) + max_packet_size))) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Buffer too large and unable to allocate"));
|
||||
if (!ringbuf_alloc(&self->ringbuf, buffer_size * (sizeof(uint16_t) + characteristic->max_length), false)) {
|
||||
mp_raise_ValueError(translate("Buffer too large and unable to allocate"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,13 +110,12 @@ void common_hal_bleio_packet_buffer_construct(
|
||||
self->packet_queued = false;
|
||||
self->pending_index = 0;
|
||||
self->pending_size = 0;
|
||||
self->outgoing[0] = m_malloc(max_packet_size);
|
||||
self->outgoing[1] = m_malloc(max_packet_size);
|
||||
self->outgoing[0] = m_malloc(characteristic->max_length, false);
|
||||
self->outgoing[1] = m_malloc(characteristic->max_length, false);
|
||||
} else {
|
||||
self->outgoing[0] = NULL;
|
||||
self->outgoing[1] = NULL;
|
||||
}
|
||||
self->max_packet_size = max_packet_size;
|
||||
|
||||
bleio_characteristic_set_observer(self->characteristic, self);
|
||||
}
|
||||
@ -148,10 +147,9 @@ mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self
|
||||
return ret;
|
||||
}
|
||||
|
||||
mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self,
|
||||
const uint8_t *data, size_t len, uint8_t *header, size_t header_len) {
|
||||
mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len, uint8_t *header, size_t header_len) {
|
||||
if (self->outgoing[0] == NULL) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Writes not supported on Characteristic"));
|
||||
mp_raise_bleio_BluetoothError(translate("Writes not supported on Characteristic"));
|
||||
}
|
||||
if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||
return -1;
|
||||
@ -160,7 +158,7 @@ mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self,
|
||||
|
||||
if (len + header_len > outgoing_packet_length) {
|
||||
// Supplied data will not fit in a single BLE packet.
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Total data to write is larger than outgoing_packet_length"));
|
||||
mp_raise_ValueError(translate("Total data to write is larger than outgoing_packet_length"));
|
||||
}
|
||||
|
||||
if (len + self->pending_size > outgoing_packet_length) {
|
||||
@ -245,8 +243,7 @@ mp_int_t common_hal_bleio_packet_buffer_get_outgoing_packet_length(bleio_packet_
|
||||
if (self->conn_handle != BLE_CONN_HANDLE_INVALID) {
|
||||
bleio_connection_internal_t *connection = bleio_conn_handle_to_connection(self->conn_handle);
|
||||
if (connection) {
|
||||
return MIN(MIN(common_hal_bleio_connection_get_max_packet_length(connection),
|
||||
self->max_packet_size),
|
||||
return MIN(common_hal_bleio_connection_get_max_packet_length(connection),
|
||||
self->characteristic->max_length);
|
||||
}
|
||||
}
|
||||
@ -254,7 +251,7 @@ mp_int_t common_hal_bleio_packet_buffer_get_outgoing_packet_length(bleio_packet_
|
||||
// we can't tell what the largest outgoing packet length would be.
|
||||
return -1;
|
||||
}
|
||||
return MIN(self->characteristic->max_length, self->max_packet_size);
|
||||
return self->characteristic->max_length;
|
||||
}
|
||||
|
||||
bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self) {
|
||||
@ -264,6 +261,5 @@ bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self) {
|
||||
void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) {
|
||||
if (!common_hal_bleio_packet_buffer_deinited(self)) {
|
||||
bleio_characteristic_clear_observer(self->characteristic);
|
||||
ringbuf_deinit(&self->ringbuf);
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,6 @@ typedef struct {
|
||||
// We remember the conn_handle so we can do a NOTIFY/INDICATE to a client.
|
||||
// We can find out the conn_handle on a Characteristic write or a CCCD write (but not a read).
|
||||
volatile uint16_t conn_handle;
|
||||
uint16_t max_packet_size;
|
||||
uint8_t pending_index;
|
||||
uint8_t write_type;
|
||||
bool client;
|
||||
|
@ -53,7 +53,7 @@ uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uu
|
||||
void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary) {
|
||||
if (_common_hal_bleio_service_construct(self, uuid, is_secondary,
|
||||
mp_obj_new_list(0, NULL)) != 0) {
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("Failed to add service"));
|
||||
mp_raise_RuntimeError(translate("Failed to add service"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,12 +84,11 @@ bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) {
|
||||
|
||||
void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self,
|
||||
bleio_characteristic_obj_t *characteristic,
|
||||
mp_buffer_info_t *initial_value_bufinfo,
|
||||
const char *user_description) {
|
||||
mp_buffer_info_t *initial_value_bufinfo) {
|
||||
|
||||
if (self->handle != common_hal_bleio_adapter_obj.last_added_service_handle) {
|
||||
mp_raise_bleio_BluetoothError(
|
||||
MP_ERROR_TEXT("Characteristic can only be added to most recently added service"));
|
||||
translate("Characteristic can only be added to most recently added service"));
|
||||
}
|
||||
characteristic->decl_handle = bleio_adapter_add_attribute(
|
||||
&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(characteristic));
|
||||
@ -101,7 +100,8 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self,
|
||||
|
||||
if (characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE)) {
|
||||
// We need a CCCD if this characteristic is doing notify or indicate.
|
||||
bleio_descriptor_obj_t *cccd = mp_obj_malloc(bleio_descriptor_obj_t, &bleio_descriptor_type);
|
||||
bleio_descriptor_obj_t *cccd = m_new_obj(bleio_descriptor_obj_t);
|
||||
cccd->base.type = &bleio_descriptor_type;
|
||||
|
||||
uint16_t zero = 0;
|
||||
mp_buffer_info_t zero_cccd_value = {
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "shared-bindings/_bleio/Descriptor.h"
|
||||
#include "shared-bindings/_bleio/Service.h"
|
||||
#include "shared-bindings/_bleio/UUID.h"
|
||||
#include "supervisor/shared/bluetooth/bluetooth.h"
|
||||
#include "supervisor/shared/bluetooth.h"
|
||||
|
||||
// UUID shared by all cccd's.
|
||||
bleio_uuid_obj_t cccd_uuid;
|
||||
@ -50,18 +50,13 @@ bool vm_used_ble;
|
||||
|
||||
// switch (sec_status) {
|
||||
// case BLE_GAP_SEC_STATUS_UNSPECIFIED:
|
||||
// mp_raise_bleio_SecurityError(MP_ERROR_TEXT("Unspecified issue. Can be that the pairing prompt on the other device was declined or ignored."));
|
||||
// mp_raise_bleio_SecurityError(translate("Unspecified issue. Can be that the pairing prompt on the other device was declined or ignored."));
|
||||
// return;
|
||||
// default:
|
||||
// mp_raise_bleio_SecurityError(MP_ERROR_TEXT("Unknown security error: 0x%04x"), sec_status);
|
||||
// mp_raise_bleio_SecurityError(translate("Unknown security error: 0x%04x"), sec_status);
|
||||
// }
|
||||
// }
|
||||
|
||||
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.
|
||||
void bleio_reset() {
|
||||
// Create a UUID object for all CCCD's.
|
||||
@ -96,14 +91,14 @@ bleio_adapter_obj_t common_hal_bleio_adapter_obj = {
|
||||
|
||||
bleio_adapter_obj_t *common_hal_bleio_allocate_adapter_or_raise(void) {
|
||||
if (common_hal_bleio_adapter_obj.allocated) {
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("Too many Adapters"));
|
||||
mp_raise_RuntimeError(translate("Too many Adapters"));
|
||||
}
|
||||
return &common_hal_bleio_adapter_obj;
|
||||
}
|
||||
|
||||
void common_hal_bleio_check_connected(uint16_t conn_handle) {
|
||||
if (conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||
mp_raise_ConnectionError(MP_ERROR_TEXT("Not connected"));
|
||||
mp_raise_ConnectionError(translate("Not connected"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,6 +107,6 @@ void common_hal_bleio_gc_collect(void) {
|
||||
}
|
||||
|
||||
|
||||
void bleio_hci_background(void) {
|
||||
void bleio_background(void) {
|
||||
bleio_adapter_background(&common_hal_bleio_adapter_obj);
|
||||
}
|
||||
|
@ -34,7 +34,8 @@
|
||||
#include "att.h"
|
||||
#include "hci.h"
|
||||
|
||||
void bleio_hci_background(void);
|
||||
void bleio_background(void);
|
||||
void bleio_reset(void);
|
||||
|
||||
typedef struct {
|
||||
// ble_gap_enc_key_t own_enc;
|
||||
|
@ -1,12 +1,6 @@
|
||||
// Derived from ArduinoBLE.
|
||||
// Copyright 2020 Dan Halbert for Adafruit Industries
|
||||
|
||||
// Some functions here are unused now, but may be used in the future.
|
||||
// Don't warn or error about this, and depend on the compiler & linker to
|
||||
// eliminate the associated code.
|
||||
#pragma GCC diagnostic ignored "-Wunused"
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
|
||||
/*
|
||||
This file is part of the ArduinoBLE library.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
@ -32,7 +26,6 @@
|
||||
// Zephyr include files to define HCI communication values and structs.
|
||||
// #include "hci_include/hci.h"
|
||||
// #include "hci_include/hci_err.h"
|
||||
#include "hci_include/att_internal.h"
|
||||
#include "hci_include/l2cap_internal.h"
|
||||
|
||||
#include "py/obj.h"
|
||||
@ -95,7 +88,7 @@ STATIC uint8_t bleio_properties_to_ble_spec_properties(uint8_t bleio_properties)
|
||||
return ble_spec_properties;
|
||||
}
|
||||
|
||||
// FIX not currently used; re-enable when used.
|
||||
// FIX not currently used; reenable when used.
|
||||
#if 0
|
||||
STATIC uint8_t ble_spec_properties_to_bleio_properties(uint8_t ble_spec_properties) {
|
||||
uint8_t bleio_properties = 0;
|
||||
@ -546,7 +539,7 @@ void att_remove_connection(uint16_t conn_handle, uint8_t reason) {
|
||||
.len = sizeof(zero),
|
||||
};
|
||||
|
||||
if (mp_obj_is_type(attribute_obj, &bleio_descriptor_type)) {
|
||||
if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) {
|
||||
bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj);
|
||||
if (bleio_uuid_get_uuid16_or_unknown(descriptor->uuid) == BLE_UUID_CCCD) {
|
||||
common_hal_bleio_descriptor_set_value(descriptor, &zero_cccd_value);
|
||||
@ -807,7 +800,7 @@ STATIC void process_find_info_req(uint16_t conn_handle, uint16_t mtu, uint8_t dl
|
||||
// Fetch the uuid for the given attribute, which might be a characteristic or a descriptor.
|
||||
bleio_uuid_obj_t *uuid;
|
||||
|
||||
if (mp_obj_is_type(attribute_obj, &bleio_characteristic_type)) {
|
||||
if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) {
|
||||
bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj);
|
||||
if (characteristic->handle != handle) {
|
||||
// If the handles don't match, this is the characteristic definition attribute.
|
||||
@ -863,7 +856,7 @@ STATIC void process_find_info_req(uint16_t conn_handle, uint16_t mtu, uint8_t dl
|
||||
}
|
||||
}
|
||||
|
||||
static int att_find_info_req(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, uint8_t response_buffer[]) {
|
||||
int att_find_info_req(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, uint8_t response_buffer[]) {
|
||||
struct __packed req {
|
||||
struct bt_att_hdr h;
|
||||
struct bt_att_find_info_req r;
|
||||
@ -931,7 +924,7 @@ STATIC void process_find_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t dl
|
||||
}
|
||||
}
|
||||
|
||||
static void process_read_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t data[]) {
|
||||
void process_read_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t data[]) {
|
||||
struct bt_att_read_group_req *req = (struct bt_att_read_group_req *)data;
|
||||
uint16_t type_uuid = req->uuid[0] | (req->uuid[1] << 8);
|
||||
|
||||
@ -963,7 +956,7 @@ static void process_read_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t d
|
||||
// Keep track of the first one to make sure.
|
||||
size_t sizeof_first_service_uuid = 0;
|
||||
|
||||
// Size of a single bt_att_group_data chunk. Start with the initial size, and
|
||||
// Size of a single bt_att_group_data chunk. Start with the intial size, and
|
||||
// add the uuid size in the loop below.
|
||||
size_t data_length = sizeof(struct bt_att_group_data);
|
||||
|
||||
@ -978,7 +971,7 @@ static void process_read_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t d
|
||||
}
|
||||
|
||||
mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle);
|
||||
if (mp_obj_is_type(attribute_obj, &bleio_service_type)) {
|
||||
if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_service_type)) {
|
||||
bleio_service_obj_t *service = MP_OBJ_TO_PTR(attribute_obj);
|
||||
|
||||
// Is this a 16-bit or a 128-bit uuid? It must match in size with any previous attribute
|
||||
@ -1015,7 +1008,7 @@ static void process_read_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t d
|
||||
}
|
||||
}
|
||||
|
||||
static int att_read_group_req(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, uint16_t uuid, uint8_t response_buffer[]) {
|
||||
int att_read_group_req(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, uint16_t uuid, uint8_t response_buffer[]) {
|
||||
|
||||
typedef struct __packed {
|
||||
struct bt_att_hdr h;
|
||||
@ -1090,7 +1083,7 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui
|
||||
size_t rsp_length = sizeof(rsp_t);
|
||||
|
||||
mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle);
|
||||
if (mp_obj_is_type(attribute_obj, &bleio_service_type)) {
|
||||
if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_service_type)) {
|
||||
if (offset) {
|
||||
send_error(conn_handle, BT_ATT_ERR_ATTRIBUTE_NOT_LONG, handle, BT_ATT_ERR_INVALID_PDU);
|
||||
return;
|
||||
@ -1102,7 +1095,7 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui
|
||||
common_hal_bleio_uuid_pack_into(service->uuid, rsp->r.value);
|
||||
rsp_length += sizeof_service_uuid;
|
||||
|
||||
} else if (mp_obj_is_type(attribute_obj, &bleio_characteristic_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) {
|
||||
bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj);
|
||||
if (characteristic->decl_handle == handle) {
|
||||
// Read characteristic declaration. Return properties, value handle, and uuid.
|
||||
@ -1142,7 +1135,7 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui
|
||||
memcpy(rsp->r.value, bufinfo.buf + offset, value_length);
|
||||
rsp_length += value_length;
|
||||
}
|
||||
} else if (mp_obj_is_type(attribute_obj, &bleio_descriptor_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) {
|
||||
bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj);
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
@ -1210,7 +1203,7 @@ STATIC void process_read_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t dl
|
||||
mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle);
|
||||
|
||||
if (type_uuid == BLE_UUID_CHARACTERISTIC &&
|
||||
mp_obj_is_type(attribute_obj, &bleio_characteristic_type)) {
|
||||
MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) {
|
||||
// Request is for characteristic declarations.
|
||||
bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj);
|
||||
|
||||
@ -1257,7 +1250,7 @@ STATIC void process_read_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t dl
|
||||
rsp_length += data_length;
|
||||
no_data = false;
|
||||
|
||||
} else if (mp_obj_is_type(attribute_obj, &bleio_descriptor_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) {
|
||||
// See if request is for a descriptor value with a 16-bit UUID, such as the CCCD.
|
||||
bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj);
|
||||
if (bleio_uuid_get_uuid16_or_unknown(descriptor->uuid) == type_uuid) {
|
||||
@ -1278,7 +1271,7 @@ STATIC void process_read_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t dl
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (mp_obj_is_type(attribute_obj, &bleio_characteristic_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) {
|
||||
// See if request is for a characteristic value with a 16-bit UUID.
|
||||
bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj);
|
||||
if (bleio_uuid_get_uuid16_or_unknown(characteristic->uuid) == type_uuid) {
|
||||
@ -1311,7 +1304,7 @@ STATIC void process_read_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t dl
|
||||
}
|
||||
}
|
||||
|
||||
static int att_read_type_req(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, uint16_t type, uint8_t response_buffer[]) {
|
||||
int att_read_type_req(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, uint16_t type, uint8_t response_buffer[]) {
|
||||
typedef struct __packed {
|
||||
struct bt_att_hdr h;
|
||||
struct bt_att_read_type_req r;
|
||||
@ -1366,7 +1359,7 @@ STATIC void process_write_req_or_cmd(uint16_t conn_handle, uint16_t mtu, uint8_t
|
||||
|
||||
mp_obj_t attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, req->handle);
|
||||
|
||||
if (mp_obj_is_type(attribute_obj, &bleio_characteristic_type)) {
|
||||
if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) {
|
||||
bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj);
|
||||
|
||||
// Don't write the characteristic declaration.
|
||||
@ -1384,7 +1377,7 @@ STATIC void process_write_req_or_cmd(uint16_t conn_handle, uint16_t mtu, uint8_t
|
||||
// Just change the local value. Don't fire off notifications, etc.
|
||||
bleio_characteristic_set_local_value(characteristic, &bufinfo);
|
||||
|
||||
} else if (mp_obj_is_type(attribute_obj, &bleio_descriptor_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) {
|
||||
bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj);
|
||||
// Only CCCD's are writable.
|
||||
if (bleio_uuid_get_uuid16_or_unknown(descriptor->uuid) != BLE_UUID_CCCD) {
|
||||
@ -1434,7 +1427,7 @@ STATIC void process_prepare_write_req(uint16_t conn_handle, uint16_t mtu, uint8_
|
||||
|
||||
mp_obj_t *attribute = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle);
|
||||
|
||||
if (!mp_obj_is_type(attribute, &bleio_characteristic_type)) {
|
||||
if (!MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) {
|
||||
send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_ATTRIBUTE_NOT_LONG);
|
||||
return;
|
||||
}
|
||||
@ -1721,58 +1714,58 @@ void att_process_data(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
|
||||
}
|
||||
|
||||
// FIX Do we need all of these?
|
||||
static void check_att_err(uint8_t err) {
|
||||
mp_rom_error_text_t msg = NULL;
|
||||
void check_att_err(uint8_t err) {
|
||||
const compressed_string_t *msg = NULL;
|
||||
switch (err) {
|
||||
case 0:
|
||||
return;
|
||||
case BT_ATT_ERR_INVALID_HANDLE:
|
||||
msg = MP_ERROR_TEXT("Invalid handle");
|
||||
msg = translate("Invalid handle");
|
||||
break;
|
||||
case BT_ATT_ERR_READ_NOT_PERMITTED:
|
||||
msg = MP_ERROR_TEXT("Read not permitted");
|
||||
msg = translate("Read not permitted");
|
||||
break;
|
||||
case BT_ATT_ERR_WRITE_NOT_PERMITTED:
|
||||
msg = MP_ERROR_TEXT("Write not permitted");
|
||||
msg = translate("Write not permitted");
|
||||
break;
|
||||
case BT_ATT_ERR_INVALID_PDU:
|
||||
msg = MP_ERROR_TEXT("Invalid PDU");
|
||||
msg = translate("Invalid PDU");
|
||||
break;
|
||||
case BT_ATT_ERR_NOT_SUPPORTED:
|
||||
msg = MP_ERROR_TEXT("Not supported");
|
||||
msg = translate("Not supported");
|
||||
break;
|
||||
case BT_ATT_ERR_INVALID_OFFSET:
|
||||
msg = MP_ERROR_TEXT("Invalid offset");
|
||||
msg = translate("Invalid offset");
|
||||
break;
|
||||
case BT_ATT_ERR_PREPARE_QUEUE_FULL:
|
||||
msg = MP_ERROR_TEXT("Prepare queue full");
|
||||
msg = translate("Prepare queue full");
|
||||
break;
|
||||
case BT_ATT_ERR_ATTRIBUTE_NOT_FOUND:
|
||||
msg = MP_ERROR_TEXT("Attribute not found");
|
||||
msg = translate("Attribute not found");
|
||||
break;
|
||||
case BT_ATT_ERR_ATTRIBUTE_NOT_LONG:
|
||||
msg = MP_ERROR_TEXT("Attribute not long");
|
||||
msg = translate("Attribute not long");
|
||||
break;
|
||||
case BT_ATT_ERR_ENCRYPTION_KEY_SIZE:
|
||||
msg = MP_ERROR_TEXT("Encryption key size");
|
||||
msg = translate("Encryption key size");
|
||||
break;
|
||||
case BT_ATT_ERR_INVALID_ATTRIBUTE_LEN:
|
||||
msg = MP_ERROR_TEXT("Invalid attribute length");
|
||||
msg = translate("Invalid attribute length");
|
||||
break;
|
||||
case BT_ATT_ERR_UNLIKELY:
|
||||
msg = MP_ERROR_TEXT("Unlikely");
|
||||
msg = translate("Unlikely");
|
||||
break;
|
||||
case BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE:
|
||||
msg = MP_ERROR_TEXT("Unsupported group type");
|
||||
msg = translate("Unsupported group type");
|
||||
break;
|
||||
case BT_ATT_ERR_INSUFFICIENT_RESOURCES:
|
||||
msg = MP_ERROR_TEXT("Insufficient resources");
|
||||
msg = translate("Insufficient resources");
|
||||
break;
|
||||
case BT_ATT_ERR_DB_OUT_OF_SYNC:
|
||||
msg = MP_ERROR_TEXT("DB out of sync");
|
||||
msg = translate("DB out of sync");
|
||||
break;
|
||||
case BT_ATT_ERR_VALUE_NOT_ALLOWED:
|
||||
msg = MP_ERROR_TEXT("Value not allowed");
|
||||
msg = translate("Value not allowed");
|
||||
break;
|
||||
}
|
||||
if (msg) {
|
||||
@ -1781,15 +1774,15 @@ static void check_att_err(uint8_t err) {
|
||||
|
||||
switch (err) {
|
||||
case BT_ATT_ERR_AUTHENTICATION:
|
||||
msg = MP_ERROR_TEXT("Insufficient authentication");
|
||||
msg = translate("Insufficient authentication");
|
||||
break;
|
||||
case BT_ATT_ERR_INSUFFICIENT_ENCRYPTION:
|
||||
msg = MP_ERROR_TEXT("Insufficient encryption");
|
||||
msg = translate("Insufficient encryption");
|
||||
break;
|
||||
}
|
||||
if (msg) {
|
||||
mp_raise_bleio_SecurityError(msg);
|
||||
}
|
||||
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Unknown ATT error: 0x%02x"), err);
|
||||
mp_raise_bleio_BluetoothError(translate("Unknown ATT error: 0x%02x"), err);
|
||||
}
|
||||
|
@ -770,35 +770,35 @@ void hci_check_error(hci_result_t result) {
|
||||
return;
|
||||
|
||||
case HCI_RESPONSE_TIMEOUT:
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Timeout waiting for HCI response"));
|
||||
mp_raise_bleio_BluetoothError(translate("Timeout waiting for HCI response"));
|
||||
return;
|
||||
|
||||
case HCI_WRITE_TIMEOUT:
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Timeout waiting to write HCI request"));
|
||||
mp_raise_bleio_BluetoothError(translate("Timeout waiting to write HCI request"));
|
||||
return;
|
||||
|
||||
case HCI_READ_ERROR:
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Error reading from HCI adapter"));
|
||||
mp_raise_bleio_BluetoothError(translate("Error reading from HCI adapter"));
|
||||
return;
|
||||
|
||||
case HCI_WRITE_ERROR:
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Error writing to HCI adapter"));
|
||||
mp_raise_bleio_BluetoothError(translate("Error writing to HCI adapter"));
|
||||
return;
|
||||
|
||||
case HCI_PACKET_SIZE_ERROR:
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("HCI packet size mismatch"));
|
||||
mp_raise_RuntimeError(translate("HCI packet size mismatch"));
|
||||
return;
|
||||
|
||||
case HCI_ATT_ERROR:
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("Error in ATT protocol code"));
|
||||
mp_raise_RuntimeError(translate("Error in ATT protocol code"));
|
||||
return;
|
||||
|
||||
default:
|
||||
// Should be an HCI status error, > 0.
|
||||
if (result > 0) {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("HCI status error: %02x"), result);
|
||||
mp_raise_bleio_BluetoothError(translate("HCI status error: %02x"), result);
|
||||
} else {
|
||||
mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Unknown hci_result_t: %d"), result);
|
||||
mp_raise_bleio_BluetoothError(translate("Unknown hci_result_t: %d"), result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
// for __packed
|
||||
@ -150,7 +149,7 @@ struct bt_att_read_mult_req {
|
||||
uint16_t handles[];
|
||||
} __packed;
|
||||
|
||||
/* Read Multiple Response */
|
||||
/* Read Multiple Respose */
|
||||
#define BT_ATT_OP_READ_MULT_RSP 0x0f
|
||||
struct bt_att_read_mult_rsp {
|
||||
uint8_t _dummy[0];
|
||||
@ -243,7 +242,7 @@ struct bt_att_read_mult_vl_req {
|
||||
uint16_t handles[];
|
||||
} __packed;
|
||||
|
||||
/* Read Multiple Response */
|
||||
/* Read Multiple Respose */
|
||||
#define BT_ATT_OP_READ_MULT_VL_RSP 0x21
|
||||
struct bt_att_read_mult_vl_rsp {
|
||||
uint16_t len;
|
||||
|
@ -1,23 +0,0 @@
|
||||
# MicroPython & CircuitPython License
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013-2022 Damien P. George and others
|
||||
|
||||
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.
|
@ -13,9 +13,12 @@ Building the documentation locally
|
||||
If you're making changes to the documentation, you should build the
|
||||
documentation locally so that you can preview your changes.
|
||||
|
||||
Install the necessary packages, preferably in a virtualenv, in `circuitpython/`:
|
||||
Install Sphinx, recommonmark, and optionally (for the RTD-styling), sphinx_rtd_theme,
|
||||
preferably in a virtualenv:
|
||||
|
||||
pip install -r requirements-doc.txt
|
||||
pip install sphinx
|
||||
pip install recommonmark
|
||||
pip install sphinx_rtd_theme
|
||||
|
||||
In `circuitpython/`, build the docs:
|
||||
|
||||
|
@ -14,22 +14,6 @@
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if support_matrix_reverse[obj.name] is defined %}
|
||||
.. raw:: html
|
||||
|
||||
<p>
|
||||
<details>
|
||||
<summary>Available on these boards</summary>
|
||||
<ul>
|
||||
{% for board in support_matrix_reverse[obj.name] %}
|
||||
<li> {{ board }}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</details>
|
||||
</p>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% block subpackages %}
|
||||
{% set visible_subpackages = obj.subpackages|selectattr("display")|list %}
|
||||
{% if visible_subpackages %}
|
||||
|
@ -7,7 +7,7 @@ These instructions also apply to `analogio`, `busio`, `pulseio` and `touchio`. M
|
||||
Common HAL related files are found in these locations:
|
||||
|
||||
* `shared-bindings` Shared home for the Python <-> C bindings which includes inline RST documentation for the created interfaces. The common hal functions are defined in the .h files of the corresponding C files.
|
||||
* `shared-module` Shared home for C code built on the Common HAL and used by all ports. This code only uses `common_hal` methods defined in `shared-bindings`.
|
||||
* `shared-modules` Shared home for C code built on the Common HAL and used by all ports. This code only uses `common_hal` methods defined in `shared-bindings`.
|
||||
* `<port>/common-hal` Port-specific implementation of the Common HAL.
|
||||
|
||||
Each folder has the substructure of <python module name>/<class name> and they should match 1:1. `__init__.c` is used for module globals that are not classes (similar to `__init__.py`).
|
||||
|
@ -18,7 +18,7 @@ Start libraries with the cookiecutter
|
||||
Cookiecutter is a tool that lets you bootstrap a new repo based on another repo.
|
||||
We've made one `here <https://github.com/adafruit/cookiecutter-adafruit-circuitpython>`_
|
||||
for CircuitPython libraries that include configs for Travis CI and ReadTheDocs
|
||||
along with a setup.py, license, code of conduct, readme among other files.
|
||||
along with a setup.py, license, code of conduct and readme.
|
||||
|
||||
.. code-block::sh
|
||||
|
||||
@ -99,7 +99,7 @@ For example, a user can then use ``deinit()```::
|
||||
import board
|
||||
import time
|
||||
|
||||
led = digitalio.DigitalInOut(board.LED)
|
||||
led = digitalio.DigitalInOut(board.D13)
|
||||
led.direction = digitalio.Direction.OUTPUT
|
||||
|
||||
for i in range(10):
|
||||
@ -119,7 +119,7 @@ Alternatively, using a ``with`` statement ensures that the hardware is deinitial
|
||||
import board
|
||||
import time
|
||||
|
||||
with digitalio.DigitalInOut(board.LED) as led:
|
||||
with digitalio.DigitalInOut(board.D13) as led:
|
||||
led.direction = digitalio.Direction.OUTPUT
|
||||
|
||||
for i in range(10):
|
||||
@ -141,7 +141,7 @@ statement will ensure hardware isn't enabled longer than needed.
|
||||
Verify your device
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Whenever possible, make sure the device you are talking to is the device you expect.
|
||||
Whenever possible, make sure device you are talking to is the device you expect.
|
||||
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
|
||||
expectation. Validating this upfront will help catch mistakes.
|
||||
@ -202,10 +202,10 @@ interchangeably with the CPython name. This is confusing. Instead, think up a
|
||||
new name that is related to the extra functionality you are adding.
|
||||
|
||||
For example, storage mounting and unmounting related functions were moved from
|
||||
``uos`` into a new `storage` module. These names better match their
|
||||
functionality and do not 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.
|
||||
``uos`` into a new `storage` module. Terminal related functions were moved into
|
||||
`multiterminal`. These names better match their functionality and do not
|
||||
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.
|
||||
|
||||
Example
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -213,7 +213,7 @@ Example
|
||||
When adding extra functionality to CircuitPython to mimic what a normal
|
||||
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,
|
||||
mounting and unmounting drives is not a part of CPython so it should be done in a
|
||||
mounting and unmount 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.
|
||||
That way when someone moves the code to CPython they know what parts need to be
|
||||
adapted.
|
||||
@ -238,44 +238,11 @@ Module description
|
||||
After the license comment::
|
||||
|
||||
"""
|
||||
`<module name>`
|
||||
`<module name>` - <Short description>
|
||||
=================================================
|
||||
|
||||
<Longer description>
|
||||
|
||||
* Author(s):
|
||||
|
||||
Implementation Notes
|
||||
--------------------
|
||||
|
||||
|
||||
**Hardware:**
|
||||
|
||||
* `Adafruit Device Description
|
||||
<hyperlink>`_ (Product ID: <Product Number>)
|
||||
|
||||
**Software and Dependencies:**
|
||||
|
||||
* Adafruit CircuitPython firmware for the supported boards:
|
||||
https://circuitpython.org/downloads
|
||||
|
||||
* Adafruit's Bus Device library:
|
||||
https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
|
||||
|
||||
* Adafruit's Register library:
|
||||
https://github.com/adafruit/Adafruit_CircuitPython_Register
|
||||
|
||||
<Longer description.>
|
||||
"""
|
||||
|
||||
Version description
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
After the import statements::
|
||||
|
||||
__version__ = "0.0.0+auto.0"
|
||||
__repo__ = "<repo github link>"
|
||||
|
||||
|
||||
Class description
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -285,7 +252,7 @@ At the class level document what class does and how to initialize it::
|
||||
"""DS3231 real-time clock.
|
||||
|
||||
:param ~busio.I2C i2c_bus: The I2C bus the DS3231 is connected to.
|
||||
:param int address: The I2C address of the device. Defaults to :const:`0x40`
|
||||
:param int address: The I2C address of the device.
|
||||
"""
|
||||
|
||||
def __init__(self, i2c_bus, address=0x40):
|
||||
@ -300,85 +267,7 @@ Renders as:
|
||||
DS3231 real-time clock.
|
||||
|
||||
:param ~busio.I2C i2c_bus: The I2C bus the DS3231 is connected to.
|
||||
:param int address: The I2C address of the device. Defaults to :const:`0x40`
|
||||
|
||||
|
||||
Documenting Parameters
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Although there are different ways to document class and functions definitions in Python,
|
||||
the following is the prevalent method of documenting parameters
|
||||
for CircuitPython libraries. When documenting class parameters you should use the
|
||||
following structure:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
:param param_type param_name: Parameter_description
|
||||
|
||||
|
||||
param_type
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The type of the parameter. This could be, among others, ``int``, ``float``, ``str``, ``bool``, etc.
|
||||
To document an object in the CircuitPython domain, you need to include a ``~`` before the
|
||||
definition as shown in the following example:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
:param ~busio.I2C i2c_bus: The I2C bus the DS3231 is connected to.
|
||||
|
||||
|
||||
To include references to CircuitPython modules, cookiecutter creates an entry in the
|
||||
intersphinx_mapping section in the ``conf.py`` file located within the ``docs`` directory.
|
||||
To add different types outside CircuitPython you need to include them in the intersphinx_mapping::
|
||||
|
||||
|
||||
intersphinx_mapping = {
|
||||
"python": ("https://docs.python.org/3.4", None),
|
||||
"BusDevice":("https://circuitpython.readthedocs.io/projects/busdevice/en/latest/", None,),
|
||||
"CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None),
|
||||
}
|
||||
|
||||
The intersphinx_mapping above includes references to Python, BusDevice and CircuitPython
|
||||
Documentation
|
||||
|
||||
When the parameter have two different types, you should reference them as follows::
|
||||
|
||||
|
||||
class Character_LCD:
|
||||
"""Base class for character LCD
|
||||
|
||||
:param ~digitalio.DigitalInOut rs: The reset data line
|
||||
:param ~pwmio.PWMOut,~digitalio.DigitalInOut blue: Blue RGB Anode
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, rs, blue):
|
||||
self._rc = rs
|
||||
self.blue = blue
|
||||
|
||||
|
||||
Renders as:
|
||||
|
||||
.. py:class:: Character_LCD(rs, blue)
|
||||
:noindex:
|
||||
|
||||
Base class for character LCD
|
||||
|
||||
:param ~digitalio.DigitalInOut rs: The reset data line
|
||||
:param ~pwmio.PWMOut,~digitalio.DigitalInOut blue: Blue RGB Anode
|
||||
|
||||
|
||||
param_name
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Parameter name used in the class or method definition
|
||||
|
||||
|
||||
Parameter_description
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Parameter description. When the parameter defaults to a particular value, it is good
|
||||
practice to include the default::
|
||||
|
||||
:param int pitch: Pitch value for the servo. Defaults to :const:`4500`
|
||||
|
||||
:param int address: The I2C address of the device.
|
||||
|
||||
Attributes
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -494,53 +383,6 @@ Renders as:
|
||||
|
||||
:param float degrees: Degrees to turn right
|
||||
|
||||
Documentation References to other Libraries
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
When you need to make references to documentation in other libraries you should refer the class using single
|
||||
backticks ``:class:`~adafruit_motor.servo.Servo```. You must also add the reference in the ``conf.py`` file in the
|
||||
``intersphinx_mapping section`` by adding a new entry::
|
||||
|
||||
"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
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -600,50 +442,6 @@ SPI Example
|
||||
spi.readinto(self.buf)
|
||||
return self.buf[0]
|
||||
|
||||
|
||||
|
||||
Class documentation example template
|
||||
--------------------------------------------------------------------------------
|
||||
When documenting classes, you should use the following template to illustrate basic usage.
|
||||
It is similar with the simpletest example, however this will display the information in the Read The Docs
|
||||
documentation.
|
||||
The advantage of using this template is it makes the documentation consistent across the libraries.
|
||||
|
||||
This is an example for a AHT20 temperature sensor. Include the following after the class parameter:
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
"""
|
||||
|
||||
**Quickstart: Importing and using the AHT10/AHT20 temperature sensor**
|
||||
|
||||
Here is an example of using the :class:`AHTx0` class.
|
||||
First you will need to import the libraries to use the sensor
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import board
|
||||
import adafruit_ahtx0
|
||||
|
||||
Once this is done you can define your `board.I2C` object and define your sensor object
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
i2c = board.I2C() # uses board.SCL and board.SDA
|
||||
aht = adafruit_ahtx0.AHTx0(i2c)
|
||||
|
||||
Now you have access to the temperature and humidity using
|
||||
the :attr:`temperature` and :attr:`relative_humidity` attributes
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
temperature = aht.temperature
|
||||
relative_humidity = aht.relative_humidity
|
||||
|
||||
"""
|
||||
|
||||
|
||||
Use composition
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -660,10 +458,10 @@ object instead of the pins themselves. This allows the calling code to provide
|
||||
any object with the appropriate methods such as an I2C expansion board.
|
||||
|
||||
Another example is to expect a :py:class:`~digitalio.DigitalInOut` for a pin to
|
||||
toggle instead of a :py:class:`~microcontroller.Pin` from :py:mod:`board`.
|
||||
Taking in the :py:class:`~microcontroller.Pin` object alone would limit the
|
||||
driver to pins on the actual microcontroller instead of pins provided by another
|
||||
driver such as an IO expander.
|
||||
toggle instead of a :py:class:`~microcontroller.Pin` from `board`. Taking in the
|
||||
:py:class:`~microcontroller.Pin` object alone would limit the driver to pins on
|
||||
the actual microcontroller instead of pins provided by another driver such as an
|
||||
IO expander.
|
||||
|
||||
Lots of small modules
|
||||
--------------------------------------------------------------------------------
|
||||
@ -715,34 +513,8 @@ when using ``const()``, keep in mind these general guide lines:
|
||||
|
||||
- Always use via an import, ex: ``from micropython import const``
|
||||
- Limit use to global (module level) variables only.
|
||||
- Only used when the user will not need access to variable and prefix name with
|
||||
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
|
||||
------------------
|
||||
When adding examples, cookiecutter will add a ``<name>_simpletest.py`` file in the examples directory for you.
|
||||
Be sure to include code with the library minimal functionalities to work on a device.
|
||||
You could other examples if needed featuring different
|
||||
functionalities of the library.
|
||||
If you add additional examples, be sure to include them in the ``examples.rst``. Naming of the examples
|
||||
files should use the name of the library followed by a description, using underscore to separate them.
|
||||
|
||||
- If user will not need access to variable, prefix name with a leading
|
||||
underscore, ex: ``_SOME_CONST``.
|
||||
|
||||
Sensor properties and units
|
||||
--------------------------------------------------------------------------------
|
||||
@ -764,7 +536,7 @@ properties.
|
||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||
| ``gyro`` | (float, float, float) | x, y, z radians per second |
|
||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||
| ``temperature`` | float | degrees Celsius |
|
||||
| ``temperature`` | float | degrees centigrade |
|
||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||
| ``CO2`` | float | measured CO2 in ppm |
|
||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||
@ -772,9 +544,9 @@ properties.
|
||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||
| ``TVOC`` | float | Total Volatile Organic Compounds in ppb |
|
||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||
| ``distance`` | float | centimeters (cm) |
|
||||
| ``distance`` | float | centimeters |
|
||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||
| ``proximity`` | int | non-unit-specific proximity values (monotonic but not actual distance) |
|
||||
| ``proximity`` | int | non-unit-specifc proximity values (monotonic but not actual distance) |
|
||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||
| ``light`` | float | non-unit-specific light levels (should be monotonic but is not lux) |
|
||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||
@ -796,7 +568,7 @@ properties.
|
||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||
| ``duty_cycle`` | int | 16-bit PWM duty cycle (regardless of output resolution) |
|
||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||
| ``frequency`` | int | Hertz (Hz) |
|
||||
| ``frequency`` | int | Hertz |
|
||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||
| ``value`` | bool | Digital logic |
|
||||
+-----------------------+-----------------------+-------------------------------------------------------------------------+
|
||||
@ -807,16 +579,6 @@ properties.
|
||||
| ``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
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -830,8 +592,9 @@ mimic the structure in ``shared-bindings``.
|
||||
To test your native modules or core enhancements, follow these Adafruit Learning Guides
|
||||
for building local firmware to flash onto your device(s):
|
||||
|
||||
`Build CircuitPython <https://learn.adafruit.com/building-circuitpython>`_
|
||||
`SAMD21 - Build Firmware Learning Guide <https://learn.adafruit.com/micropython-for-samd21/build-firmware>`_
|
||||
|
||||
`ESP8266 - Build Firmware Learning Guide <https://learn.adafruit.com/building-and-running-micropython-on-the-esp8266/overview>`_
|
||||
|
||||
MicroPython compatibility
|
||||
--------------------------------------------------------------------------------
|
||||
|
33
docs/drivers.rst
Normal file
33
docs/drivers.rst
Normal file
@ -0,0 +1,33 @@
|
||||
Additional CircuitPython Libraries and Drivers on GitHub
|
||||
=========================================================
|
||||
|
||||
These are libraries and drivers available in separate GitHub repos. They are
|
||||
designed for use with CircuitPython and may or may not work with
|
||||
`MicroPython <https://micropython.org>`_.
|
||||
|
||||
|
||||
Adafruit CircuitPython Library Bundle
|
||||
--------------------------------------
|
||||
|
||||
We provide a bundle of all our libraries to ease installation of drivers and
|
||||
their dependencies. The bundle is primarily geared to the Adafruit Express line
|
||||
of boards which feature a relatively large external flash. With Express boards,
|
||||
it's easy to copy them all onto the filesystem. However, if you don't have
|
||||
enough space simply copy things over as they are needed.
|
||||
|
||||
- The Adafruit bundles are available on GitHub: <https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases>.
|
||||
|
||||
- Documentation for the bundle, which includes links to documentation for all
|
||||
libraries, is available here: <https://circuitpython.readthedocs.io/projects/bundle/en/latest/>.
|
||||
|
||||
|
||||
CircuitPython Community Library Bundle
|
||||
---------------------------------------
|
||||
|
||||
This bundle contains non-Adafruit sponsored libraries, that are written and submitted
|
||||
by members of the community.
|
||||
|
||||
- The Community bundles are available on GitHub: <https://github.com/adafruit/CircuitPython_Community_Bundle/releases>.
|
||||
|
||||
- Documentation is not available on ReadTheDocs at this time. See each library for any
|
||||
included documentation.
|
@ -1,96 +0,0 @@
|
||||
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 uses a file called ``settings.toml`` 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 ``settings.toml`` file contents
|
||||
on every access.
|
||||
|
||||
CircuitPython only supports a subset of the full toml specification, see below
|
||||
for more details. The subset is very "Python-like", which is a key reason we
|
||||
selected the format.
|
||||
|
||||
Due to technical limitations it probably also accepts some files that are
|
||||
not valid TOML files; bugs of this nature are subject to change (i.e., be
|
||||
fixed) without the usual deprecation period for incompatible changes.
|
||||
|
||||
File format example:
|
||||
|
||||
.. code-block::
|
||||
|
||||
str_key="Hello world" # with trailing comment
|
||||
int_key = 7
|
||||
unicode_key="œuvre"
|
||||
unicode_key2="\\u0153uvre" # same as above
|
||||
unicode_key3="\\U00000153uvre" # same as above
|
||||
escape_codes="supported, including \\r\\n\\"\\\\"
|
||||
# comment
|
||||
[subtable]
|
||||
subvalue="cannot retrieve this using getenv"
|
||||
|
||||
|
||||
Details of the toml language subset
|
||||
-----------------------------------
|
||||
|
||||
* The content is required to be in UTF-8 encoding
|
||||
* The supported data types are string and integer
|
||||
* Only basic strings are supported, not triple-quoted strings
|
||||
* Only integers supported by strtol. (no 0o, no 0b, no underscores 1_000, 011
|
||||
is 9, not 11)
|
||||
* Only bare keys are supported
|
||||
* Duplicate keys are not diagnosed.
|
||||
* Comments are supported
|
||||
* Only values from the "root table" can be retrieved
|
||||
* due to technical limitations, the content of multi-line
|
||||
strings can erroneously be parsed as a value.
|
||||
|
||||
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_HEAP_START_SIZE
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets the initial size of the python heap, allocated from the outer heap. Must be a multiple of 4.
|
||||
The default is currently 8192.
|
||||
The python heap will grow by doubling and redoubling this initial size until it cannot fit in the outer heap.
|
||||
Larger values will reserve more RAM for python use and prevent the supervisor and SDK
|
||||
from large allocations of their own.
|
||||
Smaller values will likely grow sooner than large start sizes.
|
||||
|
||||
CIRCUITPY_PYSTACK_SIZE
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets the size of the python stack. Must be a multiple of 4. The default value is currently 1536.
|
||||
Increasing the stack reduces the size of the heap available to python code.
|
||||
Used to avoid "Pystack exhausted" errors when the code can't be reworked to avoid it.
|
||||
|
||||
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_WEB_INSTANCE_NAME
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Name the board advertises as for the WEB workflow. Defaults to human readable board name if 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.
|
@ -19,12 +19,9 @@ Full Table of Contents
|
||||
:caption: API and Usage
|
||||
|
||||
../shared-bindings/index.rst
|
||||
library/index.rst
|
||||
supported_ports.rst
|
||||
troubleshooting.rst
|
||||
libraries.rst
|
||||
workflows
|
||||
environment.rst
|
||||
drivers.rst
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
@ -33,11 +30,12 @@ Full Table of Contents
|
||||
design_guide
|
||||
porting
|
||||
common_hal
|
||||
reference/glossary.rst
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Python stand
|
||||
:caption: MicroPython specific
|
||||
|
||||
library/index.rst
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
@ -47,7 +45,7 @@ Full Table of Contents
|
||||
../CONTRIBUTING
|
||||
../BUILDING
|
||||
../CODE_OF_CONDUCT
|
||||
../docs/LICENSE
|
||||
../license.rst
|
||||
../WEBUSB_README
|
||||
|
||||
Indices and tables
|
||||
|
@ -1,31 +0,0 @@
|
||||
Adafruit CircuitPython Libraries
|
||||
================================
|
||||
|
||||
Documentation for all Adafruit-sponsored CircuitPython libraries is at:
|
||||
<https://docs.circuitpython.org/projects/bundle/en/latest/drivers.html>.
|
||||
|
||||
|
||||
CircuitPython Library Bundles
|
||||
=============================
|
||||
|
||||
Many Python libraries, including device drivers, have been written for use with CircuitPython.
|
||||
They are maintained in separate GitHub repos, one per library.
|
||||
|
||||
Libraries are packaged in *bundles*, which are ZIP files that are snapshots in time of a group of libraries.
|
||||
|
||||
Adafruit sponsors and maintains several hundred libraries, packaged in the **Adafruit Library Bundle**.
|
||||
Adafruit-sponsored libraries are also available on <https://pypi.org>.
|
||||
|
||||
Yet other libraries are maintained by members of the CircuitPython community,
|
||||
and are packaged in the **CircuitPython Community Library Bundle**.
|
||||
|
||||
The Adafruit bundles are available on GitHub: <https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases>.
|
||||
The Community bundles are available at: <https://github.com/adafruit/CircuitPython_Community_Bundle/releases>.
|
||||
|
||||
More detailed information about the bundles, and download links for the latest bundles
|
||||
are at <https://circuitpython.org/libraries>.
|
||||
|
||||
Documentation about bundle construction is at: <https://circuitpython.readthedocs.io/projects/bundle/en/latest/>.
|
||||
|
||||
Documentation for Community Libraries is not available on ReadTheDocs at this time. See the GitHub repository
|
||||
for each library for any included documentation.
|
@ -4,7 +4,7 @@
|
||||
.. module:: array
|
||||
:synopsis: efficient arrays of numeric data
|
||||
|
||||
|see_cpython_module| :mod:`python:array`.
|
||||
|see_cpython_module| :mod:`cpython:array`.
|
||||
|
||||
Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``,
|
||||
``L``, ``q``, ``Q``, ``f``, ``d`` (the latter 2 depending on the
|
||||
@ -13,7 +13,7 @@ floating-point support).
|
||||
Classes
|
||||
-------
|
||||
|
||||
.. class:: array(typecode, [iterable])
|
||||
.. class:: array.array(typecode, [iterable])
|
||||
|
||||
Create array with elements of given type. Initial contents of the
|
||||
array are given by an `iterable`. If it is not provided, an empty
|
||||
@ -27,55 +27,3 @@ Classes
|
||||
|
||||
Append new elements as contained in `iterable` to the end of
|
||||
array, growing it.
|
||||
|
||||
.. method:: __getitem__(index)
|
||||
|
||||
Indexed read of the array, called as ``a[index]`` (where ``a`` is an ``array``).
|
||||
Returns a value if *index* is an ``int`` and an ``array`` if *index* is a slice.
|
||||
Negative indices count from the end and ``IndexError`` is thrown if the index is
|
||||
out of range.
|
||||
|
||||
**Note:** ``__getitem__`` cannot be called directly (``a.__getitem__(index)`` fails) and
|
||||
is not present in ``__dict__``, however ``a[index]`` does work.
|
||||
|
||||
.. method:: __setitem__(index, value)
|
||||
|
||||
Indexed write into the array, called as ``a[index] = value`` (where ``a`` is an ``array``).
|
||||
``value`` is a single value if *index* is an ``int`` and an ``array`` if *index* is a slice.
|
||||
Negative indices count from the end and ``IndexError`` is thrown if the index is out of range.
|
||||
|
||||
**Note:** ``__setitem__`` cannot be called directly (``a.__setitem__(index, value)`` fails) and
|
||||
is not present in ``__dict__``, however ``a[index] = value`` does work.
|
||||
|
||||
.. method:: __len__()
|
||||
|
||||
Returns the number of items in the array, called as ``len(a)`` (where ``a`` is an ``array``).
|
||||
|
||||
**Note:** ``__len__`` cannot be called directly (``a.__len__()`` fails) and the
|
||||
method is not present in ``__dict__``, however ``len(a)`` does work.
|
||||
|
||||
.. method:: __add__(other)
|
||||
|
||||
Return a new ``array`` that is the concatenation of the array with *other*, called as
|
||||
``a + other`` (where ``a`` and *other* are both ``arrays``).
|
||||
|
||||
**Note:** ``__add__`` cannot be called directly (``a.__add__(other)`` fails) and
|
||||
is not present in ``__dict__``, however ``a + other`` does work.
|
||||
|
||||
.. method:: __iadd__(other)
|
||||
|
||||
Concatenates the array with *other* in-place, called as ``a += other`` (where ``a`` and *other*
|
||||
are both ``arrays``). Equivalent to ``extend(other)``.
|
||||
|
||||
**Note:** ``__iadd__`` cannot be called directly (``a.__iadd__(other)`` fails) and
|
||||
is not present in ``__dict__``, however ``a += other`` does work.
|
||||
|
||||
.. method:: __repr__()
|
||||
|
||||
Returns the string representation of the array, called as ``str(a)`` or ``repr(a)```
|
||||
(where ``a`` is an ``array``). Returns the string ``"array(<type>, [<elements>])"``,
|
||||
where ``<type>`` is the type code letter for the array and ``<elements>`` is a comma
|
||||
separated list of the elements of the array.
|
||||
|
||||
**Note:** ``__repr__`` cannot be called directly (``a.__repr__()`` fails) and
|
||||
is not present in ``__dict__``, however ``str(a)`` and ``repr(a)`` both work.
|
||||
|
@ -1,10 +1,10 @@
|
||||
:mod:`binascii` -- binary/ASCII conversions
|
||||
===========================================
|
||||
============================================
|
||||
|
||||
.. module:: binascii
|
||||
:synopsis: binary/ASCII conversions
|
||||
|
||||
|see_cpython_module| :mod:`python:binascii`.
|
||||
|see_cpython_module| :mod:`cpython:binascii`.
|
||||
|
||||
This module implements conversions between binary data and various
|
||||
encodings of it in ASCII form (in both directions).
|
||||
@ -14,11 +14,13 @@ Functions
|
||||
|
||||
.. function:: hexlify(data, [sep])
|
||||
|
||||
Convert the bytes in the *data* object to a hexadecimal representation.
|
||||
Returns a bytes object.
|
||||
Convert binary data to hexadecimal representation. Returns bytes string.
|
||||
|
||||
If the additional argument *sep* is supplied it is used as a separator
|
||||
between hexadecimal values.
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
If additional argument, *sep* is supplied, it is used as a separator
|
||||
between hexadecimal values.
|
||||
|
||||
.. function:: unhexlify(data)
|
||||
|
||||
@ -31,14 +33,8 @@ Functions
|
||||
Conforms to `RFC 2045 s.6.8 <https://tools.ietf.org/html/rfc2045#section-6.8>`_.
|
||||
Returns a bytes object.
|
||||
|
||||
.. function:: b2a_base64(data, *, newline=True)
|
||||
.. function:: b2a_base64(data)
|
||||
|
||||
Encode binary data in base64 format, as in `RFC 3548
|
||||
<https://tools.ietf.org/html/rfc3548.html>`_. Returns the encoded data
|
||||
followed by a newline character if ``newline`` is true, as a bytes object.
|
||||
|
||||
.. function:: crc32(data, value=0, /)
|
||||
|
||||
Compute CRC-32, the 32-bit checksum of the bytes in *data* starting with an
|
||||
initial CRC of *value*. The default initial CRC is 0. The algorithm is
|
||||
consistent with the ZIP file checksum.
|
||||
followed by a newline character, as a bytes object.
|
||||
|
161
docs/library/btree.rst
Normal file
161
docs/library/btree.rst
Normal file
@ -0,0 +1,161 @@
|
||||
:mod:`btree` -- simple BTree database
|
||||
=====================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: btree
|
||||
:synopsis: simple BTree database
|
||||
|
||||
The ``btree`` module implements a simple key-value database using external
|
||||
storage (disk files, or in general case, a random-access ``stream``). Keys are
|
||||
stored sorted in the database, and besides efficient retrieval by a key
|
||||
value, a database also supports efficient ordered range scans (retrieval
|
||||
of values with the keys in a given range). On the application interface
|
||||
side, BTree database work as close a possible to a way standard `dict`
|
||||
type works, one notable difference is that both keys and values must
|
||||
be `bytes` objects (so, if you want to store objects of other types, you
|
||||
need to serialize them to `bytes` first).
|
||||
|
||||
The module is based on the well-known BerkelyDB library, version 1.xx.
|
||||
|
||||
Example::
|
||||
|
||||
import btree
|
||||
|
||||
# First, we need to open a stream which holds a database
|
||||
# This is usually a file, but can be in-memory database
|
||||
# using uio.BytesIO, a raw flash partition, etc.
|
||||
# Oftentimes, you want to create a database file if it doesn't
|
||||
# exist and open if it exists. Idiom below takes care of this.
|
||||
# DO NOT open database with "a+b" access mode.
|
||||
try:
|
||||
f = open("mydb", "r+b")
|
||||
except OSError:
|
||||
f = open("mydb", "w+b")
|
||||
|
||||
# Now open a database itself
|
||||
db = btree.open(f)
|
||||
|
||||
# The keys you add will be sorted internally in the database
|
||||
db[b"3"] = b"three"
|
||||
db[b"1"] = b"one"
|
||||
db[b"2"] = b"two"
|
||||
|
||||
# Assume that any changes are cached in memory unless
|
||||
# explicitly flushed (or database closed). Flush database
|
||||
# at the end of each "transaction".
|
||||
db.flush()
|
||||
|
||||
# Prints b'two'
|
||||
print(db[b"2"])
|
||||
|
||||
# Iterate over sorted keys in the database, starting from b"2"
|
||||
# until the end of the database, returning only values.
|
||||
# Mind that arguments passed to values() method are *key* values.
|
||||
# Prints:
|
||||
# b'two'
|
||||
# b'three'
|
||||
for word in db.values(b"2"):
|
||||
print(word)
|
||||
|
||||
del db[b"2"]
|
||||
|
||||
# No longer true, prints False
|
||||
print(b"2" in db)
|
||||
|
||||
# Prints:
|
||||
# b"1"
|
||||
# b"3"
|
||||
for key in db:
|
||||
print(key)
|
||||
|
||||
db.close()
|
||||
|
||||
# Don't forget to close the underlying stream!
|
||||
f.close()
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: open(stream, \*, flags=0, pagesize=0, cachesize=0, minkeypage=0)
|
||||
|
||||
Open a database from a random-access ``stream`` (like an open file). All
|
||||
other parameters are optional and keyword-only, and allow to tweak advanced
|
||||
parameters of the database operation (most users will not need them):
|
||||
|
||||
* *flags* - Currently unused.
|
||||
* *pagesize* - Page size used for the nodes in BTree. Acceptable range
|
||||
is 512-65536. If 0, a port-specific default will be used, optimized for
|
||||
port's memory usage and/or performance.
|
||||
* *cachesize* - Suggested memory cache size in bytes. For a
|
||||
board with enough memory using larger values may improve performance.
|
||||
Cache policy is as follows: entire cache is not allocated at once;
|
||||
instead, accessing a new page in database will allocate a memory buffer
|
||||
for it, until value specified by *cachesize* is reached. Then, these
|
||||
buffers will be managed using LRU (least recently used) policy. More
|
||||
buffers may still be allocated if needed (e.g., if a database contains
|
||||
big keys and/or values). Allocated cache buffers aren't reclaimed.
|
||||
* *minkeypage* - Minimum number of keys to store per page. Default value
|
||||
of 0 equivalent to 2.
|
||||
|
||||
Returns a BTree object, which implements a dictionary protocol (set
|
||||
of methods), and some additional methods described below.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: btree.close()
|
||||
|
||||
Close the database. It's mandatory to close the database at the end of
|
||||
processing, as some unwritten data may be still in the cache. Note that
|
||||
this does not close underlying stream with which the database was opened,
|
||||
it should be closed separately (which is also mandatory to make sure that
|
||||
data flushed from buffer to the underlying storage).
|
||||
|
||||
.. method:: btree.flush()
|
||||
|
||||
Flush any data in cache to the underlying stream.
|
||||
|
||||
.. method:: btree.__getitem__(key)
|
||||
btree.get(key, default=None)
|
||||
btree.__setitem__(key, val)
|
||||
btree.__detitem__(key)
|
||||
btree.__contains__(key)
|
||||
|
||||
Standard dictionary methods.
|
||||
|
||||
.. method:: btree.__iter__()
|
||||
|
||||
A BTree object can be iterated over directly (similar to a dictionary)
|
||||
to get access to all keys in order.
|
||||
|
||||
.. method:: btree.keys([start_key, [end_key, [flags]]])
|
||||
btree.values([start_key, [end_key, [flags]]])
|
||||
btree.items([start_key, [end_key, [flags]]])
|
||||
|
||||
These methods are similar to standard dictionary methods, but also can
|
||||
take optional parameters to iterate over a key sub-range, instead of
|
||||
the entire database. Note that for all 3 methods, *start_key* and
|
||||
*end_key* arguments represent key values. For example, `values()`
|
||||
method will iterate over values corresponding to they key range
|
||||
given. None values for *start_key* means "from the first key", no
|
||||
*end_key* or its value of None means "until the end of database".
|
||||
By default, range is inclusive of *start_key* and exclusive of
|
||||
*end_key*, you can include *end_key* in iteration by passing *flags*
|
||||
of `btree.INCL`. You can iterate in descending key direction
|
||||
by passing *flags* of `btree.DESC`. The flags values can be ORed
|
||||
together.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: INCL
|
||||
|
||||
A flag for `keys()`, `values()`, `items()` methods to specify that
|
||||
scanning should be inclusive of the end key.
|
||||
|
||||
.. data:: DESC
|
||||
|
||||
A flag for `keys()`, `values()`, `items()` methods to specify that
|
||||
scanning should be in descending direction of keys.
|
@ -1,24 +1,14 @@
|
||||
:mod:`builtins` -- builtin functions and exceptions
|
||||
===================================================
|
||||
|
||||
.. module:: builtins
|
||||
:synopsis: builtin Python functions
|
||||
Builtin functions and exceptions
|
||||
================================
|
||||
|
||||
All builtin functions and exceptions are described here. They are also
|
||||
available via the ``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.
|
||||
available via ``builtins`` module.
|
||||
|
||||
Functions and types
|
||||
-------------------
|
||||
|
||||
Not all of these functions and types are turned on in all CircuitPython ports, for space reasons.
|
||||
|
||||
.. function:: abs()
|
||||
|
||||
.. function:: all()
|
||||
@ -33,7 +23,7 @@ Functions and types
|
||||
|
||||
.. class:: bytes()
|
||||
|
||||
|see_cpython| `python:bytes`.
|
||||
|see_cpython| `bytes`.
|
||||
|
||||
.. function:: callable()
|
||||
|
||||
@ -68,7 +58,7 @@ Functions and types
|
||||
|
||||
.. class:: frozenset()
|
||||
|
||||
`frozenset()` is not enabled on the smallest CircuitPython boards for space reasons.
|
||||
`frozenset()` is not enabled on non-Express CircuitPython boards.
|
||||
|
||||
.. function:: getattr()
|
||||
|
||||
@ -88,12 +78,12 @@ Functions and types
|
||||
|
||||
.. classmethod:: from_bytes(bytes, byteorder)
|
||||
|
||||
In CircuitPython, the ``byteorder`` parameter must be positional (this is
|
||||
In CircuitPython, ``byteorder`` parameter must be positional (this is
|
||||
compatible with CPython).
|
||||
|
||||
.. method:: to_bytes(size, byteorder)
|
||||
|
||||
In CircuitPython, the ``byteorder`` parameter must be positional (this is
|
||||
In CircuitPython, ``byteorder`` parameter must be positional (this is
|
||||
compatible with CPython).
|
||||
|
||||
.. function:: isinstance()
|
||||
@ -138,7 +128,7 @@ Functions and types
|
||||
|
||||
.. function:: reversed()
|
||||
|
||||
`reversed()` is not enabled on the smallest CircuitPython boards for space reasons.
|
||||
`reversed()` is not enabled on non-Express CircuitPython boards.
|
||||
|
||||
.. function:: round()
|
||||
|
||||
@ -170,34 +160,20 @@ Functions and types
|
||||
Exceptions
|
||||
----------
|
||||
|
||||
.. exception:: ArithmeticError
|
||||
|
||||
.. exception:: AssertionError
|
||||
|
||||
.. exception:: AttributeError
|
||||
|
||||
.. exception:: BaseException
|
||||
|
||||
.. exception:: BrokenPipeError
|
||||
|
||||
.. exception:: ConnectionError
|
||||
|
||||
.. exception:: EOFError
|
||||
|
||||
.. exception:: Exception
|
||||
|
||||
.. exception:: ImportError
|
||||
|
||||
.. exception:: IndentationError
|
||||
|
||||
.. exception:: IndexError
|
||||
|
||||
.. exception:: KeyboardInterrupt
|
||||
|
||||
.. exception:: KeyError
|
||||
|
||||
.. exception:: LookupError
|
||||
|
||||
.. exception:: MemoryError
|
||||
|
||||
.. exception:: NameError
|
||||
@ -206,7 +182,9 @@ Exceptions
|
||||
|
||||
.. exception:: OSError
|
||||
|
||||
.. exception:: OverflowError
|
||||
|see_cpython| :py:class:`cpython:OSError`. CircuitPython doesn't implement the ``errno``
|
||||
attribute, instead use the standard way to access exception arguments:
|
||||
``exc.args[0]``.
|
||||
|
||||
.. exception:: RuntimeError
|
||||
|
||||
@ -214,33 +192,18 @@ Exceptions
|
||||
|
||||
`ReloadException` is used internally to deal with soft restarts.
|
||||
|
||||
Not a part of the CPython standard library
|
||||
|
||||
.. exception:: StopAsyncIteration
|
||||
|
||||
.. exception:: StopIteration
|
||||
|
||||
.. exception:: SyntaxError
|
||||
|
||||
.. exception:: SystemExit
|
||||
|
||||
|see_cpython| `python:SystemExit`.
|
||||
|
||||
.. exception:: TimeoutError
|
||||
|see_cpython| :py:class:`cpython:SystemExit`.
|
||||
|
||||
.. exception:: TypeError
|
||||
|
||||
|see_cpython| `python:TypeError`.
|
||||
|
||||
.. exception:: UnicodeError
|
||||
|see_cpython| :py:class:`cpython:TypeError`.
|
||||
|
||||
.. exception:: ValueError
|
||||
|
||||
.. exception:: ZeroDivisionError
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: Ellipsis
|
||||
|
||||
.. data:: NotImplemented
|
||||
|
@ -1,12 +1,12 @@
|
||||
:mod:`collections` -- collection and container types
|
||||
====================================================
|
||||
=====================================================
|
||||
|
||||
**Limitations:** Not implemented on the smallest CircuitPython boards for space reasons.
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: collections
|
||||
:synopsis: collection and container types
|
||||
|
||||
|see_cpython_module| :mod:`python:collections`.
|
||||
|see_cpython_module| :mod:`cpython:collections`.
|
||||
|
||||
This module implements advanced collection and container types to
|
||||
hold/accumulate various objects.
|
||||
@ -14,33 +14,6 @@ hold/accumulate various objects.
|
||||
Classes
|
||||
-------
|
||||
|
||||
.. class:: deque(iterable, maxlen[, flags])
|
||||
|
||||
Deques (double-ended queues) are a list-like container that support O(1)
|
||||
appends and pops from either side of the deque. New deques are created
|
||||
using the following arguments:
|
||||
|
||||
- *iterable* must be the empty tuple, and the new deque is created empty.
|
||||
|
||||
- *maxlen* must be specified and the deque will be bounded to this
|
||||
maximum length. Once the deque is full, any new items added will
|
||||
discard items from the opposite end.
|
||||
|
||||
- The optional *flags* can be 1 to check for overflow when adding items.
|
||||
|
||||
As well as supporting ``bool`` and ``len``, deque objects have the following
|
||||
methods:
|
||||
|
||||
.. method:: deque.append(x)
|
||||
|
||||
Add *x* to the right side of the deque.
|
||||
Raises IndexError if overflow checking is enabled and there is no more room left.
|
||||
|
||||
.. method:: deque.popleft()
|
||||
|
||||
Remove and return an item from the left side of the deque.
|
||||
Raises IndexError if no items are present.
|
||||
|
||||
.. function:: namedtuple(name, fields)
|
||||
|
||||
This is factory function to create a new namedtuple type with a specific
|
||||
@ -59,7 +32,7 @@ Classes
|
||||
print(t1.name)
|
||||
assert t2.name == t2[1]
|
||||
|
||||
.. class:: OrderedDict(...)
|
||||
.. function:: OrderedDict(...)
|
||||
|
||||
``dict`` type subclass which remembers and preserves the order of keys
|
||||
added. When ordered dict is iterated over, keys/items are returned in
|
||||
|
@ -1,325 +0,0 @@
|
||||
:mod:`uctypes` -- access binary data in a structured way
|
||||
========================================================
|
||||
|
||||
.. module:: uctypes
|
||||
:synopsis: access binary data in a structured way
|
||||
|
||||
This module implements "foreign data interface" for MicroPython. The idea
|
||||
behind it is similar to CPython's ``ctypes`` modules, but the actual API is
|
||||
different, streamlined and optimized for small size. The basic idea of the
|
||||
module is to define data structure layout with about the same power as the
|
||||
C language allows, and then access it using familiar dot-syntax to reference
|
||||
sub-fields.
|
||||
|
||||
.. warning::
|
||||
|
||||
``uctypes`` module allows access to arbitrary memory addresses of the
|
||||
machine (including I/O and control registers). Uncareful usage of it
|
||||
may lead to crashes, data loss, and even hardware malfunction.
|
||||
|
||||
.. seealso::
|
||||
|
||||
Module :mod:`struct`
|
||||
Standard Python way to access binary data structures (doesn't scale
|
||||
well to large and complex structures).
|
||||
|
||||
Usage examples::
|
||||
|
||||
import uctypes
|
||||
|
||||
# Example 1: Subset of ELF file header
|
||||
# https://wikipedia.org/wiki/Executable_and_Linkable_Format#File_header
|
||||
ELF_HEADER = {
|
||||
"EI_MAG": (0x0 | uctypes.ARRAY, 4 | uctypes.UINT8),
|
||||
"EI_DATA": 0x5 | uctypes.UINT8,
|
||||
"e_machine": 0x12 | uctypes.UINT16,
|
||||
}
|
||||
|
||||
# "f" is an ELF file opened in binary mode
|
||||
buf = f.read(uctypes.sizeof(ELF_HEADER, uctypes.LITTLE_ENDIAN))
|
||||
header = uctypes.struct(uctypes.addressof(buf), ELF_HEADER, uctypes.LITTLE_ENDIAN)
|
||||
assert header.EI_MAG == b"\x7fELF"
|
||||
assert header.EI_DATA == 1, "Oops, wrong endianness. Could retry with uctypes.BIG_ENDIAN."
|
||||
print("machine:", hex(header.e_machine))
|
||||
|
||||
|
||||
# Example 2: In-memory data structure, with pointers
|
||||
COORD = {
|
||||
"x": 0 | uctypes.FLOAT32,
|
||||
"y": 4 | uctypes.FLOAT32,
|
||||
}
|
||||
|
||||
STRUCT1 = {
|
||||
"data1": 0 | uctypes.UINT8,
|
||||
"data2": 4 | uctypes.UINT32,
|
||||
"ptr": (8 | uctypes.PTR, COORD),
|
||||
}
|
||||
|
||||
# Suppose you have address of a structure of type STRUCT1 in "addr"
|
||||
# uctypes.NATIVE is optional (used by default)
|
||||
struct1 = uctypes.struct(addr, STRUCT1, uctypes.NATIVE)
|
||||
print("x:", struct1.ptr[0].x)
|
||||
|
||||
|
||||
# Example 3: Access to CPU registers. Subset of STM32F4xx WWDG block
|
||||
WWDG_LAYOUT = {
|
||||
"WWDG_CR": (0, {
|
||||
# BFUINT32 here means size of the WWDG_CR register
|
||||
"WDGA": 7 << uctypes.BF_POS | 1 << uctypes.BF_LEN | uctypes.BFUINT32,
|
||||
"T": 0 << uctypes.BF_POS | 7 << uctypes.BF_LEN | uctypes.BFUINT32,
|
||||
}),
|
||||
"WWDG_CFR": (4, {
|
||||
"EWI": 9 << uctypes.BF_POS | 1 << uctypes.BF_LEN | uctypes.BFUINT32,
|
||||
"WDGTB": 7 << uctypes.BF_POS | 2 << uctypes.BF_LEN | uctypes.BFUINT32,
|
||||
"W": 0 << uctypes.BF_POS | 7 << uctypes.BF_LEN | uctypes.BFUINT32,
|
||||
}),
|
||||
}
|
||||
|
||||
WWDG = uctypes.struct(0x40002c00, WWDG_LAYOUT)
|
||||
|
||||
WWDG.WWDG_CFR.WDGTB = 0b10
|
||||
WWDG.WWDG_CR.WDGA = 1
|
||||
print("Current counter:", WWDG.WWDG_CR.T)
|
||||
|
||||
Defining structure layout
|
||||
-------------------------
|
||||
|
||||
Structure layout is defined by a "descriptor" - a Python dictionary which
|
||||
encodes field names as keys and other properties required to access them as
|
||||
associated values::
|
||||
|
||||
{
|
||||
"field1": <properties>,
|
||||
"field2": <properties>,
|
||||
...
|
||||
}
|
||||
|
||||
Currently, ``uctypes`` requires explicit specification of offsets for each
|
||||
field. Offset are given in bytes from the structure start.
|
||||
|
||||
Following are encoding examples for various field types:
|
||||
|
||||
* Scalar types::
|
||||
|
||||
"field_name": offset | uctypes.UINT32
|
||||
|
||||
in other words, the value is a scalar type identifier ORed with a field offset
|
||||
(in bytes) from the start of the structure.
|
||||
|
||||
* Recursive structures::
|
||||
|
||||
"sub": (offset, {
|
||||
"b0": 0 | uctypes.UINT8,
|
||||
"b1": 1 | uctypes.UINT8,
|
||||
})
|
||||
|
||||
i.e. value is a 2-tuple, first element of which is an offset, and second is
|
||||
a structure descriptor dictionary (note: offsets in recursive descriptors
|
||||
are relative to the structure it defines). Of course, recursive structures
|
||||
can be specified not just by a literal dictionary, but by referring to a
|
||||
structure descriptor dictionary (defined earlier) by name.
|
||||
|
||||
* Arrays of primitive types::
|
||||
|
||||
"arr": (offset | uctypes.ARRAY, size | uctypes.UINT8),
|
||||
|
||||
i.e. value is a 2-tuple, first element of which is ARRAY flag ORed
|
||||
with offset, and second is scalar element type ORed number of elements
|
||||
in the array.
|
||||
|
||||
* Arrays of aggregate types::
|
||||
|
||||
"arr2": (offset | uctypes.ARRAY, size, {"b": 0 | uctypes.UINT8}),
|
||||
|
||||
i.e. value is a 3-tuple, first element of which is ARRAY flag ORed
|
||||
with offset, second is a number of elements in the array, and third is
|
||||
a descriptor of element type.
|
||||
|
||||
* Pointer to a primitive type::
|
||||
|
||||
"ptr": (offset | uctypes.PTR, uctypes.UINT8),
|
||||
|
||||
i.e. value is a 2-tuple, first element of which is PTR flag ORed
|
||||
with offset, and second is a scalar element type.
|
||||
|
||||
* Pointer to an aggregate type::
|
||||
|
||||
"ptr2": (offset | uctypes.PTR, {"b": 0 | uctypes.UINT8}),
|
||||
|
||||
i.e. value is a 2-tuple, first element of which is PTR flag ORed
|
||||
with offset, second is a descriptor of type pointed to.
|
||||
|
||||
* Bitfields::
|
||||
|
||||
"bitf0": offset | uctypes.BFUINT16 | lsbit << uctypes.BF_POS | bitsize << uctypes.BF_LEN,
|
||||
|
||||
i.e. value is a type of scalar value containing given bitfield (typenames are
|
||||
similar to scalar types, but prefixes with ``BF``), ORed with offset for
|
||||
scalar value containing the bitfield, and further ORed with values for
|
||||
bit position and bit length of the bitfield within the scalar value, shifted by
|
||||
BF_POS and BF_LEN bits, respectively. A bitfield position is counted
|
||||
from the least significant bit of the scalar (having position of 0), and
|
||||
is the number of right-most bit of a field (in other words, it's a number
|
||||
of bits a scalar needs to be shifted right to extract the bitfield).
|
||||
|
||||
In the example above, first a UINT16 value will be extracted at offset 0
|
||||
(this detail may be important when accessing hardware registers, where
|
||||
particular access size and alignment are required), and then bitfield
|
||||
whose rightmost bit is *lsbit* bit of this UINT16, and length
|
||||
is *bitsize* bits, will be extracted. For example, if *lsbit* is 0 and
|
||||
*bitsize* is 8, then effectively it will access least-significant byte
|
||||
of UINT16.
|
||||
|
||||
Note that bitfield operations are independent of target byte endianness,
|
||||
in particular, example above will access least-significant byte of UINT16
|
||||
in both little- and big-endian structures. But it depends on the least
|
||||
significant bit being numbered 0. Some targets may use different
|
||||
numbering in their native ABI, but ``uctypes`` always uses the normalized
|
||||
numbering described above.
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. class:: struct(addr, descriptor, layout_type=NATIVE, /)
|
||||
|
||||
Instantiate a "foreign data structure" object based on structure address in
|
||||
memory, descriptor (encoded as a dictionary), and layout type (see below).
|
||||
|
||||
.. data:: LITTLE_ENDIAN
|
||||
|
||||
Layout type for a little-endian packed structure. (Packed means that every
|
||||
field occupies exactly as many bytes as defined in the descriptor, i.e.
|
||||
the alignment is 1).
|
||||
|
||||
.. data:: BIG_ENDIAN
|
||||
|
||||
Layout type for a big-endian packed structure.
|
||||
|
||||
.. data:: NATIVE
|
||||
|
||||
Layout type for a native structure - with data endianness and alignment
|
||||
conforming to the ABI of the system on which MicroPython runs.
|
||||
|
||||
.. function:: sizeof(struct, layout_type=NATIVE, /)
|
||||
|
||||
Return size of data structure in bytes. The *struct* argument can be
|
||||
either a structure class or a specific instantiated structure object
|
||||
(or its aggregate field).
|
||||
|
||||
.. function:: addressof(obj)
|
||||
|
||||
Return address of an object. Argument should be bytes, bytearray or
|
||||
other object supporting buffer protocol (and address of this buffer
|
||||
is what actually returned).
|
||||
|
||||
.. function:: bytes_at(addr, size)
|
||||
|
||||
Capture memory at the given address and size as bytes object. As bytes
|
||||
object is immutable, memory is actually duplicated and copied into
|
||||
bytes object, so if memory contents change later, created object
|
||||
retains original value.
|
||||
|
||||
.. function:: bytearray_at(addr, size)
|
||||
|
||||
Capture memory at the given address and size as bytearray object.
|
||||
Unlike bytes_at() function above, memory is captured by reference,
|
||||
so it can be both written too, and you will access current value
|
||||
at the given memory address.
|
||||
|
||||
.. data:: UINT8
|
||||
INT8
|
||||
UINT16
|
||||
INT16
|
||||
UINT32
|
||||
INT32
|
||||
UINT64
|
||||
INT64
|
||||
|
||||
Integer types for structure descriptors. Constants for 8, 16, 32,
|
||||
and 64 bit types are provided, both signed and unsigned.
|
||||
|
||||
.. data:: FLOAT32
|
||||
FLOAT64
|
||||
|
||||
Floating-point types for structure descriptors.
|
||||
|
||||
.. data:: VOID
|
||||
|
||||
``VOID`` is an alias for ``UINT8``, and is provided to conveniently define
|
||||
C's void pointers: ``(uctypes.PTR, uctypes.VOID)``.
|
||||
|
||||
.. data:: PTR
|
||||
ARRAY
|
||||
|
||||
Type constants for pointers and arrays. Note that there is no explicit
|
||||
constant for structures, it's implicit: an aggregate type without ``PTR``
|
||||
or ``ARRAY`` flags is a structure.
|
||||
|
||||
Structure descriptors and instantiating structure objects
|
||||
---------------------------------------------------------
|
||||
|
||||
Given a structure descriptor dictionary and its layout type, you can
|
||||
instantiate a specific structure instance at a given memory address
|
||||
using :class:`uctypes.struct()` constructor. Memory address usually comes from
|
||||
following sources:
|
||||
|
||||
* Predefined address, when accessing hardware registers on a baremetal
|
||||
system. Lookup these addresses in datasheet for a particular MCU/SoC.
|
||||
* As a return value from a call to some FFI (Foreign Function Interface)
|
||||
function.
|
||||
* From `uctypes.addressof()`, when you want to pass arguments to an FFI
|
||||
function, or alternatively, to access some data for I/O (for example,
|
||||
data read from a file or network socket).
|
||||
|
||||
Structure objects
|
||||
-----------------
|
||||
|
||||
Structure objects allow accessing individual fields using standard dot
|
||||
notation: ``my_struct.substruct1.field1``. If a field is of scalar type,
|
||||
getting it will produce a primitive value (Python integer or float)
|
||||
corresponding to the value contained in a field. A scalar field can also
|
||||
be assigned to.
|
||||
|
||||
If a field is an array, its individual elements can be accessed with
|
||||
the standard subscript operator ``[]`` - both read and assigned to.
|
||||
|
||||
If a field is a pointer, it can be dereferenced using ``[0]`` syntax
|
||||
(corresponding to C ``*`` operator, though ``[0]`` works in C too).
|
||||
Subscripting a pointer with other integer values but 0 are also supported,
|
||||
with the same semantics as in C.
|
||||
|
||||
Summing up, accessing structure fields generally follows the C syntax,
|
||||
except for pointer dereference, when you need to use ``[0]`` operator
|
||||
instead of ``*``.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
1. Accessing non-scalar fields leads to allocation of intermediate objects
|
||||
to represent them. This means that special care should be taken to
|
||||
layout a structure which needs to be accessed when memory allocation
|
||||
is disabled (e.g. from an interrupt). The recommendations are:
|
||||
|
||||
* Avoid accessing nested structures. For example, instead of
|
||||
``mcu_registers.peripheral_a.register1``, define separate layout
|
||||
descriptors for each peripheral, to be accessed as
|
||||
``peripheral_a.register1``. Or just cache a particular peripheral:
|
||||
``peripheral_a = mcu_registers.peripheral_a``. If a register
|
||||
consists of multiple bitfields, you would need to cache references
|
||||
to a particular register: ``reg_a = mcu_registers.peripheral_a.reg_a``.
|
||||
* Avoid other non-scalar data, like arrays. For example, instead of
|
||||
``peripheral_a.register[0]`` use ``peripheral_a.register0``. Again,
|
||||
an alternative is to cache intermediate values, e.g.
|
||||
``register0 = peripheral_a.register[0]``.
|
||||
|
||||
2. Range of offsets supported by the ``uctypes`` module is limited.
|
||||
The exact range supported is considered an implementation detail,
|
||||
and the general suggestion is to split structure definitions to
|
||||
cover from a few kilobytes to a few dozen of kilobytes maximum.
|
||||
In most cases, this is a natural situation anyway, e.g. it doesn't make
|
||||
sense to define all registers of an MCU (spread over 32-bit address
|
||||
space) in one structure, but rather a peripheral block by peripheral
|
||||
block. In some extreme cases, you may need to split a structure in
|
||||
several parts artificially (e.g. if accessing native data structure
|
||||
with multi-megabyte array in the middle, though that would be a very
|
||||
synthetic case).
|
@ -4,10 +4,9 @@
|
||||
.. module:: errno
|
||||
:synopsis: system error codes
|
||||
|
||||
|see_cpython_module| :mod:`python:errno`.
|
||||
|see_cpython_module| :mod:`cpython:errno`.
|
||||
|
||||
This module provides access to symbolic error codes for `OSError` exception.
|
||||
The codes available may vary per CircuitPython build.
|
||||
|
||||
Constants
|
||||
---------
|
||||
@ -15,13 +14,13 @@ Constants
|
||||
.. data:: EEXIST, EAGAIN, etc.
|
||||
|
||||
Error codes, based on ANSI C/POSIX standard. All error codes start with
|
||||
"E". Errors are usually accessible as ``exc.errno``
|
||||
"E". Errors are usually accessible as ``exc.args[0]``
|
||||
where ``exc`` is an instance of `OSError`. Usage example::
|
||||
|
||||
try:
|
||||
os.mkdir("my_dir")
|
||||
except OSError as exc:
|
||||
if exc.errno == errno.EEXIST:
|
||||
if exc.args[0] == errno.EEXIST:
|
||||
print("Directory already exists")
|
||||
|
||||
.. data:: errorcode
|
||||
@ -29,5 +28,5 @@ Constants
|
||||
Dictionary mapping numeric error codes to strings with symbolic error
|
||||
code (see above)::
|
||||
|
||||
>>> print(errno.errorcode[errno.EEXIST])
|
||||
>>> print(errno.errorcode[uerrno.EEXIST])
|
||||
EEXIST
|
||||
|
163
docs/library/framebuf.rst
Normal file
163
docs/library/framebuf.rst
Normal file
@ -0,0 +1,163 @@
|
||||
:mod:`framebuf` --- Frame buffer manipulation
|
||||
=============================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: framebuf
|
||||
:synopsis: Frame buffer manipulation
|
||||
|
||||
This module provides a general frame buffer which can be used to create
|
||||
bitmap images, which can then be sent to a display.
|
||||
|
||||
class FrameBuffer
|
||||
-----------------
|
||||
|
||||
The FrameBuffer class provides a pixel buffer which can be drawn upon with
|
||||
pixels, lines, rectangles, text and even other FrameBuffer's. It is useful
|
||||
when generating output for displays.
|
||||
|
||||
For example::
|
||||
|
||||
import framebuf
|
||||
|
||||
# FrameBuffer needs 2 bytes for every RGB565 pixel
|
||||
fbuf = FrameBuffer(bytearray(10 * 100 * 2), 10, 100, framebuf.RGB565)
|
||||
|
||||
fbuf.fill(0)
|
||||
fbuf.text('MicroPython!', 0, 0, 0xffff)
|
||||
fbuf.hline(0, 10, 96, 0xffff)
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: FrameBuffer(buffer, width, height, format, stride=width)
|
||||
|
||||
Construct a FrameBuffer object. The parameters are:
|
||||
|
||||
- *buffer* is an object with a buffer protocol which must be large
|
||||
enough to contain every pixel defined by the width, height and
|
||||
format of the FrameBuffer.
|
||||
- *width* is the width of the FrameBuffer in pixels
|
||||
- *height* is the height of the FrameBuffer in pixels
|
||||
- *format* specifies the type of pixel used in the FrameBuffer;
|
||||
permissible values are listed under Constants below. These set the
|
||||
number of bits used to encode a color value and the layout of these
|
||||
bits in *buffer*.
|
||||
Where a color value c is passed to a method, c is a small integer
|
||||
with an encoding that is dependent on the format of the FrameBuffer.
|
||||
- *stride* is the number of pixels between each horizontal line
|
||||
of pixels in the FrameBuffer. This defaults to *width* but may
|
||||
need adjustments when implementing a FrameBuffer within another
|
||||
larger FrameBuffer or screen. The *buffer* size must accommodate
|
||||
an increased step size.
|
||||
|
||||
One must specify valid *buffer*, *width*, *height*, *format* and
|
||||
optionally *stride*. Invalid *buffer* size or dimensions may lead to
|
||||
unexpected errors.
|
||||
|
||||
Drawing primitive shapes
|
||||
------------------------
|
||||
|
||||
The following methods draw shapes onto the FrameBuffer.
|
||||
|
||||
.. method:: FrameBuffer.fill(c)
|
||||
|
||||
Fill the entire FrameBuffer with the specified color.
|
||||
|
||||
.. method:: FrameBuffer.pixel(x, y[, c])
|
||||
|
||||
If *c* is not given, get the color value of the specified pixel.
|
||||
If *c* is given, set the specified pixel to the given color.
|
||||
|
||||
.. method:: FrameBuffer.hline(x, y, w, c)
|
||||
.. method:: FrameBuffer.vline(x, y, h, c)
|
||||
.. method:: FrameBuffer.line(x1, y1, x2, y2, c)
|
||||
|
||||
Draw a line from a set of coordinates using the given color and
|
||||
a thickness of 1 pixel. The `line` method draws the line up to
|
||||
a second set of coordinates whereas the `hline` and `vline`
|
||||
methods draw horizontal and vertical lines respectively up to
|
||||
a given length.
|
||||
|
||||
.. method:: FrameBuffer.rect(x, y, w, h, c)
|
||||
.. method:: FrameBuffer.fill_rect(x, y, w, h, c)
|
||||
|
||||
Draw a rectangle at the given location, size and color. The `rect`
|
||||
method draws only a 1 pixel outline whereas the `fill_rect` method
|
||||
draws both the outline and interior.
|
||||
|
||||
Drawing text
|
||||
------------
|
||||
|
||||
.. method:: FrameBuffer.text(s, x, y[, c])
|
||||
|
||||
Write text to the FrameBuffer using the the coordinates as the upper-left
|
||||
corner of the text. The color of the text can be defined by the optional
|
||||
argument but is otherwise a default value of 1. All characters have
|
||||
dimensions of 8x8 pixels and there is currently no way to change the font.
|
||||
|
||||
|
||||
Other methods
|
||||
-------------
|
||||
|
||||
.. method:: FrameBuffer.scroll(xstep, ystep)
|
||||
|
||||
Shift the contents of the FrameBuffer by the given vector. This may
|
||||
leave a footprint of the previous colors in the FrameBuffer.
|
||||
|
||||
.. method:: FrameBuffer.blit(fbuf, x, y[, key])
|
||||
|
||||
Draw another FrameBuffer on top of the current one at the given coordinates.
|
||||
If *key* is specified then it should be a color integer and the
|
||||
corresponding color will be considered transparent: all pixels with that
|
||||
color value will not be drawn.
|
||||
|
||||
This method works between FrameBuffer instances utilising different formats,
|
||||
but the resulting colors may be unexpected due to the mismatch in color
|
||||
formats.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: framebuf.MONO_VLSB
|
||||
|
||||
Monochrome (1-bit) color format
|
||||
This defines a mapping where the bits in a byte are vertically mapped with
|
||||
bit 0 being nearest the top of the screen. Consequently each byte occupies
|
||||
8 vertical pixels. Subsequent bytes appear at successive horizontal
|
||||
locations until the rightmost edge is reached. Further bytes are rendered
|
||||
at locations starting at the leftmost edge, 8 pixels lower.
|
||||
|
||||
.. data:: framebuf.MONO_HLSB
|
||||
|
||||
Monochrome (1-bit) color format
|
||||
This defines a mapping where the bits in a byte are horizontally mapped.
|
||||
Each byte occupies 8 horizontal pixels with bit 0 being the leftmost.
|
||||
Subsequent bytes appear at successive horizontal locations until the
|
||||
rightmost edge is reached. Further bytes are rendered on the next row, one
|
||||
pixel lower.
|
||||
|
||||
.. data:: framebuf.MONO_HMSB
|
||||
|
||||
Monochrome (1-bit) color format
|
||||
This defines a mapping where the bits in a byte are horizontally mapped.
|
||||
Each byte occupies 8 horizontal pixels with bit 7 being the leftmost.
|
||||
Subsequent bytes appear at successive horizontal locations until the
|
||||
rightmost edge is reached. Further bytes are rendered on the next row, one
|
||||
pixel lower.
|
||||
|
||||
.. data:: framebuf.RGB565
|
||||
|
||||
Red Green Blue (16-bit, 5+6+5) color format
|
||||
|
||||
.. data:: framebuf.GS2_HMSB
|
||||
|
||||
Grayscale (2-bit) color format
|
||||
|
||||
.. data:: framebuf.GS4_HMSB
|
||||
|
||||
Grayscale (4-bit) color format
|
||||
|
||||
.. data:: framebuf.GS8
|
||||
|
||||
Grayscale (8-bit) color format
|
@ -1,10 +1,12 @@
|
||||
:mod:`gc` -- control the garbage collector
|
||||
==========================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: gc
|
||||
:synopsis: control the garbage collector
|
||||
|
||||
|see_cpython_module| :mod:`python:gc`.
|
||||
|see_cpython_module| :mod:`cpython:gc`.
|
||||
|
||||
Functions
|
||||
---------
|
||||
@ -24,7 +26,7 @@ Functions
|
||||
|
||||
.. function:: mem_alloc()
|
||||
|
||||
Return the number of bytes of heap RAM that are allocated by Python code.
|
||||
Return the number of bytes of heap RAM that are allocated.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
@ -33,8 +35,8 @@ Functions
|
||||
|
||||
.. function:: mem_free()
|
||||
|
||||
Return the number of bytes of heap RAM that is available for Python
|
||||
code to allocate, or -1 if this amount is not known.
|
||||
Return the number of bytes of available heap RAM, or -1 if this amount
|
||||
is not known.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
@ -61,6 +63,6 @@ Functions
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
This function is a MicroPython extension. CPython has a similar
|
||||
This function is a a MicroPython extension. CPython has a similar
|
||||
function - ``set_threshold()``, but due to different GC
|
||||
implementations, its signature and semantics are different.
|
||||
|
59
docs/library/hashlib.rst
Normal file
59
docs/library/hashlib.rst
Normal file
@ -0,0 +1,59 @@
|
||||
:mod:`hashlib` -- hashing algorithms
|
||||
=====================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: hashlib
|
||||
:synopsis: hashing algorithms
|
||||
|
||||
|see_cpython_module| :mod:`cpython:hashlib`.
|
||||
|
||||
This module implements binary data hashing algorithms. The exact inventory
|
||||
of available algorithms depends on a board. Among the algorithms which may
|
||||
be implemented:
|
||||
|
||||
* SHA256 - The current generation, modern hashing algorithm (of SHA2 series).
|
||||
It is suitable for cryptographically-secure purposes. Included in the
|
||||
MicroPython core and any board is recommended to provide this, unless
|
||||
it has particular code size constraints.
|
||||
|
||||
* SHA1 - A previous generation algorithm. Not recommended for new usages,
|
||||
but SHA1 is a part of number of Internet standards and existing
|
||||
applications, so boards targeting network connectivity and
|
||||
interoperability will try to provide this.
|
||||
|
||||
* MD5 - A legacy algorithm, not considered cryptographically secure. Only
|
||||
selected boards, targeting interoperability with legacy applications,
|
||||
will offer this.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: hashlib.sha256([data])
|
||||
|
||||
Create an SHA256 hasher object and optionally feed ``data`` into it.
|
||||
|
||||
.. class:: hashlib.sha1([data])
|
||||
|
||||
Create an SHA1 hasher object and optionally feed ``data`` into it.
|
||||
|
||||
.. class:: hashlib.md5([data])
|
||||
|
||||
Create an MD5 hasher object and optionally feed ``data`` into it.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: hash.update(data)
|
||||
|
||||
Feed more binary data into hash.
|
||||
|
||||
.. method:: hash.digest()
|
||||
|
||||
Return hash for all data passed through hash, as a bytes object. After this
|
||||
method is called, more data cannot be fed into the hash any longer.
|
||||
|
||||
.. method:: hash.hexdigest()
|
||||
|
||||
This method is NOT implemented. Use ``binascii.hexlify(hash.digest())``
|
||||
to achieve a similar effect.
|
@ -1,33 +0,0 @@
|
||||
:mod:`heapq` -- heap queue algorithm
|
||||
====================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: heapq
|
||||
:synopsis: heap queue algorithm
|
||||
|
||||
|see_cpython_module| :mod:`python:heapq`.
|
||||
|
||||
This module implements the
|
||||
`min heap queue algorithm <https://en.wikipedia.org/wiki/Heap_%28data_structure%29>`_.
|
||||
|
||||
A heap queue is essentially a list that has its elements stored in such a way
|
||||
that the first item of the list is always the smallest.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: heappush(heap, item)
|
||||
|
||||
Push the ``item`` onto the ``heap``.
|
||||
|
||||
.. function:: heappop(heap)
|
||||
|
||||
Pop the first item from the ``heap``, and return it. Raise ``IndexError`` if
|
||||
``heap`` is empty.
|
||||
|
||||
The returned item will be the smallest item in the ``heap``.
|
||||
|
||||
.. function:: heapify(x)
|
||||
|
||||
Convert the list ``x`` into a heap. This is an in-place operation.
|
@ -1,47 +1,53 @@
|
||||
.. _micropython_lib:
|
||||
|
||||
Standard Libraries
|
||||
==================
|
||||
MicroPython libraries
|
||||
=====================
|
||||
|
||||
Python standard libraries
|
||||
-------------------------
|
||||
Python standard libraries and micro-libraries
|
||||
---------------------------------------------
|
||||
|
||||
The libraries below implement a subset of the corresponding
|
||||
standard Python (CPython) library. They are implemented in C, not Python.
|
||||
The libraries below are inherited from MicroPython.
|
||||
They are similar to the standard Python libraries with the same name.
|
||||
They implement a subset of or a variant of the corresponding
|
||||
standard Python library.
|
||||
|
||||
CircuitPython's long-term goal is that code written in CircuitPython
|
||||
using Python standard libraries will be runnable on CPython without changes.
|
||||
|
||||
These libraries are not enabled on CircuitPython builds with
|
||||
limited flash memory:
|
||||
limited flash memory, usually on non-Express builds:
|
||||
``binascii``, ``errno``, ``json``, ``re``.
|
||||
|
||||
These libraries are not currently enabled in any CircuitPython build, but may be in the future:
|
||||
``ctypes``, ``platform``
|
||||
These libraries are not currently enabled in any CircuitPython build, but may be in the future,
|
||||
with the ``u`` prefix dropped:
|
||||
``uctypes``, ``uhashlib``, ``uzlib``.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
builtins.rst
|
||||
heapq.rst
|
||||
uheapq.rst
|
||||
array.rst
|
||||
binascii.rst
|
||||
collections.rst
|
||||
errno.rst
|
||||
gc.rst
|
||||
hashlib.rst
|
||||
io.rst
|
||||
json.rst
|
||||
platform.rst
|
||||
re.rst
|
||||
sys.rst
|
||||
ctypes.rst
|
||||
select.rst
|
||||
uctypes.rst
|
||||
uselect.rst
|
||||
usocket.rst
|
||||
ussl.rst
|
||||
uzlib.rst
|
||||
|
||||
Omitted ``string`` functions
|
||||
----------------------------
|
||||
Omitted functions in the ``string`` library
|
||||
-------------------------------------------
|
||||
|
||||
A few string operations are not enabled on small builds
|
||||
due to limited flash memory:
|
||||
(usually non-Express), due to limited flash memory:
|
||||
``string.center()``, ``string.partition()``, ``string.splitlines()``,
|
||||
``string.reversed()``.
|
||||
|
||||
@ -49,10 +55,13 @@ due to limited flash memory:
|
||||
CircuitPython/MicroPython-specific libraries
|
||||
--------------------------------------------
|
||||
|
||||
Functionality specific to the CircuitPython/MicroPython implementations is available in
|
||||
the following libraries.
|
||||
Functionality specific to the CircuitPython/MicroPython implementation is available in
|
||||
the following libraries. These libraries may change significantly or be removed in future
|
||||
versions of CircuitPython.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
btree.rst
|
||||
framebuf.rst
|
||||
micropython.rst
|
||||
|
@ -1,10 +1,10 @@
|
||||
:mod:`io` -- input/output streams
|
||||
=================================
|
||||
==================================
|
||||
|
||||
.. module:: io
|
||||
:synopsis: input/output streams
|
||||
|
||||
|see_cpython_module| :mod:`python:io`.
|
||||
|see_cpython_module| :mod:`cpython:io`.
|
||||
|
||||
This module contains additional types of ``stream`` (file-like) objects
|
||||
and helper functions.
|
||||
@ -112,20 +112,3 @@ Classes
|
||||
.. method:: getvalue()
|
||||
|
||||
Get the current contents of the underlying buffer which holds data.
|
||||
|
||||
.. class:: StringIO(alloc_size)
|
||||
:noindex:
|
||||
.. class:: BytesIO(alloc_size)
|
||||
:noindex:
|
||||
|
||||
Create an empty `StringIO`/`BytesIO` object, preallocated to hold up
|
||||
to *alloc_size* number of bytes. That means that writing that amount
|
||||
of bytes won't lead to reallocation of the buffer, and thus won't hit
|
||||
out-of-memory situation or lead to memory fragmentation. These constructors
|
||||
are a MicroPython extension and are recommended for usage only in special
|
||||
cases and in system-level libraries, not for end-user applications.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
These constructors are a MicroPython extension.
|
||||
|
@ -1,10 +1,10 @@
|
||||
:mod:`json` -- JSON encoding and decoding
|
||||
=========================================
|
||||
==========================================
|
||||
|
||||
.. module:: json
|
||||
:synopsis: JSON encoding and decoding
|
||||
|
||||
|see_cpython_module| :mod:`python:json`.
|
||||
|see_cpython_module| :mod:`cpython:json`.
|
||||
|
||||
This modules allows to convert between Python objects and the JSON
|
||||
data format.
|
||||
@ -12,20 +12,14 @@ data format.
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: dump(obj, stream, separators=None)
|
||||
.. function:: dump(obj, stream)
|
||||
|
||||
Serialise ``obj`` to a JSON string, writing it to the given *stream*.
|
||||
|
||||
If specified, separators should be an ``(item_separator, key_separator)``
|
||||
tuple. The default is ``(', ', ': ')``. To get the most compact JSON
|
||||
representation, you should specify ``(',', ':')`` to eliminate whitespace.
|
||||
|
||||
.. function:: dumps(obj, separators=None)
|
||||
.. function:: dumps(obj)
|
||||
|
||||
Return ``obj`` represented as a JSON string.
|
||||
|
||||
The arguments have the same meaning as in `dump`.
|
||||
|
||||
.. function:: load(stream)
|
||||
|
||||
Parse the given ``stream``, interpreting it as a JSON string and
|
||||
|
@ -1,5 +1,7 @@
|
||||
:mod:`micropython` -- MicroPython extensions and internals
|
||||
==========================================================
|
||||
:mod:`micropython` -- access and control MicroPython internals
|
||||
==============================================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: micropython
|
||||
:synopsis: access and control MicroPython internals
|
||||
@ -9,7 +11,7 @@ Functions
|
||||
|
||||
.. function:: const(expr)
|
||||
|
||||
Used to declare that the expression is a constant so that the compiler can
|
||||
Used to declare that the expression is a constant so that the compile can
|
||||
optimise it. The use of this function should be as follows::
|
||||
|
||||
from micropython import const
|
||||
@ -26,3 +28,66 @@ Functions
|
||||
provided as part of the :mod:`micropython` module mainly so that scripts can be
|
||||
written which run under both CPython and MicroPython, by following the above
|
||||
pattern.
|
||||
|
||||
.. function:: opt_level([level])
|
||||
|
||||
If *level* is given then this function sets the optimisation level for subsequent
|
||||
compilation of scripts, and returns ``None``. Otherwise it returns the current
|
||||
optimisation level.
|
||||
|
||||
The optimisation level controls the following compilation features:
|
||||
|
||||
- Assertions: at level 0 assertion statements are enabled and compiled into the
|
||||
bytecode; at levels 1 and higher assertions are not compiled.
|
||||
- Built-in ``__debug__`` variable: at level 0 this variable expands to ``True``;
|
||||
at levels 1 and higher it expands to ``False``.
|
||||
- Source-code line numbers: at levels 0, 1 and 2 source-code line number are
|
||||
stored along with the bytecode so that exceptions can report the line number
|
||||
they occurred at; at levels 3 and higher line numbers are not stored.
|
||||
|
||||
The default optimisation level is usually level 0.
|
||||
|
||||
.. function:: mem_info([verbose])
|
||||
|
||||
Print information about currently used memory. If the *verbose* argument
|
||||
is given then extra information is printed.
|
||||
|
||||
The information that is printed is implementation dependent, but currently
|
||||
includes the amount of stack and heap used. In verbose mode it prints out
|
||||
the entire heap indicating which blocks are used and which are free.
|
||||
|
||||
.. function:: qstr_info([verbose])
|
||||
|
||||
Print information about currently interned strings. If the *verbose*
|
||||
argument is given then extra information is printed.
|
||||
|
||||
The information that is printed is implementation dependent, but currently
|
||||
includes the number of interned strings and the amount of RAM they use. In
|
||||
verbose mode it prints out the names of all RAM-interned strings.
|
||||
|
||||
.. function:: stack_use()
|
||||
|
||||
Return an integer representing the current amount of stack that is being
|
||||
used. The absolute value of this is not particularly useful, rather it
|
||||
should be used to compute differences in stack usage at different points.
|
||||
|
||||
.. function:: heap_lock()
|
||||
.. function:: heap_unlock()
|
||||
|
||||
Lock or unlock the heap. When locked no memory allocation can occur and a
|
||||
`MemoryError` will be raised if any heap allocation is attempted.
|
||||
|
||||
These functions can be nested, ie `heap_lock()` can be called multiple times
|
||||
in a row and the lock-depth will increase, and then `heap_unlock()` must be
|
||||
called the same number of times to make the heap available again.
|
||||
|
||||
.. function:: kbd_intr(chr)
|
||||
|
||||
Set the character that will raise a `KeyboardInterrupt` exception. By
|
||||
default this is set to 3 during script execution, corresponding to Ctrl-C.
|
||||
Passing -1 to this function will disable capture of Ctrl-C, and passing 3
|
||||
will restore it.
|
||||
|
||||
This function can be used to prevent the capturing of Ctrl-C on the
|
||||
incoming stream of characters that is usually used for the REPL, in case
|
||||
that stream is used for other purposes.
|
||||
|
@ -1,38 +0,0 @@
|
||||
:mod:`platform` -- access to underlying platform’s identifying data
|
||||
===================================================================
|
||||
|
||||
.. module:: platform
|
||||
:synopsis: access to underlying platform’s identifying data
|
||||
|
||||
|see_cpython_module| :mod:`python:platform`.
|
||||
|
||||
This module tries to retrieve as much platform-identifying data as possible. It
|
||||
makes this information available via function APIs.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: platform()
|
||||
|
||||
Returns a string identifying the underlying platform. This string is composed
|
||||
of several substrings in the following order, delimited by dashes (``-``):
|
||||
|
||||
- the name of the platform system (e.g. Unix, Windows or MicroPython)
|
||||
- the MicroPython version
|
||||
- the architecture of the platform
|
||||
- the version of the underlying platform
|
||||
- the concatenation of the name of the libc that MicroPython is linked to
|
||||
and its corresponding version.
|
||||
|
||||
For example, this could be
|
||||
``"MicroPython-1.20.0-xtensa-IDFv4.2.4-with-newlib3.0.0"``.
|
||||
|
||||
.. function:: python_compiler()
|
||||
|
||||
Returns a string identifying the compiler used for compiling MicroPython.
|
||||
|
||||
.. function:: libc_ver()
|
||||
|
||||
Returns a tuple of strings *(lib, version)*, where *lib* is the name of the
|
||||
libc that MicroPython is linked to, and *version* the corresponding version
|
||||
of this libc.
|
@ -1,110 +1,50 @@
|
||||
:mod:`re` -- simple regular expressions
|
||||
=======================================
|
||||
========================================
|
||||
|
||||
.. module:: re
|
||||
:synopsis: regular expressions
|
||||
|
||||
|see_cpython_module| :mod:`python:re`.
|
||||
|see_cpython_module| :mod:`cpython:re`.
|
||||
|
||||
This module implements regular expression operations. Regular expression
|
||||
syntax supported is a subset of CPython ``re`` module (and actually is
|
||||
a subset of POSIX extended regular expressions).
|
||||
|
||||
Supported operators and special sequences are:
|
||||
Supported operators are:
|
||||
|
||||
``.``
|
||||
``'.'``
|
||||
Match any character.
|
||||
|
||||
``[...]``
|
||||
``'[...]'``
|
||||
Match set of characters. Individual characters and ranges are supported,
|
||||
including negated sets (e.g. ``[^a-c]``).
|
||||
|
||||
``^``
|
||||
Match the start of the string.
|
||||
``'^'``
|
||||
|
||||
``$``
|
||||
Match the end of the string.
|
||||
``'$'``
|
||||
|
||||
``?``
|
||||
Match zero or one of the previous sub-pattern.
|
||||
``'?'``
|
||||
|
||||
``*``
|
||||
Match zero or more of the previous sub-pattern.
|
||||
``'*'``
|
||||
|
||||
``+``
|
||||
Match one or more of the previous sub-pattern.
|
||||
``'+'``
|
||||
|
||||
``??``
|
||||
Non-greedy version of ``?``, match zero or one, with the preference
|
||||
for zero.
|
||||
``'??'``
|
||||
|
||||
``*?``
|
||||
Non-greedy version of ``*``, match zero or more, with the preference
|
||||
for the shortest match.
|
||||
``'*?'``
|
||||
|
||||
``+?``
|
||||
Non-greedy version of ``+``, match one or more, with the preference
|
||||
for the shortest match.
|
||||
``'+?'``
|
||||
|
||||
``|``
|
||||
Match either the left-hand side or the right-hand side sub-patterns of
|
||||
this operator.
|
||||
``'|'``
|
||||
|
||||
``(...)``
|
||||
``'(...)'``
|
||||
Grouping. Each group is capturing (a substring it captures can be accessed
|
||||
with `match.group()` method).
|
||||
|
||||
``\d``
|
||||
Matches digit. Equivalent to ``[0-9]``.
|
||||
**NOT SUPPORTED**: Counted repetitions (``{m,n}``), more advanced assertions
|
||||
(``\b``, ``\B``), named groups (``(?P<name>...)``), non-capturing groups
|
||||
(``(?:...)``), etc.
|
||||
|
||||
``\D``
|
||||
Matches non-digit. Equivalent to ``[^0-9]``.
|
||||
|
||||
``\s``
|
||||
Matches whitespace. Equivalent to ``[ \t-\r]``.
|
||||
|
||||
``\S``
|
||||
Matches non-whitespace. Equivalent to ``[^ \t-\r]``.
|
||||
|
||||
``\w``
|
||||
Matches "word characters" (ASCII only). Equivalent to ``[A-Za-z0-9_]``.
|
||||
|
||||
``\W``
|
||||
Matches non "word characters" (ASCII only). Equivalent to ``[^A-Za-z0-9_]``.
|
||||
|
||||
``\``
|
||||
Escape character. Any other character following the backslash, except
|
||||
for those listed above, is taken literally. For example, ``\*`` is
|
||||
equivalent to literal ``*`` (not treated as the ``*`` operator).
|
||||
Note that ``\r``, ``\n``, etc. are not handled specially, and will be
|
||||
equivalent to literal letters ``r``, ``n``, etc. Due to this, it's
|
||||
not recommended to use raw Python strings (``r""``) for regular
|
||||
expressions. For example, ``r"\r\n"`` when used as the regular
|
||||
expression is equivalent to ``"rn"``. To match CR character followed
|
||||
by LF, use ``"\r\n"``.
|
||||
|
||||
**NOT SUPPORTED**:
|
||||
|
||||
* counted repetitions (``{m,n}``)
|
||||
* named groups (``(?P<name>...)``)
|
||||
* non-capturing groups (``(?:...)``)
|
||||
* more advanced assertions (``\b``, ``\B``)
|
||||
* special character escapes like ``\r``, ``\n`` - use Python's own escaping
|
||||
instead
|
||||
* etc.
|
||||
|
||||
Example::
|
||||
|
||||
import re
|
||||
|
||||
# As re doesn't support escapes itself, use of r"" strings is not
|
||||
# recommended.
|
||||
regex = re.compile("[\r\n]")
|
||||
|
||||
regex.split("line1\rline2\nline3\r\n")
|
||||
|
||||
# Result:
|
||||
# ['line1', 'line2', 'line3', '', '']
|
||||
|
||||
Functions
|
||||
---------
|
||||
@ -124,26 +64,9 @@ Functions
|
||||
string for first position which matches regex (which still may be
|
||||
0 if regex is anchored).
|
||||
|
||||
.. function:: sub(regex_str, replace, string, count=0, flags=0, /)
|
||||
|
||||
Compile *regex_str* and search for it in *string*, replacing all matches
|
||||
with *replace*, and returning the new string.
|
||||
|
||||
*replace* can be a string or a function. If it is a string then escape
|
||||
sequences of the form ``\<number>`` and ``\g<number>`` can be used to
|
||||
expand to the corresponding group (or an empty string for unmatched groups).
|
||||
If *replace* is a function then it must take a single argument (the match)
|
||||
and should return a replacement string.
|
||||
|
||||
If *count* is specified and non-zero then substitution will stop after
|
||||
this many substitutions are made. The *flags* argument is ignored.
|
||||
|
||||
Note: availability of this function depends on :term:`MicroPython port`.
|
||||
|
||||
.. data:: DEBUG
|
||||
|
||||
Flag value, display debug information about compiled expression.
|
||||
(Availability depends on :term:`MicroPython port`.)
|
||||
|
||||
|
||||
.. _regex:
|
||||
@ -156,14 +79,12 @@ Compiled regular expression. Instances of this class are created using
|
||||
|
||||
.. method:: regex.match(string)
|
||||
regex.search(string)
|
||||
regex.sub(replace, string, count=0, flags=0, /)
|
||||
|
||||
Similar to the module-level functions :meth:`match`, :meth:`search`
|
||||
and :meth:`sub`.
|
||||
Similar to the module-level functions :meth:`match` and :meth:`search`.
|
||||
Using methods is (much) more efficient if the same regex is applied to
|
||||
multiple strings.
|
||||
|
||||
.. method:: regex.split(string, max_split=-1, /)
|
||||
.. method:: regex.split(string, max_split=-1)
|
||||
|
||||
Split a *string* using regex. If *max_split* is given, it specifies
|
||||
maximum number of splits to perform. Returns list of strings (there
|
||||
@ -172,31 +93,9 @@ Compiled regular expression. Instances of this class are created using
|
||||
Match objects
|
||||
-------------
|
||||
|
||||
Match objects as returned by `match()` and `search()` methods, and passed
|
||||
to the replacement function in `sub()`.
|
||||
Match objects as returned by `match()` and `search()` methods.
|
||||
|
||||
.. method:: match.group(index)
|
||||
.. method:: match.group([index])
|
||||
|
||||
Return matching (sub)string. *index* is 0 for entire match,
|
||||
1 and above for each capturing group. Only numeric groups are supported.
|
||||
|
||||
.. method:: match.groups()
|
||||
|
||||
Return a tuple containing all the substrings of the groups of the match.
|
||||
|
||||
Note: availability of this method depends on :term:`MicroPython port`.
|
||||
|
||||
.. method:: match.start([index])
|
||||
match.end([index])
|
||||
|
||||
Return the index in the original string of the start or end of the
|
||||
substring group that was matched. *index* defaults to the entire
|
||||
group, otherwise it will select a group.
|
||||
|
||||
Note: availability of these methods depends on :term:`MicroPython port`.
|
||||
|
||||
.. method:: match.span([index])
|
||||
|
||||
Returns the 2-tuple ``(match.start(index), match.end(index))``.
|
||||
|
||||
Note: availability of this method depends on :term:`MicroPython port`.
|
||||
|
@ -1,99 +0,0 @@
|
||||
:mod:`select` -- wait for events on a set of streams
|
||||
====================================================
|
||||
|
||||
.. module:: select
|
||||
:synopsis: wait for events on a set of streams
|
||||
|
||||
|see_cpython_module| :mod:`cpython:select`.
|
||||
|
||||
This module provides functions to efficiently wait for events on multiple
|
||||
``stream`` objects (select streams which are ready for operations).
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: poll()
|
||||
|
||||
Create an instance of the Poll class.
|
||||
|
||||
.. function:: select(rlist, wlist, xlist[, timeout])
|
||||
|
||||
Wait for activity on a set of objects.
|
||||
|
||||
This function is provided by some MicroPython ports for compatibility
|
||||
and is not efficient. Usage of :class:`Poll` is recommended instead.
|
||||
|
||||
.. _class: Poll
|
||||
|
||||
class ``Poll``
|
||||
--------------
|
||||
|
||||
Methods
|
||||
~~~~~~~
|
||||
|
||||
.. method:: poll.register(obj[, eventmask])
|
||||
|
||||
Register ``stream`` *obj* for polling. *eventmask* is logical OR of:
|
||||
|
||||
* ``select.POLLIN`` - data available for reading
|
||||
* ``select.POLLOUT`` - more data can be written
|
||||
|
||||
Note that flags like ``select.POLLHUP`` and ``select.POLLERR`` are
|
||||
*not* valid as input eventmask (these are unsolicited events which
|
||||
will be returned from `poll()` regardless of whether they are asked
|
||||
for). This semantics is per POSIX.
|
||||
|
||||
*eventmask* defaults to ``select.POLLIN | select.POLLOUT``.
|
||||
|
||||
It is OK to call this function multiple times for the same *obj*.
|
||||
Successive calls will update *obj*'s eventmask to the value of
|
||||
*eventmask* (i.e. will behave as `modify()`).
|
||||
|
||||
.. method:: poll.unregister(obj)
|
||||
|
||||
Unregister *obj* from polling.
|
||||
|
||||
.. method:: poll.modify(obj, eventmask)
|
||||
|
||||
Modify the *eventmask* for *obj*. If *obj* is not registered, `OSError`
|
||||
is raised with error of ENOENT.
|
||||
|
||||
.. method:: poll.poll(timeout=-1, /)
|
||||
|
||||
Wait for at least one of the registered objects to become ready or have an
|
||||
exceptional condition, with optional timeout in milliseconds (if *timeout*
|
||||
arg is not specified or -1, there is no timeout).
|
||||
|
||||
Returns list of (``obj``, ``event``, ...) tuples. There may be other elements in
|
||||
tuple, depending on a platform and version, so don't assume that its size is 2.
|
||||
The ``event`` element specifies which events happened with a stream and
|
||||
is a combination of ``select.POLL*`` constants described above. Note that
|
||||
flags ``select.POLLHUP`` and ``select.POLLERR`` can be returned at any time
|
||||
(even if were not asked for), and must be acted on accordingly (the
|
||||
corresponding stream unregistered from poll and likely closed), because
|
||||
otherwise all further invocations of `poll()` may return immediately with
|
||||
these flags set for this stream again.
|
||||
|
||||
In case of timeout, an empty list is returned.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
Tuples returned may contain more than 2 elements as described above.
|
||||
|
||||
.. method:: poll.ipoll(timeout=-1, flags=0, /)
|
||||
|
||||
Like :meth:`poll.poll`, but instead returns an iterator which yields a
|
||||
"callee-owned tuple". This function provides an efficient, allocation-free
|
||||
way to poll on streams.
|
||||
|
||||
If *flags* is 1, one-shot behaviour for events is employed: streams for
|
||||
which events happened will have their event masks automatically reset
|
||||
(equivalent to ``poll.modify(obj, 0)``), so new events for such a stream
|
||||
won't be processed until new mask is set with `poll.modify()`. This
|
||||
behaviour is useful for asynchronous I/O schedulers.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
This function is a MicroPython extension.
|
@ -1,20 +1,36 @@
|
||||
:mod:`sys` -- system specific functions
|
||||
=======================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: sys
|
||||
:synopsis: system specific functions
|
||||
|
||||
|see_cpython_module| :mod:`python:sys`.
|
||||
|see_cpython_module| :mod:`cpython:sys`.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: exit(retval=0, /)
|
||||
.. function:: exit(retval=0)
|
||||
|
||||
Terminate current program with a given exit code. Underlyingly, this
|
||||
function raise as `SystemExit` exception. If an argument is given, its
|
||||
value given as an argument to `SystemExit`.
|
||||
|
||||
.. function:: print_exception(exc, file=sys.stdout)
|
||||
|
||||
Print exception with a traceback to a file-like object *file* (or
|
||||
`sys.stdout` by default).
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
This is simplified version of a function which appears in the
|
||||
``traceback`` module in CPython. Unlike ``traceback.print_exception()``,
|
||||
this function takes just exception value instead of exception type,
|
||||
exception value, and traceback object; *file* argument should be
|
||||
positional; further arguments are not supported.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
@ -33,8 +49,6 @@ Constants
|
||||
|
||||
* *name* - string "circuitpython"
|
||||
* *version* - tuple (major, minor, micro), e.g. (1, 7, 0)
|
||||
* *_machine* - string describing the underlying machine
|
||||
* *_mpy* - supported mpy file-format version (optional attribute)
|
||||
|
||||
This object is the recommended way to distinguish CircuitPython from other
|
||||
Python implementations (note that it still may not exist in the very
|
||||
@ -80,14 +94,6 @@ Constants
|
||||
|
||||
A mutable list of directories to search for imported modules.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
On MicroPython, an entry with the value ``".frozen"`` will indicate that import
|
||||
should search :term:`frozen modules <frozen module>` at that point in the search.
|
||||
If no frozen module is found then search will *not* look for a directory called
|
||||
``.frozen``, instead it will continue with the next entry in ``sys.path``.
|
||||
|
||||
.. data:: platform
|
||||
|
||||
The platform that CircuitPython is running on. For OS/RTOS ports, this is
|
||||
@ -97,12 +103,6 @@ Constants
|
||||
If you need to check whether your program runs on CircuitPython (vs other
|
||||
Python implementation), use `sys.implementation` instead.
|
||||
|
||||
.. data:: ps1
|
||||
ps2
|
||||
|
||||
Mutable attributes holding strings, which are used for the REPL prompt. The defaults
|
||||
give the standard Python prompt of ``>>>`` and ``...``.
|
||||
|
||||
.. data:: stderr
|
||||
|
||||
Standard error ``stream``.
|
||||
@ -115,14 +115,6 @@ Constants
|
||||
|
||||
Standard output ``stream``.
|
||||
|
||||
.. data:: tracebacklimit
|
||||
|
||||
A mutable attribute holding an integer value which is the maximum number of traceback
|
||||
entries to store in an exception. Set to 0 to disable adding tracebacks. Defaults
|
||||
to 1000.
|
||||
|
||||
Note: this is not available on all ports.
|
||||
|
||||
.. data:: version
|
||||
|
||||
Python language version that this implementation conforms to, as a string.
|
||||
@ -130,9 +122,3 @@ Constants
|
||||
.. data:: version_info
|
||||
|
||||
Python language version that this implementation conforms to, as a tuple of ints.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
Only the first three version numbers (major, minor, micro) are supported and
|
||||
they can be referenced only by index, not by name.
|
||||
|
212
docs/library/uctypes.rst
Normal file
212
docs/library/uctypes.rst
Normal file
@ -0,0 +1,212 @@
|
||||
:mod:`uctypes` -- access binary data in a structured way
|
||||
========================================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: uctypes
|
||||
:synopsis: access binary data in a structured way
|
||||
|
||||
This module implements "foreign data interface" for MicroPython. The idea
|
||||
behind it is similar to CPython's ``ctypes`` modules, but the actual API is
|
||||
different, streamlined and optimized for small size. The basic idea of the
|
||||
module is to define data structure layout with about the same power as the
|
||||
C language allows, and then access it using familiar dot-syntax to reference
|
||||
sub-fields.
|
||||
|
||||
.. seealso::
|
||||
|
||||
Module :mod:`struct`
|
||||
Standard Python way to access binary data structures (doesn't scale
|
||||
well to large and complex structures).
|
||||
|
||||
Defining structure layout
|
||||
-------------------------
|
||||
|
||||
Structure layout is defined by a "descriptor" - a Python dictionary which
|
||||
encodes field names as keys and other properties required to access them as
|
||||
associated values. Currently, uctypes requires explicit specification of
|
||||
offsets for each field. Offset are given in bytes from a structure start.
|
||||
|
||||
Following are encoding examples for various field types:
|
||||
|
||||
* Scalar types::
|
||||
|
||||
"field_name": offset | uctypes.UINT32
|
||||
|
||||
in other words, value is scalar type identifier ORed with field offset
|
||||
(in bytes) from the start of the structure.
|
||||
|
||||
* Recursive structures::
|
||||
|
||||
"sub": (offset, {
|
||||
"b0": 0 | uctypes.UINT8,
|
||||
"b1": 1 | uctypes.UINT8,
|
||||
})
|
||||
|
||||
i.e. value is a 2-tuple, first element of which is offset, and second is
|
||||
a structure descriptor dictionary (note: offsets in recursive descriptors
|
||||
are relative to the structure it defines).
|
||||
|
||||
* Arrays of primitive types::
|
||||
|
||||
"arr": (offset | uctypes.ARRAY, size | uctypes.UINT8),
|
||||
|
||||
i.e. value is a 2-tuple, first element of which is ARRAY flag ORed
|
||||
with offset, and second is scalar element type ORed number of elements
|
||||
in array.
|
||||
|
||||
* Arrays of aggregate types::
|
||||
|
||||
"arr2": (offset | uctypes.ARRAY, size, {"b": 0 | uctypes.UINT8}),
|
||||
|
||||
i.e. value is a 3-tuple, first element of which is ARRAY flag ORed
|
||||
with offset, second is a number of elements in array, and third is
|
||||
descriptor of element type.
|
||||
|
||||
* Pointer to a primitive type::
|
||||
|
||||
"ptr": (offset | uctypes.PTR, uctypes.UINT8),
|
||||
|
||||
i.e. value is a 2-tuple, first element of which is PTR flag ORed
|
||||
with offset, and second is scalar element type.
|
||||
|
||||
* Pointer to an aggregate type::
|
||||
|
||||
"ptr2": (offset | uctypes.PTR, {"b": 0 | uctypes.UINT8}),
|
||||
|
||||
i.e. value is a 2-tuple, first element of which is PTR flag ORed
|
||||
with offset, second is descriptor of type pointed to.
|
||||
|
||||
* Bitfields::
|
||||
|
||||
"bitf0": offset | uctypes.BFUINT16 | lsbit << uctypes.BF_POS | bitsize << uctypes.BF_LEN,
|
||||
|
||||
i.e. value is type of scalar value containing given bitfield (typenames are
|
||||
similar to scalar types, but prefixes with "BF"), ORed with offset for
|
||||
scalar value containing the bitfield, and further ORed with values for
|
||||
bit offset and bit length of the bitfield within scalar value, shifted by
|
||||
BF_POS and BF_LEN positions, respectively. Bitfield position is counted
|
||||
from the least significant bit, and is the number of right-most bit of a
|
||||
field (in other words, it's a number of bits a scalar needs to be shifted
|
||||
right to extract the bitfield).
|
||||
|
||||
In the example above, first a UINT16 value will be extracted at offset 0
|
||||
(this detail may be important when accessing hardware registers, where
|
||||
particular access size and alignment are required), and then bitfield
|
||||
whose rightmost bit is *lsbit* bit of this UINT16, and length
|
||||
is *bitsize* bits, will be extracted. For example, if *lsbit* is 0 and
|
||||
*bitsize* is 8, then effectively it will access least-significant byte
|
||||
of UINT16.
|
||||
|
||||
Note that bitfield operations are independent of target byte endianness,
|
||||
in particular, example above will access least-significant byte of UINT16
|
||||
in both little- and big-endian structures. But it depends on the least
|
||||
significant bit being numbered 0. Some targets may use different
|
||||
numbering in their native ABI, but ``uctypes`` always uses the normalized
|
||||
numbering described above.
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. class:: struct(addr, descriptor, layout_type=NATIVE)
|
||||
|
||||
Instantiate a "foreign data structure" object based on structure address in
|
||||
memory, descriptor (encoded as a dictionary), and layout type (see below).
|
||||
|
||||
.. data:: LITTLE_ENDIAN
|
||||
|
||||
Layout type for a little-endian packed structure. (Packed means that every
|
||||
field occupies exactly as many bytes as defined in the descriptor, i.e.
|
||||
the alignment is 1).
|
||||
|
||||
.. data:: BIG_ENDIAN
|
||||
|
||||
Layout type for a big-endian packed structure.
|
||||
|
||||
.. data:: NATIVE
|
||||
|
||||
Layout type for a native structure - with data endianness and alignment
|
||||
conforming to the ABI of the system on which MicroPython runs.
|
||||
|
||||
.. function:: sizeof(struct)
|
||||
|
||||
Return size of data structure in bytes. Argument can be either structure
|
||||
class or specific instantiated structure object (or its aggregate field).
|
||||
|
||||
.. function:: addressof(obj)
|
||||
|
||||
Return address of an object. Argument should be bytes, bytearray or
|
||||
other object supporting buffer protocol (and address of this buffer
|
||||
is what actually returned).
|
||||
|
||||
.. function:: bytes_at(addr, size)
|
||||
|
||||
Capture memory at the given address and size as bytes object. As bytes
|
||||
object is immutable, memory is actually duplicated and copied into
|
||||
bytes object, so if memory contents change later, created object
|
||||
retains original value.
|
||||
|
||||
.. function:: bytearray_at(addr, size)
|
||||
|
||||
Capture memory at the given address and size as bytearray object.
|
||||
Unlike bytes_at() function above, memory is captured by reference,
|
||||
so it can be both written too, and you will access current value
|
||||
at the given memory address.
|
||||
|
||||
Structure descriptors and instantiating structure objects
|
||||
---------------------------------------------------------
|
||||
|
||||
Given a structure descriptor dictionary and its layout type, you can
|
||||
instantiate a specific structure instance at a given memory address
|
||||
using :class:`uctypes.struct()` constructor. Memory address usually comes from
|
||||
following sources:
|
||||
|
||||
* Predefined address, when accessing hardware registers on a baremetal
|
||||
system. Lookup these addresses in datasheet for a particular MCU/SoC.
|
||||
* As a return value from a call to some FFI (Foreign Function Interface)
|
||||
function.
|
||||
* From uctypes.addressof(), when you want to pass arguments to an FFI
|
||||
function, or alternatively, to access some data for I/O (for example,
|
||||
data read from a file or network socket).
|
||||
|
||||
Structure objects
|
||||
-----------------
|
||||
|
||||
Structure objects allow accessing individual fields using standard dot
|
||||
notation: ``my_struct.substruct1.field1``. If a field is of scalar type,
|
||||
getting it will produce a primitive value (Python integer or float)
|
||||
corresponding to the value contained in a field. A scalar field can also
|
||||
be assigned to.
|
||||
|
||||
If a field is an array, its individual elements can be accessed with
|
||||
the standard subscript operator ``[]`` - both read and assigned to.
|
||||
|
||||
If a field is a pointer, it can be dereferenced using ``[0]`` syntax
|
||||
(corresponding to C ``*`` operator, though ``[0]`` works in C too).
|
||||
Subscripting a pointer with other integer values but 0 are supported too,
|
||||
with the same semantics as in C.
|
||||
|
||||
Summing up, accessing structure fields generally follows C syntax,
|
||||
except for pointer dereference, when you need to use ``[0]`` operator
|
||||
instead of ``*``.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
Accessing non-scalar fields leads to allocation of intermediate objects
|
||||
to represent them. This means that special care should be taken to
|
||||
layout a structure which needs to be accessed when memory allocation
|
||||
is disabled (e.g. from an interrupt). The recommendations are:
|
||||
|
||||
* Avoid nested structures. For example, instead of
|
||||
``mcu_registers.peripheral_a.register1``, define separate layout
|
||||
descriptors for each peripheral, to be accessed as
|
||||
``peripheral_a.register1``.
|
||||
* Avoid other non-scalar data, like array. For example, instead of
|
||||
``peripheral_a.register[0]`` use ``peripheral_a.register0``.
|
||||
|
||||
Note that these recommendations will lead to decreased readability
|
||||
and conciseness of layouts, so they should be used only if the need
|
||||
to access structure fields without allocation is anticipated (it's
|
||||
even possible to define 2 parallel layouts - one for normal usage,
|
||||
and a restricted one to use when memory allocation is prohibited).
|
29
docs/library/uheapq.rst
Normal file
29
docs/library/uheapq.rst
Normal file
@ -0,0 +1,29 @@
|
||||
:mod:`uheapq` -- heap queue algorithm
|
||||
=====================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: uheapq
|
||||
:synopsis: heap queue algorithm
|
||||
|
||||
|see_cpython_module| :mod:`cpython:heapq`.
|
||||
|
||||
This module implements the heap queue algorithm.
|
||||
|
||||
A heap queue is simply a list that has its elements stored in a certain way.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: heappush(heap, item)
|
||||
|
||||
Push the ``item`` onto the ``heap``.
|
||||
|
||||
.. function:: heappop(heap)
|
||||
|
||||
Pop the first item from the ``heap``, and return it. Raises IndexError if
|
||||
heap is empty.
|
||||
|
||||
.. function:: heapify(x)
|
||||
|
||||
Convert the list ``x`` into a heap. This is an in-place operation.
|
96
docs/library/uselect.rst
Normal file
96
docs/library/uselect.rst
Normal file
@ -0,0 +1,96 @@
|
||||
:mod:`uselect` -- wait for events on a set of streams
|
||||
========================================================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: uselect
|
||||
:synopsis: wait for events on a set of streams
|
||||
|
||||
|see_cpython_module| :mod:`cpython:select`.
|
||||
|
||||
This module provides functions to efficiently wait for events on multiple
|
||||
``stream`` objects (select streams which are ready for operations).
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: poll()
|
||||
|
||||
Create an instance of the Poll class.
|
||||
|
||||
.. function:: select(rlist, wlist, xlist[, timeout])
|
||||
|
||||
Wait for activity on a set of objects.
|
||||
|
||||
This function is provided by some MicroPython ports for compatibility
|
||||
and is not efficient. Usage of :class:`Poll` is recommended instead.
|
||||
|
||||
.. _class: Poll
|
||||
|
||||
class ``Poll``
|
||||
--------------
|
||||
|
||||
Methods
|
||||
~~~~~~~
|
||||
|
||||
.. method:: poll.register(obj[, eventmask])
|
||||
|
||||
Register ``stream`` *obj* for polling. *eventmask* is logical OR of:
|
||||
|
||||
* ``uselect.POLLIN`` - data available for reading
|
||||
* ``uselect.POLLOUT`` - more data can be written
|
||||
|
||||
Note that flags like ``uselect.POLLHUP`` and ``uselect.POLLERR`` are
|
||||
*not* valid as input eventmask (these are unsolicited events which
|
||||
will be returned from `poll()` regardless of whether they are asked
|
||||
for). This semantics is per POSIX.
|
||||
|
||||
*eventmask* defaults to ``uselect.POLLIN | uselect.POLLOUT``.
|
||||
|
||||
.. method:: poll.unregister(obj)
|
||||
|
||||
Unregister *obj* from polling.
|
||||
|
||||
.. method:: poll.modify(obj, eventmask)
|
||||
|
||||
Modify the *eventmask* for *obj*.
|
||||
|
||||
.. method:: poll.poll(timeout=-1)
|
||||
|
||||
Wait for at least one of the registered objects to become ready or have an
|
||||
exceptional condition, with optional timeout in milliseconds (if *timeout*
|
||||
arg is not specified or -1, there is no timeout).
|
||||
|
||||
Returns list of (``obj``, ``event``, ...) tuples. There may be other elements in
|
||||
tuple, depending on a platform and version, so don't assume that its size is 2.
|
||||
The ``event`` element specifies which events happened with a stream and
|
||||
is a combination of ``uselect.POLL*`` constants described above. Note that
|
||||
flags ``uselect.POLLHUP`` and ``uselect.POLLERR`` can be returned at any time
|
||||
(even if were not asked for), and must be acted on accordingly (the
|
||||
corresponding stream unregistered from poll and likely closed), because
|
||||
otherwise all further invocations of `poll()` may return immediately with
|
||||
these flags set for this stream again.
|
||||
|
||||
In case of timeout, an empty list is returned.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
Tuples returned may contain more than 2 elements as described above.
|
||||
|
||||
.. method:: poll.ipoll(timeout=-1, flags=0)
|
||||
|
||||
Like :meth:`poll.poll`, but instead returns an iterator which yields a
|
||||
``callee-owned tuples``. This function provides efficient, allocation-free
|
||||
way to poll on streams.
|
||||
|
||||
If *flags* is 1, one-shot behavior for events is employed: streams for
|
||||
which events happened will have their event masks automatically reset
|
||||
(equivalent to ``poll.modify(obj, 0)``), so new events for such a stream
|
||||
won't be processed until new mask is set with `poll.modify()`. This
|
||||
behavior is useful for asynchronous I/O schedulers.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
This function is a MicroPython extension.
|
336
docs/library/usocket.rst
Normal file
336
docs/library/usocket.rst
Normal file
@ -0,0 +1,336 @@
|
||||
*******************************
|
||||
:mod:`usocket` -- socket module
|
||||
*******************************
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: usocket
|
||||
:synopsis: socket module
|
||||
|
||||
|see_cpython_module| :mod:`cpython:socket`.
|
||||
|
||||
This module provides access to the BSD socket interface.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
For efficiency and consistency, socket objects in MicroPython implement a ``stream``
|
||||
(file-like) interface directly. In CPython, you need to convert a socket to
|
||||
a file-like object using `makefile()` method. This method is still supported
|
||||
by MicroPython (but is a no-op), so where compatibility with CPython matters,
|
||||
be sure to use it.
|
||||
|
||||
Socket address format(s)
|
||||
------------------------
|
||||
|
||||
The native socket address format of the ``usocket`` module is an opaque data type
|
||||
returned by `getaddrinfo` function, which must be used to resolve textual address
|
||||
(including numeric addresses)::
|
||||
|
||||
sockaddr = usocket.getaddrinfo('www.micropython.org', 80)[0][-1]
|
||||
# You must use getaddrinfo() even for numeric addresses
|
||||
sockaddr = usocket.getaddrinfo('127.0.0.1', 80)[0][-1]
|
||||
# Now you can use that address
|
||||
sock.connect(addr)
|
||||
|
||||
Using `getaddrinfo` is the most efficient (both in terms of memory and processing
|
||||
power) and portable way to work with addresses.
|
||||
|
||||
However, ``socket`` module (note the difference with native MicroPython
|
||||
``usocket`` module described here) provides CPython-compatible way to specify
|
||||
addresses using tuples, as described below.
|
||||
|
||||
Summing up:
|
||||
|
||||
* Always use `getaddrinfo` when writing portable applications.
|
||||
* Tuple addresses described below can be used as a shortcut for
|
||||
quick hacks and interactive use, if your port supports them.
|
||||
|
||||
Tuple address format for ``socket`` module:
|
||||
|
||||
* IPv4: *(ipv4_address, port)*, where *ipv4_address* is a string with
|
||||
dot-notation numeric IPv4 address, e.g. ``"8.8.8.8"``, and *port* is and
|
||||
integer port number in the range 1-65535. Note the domain names are not
|
||||
accepted as *ipv4_address*, they should be resolved first using
|
||||
`usocket.getaddrinfo()`.
|
||||
* IPv6: *(ipv6_address, port, flowinfo, scopeid)*, where *ipv6_address*
|
||||
is a string with colon-notation numeric IPv6 address, e.g. ``"2001:db8::1"``,
|
||||
and *port* is an integer port number in the range 1-65535. *flowinfo*
|
||||
must be 0. *scopeid* is the interface scope identifier for link-local
|
||||
addresses. Note the domain names are not accepted as *ipv6_address*,
|
||||
they should be resolved first using `usocket.getaddrinfo()`.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP)
|
||||
|
||||
Create a new socket using the given address family, socket type and
|
||||
protocol number. Note that specifying *proto* in most cases is not
|
||||
required (and not recommended, as some MicroPython ports may omit
|
||||
``IPPROTO_*`` constants). Instead, *type* argument will select needed
|
||||
protocol automatically::
|
||||
|
||||
# Create STREAM TCP socket
|
||||
socket(AF_INET, SOCK_STREAM)
|
||||
# Create DGRAM UDP socket
|
||||
socket(AF_INET, SOCK_DGRAM)
|
||||
|
||||
.. function:: getaddrinfo(host, port)
|
||||
|
||||
Translate the host/port argument into a sequence of 5-tuples that contain all the
|
||||
necessary arguments for creating a socket connected to that service. The list of
|
||||
5-tuples has following structure::
|
||||
|
||||
(family, type, proto, canonname, sockaddr)
|
||||
|
||||
The following example shows how to connect to a given url::
|
||||
|
||||
s = usocket.socket()
|
||||
s.connect(usocket.getaddrinfo('www.micropython.org', 80)[0][-1])
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
CPython raises a ``socket.gaierror`` exception (`OSError` subclass) in case
|
||||
of error in this function. MicroPython doesn't have ``socket.gaierror``
|
||||
and raises OSError directly. Note that error numbers of `getaddrinfo()`
|
||||
form a separate namespace and may not match error numbers from
|
||||
:py:mod:`uerrno` module. To distinguish `getaddrinfo()` errors, they are
|
||||
represented by negative numbers, whereas standard system errors are
|
||||
positive numbers (error numbers are accessible using ``e.args[0]`` property
|
||||
from an exception object). The use of negative values is a provisional
|
||||
detail which may change in the future.
|
||||
|
||||
.. function:: inet_ntop(af, bin_addr)
|
||||
|
||||
Convert a binary network address *bin_addr* of the given address family *af*
|
||||
to a textual representation::
|
||||
|
||||
>>> usocket.inet_ntop(usocket.AF_INET, b"\x7f\0\0\1")
|
||||
'127.0.0.1'
|
||||
|
||||
.. function:: inet_pton(af, txt_addr)
|
||||
|
||||
Convert a textual network address *txt_addr* of the given address family *af*
|
||||
to a binary representation::
|
||||
|
||||
>>> usocket.inet_pton(usocket.AF_INET, "1.2.3.4")
|
||||
b'\x01\x02\x03\x04'
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: AF_INET
|
||||
AF_INET6
|
||||
|
||||
Address family types. Availability depends on a particular ``MicroPython port``.
|
||||
|
||||
.. data:: SOCK_STREAM
|
||||
SOCK_DGRAM
|
||||
|
||||
Socket types.
|
||||
|
||||
.. data:: IPPROTO_UDP
|
||||
IPPROTO_TCP
|
||||
|
||||
IP protocol numbers. Availability depends on a particular ``MicroPython port``.
|
||||
Note that you don't need to specify these in a call to `usocket.socket()`,
|
||||
because `SOCK_STREAM` socket type automatically selects `IPPROTO_TCP`, and
|
||||
`SOCK_DGRAM` - `IPPROTO_UDP`. Thus, the only real use of these constants
|
||||
is as an argument to `usocket.socket.setsockopt()`.
|
||||
|
||||
.. data:: usocket.SOL_*
|
||||
|
||||
Socket option levels (an argument to `usocket.socket.setsockopt()`). The exact
|
||||
inventory depends on a ``MicroPython port``.
|
||||
|
||||
.. data:: usocket.SO_*
|
||||
|
||||
Socket options (an argument to `usocket.socket.setsockopt()`). The exact
|
||||
inventory depends on a ``MicroPython port``.
|
||||
|
||||
Constants specific to WiPy:
|
||||
|
||||
.. data:: IPPROTO_SEC
|
||||
|
||||
Special protocol value to create SSL-compatible socket.
|
||||
|
||||
class socket
|
||||
============
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: socket.close()
|
||||
|
||||
Mark the socket closed and release all resources. Once that happens, all future operations
|
||||
on the socket object will fail. The remote end will receive EOF indication if
|
||||
supported by protocol.
|
||||
|
||||
Sockets are automatically closed when they are garbage-collected, but it is recommended
|
||||
to `close()` them explicitly as soon you finished working with them.
|
||||
|
||||
.. method:: socket.bind(address)
|
||||
|
||||
Bind the socket to *address*. The socket must not already be bound.
|
||||
|
||||
.. method:: socket.listen([backlog])
|
||||
|
||||
Enable a server to accept connections. If *backlog* is specified, it must be at least 0
|
||||
(if it's lower, it will be set to 0); and specifies the number of unaccepted connections
|
||||
that the system will allow before refusing new connections. If not specified, a default
|
||||
reasonable value is chosen.
|
||||
|
||||
.. method:: socket.accept()
|
||||
|
||||
Accept a connection. The socket must be bound to an address and listening for connections.
|
||||
The return value is a pair (conn, address) where conn is a new socket object usable to send
|
||||
and receive data on the connection, and address is the address bound to the socket on the
|
||||
other end of the connection.
|
||||
|
||||
.. method:: socket.connect(address)
|
||||
|
||||
Connect to a remote socket at *address*.
|
||||
|
||||
.. method:: socket.send(bytes)
|
||||
|
||||
Send data to the socket. The socket must be connected to a remote socket.
|
||||
Returns number of bytes sent, which may be smaller than the length of data
|
||||
("short write").
|
||||
|
||||
.. method:: socket.sendall(bytes)
|
||||
|
||||
Send all data to the socket. The socket must be connected to a remote socket.
|
||||
Unlike `send()`, this method will try to send all of data, by sending data
|
||||
chunk by chunk consecutively.
|
||||
|
||||
The behavior of this method on non-blocking sockets is undefined. Due to this,
|
||||
on MicroPython, it's recommended to use `write()` method instead, which
|
||||
has the same "no short writes" policy for blocking sockets, and will return
|
||||
number of bytes sent on non-blocking sockets.
|
||||
|
||||
.. method:: socket.recv(bufsize)
|
||||
|
||||
Receive data from the socket. The return value is a bytes object representing the data
|
||||
received. The maximum amount of data to be received at once is specified by bufsize.
|
||||
|
||||
.. method:: socket.sendto(bytes, address)
|
||||
|
||||
Send data to the socket. The socket should not be connected to a remote socket, since the
|
||||
destination socket is specified by *address*.
|
||||
|
||||
.. method:: socket.recvfrom(bufsize)
|
||||
|
||||
Receive data from the socket. The return value is a pair *(bytes, address)* where *bytes* is a
|
||||
bytes object representing the data received and *address* is the address of the socket sending
|
||||
the data.
|
||||
|
||||
.. method:: socket.setsockopt(level, optname, value)
|
||||
|
||||
Set the value of the given socket option. The needed symbolic constants are defined in the
|
||||
socket module (SO_* etc.). The *value* can be an integer or a bytes-like object representing
|
||||
a buffer.
|
||||
|
||||
.. method:: socket.settimeout(value)
|
||||
|
||||
**Note**: Not every port supports this method, see below.
|
||||
|
||||
Set a timeout on blocking socket operations. The value argument can be a nonnegative floating
|
||||
point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations
|
||||
will raise an `OSError` exception if the timeout period value has elapsed before the operation has
|
||||
completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket
|
||||
is put in blocking mode.
|
||||
|
||||
Not every ``MicroPython port`` supports this method. A more portable and
|
||||
generic solution is to use `uselect.poll` object. This allows to wait on
|
||||
multiple objects at the same time (and not just on sockets, but on generic
|
||||
``stream`` objects which support polling). Example::
|
||||
|
||||
# Instead of:
|
||||
s.settimeout(1.0) # time in seconds
|
||||
s.read(10) # may timeout
|
||||
|
||||
# Use:
|
||||
poller = uselect.poll()
|
||||
poller.register(s, uselect.POLLIN)
|
||||
res = poller.poll(1000) # time in milliseconds
|
||||
if not res:
|
||||
# s is still not ready for input, i.e. operation timed out
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
CPython raises a ``socket.timeout`` exception in case of timeout,
|
||||
which is an `OSError` subclass. MicroPython raises an OSError directly
|
||||
instead. If you use ``except OSError:`` to catch the exception,
|
||||
your code will work both in MicroPython and CPython.
|
||||
|
||||
.. method:: socket.setblocking(flag)
|
||||
|
||||
Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking,
|
||||
else to blocking mode.
|
||||
|
||||
This method is a shorthand for certain `settimeout()` calls:
|
||||
|
||||
* ``sock.setblocking(True)`` is equivalent to ``sock.settimeout(None)``
|
||||
* ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0)``
|
||||
|
||||
.. method:: socket.makefile(mode='rb', buffering=0)
|
||||
|
||||
Return a file object associated with the socket. The exact returned type depends on the arguments
|
||||
given to makefile(). The support is limited to binary modes only ('rb', 'wb', and 'rwb').
|
||||
CPython's arguments: *encoding*, *errors* and *newline* are not supported.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
As MicroPython doesn't support buffered streams, values of *buffering*
|
||||
parameter is ignored and treated as if it was 0 (unbuffered).
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
Closing the file object returned by makefile() WILL close the
|
||||
original socket as well.
|
||||
|
||||
.. method:: socket.read([size])
|
||||
|
||||
Read up to size bytes from the socket. Return a bytes object. If *size* is not given, it
|
||||
reads all data available from the socket until EOF; as such the method will not return until
|
||||
the socket is closed. This function tries to read as much data as
|
||||
requested (no "short reads"). This may be not possible with
|
||||
non-blocking socket though, and then less data will be returned.
|
||||
|
||||
.. method:: socket.readinto(buf[, nbytes])
|
||||
|
||||
Read bytes into the *buf*. If *nbytes* is specified then read at most
|
||||
that many bytes. Otherwise, read at most *len(buf)* bytes. Just as
|
||||
`read()`, this method follows "no short reads" policy.
|
||||
|
||||
Return value: number of bytes read and stored into *buf*.
|
||||
|
||||
.. method:: socket.readline()
|
||||
|
||||
Read a line, ending in a newline character.
|
||||
|
||||
Return value: the line read.
|
||||
|
||||
.. method:: socket.write(buf)
|
||||
|
||||
Write the buffer of bytes to the socket. This function will try to
|
||||
write all data to a socket (no "short writes"). This may be not possible
|
||||
with a non-blocking socket though, and returned value will be less than
|
||||
the length of *buf*.
|
||||
|
||||
Return value: number of bytes written.
|
||||
|
||||
.. exception:: usocket.error
|
||||
|
||||
MicroPython does NOT have this exception.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
CPython used to have a ``socket.error`` exception which is now deprecated,
|
||||
and is an alias of `OSError`. In MicroPython, use `OSError` directly.
|
50
docs/library/ussl.rst
Normal file
50
docs/library/ussl.rst
Normal file
@ -0,0 +1,50 @@
|
||||
:mod:`ussl` -- SSL/TLS module
|
||||
=============================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: ussl
|
||||
:synopsis: TLS/SSL wrapper for socket objects
|
||||
|
||||
|see_cpython_module| :mod:`cpython:ssl`.
|
||||
|
||||
This module provides access to Transport Layer Security (previously and
|
||||
widely known as “Secure Sockets Layer”) encryption and peer authentication
|
||||
facilities for network sockets, both client-side and server-side.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: ussl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None)
|
||||
|
||||
Takes a ``stream`` *sock* (usually usocket.socket instance of ``SOCK_STREAM`` type),
|
||||
and returns an instance of ssl.SSLSocket, which wraps the underlying stream in
|
||||
an SSL context. Returned object has the usual ``stream`` interface methods like
|
||||
``read()``, ``write()``, etc. In MicroPython, the returned object does not expose
|
||||
socket interface and methods like ``recv()``, ``send()``. In particular, a
|
||||
server-side SSL socket should be created from a normal socket returned from
|
||||
:meth:`~usocket.socket.accept()` on a non-SSL listening server socket.
|
||||
|
||||
Depending on the underlying module implementation in a particular
|
||||
``MicroPython port``, some or all keyword arguments above may be not supported.
|
||||
|
||||
.. warning::
|
||||
|
||||
Some implementations of ``ussl`` module do NOT validate server certificates,
|
||||
which makes an SSL connection established prone to man-in-the-middle attacks.
|
||||
|
||||
Exceptions
|
||||
----------
|
||||
|
||||
.. data:: ssl.SSLError
|
||||
|
||||
This exception does NOT exist. Instead its base class, OSError, is used.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: ussl.CERT_NONE
|
||||
ussl.CERT_OPTIONAL
|
||||
ussl.CERT_REQUIRED
|
||||
|
||||
Supported values for *cert_reqs* parameter.
|
40
docs/library/uzlib.rst
Normal file
40
docs/library/uzlib.rst
Normal file
@ -0,0 +1,40 @@
|
||||
:mod:`uzlib` -- zlib decompression
|
||||
==================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: uzlib
|
||||
:synopsis: zlib decompression
|
||||
|
||||
|see_cpython_module| :mod:`cpython:zlib`.
|
||||
|
||||
This module allows to decompress binary data compressed with
|
||||
`DEFLATE algorithm <https://en.wikipedia.org/wiki/DEFLATE>`_
|
||||
(commonly used in zlib library and gzip archiver). Compression
|
||||
is not yet implemented.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: decompress(data, wbits=0, bufsize=0)
|
||||
|
||||
Return decompressed *data* as bytes. *wbits* is DEFLATE dictionary window
|
||||
size used during compression (8-15, the dictionary size is power of 2 of
|
||||
that value). Additionally, if value is positive, *data* is assumed to be
|
||||
zlib stream (with zlib header). Otherwise, if it's negative, it's assumed
|
||||
to be raw DEFLATE stream. *bufsize* parameter is for compatibility with
|
||||
CPython and is ignored.
|
||||
|
||||
.. class:: DecompIO(stream, wbits=0)
|
||||
|
||||
Create a ``stream`` wrapper which allows transparent decompression of
|
||||
compressed data in another *stream*. This allows to process compressed
|
||||
streams with data larger than available heap size. In addition to
|
||||
values described in :func:`decompress`, *wbits* may take values
|
||||
24..31 (16 + 8..15), meaning that input stream has gzip header.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
This class is MicroPython extension. It's included on provisional
|
||||
basis and may be changed considerably or removed in later versions.
|
60
docs/pdf.rst
60
docs/pdf.rst
@ -1,60 +0,0 @@
|
||||
:orphan:
|
||||
|
||||
Adafruit CircuitPython API Reference
|
||||
====================================
|
||||
|
||||
Welcome to the API reference documentation for Adafruit CircuitPython.
|
||||
This contains low-level API reference docs which may link out to separate
|
||||
*"getting started"* guides. `Adafruit <https://adafruit.com>`_ has many
|
||||
excellent tutorials available through the
|
||||
`Adafruit Learning System <https://learn.adafruit.com/>`_.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
../README.rst
|
||||
libraries.rst
|
||||
workflows
|
||||
environment.rst
|
||||
troubleshooting.rst
|
||||
../CONTRIBUTING
|
||||
../BUILDING
|
||||
../WEBUSB_README
|
||||
supported_ports.rst
|
||||
|
||||
Design and porting reference
|
||||
----------------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
design_guide
|
||||
porting
|
||||
common_hal
|
||||
|
||||
API Reference
|
||||
----------------------
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 3
|
||||
|
||||
library/index.rst
|
||||
../shared-bindings/*/index
|
||||
../shared-bindings/help
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
reference/glossary.rst
|
||||
../CODE_OF_CONDUCT
|
||||
../docs/LICENSE
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user