Compare commits

..

64 Commits
main ... 6.3.x

Author SHA1 Message Date
Dan Halbert
e494ca4b51
Merge pull request #4757 from dhalbert/6.3.x-cherry-pick-from-main
6.3.x cherry pick from main
2021-05-25 16:00:13 -04:00
Dan Halbert
25f09479fc Lengthen xosc startup time for RP2040 2021-05-25 14:47:59 -04:00
Dan Halbert
378a727ed0 Merge branch '6.3.x-cherry-pick-from-main' of https://github.com/dhalbert/circuitpython into 6.3.x-cherry-pick-from-main 2021-05-25 09:56:46 -04:00
Dan Halbert
74833ad35f unlock board.I2C() on reset 2021-05-25 09:56:33 -04:00
Dan Halbert
652860ad2d
Merge branch '6.3.x' into 6.3.x-cherry-pick-from-main 2021-05-25 09:55:50 -04:00
Dan Halbert
8f6b5e885c manual update to add Arduino Nano RP2040 from #4802 2021-05-25 09:54:16 -04:00
Dan Halbert
44c398d186 update nvm.toml 2021-05-25 09:49:41 -04:00
Dan Halbert
1d39be4954
Merge pull request #4779 from tannewt/fix_sm_rp2040
Fix safe mode on rp2040
2021-05-19 14:21:08 -04:00
Dan Halbert
6d6089f4c2 bump xtensa cache id 2021-05-18 22:33:29 -04:00
Scott Shawcroft
ef4993a7a6
Fix safe mode on rp2040 2021-05-18 17:37:21 -07:00
Dan Halbert
17955ba5e2 update frozen libs (with HID at 4.3.0, not 5.0.0)
HID 4.3.0 removes gamepad. Don't do that until CircuitPython 7.0.0
2021-05-16 13:50:43 -04:00
Dan Halbert
1ef1301346 fix proxlight trinkey build 2021-05-15 23:40:45 -04:00
Dan Halbert
934534c9ee fix logic for suppressing ja and ko clean builds when not necessary 2021-05-15 16:03:12 -04:00
Dan Halbert
83fcdba9c4 Make busio.SPI be NotImplementedError on proxlight to save space 2021-05-15 16:03:10 -04:00
Dan Halbert
3d49d180d1 add CIRCUITPY_PIXELBUF to all trinkeys; add NeoPixel to prox 2021-05-15 16:01:42 -04:00
Dan Halbert
3201c16d3b Update Rotary Trinkey and Slide Trinkey pins 2021-05-15 15:57:11 -04:00
zapwizard
8b97d8f13a Update pins.c
Both D0 and D1 were assigned to pin_GPIO7, fixed D0 to pin_GPIO6, which also matches the comment.
2021-05-14 15:45:18 -04:00
Dan Halbert
d8b1df380e update ulab to 1.7.8 2021-05-13 17:00:34 -04:00
Dan Halbert
c605b8e068 update xtensa cache key 2021-05-13 16:36:36 -04:00
nm3210
89c412e7f6 Fix pre-commit whitespace error 2021-05-13 16:34:56 -04:00
nm3210
3a2decba00 Update Sparkfun Thing Plus RP2040 pins to match board
This fixes some missing and incorrectly-assigned pins for the SparkFun Thing Plus RP2040 protoboard so that they actually match what the board says. This also changes the default SPI pins from the SD card pins to the breakout pins on the side of the board.
2021-05-13 16:34:56 -04:00
Lucian Copeland
da50901576 Set reload reason when reloaded from repl 2021-05-13 16:33:25 -04:00
Lucian Copeland
8f9122af50 Remove overwrite of run_reason in main
When `reload_requested` is detected, the run reason will no longer be
automatically overwritten as an AUTO_RELOAD, making SUPERVISOR_RELOAD a
detectable reload reason. Autoreload now sets the reload reason itself.
2021-05-13 16:33:14 -04:00
lady ada
47dbf9ef3e moar trinkz 2021-05-13 15:31:59 -04:00
Kattni Rembor
fb9e4cf306 Add LED pin to Adafruit boards. 2021-05-13 15:29:53 -04:00
Neradoc
57c52c758e fix FunHome to FunHouse
FunHouse, sweet FunHouse.
2021-05-13 15:28:52 -04:00
Ben Bleything
cae4eea42b free up PA00 and PA01 on BHB 2021-05-13 15:28:00 -04:00
nm3210
3474f6b1f9 Swap mis-labelled D0/D1 pins on SparkFun Pro Micro RP2040 2021-05-13 15:25:56 -04:00
Lucian Copeland
2c26e87854 Remove settings for DNP oscillator 2021-05-13 15:24:58 -04:00
Kattni Rembor
67b85dc2e0 Fix board definition. 2021-05-13 15:22:35 -04:00
Kattni Rembor
173cc4bd5f Fixing board definition. 2021-05-13 15:22:35 -04:00
ZodiusInfuser
43ad85dca5 Tweaked board name 2021-05-13 15:19:28 -04:00
ZodiusInfuser
ef726bb87a Tweaked board name 2021-05-13 15:19:28 -04:00
anecdata
a367d562ab Update mpconfigboard.h 2021-05-13 15:18:30 -04:00
Benny Meisels
252f14e992 Add board definition files for ARAMCON2 Badge 2021-05-13 15:17:19 -04:00
George White
97f75ad517 Fix pin definitions
I missed a few pin definitions. Fixed those.
2021-05-13 15:15:17 -04:00
George White
655f0c0eec pre-commit trailing space fixes 2021-05-13 15:15:17 -04:00
George White
702485dae8 Added Sparkfun MicroMod RP2040
Added board definition for the Sparkfun MicroMod RP2040.

Mostly followed the format for pins from the MicroMod nRF52840 board
definition, as MicroMod tries to standardize pins across
microcontrollers.
2021-05-13 15:15:17 -04:00
Dan Halbert
e643e2e561 Add VBUS_SENSE (GP24) to board
Prompted by https://forums.adafruit.com/viewtopic.php?f=60&t=178237.
Also add some whitespace to make pin aliases stand out, and add GP23 as an alias for `SMPS_MODE`.
2021-05-13 15:14:25 -04:00
ZodiusInfuser
93055e728e Sorted board list 2021-05-13 15:12:50 -04:00
ZodiusInfuser
b6494919a9 Removed trailing whitespaces 2021-05-13 15:12:50 -04:00
ZodiusInfuser
e43ddc0e17 Removed whitespaces 2021-05-13 15:12:50 -04:00
ZodiusInfuser
919295039d Added correct USB PIDs 2021-05-13 15:12:50 -04:00
ZodiusInfuser
45e141c6f8 Added definitions for PicoLipo boards 2021-05-13 15:12:50 -04:00
Dan Halbert
fbfd436ea9 turn storage back on 2021-05-13 15:10:36 -04:00
lady ada
8794cd4f81 try re-enabling storage 2021-05-13 15:09:21 -04:00
lady ada
507677b20a remove neopixels 2021-05-13 15:09:14 -04:00
lady ada
1dd24b6ccd rename proxsense to proxlight 2021-05-13 15:09:02 -04:00
lady ada
5d8c798256 typo 2021-05-13 15:08:55 -04:00
lady ada
cdf7acf340 add prox trinkey and rename others to adafruit_ 2021-05-13 15:08:42 -04:00
lady ada
975f992e40 try adding a submodule? 2021-05-13 15:08:22 -04:00
lady ada
68a25eb04f neokey trinkey friend 2021-05-13 15:08:14 -04:00
Dan Halbert
659f2d5bd8 Revert "add robots.txt to specify doc versions to appear in search engines" 2021-05-13 14:58:34 -04:00
Kevin Lutzer
9a38a6c46a switch orders the flash memory is listed 2021-05-13 14:57:45 -04:00
Kevin Lutzer
b3b7eb9802 add W25Q64JVxQ as a supported flash for stm32f411 black pill 2021-05-13 14:57:45 -04:00
Dan Halbert
c06e631862 D3 pin should be GPIO26 2021-05-13 14:56:39 -04:00
Brian Dean
1d07447580 boards/bdmicro_vina_d51: Replace old rev with new rev and rename.
This update to the PR retains the earlier board rev (with a rename) so
that backward binary compatibility is not lost for the earlier board
revision. The primary name 'vina-d51' is retained for the latest
revision to make it easy for customers to select the proper UF2
download - because the name matches the commercial name.

Details:

Replace bdmicro_vina_d51 with bdmicro_vina_d51_pcb7 (revision 7 of
PCB) with boardfiles unmodified. Add _pcb7 to the workflow build.

Replace bdmicro_vina_d51 boardfile content with latest PCB updates
(revision 10 ov PCB). Add minimal comments in the board files to make
it clear which PCB revision is implemented. Update the USB PID to
reflect an updated board revision.
2021-05-13 14:55:44 -04:00
Brian Dean
f66fc25d95 boards/bdmicro_vina_d51: A few updates for flexibility and expansion.
ESP-01 header renamed to AUX, and expanded to 12 pins from 8
pins. Pins 1-8 still accommodate the ESP-01, with expansion to full
SERCOM 4-pad support to allow for SPI and I2C on that expansion port
with additional GPIO control.

Update pins.c with additional signals provided AUX_1-8, along with
UART, SPI, I2C name usage as aliases to appropriate AUX_1-8
signals. Additionally, add several alternate names specific to several
expansion modules - the ESP-01, and the ATW-01 using the WINC_1500
(SPI) w/interrupt and control needed for the WINC - with assignments
to module pin positions.

Re-work SERCOM assignments to accommodate the above from other parts
of the board, which required moving a SERCOM or two around in order to
accommodate the 4-pad sercom pin mapping on the AUX port.

Built and tested using latest from 'main':

Adafruit CircuitPython 6.2.0-rc.0-70-ga1562430f-dirty on 2021-04-05;
BDMICRO VINA-D51 with samd51n20
2021-05-13 14:55:44 -04:00
sabas1080
01be02dd00 add hunter cat nfc buld.yml 2021-05-13 14:53:18 -04:00
sabas1080
223cf44ec3 change flash device 2021-05-13 14:53:18 -04:00
sabas1080
eee48f57c2 removed o¡modules not availables 2021-05-13 14:53:18 -04:00
sabas1080
f601af0a93 init port hunter cat nfc! 2021-05-13 14:53:18 -04:00
Seon Rozenblum
71cc5551f2 Changed some pins for TinyS2 2021-05-13 14:50:52 -04:00
Matthias Breithaupt
a1387b72f5 Add Artisense RD00 board files 2021-05-13 14:48:38 -04:00
6220 changed files with 144486 additions and 389016 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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"
}

View File

@ -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

View File

@ -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
View File

@ -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
View 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. -->

View File

@ -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.

View File

@ -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.

View File

@ -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... 🙂 -->

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}
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:
boards: ${{ toJSON(fromJSON(needs.scheduler.outputs.ports)[matrix.port]) }}
cp-version: ${{ needs.scheduler.outputs.cp-version }}
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'))

View File

@ -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
View 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')

View File

@ -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.*

View File

@ -1,14 +0,0 @@
{
"problemMatcher": [
{
"severity": "error",
"pattern": [
{
"regexp": "^(Build .+ and \\x1b\\[31mfailed\\x1b\\[0m)$",
"message": 1
}
],
"owner": "build-failed"
}
]
}

View File

@ -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.

View File

@ -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

View File

@ -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
View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -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
python:
version: 3
install:
- requirements: requirements-doc.txt
- requirements: docs/requirements.txt

View File

@ -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

View File

@ -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.

View File

@ -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).

View File

@ -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).

View File

@ -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.

View File

@ -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)

View File

@ -1 +0,0 @@
recursive-include . *.pyi

View File

@ -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

View File

@ -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,9 +110,8 @@ 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
- ``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
@ -129,40 +120,27 @@ Behavior
``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
- 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>`__

View File

@ -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

View File

@ -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.

105
conf.py
View File

@ -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 ----------------------------------------------
# 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

View File

@ -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));
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) {

View File

@ -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.

View File

@ -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"));
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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 = {

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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.

View File

@ -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:

View File

@ -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 %}

View File

@ -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`).

View File

@ -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
View 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.

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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,10 +14,12 @@ 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
.. 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
View 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.

View File

@ -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

View File

@ -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

View File

@ -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).

View File

@ -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
View 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

View File

@ -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
View 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.

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -1,38 +0,0 @@
:mod:`platform` -- access to underlying platforms identifying data
===================================================================
.. module:: platform
:synopsis: access to underlying platforms 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.

View File

@ -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`.

View File

@ -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.

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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.

View File

@ -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