merge from main

This commit is contained in:
Dan Halbert 2024-07-29 16:11:05 -04:00
commit be6fa2af21
100 changed files with 1913 additions and 492 deletions

2
.gitattributes vendored
View file

@ -27,4 +27,4 @@
# These should also not be modified by git.
tests/basics/string_cr_conversion.py -text
tests/basics/string_crlf_conversion.py -text
# CIRCUITPY-CHANGE: remove non-CircuitPython tests
# CIRCUITPY-CHANGE: remove non-CircuitPython tests

133
.mailmap
View file

@ -1,17 +1,36 @@
# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò
# SPDX-FileCopyrightText: 2024, Rylie Pavlik
#
# SPDX-License-Identifier: Unlicense
Alec Delaney <tekktrik@gmail.com>
Alec Delaney <tekktrik@gmail.com> <89490472+tekktrik@users.noreply.github.com>
Alec Delaney <tekktrik@gmail.com> <tekktik@gmail.com>
Alex Sirota <alex.sirota@icloud.com>
Alex Sirota <alex.sirota@icloud.com> <67526318+ajs256@users.noreply.github.com>
Alexander Steffen <devel.20.webmeister@spamgourmet.com>
Alexander Steffen <devel.20.webmeister@spamgourmet.com> <Alexander.Steffen@infineon.com>
Alexander Steffen <devel.20.webmeister@spamgourmet.com> <webmeister@users.noreply.github.com>
Anson He <ansonhe1997@gmail.com>
Ayke van Laethem <aykevanlaethem@gmail.com>
Benjamin Vernoux <bvernoux@gmail.com>
BennyE <bennye_hh@posteo.net>
BennyE <bennye_hh@posteo.net> <benny@Benny-Win10.localdomain>
Bernhard Bablok <bablokb@gmx.de>
Bernhard Boser <boser@berkeley.edu>
Bernhard Boser <boser@berkeley.edu> <49917707+iot49@users.noreply.github.com>
Bernhard Boser <boser@berkeley.edu> <boser@server.home>
Bill Sideris <bill88t@feline.gr>
Brendan <2bndy5@gmail.com>
Brent Rubell <robots199@me.com>
Brent Rubell <robots199@me.com> <brent@xn.home>
Brent Rubell <robots199@me.com> <brentru@users.noreply.github.com>
Carlos <carlos.santiago.diaz@gmail.com>
Carter Nelson <caternuson@gmail.com>
Chris Dailey <nitz@users.noreply.github.com>
Chris Packham <judge.packham@gmail.com>
Chris Packham <judge.packham@gmail.com> <chris.packham@alliedtelesis.co.nz>
Chris Wilson <christopher.david.wilson@gmail.com>
Damiano Mazzella <damianomazzella@gmail.com>
Damien George <damien.p.george@gmail.com>
Dan Halbert <halbert@adafruit.com>
@ -20,45 +39,92 @@ Daniel Pollard <daniel@learnweaver.com>
Daniel Pollard <daniel@learnweaver.com> <daniel.pollard@learnweaver.com>
Daniel Tralamazza <daniel@tralamazza.com>
Daniel Tralamazza <daniel@tralamazza.com> <tralamazza@users.noreply.github.com>
DavePutz <dwputz@gmail.com>
David Glaude <david.glaude@gmail.com>
David Glaude <david.glaude@gmail.com> <dglaude@users.noreply.github.com>
Elvis Pfützenreuter <epxx@epxx.co>
Enrique Casado <ecasado@bhdyn.com>
Enrique Casado <ecasado@bhdyn.com> <32364364+ecasadod@users.noreply.github.com>
Eva Herrada <eva.herrada@adafruit.com>
Eva Herrada <eva.herrada@adafruit.com> <33632497+dherrada@users.noreply.github.com>
Eva Herrada <eva.herrada@adafruit.com> <33632497+evaherrada@users.noreply.github.com>
Eva Herrada <eva.herrada@adafruit.com> <dylan.herrada@adafruit.com>
Eva Herrada <eva.herrada@adafruit.com> <dylan.herrada@gmail.com>
Eva Herrada <eva.herrada@adafruit.com> dherrada <=>
Florin Maticu <florin.maticu@gmail.com>
Florin Maticu <florin.maticu@gmail.com> <3575408+flom84@users.noreply.github.com>
Florin Maticu <florin.maticu@gmail.com> <flomaker84@gmail.com>
Frédéric Pierson <fpierson@garatronic.fr>
Fábio Souza <fs.embarcados@gmail.com>
George Waters <gwatersdev@gmail.com>
George Waters <gwatersdev@gmail.com> <george@georgeh2os.com>
Glenn Moloney <glenn.moloney@gmail.com>
Ha Thach <thach@tinyusb.org>
Henrik Sölver <henrik.solver@gmail.com>
Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com> <IhorNehrutsa@gmail.com>
Ilya Dmitrichenko <errordeveloper@gmail.com>
Ilya Dmitrichenko <errordeveloper@gmail.com> <ilya@xively.com>
James Bowman <jamesb@excamera.com>
James Bowman <jamesb@excamera.com> <James Bowman>
James Carr <lesamouraipourpre@gmail.com>
James Carr <lesamouraipourpre@gmail.com> <70200140+lesamouraipourpre@users.noreply.github.com>
James Nadeau <james.nadeau@gmail.com>
Jan Hrudka <jahr@atlas.cz>
Jason Pecor <14111408+jpecor@users.noreply.github.com>
Jeff Epler <jepler@gmail.com>
Jeff Epler <jepler@gmail.com> <jeff@adafruit.com>
Jeff Epler <jepler@gmail.com> <jepler@de11.u>
Jeff Epler <jepler@gmail.com> <jepler@unpythonic.net>
Jensen Kuras <jensechu@gmail.com>
Jeremy Littler <brainboardz@gmail.com>
Jeremy Littler <brainboardz@gmail.com> <87398149+BrainBoardz@users.noreply.github.com>
Jerry Needell <jerryneedell@gmail.com>
Joe Bakalor <jmbakalor@gmail.com>
Jonah Yolles-Murphy <TGTechie01@gmail.com>
Jonah Yolles-Murphy <TGTechie01@gmail.com> <39284876+TG-Techie@users.noreply.github.com>
Jonah Yolles-Murphy <TGTechie01@gmail.com> <TGTechie01@gmial.com>
Jonah Yolles-Murphy <TGTechie01@gmail.com> <tgtechie01@gmail.com>
Jonathan Giles <jonathangiles@fastmail.fm>
Jonathan Giles <jonathangiles@fastmail.fm> <jgiles@Jonathans-Air.lan>
Jonny Bergdahl <jonny@bergdahl.it>
Jonny Bergdahl <jonny@bergdahl.it> <bergdahl@users.noreply.github.com>
Jos Verlinde <jos_verlinde@hotmail.com>
Jos Verlinde <jos_verlinde@hotmail.com> <jos.verlinde@microsoft.com>
Jos Verlinde <jos_verlinde@hotmail.com> <josverl@microsoft.com>
Josh Klar <josh@klar.sh>
Josh Klar <josh@klar.sh> <j@iv597.com>
Juan Biondi <juanernestobiondi@gmail.com>
Juan Biondi <juanernestobiondi@gmail.com> <juanernestobiondi@hotmail.com>
Julia Hathaway <julia.hathaway@nxp.com>
KalbeAbbas <kalbeabbas142@gmail.com>
KalbeAbbas <kalbeabbas142@gmail.com> <kalbeabbas@142@gmail.com>
Kamil Tomaszewski <kamil.tomaszewski@sony.com>
Kamil Tomaszewski <kamil.tomaszewski@sony.com> <46525824+kamtom480@users.noreply.github.com>
Kattni <kattni@adafruit.com> <kattni@kittyfish.org>
Kattni Rembor <kattni@adafruit.com>
Kattni Rembor <kattni@kattni.com>
Kattni Rembor <kattni@kattni.com> <kattni@adafruit.com>
Kattni Rembor <kattni@kattni.com> <kattni@kittyfish.org>
Kenny <WarriorOfWire@users.noreply.github.com>
Kenny <WarriorOfWire@users.noreply.github.com> <3454741+WarriorOfWire@users.noreply.github.com>
Kevin Matocha <kmatocha@icloud.com>
Kevin Matocha <kmatocha@icloud.com> <Dad@iMac.attlocal.net>
Kevin Townsend <contact@microbuilder.eu>
Kevin Townsend <contact@microbuilder.eu> <microbuilder@users.noreply.github.com>
Krzysztof Blazewicz <blazewicz.krzysztof@gmail.com>
Krzysztof Blazewicz <blazewicz.krzysztof@gmail.com> <krzysztof.blazewicz@uxeon.com>
Lee Atkinson <latkinso42@gmail.com>
Li Weiwei <liweiwei@yeweitech.org>
Li Weiwei <liweiwei@yeweitech.org> <liweiwei@yeweitech.com>
Limor "Ladyada" Fried <limor@ladyada.net>
Limor "Ladyada" Fried <limor@ladyada.net> <ladyada>
Lucian Copeland <hierophect@gmail.com>
Lucian Copeland <hierophect@gmail.com> <hierophect@Lucians-MacBook-Air-2.local>
Mariusz Ćwikła <mariuszcwikla@gmail.com>
Mariusz Ćwikła <mariuszcwikla@gmail.com> <47976407+MariuszCwikla@users.noreply.github.com>
Mark Olsson <post@markolsson.se>
Mark Olsson <post@markolsson.se> <mark@markolsson.se>
Mark Roberts <mdroberts1243@gmail.com>
Martin Fischer <fischer.carlito@gmail.com>
Matt Land <matt-land@users.noreply.github.com>
Matt Land <matt-land@users.noreply.github.com> <mland@sparefoot.com>
Matt Wozniski <godlygeek+git@gmail.com>
@ -67,17 +133,44 @@ Melissa LeBlanc-Williams <melissa@adafruit.com>
Melissa LeBlanc-Williams <melissa@adafruit.com> <melissa@melissagirl.com>
Metallicow <metaliobovinus@gmail.com>
Metallicow <metaliobovinus@gmail.com> <edg62702@yahoo.com>
Michael McWethy <mrmcwethy@yahoo.com>
Michael Weiss <github@mishafarms.us>
MicroDev <70126934+microdev1@users.noreply.github.com>
MicroDev <70126934+microdev1@users.noreply.github.com> <70126934+MicroDev1@users.noreply.github.com>
Mike Teachman <mike.teachman@gmail.com>
Milind Movasha <milind.movasha@gmail.com>
Miroslav Zuzelka <mzuzelka@gmail.com>
Noel Gaetan <gaetan.noel@viacesi.fr>
Pablo Martinez Bernal <elpekenin@elpekenin.dev>
Pablo Martinez Bernal <elpekenin@elpekenin.dev> <58857054+elpekenin@users.noreply.github.com>
Paint Your Dragon <paintyourdragon@dslextreme.com>
Patrick <4002194+askpatrickw@users.noreply.github.com>
Peter Hinch <peter@hinch.me.uk>
Peter Hinch <peter@hinch.me.uk> <peterhinch@users.noreply.github.com>
Pierre Constantineau <jpconstantineau@gmail.com>
Pierre Constantineau <jpconstantineau@gmail.com> <jponstantineau@gmail.com>
Radomir Dopieralski <openstack@sheep.art.pl>
Radomir Dopieralski <openstack@sheep.art.pl> <deshipu@users.noreply.github.com>
Rafa Gould <rafagoulds@gmail.com>
Rafa Gould <rafagoulds@gmail.com> <50337143+rafa-gould@users.noreply.github.com>
Rami Ali <raminator626@hotmail.com>
Rami Ali <raminator626@hotmail.com> Rami Ali <flowergrass@users.noreply.github.com>
Reinhard Feger <feg@LT-Feger.icie.jku.at>
Reinhard Feger <feg@LT-Feger.icie.jku.at> <47209718+rf-eng@users.noreply.github.com>
Rick Sorensen <rick.sorensen@gmail.com>
Rick Sorensen <rick.sorensen@gmail.com> <rick@ricklinux2>
Robert HH <robert@hammelrath.com>
Rose Hooper <rhooper@toybox.ca>
Ryan Shaw <ryan.shaw@wisetechglobal.com>
Ryan Shaw <ryan.shaw@wisetechglobal.com> <ryannathans@hotmail.com>
Ryan T. Hamilton <astrobokonon@gmail.com>
Ryan T. Hamilton <astrobokonon@gmail.com> <astrobokonon@users.noreply.github.com>
Rylie Pavlik <rylie@ryliepavlik.com>
Rylie Pavlik <rylie@ryliepavlik.com> <ryan.pavlik@gmail.com>
Sabas <s@electroniccats.com>
Sabas <s@electroniccats.com> <s@theinventorhouse.org>
Sabas <s@electroniccats.com> <sabasjimenez@gmail.com>
Scott Gauche <scott.gauche@gmail.com> <sgauche@users.noreply.github.com>
Scott Shawcroft <scott@adafruit.com>
Scott Shawcroft <scott@adafruit.com> <devnull@unpythonic.net>
Scott Shawcroft <scott@adafruit.com> <scott.shawcroft@gmail.com>
@ -87,22 +180,48 @@ Sebastian Plamauer <oeplse@gmail.com>
Sebastian Plamauer <oeplse@gmail.com> <oepse@gmail.com>
Senuros <Senuros@users.noreply.github.com>
Senuros <Senuros@users.noreply.github.com> <senuros@noreply.github.com>
Seth Kerr <skerr@aggies.ncat.edu>
Seth Kerr <skerr@aggies.ncat.edu> <41877068+skerr92@users.noreply.github.com>
Seth Kerr <skerr@aggies.ncat.edu> <sethkerr@Seths-Mac-mini.local>
Shawn Hymel <hymelsr@vt.edu>
Sky Bryant <mae@wolfsky.pet>
Sky Bryant <mae@wolfsky.pet> <maeskywolf@protonmail.com>
Stephane Smith <stephane.smith@titansensor.com>
Stewart Colborne <tscolborne@outlook.com>
Stewart Colborne <tscolborne@outlook.com> <tscolborne@hotmail.com>
TG-Techie <TGTechie01@gmail.com>
TG-Techie <TGTechie01@gmail.com> <39284876+TG-Techie@users.noreply.github.com>
Sébastien Rinsoz <sebastien@yoctopuce.com>
Takeo Takahashi <takeo.takahashi.xv@renesas.com>
Thea Flowers <me@thea.codes>
Thea Flowers <me@thea.codes> <theaflowers@google.com>
Thorsten von Eicken <tve@voneicken.com>
Thorsten von Eicken <tve@voneicken.com> <tve@users.noreply.github.com>
Tim <timchinowsky@gmail.com>
Tim <timchinowsky@gmail.com> <tim@gogemio.com>
Tobias Badertscher <badi@baerospace.ch>
Tobias Badertscher <badi@baerospace.ch> <python@baerospace.ch>
Tobias Schmale <tschmale85@googlemail.com>
Trammell Hudson <hudson@trmm.net>
Tyeth Gundry <tyethgundry@googlemail.com>
Unexpected Maker <seon@unexpectedmaker.com>
Vladimír Smitka <vladimir.smitka@lynt.cz>
Yuuki NAGAO <wf.yn386@gmail.com>
adam_cummick <adamc@facts-eng.com>
applecuckoo <nufjoysb@duck.com>
applecuckoo <nufjoysb@duck.com> <113647417+applecuckoo@users.noreply.github.com>
arturo182 <github@solder.party> <arturo182@tlen.pl>
danicampora <danicampora@gmail.com>
danicampora <danicampora@gmail.com> <daniel@wipy.io>
dherrada <dylan.herrada@gmail.com>
dherrada <dylan.herrada@gmail.com> <33632497+dherrada@users.noreply.github.com>
dherrada <dylan.herrada@gmail.com> <=>
foamyguy <foamyguy@gmail.com>
glennrub <glennbakke@gmail.com>
jposada202020 <jquintana202020@gmail.com>
jposada202020 <jquintana202020@gmail.com> <34255413+jposada202020@users.noreply.github.com>
mintakka <MattC867@gmail.com>
mintakka <MattC867@gmail.com> <mattc867@gmail.com>
noqman <noqman@cytron.io>
noqman <noqman@cytron.io> <140384051+noqman@users.noreply.github.com>
retoc <retoc@users.noreply.github.com>
retoc <retoc@users.noreply.github.com> <Retoc@noreply.github.com>
roland van straten <roland@van-straten.org>
siddacious <nospam187+github@gmail.com>
siddacious <nospam187+github@gmail.com> <bsiepert@gmail.com>
siddacious <nospam187+github@gmail.com> <bsiepert@lbl.gov>

View file

@ -110,6 +110,7 @@ autoapi_template_dir = 'docs/autoapi/templates'
autoapi_python_class_content = "both"
autoapi_python_use_implicit_namespaces = True
autoapi_root = "shared-bindings"
autoapi_file_patterns = ["*.pyi"]
# Suppress cache warnings to prevent "unpickable" [sic] warning
# about autoapi_prepare_jinja_env() from sphinx >= 7.3.0.
@ -180,6 +181,7 @@ exclude_patterns = ["**/build*",
".venv",
".direnv",
".devcontainer/Readme.md",
"circuitpython-stubs",
"data",
"docs/autoapi",
"docs/README.md",

View file

@ -15,6 +15,23 @@ Functions
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, /)
This function is being deprecated and will be removed starting in
CircuitPython 10.x, `traceback.print_exception()` should be used instead.
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
---------
@ -97,12 +114,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 +126,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.

View file

@ -85,6 +85,7 @@ ADDITIONAL_MODULES = {
"sys": "CIRCUITPY_SYS",
"terminalio": "CIRCUITPY_DISPLAYIO",
"usb": "CIRCUITPY_PYUSB",
"socketpool.socketpool.AF_INET6": "CIRCUITPY_SOCKETPOOL_IPV6",
}
MODULES_NOT_IN_BINDINGS = ["binascii", "errno", "json", "re", "ulab"]

View file

@ -1079,7 +1079,7 @@ static lfs2_stag_t lfs2_dir_fetchmatch(lfs2_t *lfs2,
// if either block address is invalid we return LFS2_ERR_CORRUPT here,
// otherwise later writes to the pair could fail
if (lfs2->block_count
if (lfs2->block_count
&& (pair[0] >= lfs2->block_count || pair[1] >= lfs2->block_count)) {
return LFS2_ERR_CORRUPT;
}

View file

@ -267,7 +267,7 @@ struct lfs2_config {
#ifdef LFS2_MULTIVERSION
// On-disk version to use when writing in the form of 16-bit major version
// + 16-bit minor version. This limiting metadata to what is supported by
// older minor versions. Note that some features will be lost. Defaults to
// older minor versions. Note that some features will be lost. Defaults to
// to the most recent minor version when zero.
uint32_t disk_version;
#endif

View file

@ -1185,6 +1185,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1292,6 +1293,10 @@ msgstr ""
msgid "Layer must be a Group or TileGrid subclass"
msgstr ""
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr ""
@ -1566,7 +1571,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr "Hanya alamat IPv4 yang didukung"
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Hanysa socket IPv4 yang didukung"
@ -2241,6 +2245,10 @@ msgstr "Format tidak didukung"
msgid "Unsupported hash algorithm"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -153,7 +153,7 @@ msgstr ""
msgid "%q length must be >= %d"
msgstr ""
#: py/objmodule.c py/runtime.c
#: py/modsys.c py/objmodule.c py/runtime.c
msgid "%q moved from %q to %q"
msgstr ""
@ -1177,6 +1177,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1284,6 +1285,10 @@ msgstr ""
msgid "Layer must be a Group or TileGrid subclass"
msgstr ""
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr ""
@ -1366,10 +1371,6 @@ msgstr ""
msgid "Name or service not known"
msgstr ""
#: py/qstr.c
msgid "Name too long"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
msgid "New bitmap must be same size as old bitmap"
msgstr ""
@ -1557,7 +1558,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -2219,6 +2219,10 @@ msgstr ""
msgid "Unsupported hash algorithm"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"
@ -2321,6 +2325,7 @@ msgid "You pressed the SW38 button at start up."
msgstr ""
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
#: ports/espressif/boards/vidi_x/mpconfigboard.h
msgid "You pressed the VOLUME button at start up."
msgstr ""
@ -3499,6 +3504,10 @@ msgstr ""
msgid "name not defined"
msgstr ""
#: py/qstr.c
msgid "name too long"
msgstr ""
#: py/persistentcode.c
msgid "native code in .mpy unsupported"
msgstr ""

View file

@ -1197,6 +1197,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1304,6 +1305,10 @@ msgstr "Vrstva již v groupě je"
msgid "Layer must be a Group or TileGrid subclass"
msgstr "Vrstva musí být Group nebo TileGrid"
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr "MAC adresa byla chybná"
@ -1578,7 +1583,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr "Pouze IPv4 adresy podporovány"
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Pouze IPv4 sokety podporovány"
@ -2245,6 +2249,10 @@ msgstr "Nepodporovaný formát"
msgid "Unsupported hash algorithm"
msgstr "Nepodporovaný hash algoritmus"
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1208,6 +1208,7 @@ msgid "Interrupted by output function"
msgstr "Unterbrochen durch Ausgabefunktion"
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1315,6 +1316,10 @@ msgstr "Ebene ist bereits in der Gruppe"
msgid "Layer must be a Group or TileGrid subclass"
msgstr "Ebene muss eine Gruppe oder eine TileGrid Subklasse sein"
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr "MAC Adresse war ungültig"
@ -1590,7 +1595,6 @@ msgstr "Es wird nur 8 oder 16 bit mono mit %dx Oversampling unterstützt."
msgid "Only IPv4 addresses supported"
msgstr "Nur IPv4-Adressen werden unterstützt"
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Nur IPv4-Sockets werden unterstützt"
@ -2275,6 +2279,10 @@ msgstr "Nicht unterstütztes Format"
msgid "Unsupported hash algorithm"
msgstr "Hash Algorithmus wird nicht unterstützt"
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1203,6 +1203,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1310,6 +1311,10 @@ msgstr ""
msgid "Layer must be a Group or TileGrid subclass"
msgstr ""
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr ""
@ -1583,7 +1588,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -2247,6 +2251,10 @@ msgstr ""
msgid "Unsupported hash algorithm"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-06-28 22:09+0000\n"
"PO-Revision-Date: 2024-07-24 22:09+0000\n"
"Last-Translator: Andi Chandler <andi@gowling.com>\n"
"Language-Team: none\n"
"Language: en_GB\n"
@ -1196,6 +1196,7 @@ msgid "Interrupted by output function"
msgstr "Interrupted by output function"
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1303,6 +1304,10 @@ msgstr "Layer already in a group"
msgid "Layer must be a Group or TileGrid subclass"
msgstr "Layer must be a Group or TileGrid subclass"
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr "Length of %q must be an even multiple of channel_count * type_size"
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr "MAC address was invalid"
@ -1577,7 +1582,6 @@ msgstr "Only 8 or 16 bit mono with %dx oversampling supported."
msgid "Only IPv4 addresses supported"
msgstr "Only IPv4 addresses supported"
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Only IPv4 sockets supported"
@ -2249,6 +2253,10 @@ msgstr "Unsupported format"
msgid "Unsupported hash algorithm"
msgstr "Unsupported hash algorithm"
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr "Unsupported socket type"
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1216,6 +1216,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1323,6 +1324,10 @@ msgstr "El Layer ya esta en un grupo"
msgid "Layer must be a Group or TileGrid subclass"
msgstr "El Layer debe ser un grupo o una subclase de TileGrid"
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr "La dirección MAC es incorrecta"
@ -1598,7 +1603,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr "Solo hay capacidad para direcciones IPv4"
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Solo se admiten sockets IPv4"
@ -2280,6 +2284,10 @@ msgstr "Formato no soportado"
msgid "Unsupported hash algorithm"
msgstr "Algoritmo hash no soportado"
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1187,6 +1187,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1294,6 +1295,10 @@ msgstr ""
msgid "Layer must be a Group or TileGrid subclass"
msgstr ""
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr ""
@ -1570,7 +1575,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -2234,6 +2238,10 @@ msgstr "Hindi supportadong format"
msgid "Unsupported hash algorithm"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1225,6 +1225,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1332,6 +1333,10 @@ msgstr "Ce calque est déjà dans un groupe"
msgid "Layer must be a Group or TileGrid subclass"
msgstr "Le calque doit être une sous-classe de Group ou TileGrid"
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr "Adresse physique (MAC) invalide"
@ -1616,7 +1621,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr "Seulement les adresses IPv4 sont supportées"
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Seulement les sockets IPv4 sont supportés"
@ -2298,6 +2302,10 @@ msgstr "Format non pris en charge"
msgid "Unsupported hash algorithm"
msgstr "Algorithme de hachage non supporté"
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1179,6 +1179,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1286,6 +1287,10 @@ msgstr ""
msgid "Layer must be a Group or TileGrid subclass"
msgstr ""
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr ""
@ -1559,7 +1564,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -2221,6 +2225,10 @@ msgstr ""
msgid "Unsupported hash algorithm"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1187,6 +1187,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1294,6 +1295,10 @@ msgstr ""
msgid "Layer must be a Group or TileGrid subclass"
msgstr ""
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr ""
@ -1571,7 +1576,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -2236,6 +2240,10 @@ msgstr "Formato non supportato"
msgid "Unsupported hash algorithm"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1196,6 +1196,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1303,6 +1304,10 @@ msgstr ""
msgid "Layer must be a Group or TileGrid subclass"
msgstr ""
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr ""
@ -1578,7 +1583,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -2244,6 +2248,10 @@ msgstr "非対応の形式"
msgid "Unsupported hash algorithm"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1231,6 +1231,7 @@ msgid "Interrupted by output function"
msgstr "출력 함수로 인해 종료되었다"
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1338,6 +1339,10 @@ msgstr "레이어가 이미 그룹에 있습니다"
msgid "Layer must be a Group or TileGrid subclass"
msgstr "레이어는 그룹 또는 TileGrid 하위 클래스 여야 합니다"
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr "MAC 주소는 잘못되었습니다"
@ -1620,7 +1625,6 @@ msgstr "%dx 오버샘플링이 포함된 8 또는 16 비트 모노만 지원됩
msgid "Only IPv4 addresses supported"
msgstr "IPv4 주소만 지원됩니다"
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "IPv4 소켓만 지원됩니다"
@ -2299,6 +2303,10 @@ msgstr ""
msgid "Unsupported hash algorithm"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1182,6 +1182,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1289,6 +1290,10 @@ msgstr ""
msgid "Layer must be a Group or TileGrid subclass"
msgstr ""
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr ""
@ -1564,7 +1569,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr "Alleen IPv4 adressen worden ondersteund"
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Alleen IPv4-sockets ondersteund"
@ -2237,6 +2241,10 @@ msgstr "Niet-ondersteunde format"
msgid "Unsupported hash algorithm"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1201,6 +1201,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1308,6 +1309,10 @@ msgstr ""
msgid "Layer must be a Group or TileGrid subclass"
msgstr ""
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr ""
@ -1581,7 +1586,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -2251,6 +2255,10 @@ msgstr "Zły format"
msgid "Unsupported hash algorithm"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -6,7 +6,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
"PO-Revision-Date: 2024-07-09 02:09+0000\n"
"PO-Revision-Date: 2024-07-24 22:09+0000\n"
"Last-Translator: Wellington Terumi Uemura <wellingtonuemura@gmail.com>\n"
"Language-Team: \n"
"Language: pt_BR\n"
@ -1212,6 +1212,7 @@ msgid "Interrupted by output function"
msgstr "Interrompido pela função de saída"
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1319,6 +1320,11 @@ msgstr "Camada já está num grupo"
msgid "Layer must be a Group or TileGrid subclass"
msgstr "A camada deve ser uma subclasse Group ou TileGrid"
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
"O comprimento de %q deve ser um múltiplo par de channel_count * type_size"
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr "O endereço MAC era inválido"
@ -1596,7 +1602,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr "Somente os endereços IPv4 são suportados"
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Apenas soquetes IPv4 são suportados"
@ -2281,6 +2286,10 @@ msgstr "Formato não suportado"
msgid "Unsupported hash algorithm"
msgstr "Sem compatibilidade com o algoritmo de hash"
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr "Tipo de soquete não suportado"
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1223,6 +1223,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1330,6 +1331,10 @@ msgstr "Слой уже в группе (Group)"
msgid "Layer must be a Group or TileGrid subclass"
msgstr "Слой должен быть группой (Group) или субклассом TileGrid"
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr "MAC адрес был недействительным"
@ -1607,7 +1612,6 @@ msgstr "Только 8 или 16 бит моно с поддержкой %d."
msgid "Only IPv4 addresses supported"
msgstr "Поддерживаются только адреса IPv4"
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Поддерживаются только сокеты IPv4"
@ -2288,6 +2292,10 @@ msgstr "Неподдерживаемый формат"
msgid "Unsupported hash algorithm"
msgstr "Неподдерживаемый алгоритм хеширования"
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1204,6 +1204,7 @@ msgid "Interrupted by output function"
msgstr "Avbruten av utgångsfunktion"
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1311,6 +1312,10 @@ msgstr "Layer är redan med i en grupp"
msgid "Layer must be a Group or TileGrid subclass"
msgstr "Layer måste vara en underklass av Group eller TileGrid"
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr "MAC-adressen var ogiltig"
@ -1586,7 +1591,6 @@ msgstr "Endast 8 eller 16 bitars mono med %dx översampling stöds."
msgid "Only IPv4 addresses supported"
msgstr "Endast IPv4-adresser stöds"
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "Endast IPv4-socket stöds"
@ -2260,6 +2264,10 @@ msgstr "Format stöds inte"
msgid "Unsupported hash algorithm"
msgstr "Hash-algoritmen stöds inte"
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1197,6 +1197,7 @@ msgid "Interrupted by output function"
msgstr ""
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1305,6 +1306,10 @@ msgstr "Katman zaten bir grupta"
msgid "Layer must be a Group or TileGrid subclass"
msgstr "Katman, bir Grup ya da TileGrid alt sınıfı olmalıdır"
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr "MAC adresi geçersiz"
@ -1578,7 +1583,6 @@ msgstr ""
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -2243,6 +2247,10 @@ msgstr ""
msgid "Unsupported hash algorithm"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -1210,6 +1210,7 @@ msgid "Interrupted by output function"
msgstr "bèi shūchū gōngnéng zhōngduàn"
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
@ -1317,6 +1318,10 @@ msgstr "tú céng yǐ zài zǔ zhōng"
msgid "Layer must be a Group or TileGrid subclass"
msgstr "tú céng bìxū shì zǔ huò píng pū wǎng gé zi lèi"
#: shared-bindings/audiocore/RawSample.c
msgid "Length of %q must be an even multiple of channel_count * type_size"
msgstr ""
#: ports/espressif/common-hal/espidf/__init__.c
msgid "MAC address was invalid"
msgstr "MAC dì zhǐ wú xiào"
@ -1591,7 +1596,6 @@ msgstr "jǐn zhīchí 8wèihuò16 wèi dānshēngdào hé %dx guòcǎiyàng."
msgid "Only IPv4 addresses supported"
msgstr "Jǐn zhīchí IPv4 dìzhǐ"
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr "jǐn zhī chí IPv4 tào jiē zì"
@ -2266,6 +2270,10 @@ msgstr "Bù zhīchí de géshì"
msgid "Unsupported hash algorithm"
msgstr "bù zhīchí de hā xī suànfǎ"
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Unsupported socket type"
msgstr ""
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update failed"

View file

@ -249,34 +249,41 @@ extern void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t *self, uin
// Track it here so that if frequency is changed we can use this value to recalculate the
// proper duty cycle.
// See https://github.com/adafruit/circuitpython/issues/2086 for more details
self->duty_cycle = duty;
const pin_timer_t *t = self->timer;
if (t->is_tc) {
uint16_t adjusted_duty = tc_periods[t->index] * duty / 0xffff;
if (adjusted_duty == 0 && duty != 0) {
adjusted_duty = 1; // prevent rounding down to 0
}
#ifdef SAMD21
tc_insts[t->index]->COUNT16.CC[t->wave_output].reg = adjusted_duty;
#endif
#ifdef SAM_D5X_E5X
Tc *tc = tc_insts[t->index];
while (tc->COUNT16.SYNCBUSY.bit.CC1 != 0) {
}
tc->COUNT16.CCBUF[1].reg = adjusted_duty;
#endif
} else {
uint32_t adjusted_duty = ((uint64_t)tcc_periods[t->index]) * duty / 0xffff;
if (adjusted_duty == 0 && duty != 0) {
adjusted_duty = 1; // prevent rounding down to 0
}
uint8_t channel = tcc_channel(t);
Tcc *tcc = tcc_insts[t->index];
// Write into the CC buffer register, which will be transferred to the
// CC register on an UPDATE (when period is finished).
// Do clock domain syncing as necessary.
while (tcc->SYNCBUSY.reg != 0) {
}
// Lock out double-buffering while updating the CCB value.
tcc->CTRLBSET.bit.LUPD = 1;
#ifdef SAMD21
tcc->CCB[channel].reg = adjusted_duty;
#endif
#ifdef SAM_D5X_E5X
tcc->CCBUF[channel].reg = adjusted_duty;
#endif
tcc->CTRLBCLR.bit.LUPD = 1;
}
}

View file

@ -11,5 +11,8 @@ CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1
CIRCUITPY_ESP_USB_SERIAL_JTAG = 1
# Not enough flash
CIRCUITPY_SOCKETPOOL_IPV6 = 0
# Include these Python libraries in firmware.
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel

View file

@ -7,6 +7,7 @@
#
# LWIP
#
# CONFIG_LWIP_IPV6 is not set
CONFIG_LWIP_LOCAL_HOSTNAME="lolin-c3-pico"
# end of LWIP

View file

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

View file

@ -0,0 +1,27 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2022 Dan Halbert for Adafruit Industries
//
// SPDX-License-Identifier: MIT
#pragma once
#define MICROPY_HW_BOARD_NAME "VIDI X"
#define MICROPY_HW_MCU_NAME "ESP32"
#define MICROPY_HW_LED_STATUS (&pin_GPIO2)
#define CIRCUITPY_BOARD_SPI (1)
#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO18, .mosi = &pin_GPIO23, .miso = &pin_GPIO19}}
#define CIRCUITPY_BOARD_I2C (1)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO32, .sda = &pin_GPIO33}}
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)
// Explanation of how a user got into safe mode
#define BOARD_USER_SAFE_MODE_ACTION MP_ERROR_TEXT("You pressed the VOLUME button at start up.")
// UART pins attached to the USB-serial converter chip
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3)

View file

@ -0,0 +1,12 @@
CIRCUITPY_CREATOR_ID = 0x0D10C000
CIRCUITPY_CREATION_ID = 0x00320001
IDF_TARGET = esp32
CIRCUITPY_ESP_FLASH_SIZE = 8MB
CIRCUITPY_ESP_FLASH_MODE = qio
CIRCUITPY_ESP_FLASH_FREQ = 80m
CIRCUITPY_ESP_PSRAM_SIZE = 8MB
CIRCUITPY_ESP_PSRAM_MODE = qio
CIRCUITPY_ESP_PSRAM_FREQ = 80m

View file

@ -0,0 +1,143 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
//
// SPDX-License-Identifier: MIT
#include "py/objtuple.h"
#include "shared-bindings/board/__init__.h"
#include "shared-module/displayio/__init__.h"
static const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
{ MP_ROM_QSTR(MP_QSTR_VOLUME), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_EXP9), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_GPIO0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_EXP16), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_GPIO1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_STATUS), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_EXP8), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_EXP14), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_GPIO3), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_VSPI_CS2), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_EXP10), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_TOUCH_CS), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_GPIO4), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_VSPI_CS0), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_EXP11), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_GPIO5), MP_ROM_PTR(&pin_GPIO5) },
// GPIOs 6-11 are connected to the module's integrated SPI flash and PSRAM
{ MP_ROM_QSTR(MP_QSTR_TOUCH_IRQ), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_EXP20), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_GPIO12), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_MENU), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_EXP17), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_GPIO13), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_MIC), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_EXP19), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_GPIO14), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_IRTX), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_EXP7), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_GPIO15), MP_ROM_PTR(&pin_GPIO15) },
// GPIOs 16 and 17 are connected to the modules integrated PSRAM
{ MP_ROM_QSTR(MP_QSTR_VSPI_SCK), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_EXP12), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_TOUCH_SCK), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_LCD_SCK), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_GPIO18), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_VSPI_MISO), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_EXP13), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_TOUCH_MISO), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_LCD_MISO), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_GPIO19), MP_ROM_PTR(&pin_GPIO19) },
// GPIO 20 is only available on ESP32-PICO-V3 chip package
{ MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_EXP15), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_GPIO21), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_VSPI_CS1), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_EXP18), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_GPIO22), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_VSPI_MOSI), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_EXP28), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_GPIO23), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_TOUCH_MOSI), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_GPIO19), MP_ROM_PTR(&pin_GPIO19) },
// 24 not connected
{ MP_ROM_QSTR(MP_QSTR_IRRX), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_SPEAKER_IN), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_GPIO25), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_TEMP), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_RGB_LED), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_GPIO26), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_SELECT), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_EXP22), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_GPIO27), MP_ROM_PTR(&pin_GPIO27) },
// 28-31 not connected
{ MP_ROM_QSTR(MP_QSTR_BTN_A), MP_ROM_PTR(&pin_GPIO32) },
{ MP_ROM_QSTR(MP_QSTR_EXP23), MP_ROM_PTR(&pin_GPIO32) },
{ MP_ROM_QSTR(MP_QSTR_GPIO32), MP_ROM_PTR(&pin_GPIO32) },
{ MP_ROM_QSTR(MP_QSTR_BTN_B), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_EXP21), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_GPIO33), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_BTN_L_R), MP_ROM_PTR(&pin_GPIO34) },
{ MP_ROM_QSTR(MP_QSTR_EXP25), MP_ROM_PTR(&pin_GPIO34) },
{ MP_ROM_QSTR(MP_QSTR_GPIO34), MP_ROM_PTR(&pin_GPIO34) },
{ MP_ROM_QSTR(MP_QSTR_BTN_UP_DOWN), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_EXP24), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_GPIO35), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_ADC_BAT), MP_ROM_PTR(&pin_GPIO36) },
{ MP_ROM_QSTR(MP_QSTR_EXP27), MP_ROM_PTR(&pin_GPIO36) },
{ MP_ROM_QSTR(MP_QSTR_GPIO36), MP_ROM_PTR(&pin_GPIO36) },
// 37-38 not connected
{ MP_ROM_QSTR(MP_QSTR_START), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_EXP26), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_GPIO39), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_VIDIIC), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)},
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View file

@ -0,0 +1,15 @@
#
# Espressif IoT Development Framework Configuration
#
#
# Component config
#
#
# LWIP
#
CONFIG_LWIP_LOCAL_HOSTNAME="vidi-x"
# end of LWIP
# end of Component config
# end of Espressif IoT Development Framework Configuration

View file

@ -12,3 +12,6 @@ CIRCUITPY_ESP_FLASH_SIZE = 4MB
CIRCUITPY_ESP_PSRAM_SIZE = 2MB
CIRCUITPY_ESP_PSRAM_MODE = qio
CIRCUITPY_ESP_PSRAM_FREQ = 80m
# Not enough flash
CIRCUITPY_SOCKETPOOL_IPV6 = 0

View file

@ -7,6 +7,7 @@
#
# LWIP
#
# CONFIG_LWIP_IPV6 is not set
CONFIG_LWIP_LOCAL_HOSTNAME="waveshare-esp32-s3-tiny"
# end of LWIP

View file

@ -215,7 +215,7 @@ static bool check_valid_data(const adc_digi_output_data_t *data, const mcu_pin_o
return true;
}
uint32_t common_hal_analogbufio_bufferedin_readinto(analogbufio_bufferedin_obj_t *self, uint8_t *buffer, uint32_t len, uint8_t bytes_per_sample) {
uint32_t common_hal_analogbufio_bufferedin_readinto(analogbufio_bufferedin_obj_t *self, uint8_t *buffer, uint32_t len, uint8_t bytes_per_sample, bool loop) {
uint8_t result[NUM_SAMPLES_PER_INTERRUPT * SOC_ADC_DIGI_DATA_BYTES_PER_CONV] __attribute__ ((aligned(4))) = {0};
uint32_t captured_samples = 0;
uint32_t captured_bytes = 0;

View file

@ -20,15 +20,19 @@ void common_hal_countio_counter_construct(countio_counter_obj_t *self,
pcnt_unit_config_t unit_config = {
// Set counter limit
.low_limit = -1,
.low_limit = INT16_MIN,
.high_limit = INT16_MAX
};
// The pulse count driver automatically counts roll overs.
// Enable PCNT internal accumulator to count overflows.
unit_config.flags.accum_count = true;
// initialize PCNT
CHECK_ESP_RESULT(pcnt_new_unit(&unit_config, &self->unit));
// Set watchpoints at limis, to auto-accumulate overflows.
pcnt_unit_add_watch_point(self->unit, INT16_MIN);
pcnt_unit_add_watch_point(self->unit, INT16_MAX);
self->pin = pin->number;
pcnt_chan_config_t channel_config = {
.edge_gpio_num = self->pin,

View file

@ -30,10 +30,10 @@ static IRAM_ATTR bool timer_interrupt_handler(gptimer_handle_t timer,
static esp_err_t init_pcnt(frequencyio_frequencyin_obj_t *self) {
pcnt_unit_config_t unit_config = {
// Set counter limit
.low_limit = -INT16_MAX + 1,
.low_limit = INT16_MIN,
.high_limit = INT16_MAX
};
// The pulse count driver automatically counts roll overs.
// Enable PCNT internal accumulator to count overflows.
unit_config.flags.accum_count = true;
// initialize PCNT
@ -42,6 +42,10 @@ static esp_err_t init_pcnt(frequencyio_frequencyin_obj_t *self) {
return result;
}
// Set watchpoints at limis, to auto-accumulate overflows.
pcnt_unit_add_watch_point(self->internal_data->unit, INT16_MIN);
pcnt_unit_add_watch_point(self->internal_data->unit, INT16_MAX);
pcnt_chan_config_t channel_config = {
.edge_gpio_num = self->pin,
.level_gpio_num = -1

View file

@ -23,15 +23,19 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode
// in CircuitPython.
pcnt_unit_config_t unit_config = {
// Set counter limit
.low_limit = -INT16_MAX,
.low_limit = INT16_MIN,
.high_limit = INT16_MAX
};
// The pulse count driver automatically counts roll overs.
// Enable PCNT internal accumulator to count overflows.
unit_config.flags.accum_count = true;
// initialize PCNT
CHECK_ESP_RESULT(pcnt_new_unit(&unit_config, &self->unit));
// Set watchpoints at limits, to auto-accumulate overflows.
pcnt_unit_add_watch_point(self->unit, INT16_MIN);
pcnt_unit_add_watch_point(self->unit, INT16_MAX);
pcnt_chan_config_t channel_a_config = {
.edge_gpio_num = pin_a->number,
.level_gpio_num = pin_b->number

View file

@ -11,6 +11,8 @@
#include "py/mperrno.h"
#include "py/runtime.h"
#include "shared-bindings/socketpool/SocketPool.h"
#include "common-hal/socketpool/__init__.h"
#include "common-hal/wifi/__init__.h"
#if CIRCUITPY_SSL
#include "shared-bindings/ssl/SSLSocket.h"
#include "shared-module/ssl/SSLSocket.h"
@ -25,6 +27,24 @@
#include "components/lwip/lwip/src/include/lwip/netdb.h"
#include "components/vfs/include/esp_vfs_eventfd.h"
void socketpool_resolve_host_or_throw(int family, int type, const char *hostname, struct sockaddr_storage *addr, int port) {
struct addrinfo *result_i;
const struct addrinfo hints = {
.ai_family = family,
.ai_socktype = type,
};
int error = socketpool_getaddrinfo_common(hostname, port, &hints, &result_i);
if (error != 0 || result_i == NULL) {
common_hal_socketpool_socketpool_raise_gaierror_noname();
}
memcpy(addr, result_i->ai_addr, sizeof(struct sockaddr_storage));
lwip_freeaddrinfo(result_i);
}
static void resolve_host_or_throw(socketpool_socket_obj_t *self, const char *hostname, struct sockaddr_storage *addr, int port) {
socketpool_resolve_host_or_throw(self->family, self->type, hostname, addr, port);
}
StackType_t socket_select_stack[2 * configMINIMAL_STACK_SIZE];
/* Socket state table:
@ -175,7 +195,7 @@ static bool _socketpool_socket(socketpool_socketpool_obj_t *self,
if (family == SOCKETPOOL_AF_INET) {
addr_family = AF_INET;
ipproto = IPPROTO_IP;
#if LWIP_IPV6
#if CIRCUITPY_SOCKETPOOL_IPV6
} else { // INET6
addr_family = AF_INET6;
ipproto = IPPROTO_IPV6;
@ -230,8 +250,14 @@ bool socketpool_socket(socketpool_socketpool_obj_t *self,
socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_t *self,
socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type, int proto) {
if (family != SOCKETPOOL_AF_INET) {
mp_raise_NotImplementedError(MP_ERROR_TEXT("Only IPv4 sockets supported"));
switch (family) {
#if CIRCUITPY_SOCKETPOOL_IPV6
case SOCKETPOOL_AF_INET6:
#endif
case SOCKETPOOL_AF_INET:
break;
default:
mp_raise_NotImplementedError(MP_ERROR_TEXT("Unsupported socket type"));
}
socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t);
@ -244,9 +270,9 @@ socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_
return sock;
}
int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_t *port, socketpool_socket_obj_t *accepted) {
struct sockaddr_in accept_addr;
socklen_t socklen = sizeof(accept_addr);
int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, socketpool_socket_obj_t *accepted) {
struct sockaddr_storage peer_addr;
socklen_t socklen = sizeof(peer_addr);
int newsoc = -1;
bool timed_out = false;
uint64_t start_ticks = supervisor_ticks_ms64();
@ -257,20 +283,17 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_
timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms;
}
RUN_BACKGROUND_TASKS;
newsoc = lwip_accept(self->num, (struct sockaddr *)&accept_addr, &socklen);
newsoc = lwip_accept(self->num, (struct sockaddr *)&peer_addr, &socklen);
// In non-blocking mode, fail instead of timing out
if (newsoc == -1 && (self->timeout_ms == 0 || mp_hal_is_interrupted())) {
return -MP_EAGAIN;
}
}
if (!timed_out) {
// harmless on failure but avoiding memcpy is faster
memcpy((void *)ip, (void *)&accept_addr.sin_addr.s_addr, sizeof(accept_addr.sin_addr.s_addr));
*port = accept_addr.sin_port;
} else {
if (timed_out) {
return -ETIMEDOUT;
}
if (newsoc < 0) {
return -MP_EBADF;
}
@ -295,13 +318,16 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_
accepted->type = self->type;
}
if (peer_out) {
*peer_out = sockaddr_to_tuple(&peer_addr);
}
return newsoc;
}
socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self,
uint8_t *ip, uint32_t *port) {
socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out) {
socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t);
int newsoc = socketpool_socket_accept(self, ip, port, NULL);
int newsoc = socketpool_socket_accept(self, peer_out, NULL);
if (newsoc > 0) {
// Create the socket
@ -321,20 +347,35 @@ socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_o
size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self,
const char *host, size_t hostlen, uint32_t port) {
struct sockaddr_in bind_addr;
struct sockaddr_storage bind_addr;
const char *broadcast = "<broadcast>";
uint32_t ip;
if (hostlen == 0) {
ip = IPADDR_ANY;
} else if (hostlen == strlen(broadcast) &&
memcmp(host, broadcast, strlen(broadcast)) == 0) {
ip = IPADDR_BROADCAST;
} else {
ip = inet_addr(host);
bind_addr.ss_family = self->family;
#if CIRCUITPY_SOCKETPOOL_IPV6
if (self->family == AF_INET6) {
struct sockaddr_in6 *addr6 = (void *)&bind_addr;
addr6->sin6_port = htons(port);
// no ipv6 broadcast
if (hostlen == 0) {
memset(&addr6->sin6_addr, 0, sizeof(addr6->sin6_addr));
} else {
socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, port);
}
} else
#endif
{
struct sockaddr_in *addr4 = (void *)&bind_addr;
addr4->sin_port = htons(port);
if (hostlen == 0) {
addr4->sin_addr.s_addr = IPADDR_ANY;
} else if (hostlen == strlen(broadcast) &&
memcmp(host, broadcast, strlen(broadcast)) == 0) {
addr4->sin_addr.s_addr = IPADDR_BROADCAST;
} else {
socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, port);
}
}
bind_addr.sin_addr.s_addr = ip;
bind_addr.sin_family = AF_INET;
bind_addr.sin_port = htons(port);
int result = lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr));
if (result == 0) {
@ -376,26 +417,8 @@ void common_hal_socketpool_socket_close(socketpool_socket_obj_t *self) {
void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self,
const char *host, size_t hostlen, uint32_t port) {
const struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo *result_i;
int error = lwip_getaddrinfo(host, NULL, &hints, &result_i);
if (error != 0 || result_i == NULL) {
common_hal_socketpool_socketpool_raise_gaierror_noname();
}
// Set parameters
struct sockaddr_in dest_addr;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
dest_addr.sin_addr.s_addr = ((struct sockaddr_in *)result_i->ai_addr)->sin_addr.s_addr;
#pragma GCC diagnostic pop
lwip_freeaddrinfo(result_i);
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
struct sockaddr_storage addr;
resolve_host_or_throw(self, host, &addr, port);
// Replace above with function call -----
@ -403,7 +426,7 @@ void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self,
// All our sockets are non-blocking, so we check the timeout ourselves.
int result = -1;
result = lwip_connect(self->num, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in));
result = lwip_connect(self->num, (struct sockaddr *)&addr, addr.s2_len);
if (result == 0) {
// Connected immediately.
@ -483,9 +506,9 @@ bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *self, int back
}
mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *self,
uint8_t *buf, uint32_t len, uint8_t *ip, uint32_t *port) {
uint8_t *buf, uint32_t len, mp_obj_t *source_out) {
struct sockaddr_in source_addr;
struct sockaddr_storage source_addr;
socklen_t socklen = sizeof(source_addr);
// LWIP Socket
@ -507,10 +530,7 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *se
}
}
if (!timed_out) {
memcpy((void *)ip, (void *)&source_addr.sin_addr.s_addr, sizeof(source_addr.sin_addr.s_addr));
*port = htons(source_addr.sin_port);
} else {
if (timed_out) {
mp_raise_OSError(ETIMEDOUT);
}
@ -519,6 +539,10 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *se
return 0;
}
if (source_out) {
*source_out = sockaddr_to_tuple(&source_addr);
}
return received;
}
@ -605,29 +629,10 @@ mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t *self, const
mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *self,
const char *host, size_t hostlen, uint32_t port, const uint8_t *buf, uint32_t len) {
// Set parameters
const struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo *result_i;
int error = lwip_getaddrinfo(host, NULL, &hints, &result_i);
if (error != 0 || result_i == NULL) {
common_hal_socketpool_socketpool_raise_gaierror_noname();
}
struct sockaddr_storage addr;
resolve_host_or_throw(self, host, &addr, port);
// Set parameters
struct sockaddr_in dest_addr;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
dest_addr.sin_addr.s_addr = ((struct sockaddr_in *)result_i->ai_addr)->sin_addr.s_addr;
#pragma GCC diagnostic pop
lwip_freeaddrinfo(result_i);
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
int bytes_sent = lwip_sendto(self->num, buf, len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
int bytes_sent = lwip_sendto(self->num, buf, len, 0, (struct sockaddr *)&addr, addr.s2_len);
if (bytes_sent < 0) {
mp_raise_BrokenPipeError();
return 0;

View file

@ -9,6 +9,7 @@
#include "py/runtime.h"
#include "shared-bindings/wifi/__init__.h"
#include "common-hal/socketpool/__init__.h"
#include "components/lwip/lwip/src/include/lwip/netdb.h"
@ -22,37 +23,102 @@ void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *sel
// common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking.
mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_obj_t *self,
const char *host) {
int socketpool_getaddrinfo_common(const char *host, int service, const struct addrinfo *hints, struct addrinfo **res) {
// As of 2022, the version of lwip in esp-idf does not handle the
// trailing-dot syntax of domain names, so emulate it.
// Remove this once https://github.com/espressif/esp-idf/issues/10013 has
// been implemented
size_t strlen_host = strlen(host);
if (strlen_host && host[strlen_host - 1] == '.') {
mp_obj_t nodot = mp_obj_new_str(host, strlen_host - 1);
host = mp_obj_str_get_str(nodot);
if (host) {
size_t strlen_host = strlen(host);
if (strlen_host && host[strlen_host - 1] == '.') {
mp_obj_t nodot = mp_obj_new_str(host, strlen_host - 1);
host = mp_obj_str_get_str(nodot);
}
}
const struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo *res;
int err = lwip_getaddrinfo(host, NULL, &hints, &res);
if (err != 0 || res == NULL) {
return mp_const_none;
}
char service_buf[6];
snprintf(service_buf, sizeof(service_buf), "%d", service);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
struct in_addr *addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
#pragma GCC diagnostic pop
char ip_str[IP4ADDR_STRLEN_MAX];
inet_ntoa_r(*addr, ip_str, IP4ADDR_STRLEN_MAX);
mp_obj_t ip_obj = mp_obj_new_str(ip_str, strlen(ip_str));
lwip_freeaddrinfo(res);
return ip_obj;
return lwip_getaddrinfo(host, service_buf, hints, res);
}
static mp_obj_t format_address(const struct sockaddr *addr, int family) {
char ip_str[IPADDR_STRLEN_MAX]; // big enough for any supported address type
const struct sockaddr_in *a = (void *)addr;
switch (family) {
#if CIRCUITPY_SOCKETPOOL_IPV6
case AF_INET6:
inet_ntop(family, &((const struct sockaddr_in6 *)a)->sin6_addr, ip_str, sizeof(ip_str));
break;
#endif
default:
case AF_INET:
inet_ntop(family, &((const struct sockaddr_in *)a)->sin_addr, ip_str, sizeof(ip_str));
break;
}
return mp_obj_new_str(ip_str, strlen(ip_str));
}
static mp_obj_t convert_sockaddr(const struct addrinfo *ai, int port) {
#if CIRCUITPY_SOCKETPOOL_IPV6
mp_int_t n_tuple = ai->ai_family == AF_INET6 ? 4 : 2;
#else
mp_int_t n_tuple = 2;
#endif
mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_tuple, NULL));
result->items[0] = format_address(ai->ai_addr, ai->ai_family);
result->items[1] = MP_OBJ_NEW_SMALL_INT(port);
#if CIRCUITPY_SOCKETPOOL_IPV6
if (ai->ai_family == AF_INET6) {
const struct sockaddr_in6 *ai6 = (void *)ai->ai_addr;
result->items[2] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_flowinfo);
result->items[3] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_scope_id);
}
#endif
return result;
}
static mp_obj_t convert_addrinfo(const struct addrinfo *ai, int port) {
MP_STATIC_ASSERT(AF_INET == SOCKETPOOL_AF_INET);
#if CIRCUITPY_SOCKETPOOL_IPV6
MP_STATIC_ASSERT(AF_INET6 == SOCKETPOOL_AF_INET6);
#endif
// MP_STATIC_ASSERT(AF_UNSPEC == SOCKETPOOL_AF_UNSPEC);
mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL));
result->items[0] = MP_OBJ_NEW_SMALL_INT(ai->ai_family);
result->items[1] = MP_OBJ_NEW_SMALL_INT(ai->ai_socktype);
result->items[2] = MP_OBJ_NEW_SMALL_INT(ai->ai_protocol);
result->items[3] = ai->ai_canonname ? mp_obj_new_str(ai->ai_canonname, strlen(ai->ai_canonname)) : MP_OBJ_NEW_QSTR(MP_QSTR_);
result->items[4] = convert_sockaddr(ai, port);
return result;
}
mp_obj_t common_hal_socketpool_getaddrinfo_raise(socketpool_socketpool_obj_t *self, const char *host, int port, int family, int type, int proto, int flags) {
const struct addrinfo hints = {
.ai_flags = flags,
.ai_family = family,
.ai_protocol = proto,
.ai_socktype = type,
};
struct addrinfo *res = NULL;
int err = socketpool_getaddrinfo_common(host, port, &hints, &res);
if (err != 0 || res == NULL) {
common_hal_socketpool_socketpool_raise_gaierror_noname();
}
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_obj_t result = mp_obj_new_list(0, NULL);
for (struct addrinfo *ai = res; ai; ai = ai->ai_next) {
mp_obj_list_append(result, convert_addrinfo(ai, port));
}
nlr_pop();
lwip_freeaddrinfo(res);
return result;
} else {
lwip_freeaddrinfo(res);
nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val));
}
}

View file

@ -5,3 +5,8 @@
// SPDX-License-Identifier: MIT
#pragma once
struct addrinfo;
int socketpool_getaddrinfo_common(const char *host, int service, const struct addrinfo *hints, struct addrinfo **res);
void socketpool_resolve_host_or_throw(int family, int type, const char *hostname, struct sockaddr_storage *addr, int port);

View file

@ -13,15 +13,23 @@
#include "common-hal/wifi/__init__.h"
#include "shared/runtime/interrupt_char.h"
#include "py/gc.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "shared-bindings/ipaddress/IPv4Address.h"
#include "shared-bindings/wifi/ScannedNetworks.h"
#include "shared-bindings/wifi/AuthMode.h"
#include "shared-bindings/time/__init__.h"
#include "shared-module/ipaddress/__init__.h"
#include "common-hal/socketpool/__init__.h"
#include "components/esp_netif/include/esp_netif_net_stack.h"
#include "components/esp_wifi/include/esp_wifi.h"
#include "components/lwip/include/apps/ping/ping_sock.h"
#include "lwip/sockets.h"
#if LWIP_IPV6_DHCP6
#include "lwip/dhcp6.h"
#endif
#if CIRCUITPY_MDNS
#include "common-hal/mdns/Server.h"
@ -445,6 +453,44 @@ mp_obj_t common_hal_wifi_radio_get_ipv4_subnet_ap(wifi_radio_obj_t *self) {
return common_hal_ipaddress_new_ipv4address(self->ap_ip_info.netmask.addr);
}
static mp_obj_t common_hal_wifi_radio_get_addresses_netif(wifi_radio_obj_t *self, esp_netif_t *netif) {
if (!esp_netif_is_netif_up(netif)) {
return mp_const_empty_tuple;
}
esp_netif_ip_info_t ip_info;
esp_netif_get_ip_info(netif, &ip_info);
int n_addresses4 = ip_info.ip.addr != INADDR_NONE;
#if CIRCUITPY_SOCKETPOOL_IPV6
esp_ip6_addr_t addresses[LWIP_IPV6_NUM_ADDRESSES];
int n_addresses6 = esp_netif_get_all_ip6(netif, &addresses[0]);
#else
int n_addresses6 = 0;
#endif
int n_addresses = n_addresses4 + n_addresses6;
mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_addresses, NULL));
#if CIRCUITPY_SOCKETPOOL_IPV6
for (int i = 0; i < n_addresses6; i++) {
result->items[i] = espaddr6_to_str(&addresses[i]);
}
#endif
if (n_addresses4) {
result->items[n_addresses6] = espaddr4_to_str(&ip_info.ip);
}
return MP_OBJ_FROM_PTR(result);
}
mp_obj_t common_hal_wifi_radio_get_addresses(wifi_radio_obj_t *self) {
return common_hal_wifi_radio_get_addresses_netif(self, self->netif);
}
mp_obj_t common_hal_wifi_radio_get_addresses_ap(wifi_radio_obj_t *self) {
return common_hal_wifi_radio_get_addresses_netif(self, self->ap_netif);
}
uint32_t wifi_radio_get_ipv4_address(wifi_radio_obj_t *self) {
if (!esp_netif_is_netif_up(self->netif)) {
return 0;
@ -476,6 +522,9 @@ mp_obj_t common_hal_wifi_radio_get_ipv4_dns(wifi_radio_obj_t *self) {
esp_netif_get_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &self->dns_info);
if (self->dns_info.ip.type != ESP_IPADDR_TYPE_V4) {
return mp_const_none;
}
// dns_info is of type esp_netif_dns_info_t, which is just ever so slightly
// different than esp_netif_ip_info_t used for
// common_hal_wifi_radio_get_ipv4_address (includes both ipv4 and 6),
@ -489,12 +538,31 @@ void common_hal_wifi_radio_set_ipv4_dns(wifi_radio_obj_t *self, mp_obj_t ipv4_dn
esp_netif_set_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &dns_addr);
}
void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self) {
esp_netif_dhcpc_start(self->netif);
void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self, bool ipv4, bool ipv6) {
if (ipv4) {
esp_netif_dhcpc_start(self->netif);
} else {
esp_netif_dhcpc_stop(self->netif);
}
#if LWIP_IPV6_DHCP6
if (ipv6) {
esp_netif_create_ip6_linklocal(self->netif);
dhcp6_enable_stateless(esp_netif_get_netif_impl(self->netif));
} else {
dhcp6_disable(esp_netif_get_netif_impl(self->netif));
}
#else
if (ipv6) {
mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_ipv6);
}
#endif
}
void common_hal_wifi_radio_stop_dhcp_client(wifi_radio_obj_t *self) {
esp_netif_dhcpc_stop(self->netif);
#if LWIP_IPV6_DHCP6
dhcp6_disable(esp_netif_get_netif_impl(self->netif));
#endif
}
void common_hal_wifi_radio_start_dhcp_server(wifi_radio_obj_t *self) {
@ -568,11 +636,11 @@ mp_int_t common_hal_wifi_radio_ping(wifi_radio_obj_t *self, mp_obj_t ip_address,
CHECK_ESP_RESULT(esp_ping_new_session(&ping_config, &ping_callbacks, &ping));
}
esp_ping_start(ping);
// Use all ones as a flag that the elapsed time was not set (ping failed or timed out).
self->ping_elapsed_time = (uint32_t)(-1);
esp_ping_start(ping);
uint32_t start_time = common_hal_time_monotonic_ms();
while ((self->ping_elapsed_time == (uint32_t)(-1)) &&
(common_hal_time_monotonic_ms() - start_time < timeout_ms) &&
@ -589,3 +657,38 @@ void common_hal_wifi_radio_gc_collect(wifi_radio_obj_t *self) {
// Only bother to scan the actual object references.
gc_collect_ptr(self->current_scan);
}
mp_obj_t common_hal_wifi_radio_get_dns(wifi_radio_obj_t *self) {
if (!esp_netif_is_netif_up(self->netif)) {
return mp_const_empty_tuple;
}
esp_netif_get_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &self->dns_info);
if (self->dns_info.ip.type == ESP_IPADDR_TYPE_V4 && self->dns_info.ip.u_addr.ip4.addr == INADDR_NONE) {
return mp_const_empty_tuple;
}
mp_obj_t args[] = {
espaddr_to_str(&self->dns_info.ip),
};
return mp_obj_new_tuple(1, args);
}
void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addrs_obj) {
mp_int_t len = mp_obj_get_int(mp_obj_len(dns_addrs_obj));
mp_arg_validate_length_max(len, 1, MP_QSTR_dns);
esp_netif_dns_info_t dns_info;
if (len == 0) {
// clear DNS server
dns_info.ip.type = ESP_IPADDR_TYPE_V4;
dns_info.ip.u_addr.ip4.addr = INADDR_NONE;
} else {
mp_obj_t dns_addr_obj = mp_obj_subscr(dns_addrs_obj, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL);
struct sockaddr_storage addr_storage;
socketpool_resolve_host_or_throw(AF_UNSPEC, SOCK_STREAM, mp_obj_str_get_str(dns_addr_obj), &addr_storage, 1);
sockaddr_to_espaddr(&addr_storage, &dns_info.ip);
}
esp_netif_set_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &dns_info);
}

View file

@ -11,6 +11,7 @@
#include "shared-bindings/ipaddress/IPv4Address.h"
#include "shared-bindings/wifi/Monitor.h"
#include "shared-bindings/wifi/Radio.h"
#include "common-hal/socketpool/__init__.h"
#include "py/gc.h"
#include "py/mpstate.h"
@ -27,6 +28,8 @@ wifi_radio_obj_t common_hal_wifi_radio_obj;
#include "supervisor/port.h"
#include "supervisor/workflow.h"
#include "lwip/sockets.h"
#if CIRCUITPY_STATUS_BAR
#include "supervisor/shared/status_bar.h"
#endif
@ -232,14 +235,16 @@ void wifi_reset(void) {
}
void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_address) {
if (!mp_obj_is_type(ip_address, &ipaddress_ipv4address_type)) {
mp_raise_ValueError(MP_ERROR_TEXT("Only IPv4 addresses supported"));
if (mp_obj_is_type(ip_address, &ipaddress_ipv4address_type)) {
ipaddress_ipaddress_to_esp_idf_ip4(ip_address, (esp_ip4_addr_t *)esp_ip_address);
#if LWIP_IPV6
esp_ip_address->type = IPADDR_TYPE_V4;
#endif
} else {
struct sockaddr_storage addr_storage;
socketpool_resolve_host_or_throw(AF_UNSPEC, SOCK_STREAM, mp_obj_str_get_str(ip_address), &addr_storage, 1);
sockaddr_to_espaddr(&addr_storage, (esp_ip_addr_t *)esp_ip_address);
}
mp_obj_t packed = common_hal_ipaddress_ipv4address_get_packed(ip_address);
size_t len;
const char *bytes = mp_obj_str_get_data(packed, &len);
IP_ADDR4(esp_ip_address, bytes[0], bytes[1], bytes[2], bytes[3]);
}
void ipaddress_ipaddress_to_esp_idf_ip4(mp_obj_t ip_address, esp_ip4_addr_t *esp_ip_address) {
@ -255,3 +260,94 @@ void ipaddress_ipaddress_to_esp_idf_ip4(mp_obj_t ip_address, esp_ip4_addr_t *esp
void common_hal_wifi_gc_collect(void) {
common_hal_wifi_radio_gc_collect(&common_hal_wifi_radio_obj);
}
static mp_obj_t espaddrx_to_str(const void *espaddr, uint8_t esptype) {
char buf[IPADDR_STRLEN_MAX];
inet_ntop(esptype == ESP_IPADDR_TYPE_V6 ? AF_INET6 : AF_INET, espaddr, buf, sizeof(buf));
return mp_obj_new_str(buf, strlen(buf));
}
mp_obj_t espaddr_to_str(const esp_ip_addr_t *espaddr) {
return espaddrx_to_str(espaddr, espaddr->type);
}
mp_obj_t espaddr4_to_str(const esp_ip4_addr_t *espaddr) {
return espaddrx_to_str(espaddr, ESP_IPADDR_TYPE_V4);
}
mp_obj_t espaddr6_to_str(const esp_ip6_addr_t *espaddr) {
return espaddrx_to_str(espaddr, ESP_IPADDR_TYPE_V6);
}
mp_obj_t sockaddr_to_str(const struct sockaddr_storage *sockaddr) {
char buf[IPADDR_STRLEN_MAX];
#if CIRCUITPY_SOCKETPOOL_IPV6
if (sockaddr->ss_family == AF_INET6) {
const struct sockaddr_in6 *addr6 = (const void *)sockaddr;
inet_ntop(AF_INET6, &addr6->sin6_addr, buf, sizeof(buf));
} else
#endif
{
const struct sockaddr_in *addr = (const void *)sockaddr;
inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf));
}
return mp_obj_new_str(buf, strlen(buf));
}
mp_obj_t sockaddr_to_tuple(const struct sockaddr_storage *sockaddr) {
mp_obj_t args[4] = {
sockaddr_to_str(sockaddr),
};
int n = 2;
#if CIRCUITPY_SOCKETPOOL_IPV6
if (sockaddr->ss_family == AF_INET6) {
const struct sockaddr_in6 *addr6 = (const void *)sockaddr;
args[1] = MP_OBJ_NEW_SMALL_INT(htons(addr6->sin6_port));
args[2] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_flowinfo);
args[3] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_scope_id);
n = 4;
} else
#endif
{
const struct sockaddr_in *addr = (const void *)sockaddr;
args[1] = MP_OBJ_NEW_SMALL_INT(htons(addr->sin_port));
}
return mp_obj_new_tuple(n, args);
}
void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t *espaddr) {
#if CIRCUITPY_SOCKETPOOL_IPV6
MP_STATIC_ASSERT(IPADDR_TYPE_V4 == ESP_IPADDR_TYPE_V4);
MP_STATIC_ASSERT(IPADDR_TYPE_V6 == ESP_IPADDR_TYPE_V6);
MP_STATIC_ASSERT(sizeof(ip_addr_t) == sizeof(esp_ip_addr_t));
MP_STATIC_ASSERT(offsetof(ip_addr_t, u_addr) == offsetof(esp_ip_addr_t, u_addr));
MP_STATIC_ASSERT(offsetof(ip_addr_t, type) == offsetof(esp_ip_addr_t, type));
if (sockaddr->ss_family == AF_INET6) {
const struct sockaddr_in6 *addr6 = (const void *)sockaddr;
MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip6.addr) == sizeof(addr6->sin6_addr));
memcpy(&espaddr->u_addr.ip6.addr, &addr6->sin6_addr, sizeof(espaddr->u_addr.ip6.addr));
espaddr->u_addr.ip6.zone = addr6->sin6_scope_id;
espaddr->type = ESP_IPADDR_TYPE_V6;
} else
#endif
{
const struct sockaddr_in *addr = (const void *)sockaddr;
MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip4.addr) == sizeof(addr->sin_addr));
memcpy(&espaddr->u_addr.ip4.addr, &addr->sin_addr, sizeof(espaddr->u_addr.ip4.addr));
espaddr->type = ESP_IPADDR_TYPE_V4;
}
}
void espaddr_to_sockaddr(const esp_ip_addr_t *espaddr, struct sockaddr_storage *sockaddr, int port) {
#if CIRCUITPY_SOCKETPOOL_IPV6
if (espaddr->type == ESP_IPADDR_TYPE_V6) {
struct sockaddr_in6 *addr6 = (void *)sockaddr;
memcpy(&addr6->sin6_addr, &espaddr->u_addr.ip6.addr, sizeof(espaddr->u_addr.ip6.addr));
addr6->sin6_scope_id = espaddr->u_addr.ip6.zone;
} else
#endif
{
struct sockaddr_in *addr = (void *)sockaddr;
memcpy(&addr->sin_addr, &espaddr->u_addr.ip4.addr, sizeof(espaddr->u_addr.ip4.addr));
}
}

View file

@ -11,7 +11,17 @@
#include "lwip/api.h"
#include "components/esp_wifi/include/esp_wifi.h"
struct sockaddr_storage;
void wifi_reset(void);
void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_address);
void ipaddress_ipaddress_to_esp_idf_ip4(mp_obj_t ip_address, esp_ip4_addr_t *esp_ip_address);
mp_obj_t sockaddr_to_str(const struct sockaddr_storage *addr);
mp_obj_t sockaddr_to_tuple(const struct sockaddr_storage *addr);
mp_obj_t espaddr_to_str(const esp_ip_addr_t *espaddr);
mp_obj_t espaddr4_to_str(const esp_ip4_addr_t *espaddr);
mp_obj_t espaddr6_to_str(const esp_ip6_addr_t *espaddr);
void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t *espaddr);
void espaddr_to_sockaddr(const esp_ip_addr_t *espaddr, struct sockaddr_storage *sockaddr, int port);

View file

@ -64,6 +64,12 @@ CONFIG_FREERTOS_HZ=1000
CONFIG_LWIP_MAX_SOCKETS=8
CONFIG_LWIP_SO_RCVBUF=y
#
# IPv6
#
CONFIG_LWIP_IPV6_AUTOCONFIG=y
CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS=2
CONFIG_LWIP_IPV6_DHCP6=y
#
# TCP
#
CONFIG_LWIP_MAX_ACTIVE_TCP=4

View file

@ -49,6 +49,7 @@ CIRCUITPY_SYNTHIO_MAX_CHANNELS ?= 12
CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1
CIRCUITPY_WATCHDOG ?= 1
CIRCUITPY_WIFI ?= 1
CIRCUITPY_SOCKETPOOL_IPV6 ?= 1
# Enable _eve module
CIRCUITPY__EVE ?= 1

View file

@ -18,11 +18,112 @@
#include "py/gc.h"
#include "py/misc.h"
#include "py/mpstate.h"
#include "mpconfigport.h"
#if CIRCUITPY_SERIAL_BLE && CIRCUITPY_VERBOSE_BLE
#include "supervisor/shared/bluetooth/serial.h"
#endif
#if CIRCUITPY_VERBOSE_BLE
const char *ble_drv_evt_name(uint32_t evt) {
switch (evt) {
case BLE_GAP_EVT_CONNECTED:
return "BLE_GAP_EVT_CONNECTED";
case BLE_GAP_EVT_DISCONNECTED:
return "BLE_GAP_EVT_DISCONNECTED";
case BLE_GAP_EVT_CONN_PARAM_UPDATE:
return "BLE_GAP_EVT_CONN_PARAM_UPDATE";
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
return "BLE_GAP_EVT_SEC_PARAMS_REQUEST";
case BLE_GAP_EVT_SEC_INFO_REQUEST:
return "BLE_GAP_EVT_SEC_INFO_REQUEST";
case BLE_GAP_EVT_PASSKEY_DISPLAY:
return "BLE_GAP_EVT_PASSKEY_DISPLAY";
case BLE_GAP_EVT_KEY_PRESSED:
return "BLE_GAP_EVT_KEY_PRESSED";
case BLE_GAP_EVT_AUTH_KEY_REQUEST:
return "BLE_GAP_EVT_AUTH_KEY_REQUEST";
case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
return "BLE_GAP_EVT_LESC_DHKEY_REQUEST";
case BLE_GAP_EVT_AUTH_STATUS:
return "BLE_GAP_EVT_AUTH_STATUS";
case BLE_GAP_EVT_CONN_SEC_UPDATE:
return "BLE_GAP_EVT_CONN_SEC_UPDATE";
case BLE_GAP_EVT_TIMEOUT:
return "BLE_GAP_EVT_TIMEOUT";
case BLE_GAP_EVT_RSSI_CHANGED:
return "BLE_GAP_EVT_RSSI_CHANGED";
case BLE_GAP_EVT_ADV_REPORT:
return "BLE_GAP_EVT_ADV_REPORT";
case BLE_GAP_EVT_SEC_REQUEST:
return "BLE_GAP_EVT_SEC_REQUEST";
case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
return "BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST";
case BLE_GAP_EVT_SCAN_REQ_REPORT:
return "BLE_GAP_EVT_SCAN_REQ_REPORT";
case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
return "BLE_GAP_EVT_PHY_UPDATE_REQUEST";
case BLE_GAP_EVT_PHY_UPDATE:
return "BLE_GAP_EVT_PHY_UPDATE";
case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
return "BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST";
case BLE_GAP_EVT_DATA_LENGTH_UPDATE:
return "BLE_GAP_EVT_DATA_LENGTH_UPDATE";
case BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT:
return "BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT";
case BLE_GAP_EVT_ADV_SET_TERMINATED:
return "BLE_GAP_EVT_ADV_SET_TERMINATED";
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
return "BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP";
case BLE_GATTC_EVT_REL_DISC_RSP:
return "BLE_GATTC_EVT_REL_DISC_RSP";
case BLE_GATTC_EVT_CHAR_DISC_RSP:
return "BLE_GATTC_EVT_CHAR_DISC_RSP";
case BLE_GATTC_EVT_DESC_DISC_RSP:
return "BLE_GATTC_EVT_DESC_DISC_RSP";
case BLE_GATTC_EVT_ATTR_INFO_DISC_RSP:
return "BLE_GATTC_EVT_ATTR_INFO_DISC_RSP";
case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP:
return "BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP";
case BLE_GATTC_EVT_READ_RSP:
return "BLE_GATTC_EVT_READ_RSP";
case BLE_GATTC_EVT_CHAR_VALS_READ_RSP:
return "BLE_GATTC_EVT_CHAR_VALS_READ_RSP";
case BLE_GATTC_EVT_WRITE_RSP:
return "BLE_GATTC_EVT_WRITE_RSP";
case BLE_GATTC_EVT_HVX:
return "BLE_GATTC_EVT_HVX";
case BLE_GATTC_EVT_EXCHANGE_MTU_RSP:
return "BLE_GATTC_EVT_EXCHANGE_MTU_RSP";
case BLE_GATTC_EVT_TIMEOUT:
return "BLE_GATTC_EVT_TIMEOUT";
case BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE:
return "BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE";
case BLE_GATTS_EVT_WRITE:
return "BLE_GATTS_EVT_WRITE";
case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
return "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST";
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
return "BLE_GATTS_EVT_SYS_ATTR_MISSING";
case BLE_GATTS_EVT_HVC:
return "BLE_GATTS_EVT_HVC";
case BLE_GATTS_EVT_SC_CONFIRM:
return "BLE_GATTS_EVT_SC_CONFIRM";
case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
return "BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST";
case BLE_GATTS_EVT_TIMEOUT:
return "BLE_GATTS_EVT_TIMEOUT";
case BLE_GATTS_EVT_HVN_TX_COMPLETE:
return "BLE_GATTS_EVT_HVN_TX_COMPLETE";
default:
return "unknown EVT";
}
};
#endif
nrf_nvic_state_t nrf_nvic_state = { 0 };
// Flag indicating progress of internal flash operation.
@ -143,14 +244,11 @@ void SD_EVT_IRQHandler(void) {
}
ble_evt_t *event = (ble_evt_t *)m_ble_evt_buf;
#if CIRCUITPY_VERBOSE_BLE
size_t eid = event->header.evt_id;
if (eid != 0x1d) {
if (BLE_GAP_EVT_BASE <= eid && eid <= BLE_GAP_EVT_LAST) {
mp_printf(&mp_plat_print, "BLE GAP event: %d\n", eid - BLE_GAP_EVT_BASE);
} else {
mp_printf(&mp_plat_print, "BLE event: 0x%04x\n", event->header.evt_id);
}
if (eid != BLE_GAP_EVT_ADV_REPORT) {
mp_printf(&mp_plat_print, "BLE event: %s (0x%04x)\n", ble_drv_evt_name(eid), eid);
}
#endif

View file

@ -668,15 +668,20 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre
}
}
// Negotiate for better PHY, larger MTU and data lengths since we are the central. These are
// nice-to-haves so ignore any errors.
// Negotiate for better PHY, larger MTU and data lengths since we are the central.
// The peer may decline, which is its prerogative.
ble_gap_phys_t const phys = {
.rx_phys = BLE_GAP_PHY_AUTO,
.tx_phys = BLE_GAP_PHY_AUTO,
};
sd_ble_gap_phy_update(conn_handle, &phys);
sd_ble_gattc_exchange_mtu_request(conn_handle, BLE_GATTS_VAR_ATTR_LEN_MAX);
sd_ble_gap_data_length_update(conn_handle, NULL, NULL);
// The MTU size passed here has to match the value passed in the BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST
// event handler in Connection.c, per the SD doc:
// "The value must be equal to Server RX MTU size given in
// sd_ble_gatts_exchange_mtu_reply if an ATT_MTU exchange has
// already been performed in the other direction."
check_nrf_error(sd_ble_gattc_exchange_mtu_request(conn_handle, BLE_GATTS_VAR_ATTR_LEN_MAX));
check_nrf_error(sd_ble_gap_data_length_update(conn_handle, NULL, NULL));
// Make the connection object and return it.
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {

View file

@ -113,13 +113,15 @@ bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
if (self->mtu > 0) {
new_mtu = self->mtu;
}
self->mtu = new_mtu;
sd_ble_gatts_exchange_mtu_reply(self->conn_handle, new_mtu);
// The MTU size passed here has to match the value passed in Adapter.c, per the SD doc:
// "The value must be equal to Client RX MTU size given in
// sd_ble_gattc_exchange_mtu_request if an ATT_MTU exchange has
// already been performed in the other direction."
check_nrf_error(sd_ble_gatts_exchange_mtu_reply(self->conn_handle, BLE_GATTS_VAR_ATTR_LEN_MAX));
break;
}
case BLE_GATTC_EVT_EXCHANGE_MTU_RSP: {
ble_gattc_evt_exchange_mtu_rsp_t *response =
&ble_evt->evt.gattc_evt.params.exchange_mtu_rsp;

View file

@ -78,9 +78,11 @@ void common_hal_bleio_init(void) {
}
void bleio_user_reset() {
// Stop any user scanning or advertising.
common_hal_bleio_adapter_stop_scan(&common_hal_bleio_adapter_obj);
common_hal_bleio_adapter_stop_advertising(&common_hal_bleio_adapter_obj);
if (common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) {
// Stop any user scanning or advertising.
common_hal_bleio_adapter_stop_scan(&common_hal_bleio_adapter_obj);
common_hal_bleio_adapter_stop_advertising(&common_hal_bleio_adapter_obj);
}
ble_drv_remove_heap_handlers();

View file

@ -146,32 +146,33 @@ static int _set_vid(void) {
vid_setting = value;
/*
Voltage Divider with 3.3V: (1241 * V)
10K/ 15K = 1.98V = 2458
15K/ 10K = 1.32V = 1638
15K/4.7K = 0.79V = 980
15K/ 2K = 1.32V = 482
15K/ 1K = 1.32V = 256
10K/ 15K = 1.98V = 2458 GT 2000 = TBD
15K/ 10K = 1.32V = 1638 GT 1200 = Explorer with SSD1681 BW
15K/4.7K = 0.79V = 980 GT 600 = Explorer with SSD1681 BWR
15K/ 2K = 0.39V = 482 GT 300 = Explorer with SSD1608 BW
100K/ 10K = 0.30V = 372 ditto
15K/ 1K = 0.21V = 256 GT 150 = DCNextGen with SSD1681 BWR
Note: extreme values (using 100K or greater) will not create a strong enough current for the ADC to read accurately
Note: we do not get a usable value when the voltage divider is missing
*/
// TODO change to min/max to tighten up the ranges (requires sampling of the initial boards)
if (value > 2800) {
vid_setting = 9;
vid_setting = 9; // invalid
} else if (value > 2000) {
vid_setting = 5;
vid_setting = 5; // future
} else if (value > 1200) {
vid_setting = 4;
vid_setting = 4; // Explorer SSD1681 BW
} else if (value > 600) {
vid_setting = 3;
vid_setting = 3; // Explorer SSD1681 BWR
} else if (value > 300) {
vid_setting = 2;
vid_setting = 2; // Explorer SSD1608 BW
} else if (value > 150) {
vid_setting = 1;
vid_setting = 1; // DCNextGen SSD1681 BWR
} else {
vid_setting = 0;
}
vid_setting = 0; // invalid
}
return vid_setting;
}
@ -227,8 +228,29 @@ void board_init(void) {
display = &allocate_display()->epaper_display;
display->base.type = &epaperdisplay_epaperdisplay_type;
// VID codes: 1 = tricolor ePaper (BWR), 2 = monochrome ePaper (BW), other codes are TBD
// default to no rotation
int rotation = 0;
if (vid_setting == 1) {
// DCNextGen SSD1681 BWR rotated 270
rotation = 270;
}
// default to BWR refresh rates
float refresh_time = 15.0;
float seconds_per_frame = 20.0;
if ((vid_setting == 2) || (vid_setting == 4)) {
// BW displays have faster refresh rates
refresh_time = 1.0;
seconds_per_frame = 5.0;
}
// VID 1, 3, and 4 = SSD1681 display driver
// VID 2 = SSD1608 display driver
// VID codes: see above
if ((vid_setting == 1) || // DCNextGen SSD1681 BWR rotated 270
(vid_setting == 3) || // Explorer SSD1681 BW rotated 0
(vid_setting == 4)) { // Explorer SSD1681 BWR rotated 0
common_hal_epaperdisplay_epaperdisplay_construct(
display,
bus,
@ -241,7 +263,7 @@ void board_init(void) {
HEIGHT + 0x60, // ram_height RAM is actually only 200 bits high but we use 296 to match the 9 bits
0, // colstart
0, // rowstart
270, // rotation
rotation, // rotation
SSD_SET_RAMXPOS, // set_column_window_command
SSD_SET_RAMYPOS, // set_row_window_command
SSD_SET_RAMXCOUNT, // set_current_column_command
@ -252,16 +274,16 @@ void board_init(void) {
false, // color_bits_inverted
0xFF0000, // highlight_color (RED for tri-color display)
_refresh_sequence_ssd1681, sizeof(_refresh_sequence_ssd1681), // refresh_display_command
15.0, // refresh_time
refresh_time, // refresh_time
&pin_GPIO9, // DEFAULT_SPI_BUS_BUSY, // busy_pin
true, // busy_state
20.0, // seconds_per_frame (does not seem the user can change this)
seconds_per_frame, // seconds_per_frame (does not seem the user can change this)
true, // always_toggle_chip_select
false, // not grayscale
false, // not acep
false, // not two_byte_sequence_length
true); // address_little_endian
} else if (vid_setting == 2) {
} else if (vid_setting == 2) { // Explorer SSD1608 BW
common_hal_epaperdisplay_epaperdisplay_construct(
display,
bus,
@ -274,7 +296,7 @@ void board_init(void) {
HEIGHT /* + 0x60 */, // ram_height RAM is actually only 200 bits high but we use 296 to match the 9 bits
0, // colstart
0, // rowstart
0, // rotation
rotation, // rotation
SSD_SET_RAMXPOS, // set_column_window_command
SSD_SET_RAMYPOS, // set_row_window_command
SSD_SET_RAMXCOUNT, // set_current_column_command
@ -285,10 +307,10 @@ void board_init(void) {
false, // color_bits_inverted
0x000000, // highlight_color (RED for tri-color display)
_refresh_sequence_ssd1608, sizeof(_refresh_sequence_ssd1608), // refresh_display_command
1.0, // refresh_time
refresh_time, // refresh_time
&pin_GPIO9, // DEFAULT_SPI_BUS_BUSY, // busy_pin
true, // busy_state
5.0, // seconds_per_frame (does not seem the user can change this)
seconds_per_frame, // seconds_per_frame (does not seem the user can change this)
true, // always_toggle_chip_select
false, // not grayscale
false, // not acep

View file

@ -58,19 +58,36 @@ void common_hal_analogbufio_bufferedin_construct(analogbufio_bufferedin_obj_t *s
float clk_div = (float)ADC_CLOCK_INPUT / (float)sample_rate - 1;
adc_set_clkdiv(clk_div);
self->dma_chan[0] = dma_claim_unused_channel(true);
self->dma_chan[1] = dma_claim_unused_channel(true);
// Set up the DMA to start transferring data as soon as it appears in FIFO
uint dma_chan = dma_claim_unused_channel(true);
self->dma_chan = dma_chan;
// Set Config
self->cfg = dma_channel_get_default_config(dma_chan);
// Channel 0 reads from ADC data register and writes to buffer
self->cfg[0] = dma_channel_get_default_config(self->dma_chan[0]);
// Reading from constant address, writing to incrementing byte addresses
channel_config_set_read_increment(&(self->cfg), false);
channel_config_set_write_increment(&(self->cfg), true);
channel_config_set_read_increment(&(self->cfg[0]), false);
channel_config_set_write_increment(&(self->cfg[0]), true);
// Pace transfers based on availability of ADC samples
channel_config_set_dreq(&(self->cfg), DREQ_ADC);
channel_config_set_dreq(&(self->cfg[0]), DREQ_ADC);
channel_config_set_chain_to(&(self->cfg[0]), self->dma_chan[0]);
// If we want to loop, later we'll set channel 0 to chain to channel 1 instead.
// Channel 1 resets channel 0's write address and restarts it
self->cfg[1] = dma_channel_get_default_config(self->dma_chan[1]);
// Read from incrementing address
channel_config_set_read_increment(&(self->cfg[1]), true);
// Write to constant address (data dma write address register)
channel_config_set_write_increment(&(self->cfg[1]), false);
// Writing to 32-bit register
channel_config_set_transfer_data_size(&(self->cfg[1]), DMA_SIZE_32);
// Run as fast as possible
channel_config_set_dreq(&(self->cfg[1]), 0x3F);
// set ring to read one 32-bit value (the starting write address) over and over
channel_config_set_ring(&(self->cfg[1]), false, 2); // ring is 1<<2 = 4 bytes
// Chain to adc channel
channel_config_set_chain_to(&(self->cfg[1]), self->dma_chan[0]);
// clear any previous activity
adc_fifo_drain();
@ -86,15 +103,22 @@ void common_hal_analogbufio_bufferedin_deinit(analogbufio_bufferedin_obj_t *self
return;
}
// stop DMA
dma_channel_abort(self->dma_chan[0]);
dma_channel_abort(self->dma_chan[1]);
// Release ADC Pin
reset_pin_number(self->pin->number);
self->pin = NULL;
// Release DMA Channel
dma_channel_unclaim(self->dma_chan);
dma_channel_unclaim(self->dma_chan[0]);
dma_channel_unclaim(self->dma_chan[1]);
}
uint32_t common_hal_analogbufio_bufferedin_readinto(analogbufio_bufferedin_obj_t *self, uint8_t *buffer, uint32_t len, uint8_t bytes_per_sample) {
uint8_t *active_buffer;
uint32_t common_hal_analogbufio_bufferedin_readinto(analogbufio_bufferedin_obj_t *self, uint8_t *buffer, uint32_t len, uint8_t bytes_per_sample, bool loop) {
// RP2040 Implementation Detail
// Fills the supplied buffer with ADC values using DMA transfer.
// If the buffer is 8-bit, then values are 8-bit shifted and error bit is off.
@ -120,48 +144,77 @@ uint32_t common_hal_analogbufio_bufferedin_readinto(analogbufio_bufferedin_obj_t
uint32_t sample_count = len / bytes_per_sample;
channel_config_set_transfer_data_size(&(self->cfg), dma_size);
channel_config_set_transfer_data_size(&(self->cfg[0]), dma_size);
dma_channel_configure(self->dma_chan, &(self->cfg),
buffer, // dst
&adc_hw->fifo, // src
sample_count, // transfer count
true // start immediately
);
if (!loop) { // Set DMA to stop after one one set of transfers
channel_config_set_chain_to(&(self->cfg[0]), self->dma_chan[0]);
dma_channel_configure(self->dma_chan[0], &(self->cfg[0]),
buffer, // dst
&adc_hw->fifo, // src
sample_count, // transfer count
true // start immediately
);
// Start the ADC
adc_run(true);
// Start the ADC
adc_run(true);
// Once DMA finishes, stop any new conversions from starting, and clean up
// the FIFO in case the ADC was still mid-conversion.
uint32_t remaining_transfers = sample_count;
while (dma_channel_is_busy(self->dma_chan) &&
!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
}
remaining_transfers = dma_channel_hw_addr(self->dma_chan)->transfer_count;
// Clean up
adc_run(false);
// Stopping early so abort.
if (dma_channel_is_busy(self->dma_chan)) {
dma_channel_abort(self->dma_chan);
}
adc_fifo_drain();
size_t captured_count = sample_count - remaining_transfers;
if (dma_size == DMA_SIZE_16) {
uint16_t *buf16 = (uint16_t *)buffer;
for (size_t i = 0; i < captured_count; i++) {
uint16_t value = buf16[i];
// Check the error bit and "truncate" the buffer if there is an error.
if ((value & ADC_FIFO_ERR_BITS) != 0) {
captured_count = i;
break;
}
// Scale the values to the standard 16 bit range.
buf16[i] = (value << 4) | (value >> 8);
// Wait for DMA to finish, then stop any new conversions from starting,
// and clean up the FIFO in case the ADC was still mid-conversion.
uint32_t remaining_transfers = sample_count;
while (dma_channel_is_busy(self->dma_chan[0]) &&
!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
}
remaining_transfers = dma_channel_hw_addr(self->dma_chan[0])->transfer_count;
// Clean up
adc_run(false);
// If we stopped early, stop DMA
if (dma_channel_is_busy(self->dma_chan[0])) {
dma_channel_abort(self->dma_chan[0]);
}
adc_fifo_drain();
// Scale the values to the standard 16 bit range.
size_t captured_count = sample_count - remaining_transfers;
if (dma_size == DMA_SIZE_16) {
uint16_t *buf16 = (uint16_t *)buffer;
for (size_t i = 0; i < captured_count; i++) {
uint16_t value = buf16[i];
// Check the error bit and "truncate" the buffer if there is an error.
if ((value & ADC_FIFO_ERR_BITS) != 0) {
captured_count = i;
break;
}
buf16[i] = (value << 4) | (value >> 8);
}
}
return captured_count;
} else { // Set DMA to repeat transfers indefinitely
dma_channel_configure(self->dma_chan[1], &(self->cfg[1]),
&dma_hw->ch[self->dma_chan[0]].al2_write_addr_trig, // write address
&active_buffer, // read address
1, // transfer count
false // don't start yet
);
// put the buffer start address into a global so that it can be read by DMA
// and written into channel 0's write address
active_buffer = buffer;
channel_config_set_chain_to(&(self->cfg[0]), self->dma_chan[1]);
dma_channel_configure(self->dma_chan[0], &(self->cfg[0]),
buffer, // write address
&adc_hw->fifo, // read address
sample_count, // transfer count
true // start immediately
);
// Start the ADC
adc_run(true);
return 0;
}
return captured_count;
}

View file

@ -17,6 +17,6 @@ typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t *pin;
uint8_t chan;
uint dma_chan;
dma_channel_config cfg;
uint dma_chan[2];
dma_channel_config cfg[2];
} analogbufio_bufferedin_obj_t;

View file

@ -21,6 +21,7 @@
#include "supervisor/port.h"
#include "supervisor/shared/tick.h"
#include "supervisor/workflow.h"
#include "common-hal/socketpool/__init__.h"
#include "lwip/dns.h"
#include "lwip/err.h"
@ -36,6 +37,36 @@
#include "sdk/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch.h"
mp_obj_t socketpool_ip_addr_to_str(const ip_addr_t *addr) {
char ip_str[IPADDR_STRLEN_MAX]; // big enough for any supported address type
switch (IP_GET_TYPE(addr)) {
#if CIRCUITPY_SOCKETPOOL_IPV6
case IPADDR_TYPE_V6:
ip6addr_ntoa_r(ip_2_ip6(addr), ip_str, sizeof(ip_str));
break;
#endif
default:
ip4addr_ntoa_r(ip_2_ip4(addr), ip_str, sizeof(ip_str));
}
return mp_obj_new_str(ip_str, strlen(ip_str));
}
static mp_obj_t socketpool_ip_addr_and_port_to_tuple(const ip_addr_t *addr, int port) {
mp_obj_t args[CIRCUITPY_SOCKETPOOL_IPV6 ? 4 : 2] = {
socketpool_ip_addr_to_str(addr),
MP_OBJ_NEW_SMALL_INT(port),
};
int n = 2;
#if CIRCUITPY_SOCKETPOOL_IPV6
if (IP_GET_TYPE(addr) == IPADDR_TYPE_V6) {
items[2] = MP_OBJ_NEW_SMALL_INT(0); // sin6_flowinfo
items[3] = MP_OBJ_NEW_SMALL_INT(ip_2_ip6(addr)->zone);
n = 4;
}
#endif
return mp_obj_new_tuple(n, args);
}
#define MICROPY_PY_LWIP_SOCK_RAW (1)
#if 0 // print debugging info
@ -380,7 +411,7 @@ static mp_uint_t lwip_raw_udp_send(socketpool_socket_obj_t *socket, const byte *
}
// Helper function for recv/recvfrom to handle raw/UDP packets
static mp_uint_t lwip_raw_udp_receive(socketpool_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, uint32_t *port, int *_errno) {
static mp_uint_t lwip_raw_udp_receive(socketpool_socket_obj_t *socket, byte *buf, mp_uint_t len, mp_obj_t *peer_out, int *_errno) {
if (socket->incoming.pbuf == NULL) {
if (socket->timeout == 0) {
@ -400,9 +431,8 @@ static mp_uint_t lwip_raw_udp_receive(socketpool_socket_obj_t *socket, byte *buf
}
}
if (ip != NULL) {
memcpy(ip, &socket->peer, sizeof(socket->peer));
*port = socket->peer_port;
if (peer_out != NULL) {
*peer_out = socketpool_ip_addr_and_port_to_tuple(&socket->peer, socket->peer_port);
}
struct pbuf *p = socket->incoming.pbuf;
@ -726,7 +756,7 @@ socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_
return socket;
}
int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_t *port, socketpool_socket_obj_t *accepted) {
int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, socketpool_socket_obj_t *accepted) {
if (self->type != MOD_NETWORK_SOCK_STREAM) {
return -MP_EOPNOTSUPP;
}
@ -808,20 +838,21 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_
MICROPY_PY_LWIP_EXIT
// output values
memcpy(ip, &(accepted->pcb.tcp->remote_ip), NETUTILS_IPV4ADDR_BUFSIZE);
*port = (mp_uint_t)accepted->pcb.tcp->remote_port;
if (peer_out) {
*peer_out = socketpool_ip_addr_and_port_to_tuple(&accepted->pcb.tcp->remote_ip, accepted->pcb.tcp->remote_port);
}
return 1;
}
socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *socket,
uint8_t *ip, uint32_t *port) {
mp_obj_t *peer_out) {
// Create new socket object, do it here because we must not raise an out-of-memory
// exception when the LWIP concurrency lock is held
socketpool_socket_obj_t *accepted = m_new_obj_with_finaliser(socketpool_socket_obj_t);
socketpool_socket_reset(accepted);
int ret = socketpool_socket_accept(socket, ip, port, accepted);
int ret = socketpool_socket_accept(socket, peer_out, accepted);
if (ret <= 0) {
m_del_obj(socketpool_socket_obj_t, accepted);
@ -852,7 +883,7 @@ size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *socket,
ip_addr_t bind_addr;
const ip_addr_t *bind_addr_ptr = &bind_addr;
if (hostlen > 0) {
socketpool_resolve_host_raise(socket->pool, host, &bind_addr);
socketpool_resolve_host_raise(host, &bind_addr);
} else {
bind_addr_ptr = IP_ANY_TYPE;
}
@ -941,7 +972,7 @@ void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *socket,
// get address
ip_addr_t dest;
socketpool_resolve_host_raise(socket->pool, host, &dest);
socketpool_resolve_host_raise(host, &dest);
err_t err = ERR_ARG;
switch (socket->type) {
@ -966,7 +997,7 @@ void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *socket,
mp_raise_OSError(error_lookup_table[-err]);
}
socket->peer_port = (mp_uint_t)port;
memcpy(socket->peer, &dest, sizeof(socket->peer));
memcpy(&socket->peer, &dest, sizeof(socket->peer));
MICROPY_PY_LWIP_EXIT
// And now we wait...
@ -1054,14 +1085,17 @@ bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *socket, int ba
}
mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *socket,
uint8_t *buf, uint32_t len, uint8_t *ip, uint32_t *port) {
uint8_t *buf, uint32_t len, mp_obj_t *peer_out) {
int _errno;
mp_uint_t ret = 0;
switch (socket->type) {
case SOCKETPOOL_SOCK_STREAM: {
memcpy(ip, &socket->peer, sizeof(socket->peer));
*port = (mp_uint_t)socket->peer_port;
// output values
if (peer_out) {
*peer_out = socketpool_ip_addr_and_port_to_tuple(&socket->peer, socket->peer_port);
}
ret = lwip_tcp_receive(socket, (byte *)buf, len, &_errno);
break;
}
@ -1069,7 +1103,7 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *so
#if MICROPY_PY_LWIP_SOCK_RAW
case SOCKETPOOL_SOCK_RAW:
#endif
ret = lwip_raw_udp_receive(socket, (byte *)buf, len, ip, port, &_errno);
ret = lwip_raw_udp_receive(socket, (byte *)buf, len, peer_out, &_errno);
break;
}
if (ret == (unsigned)-1) {
@ -1092,7 +1126,7 @@ int socketpool_socket_recv_into(socketpool_socket_obj_t *socket,
#if MICROPY_PY_LWIP_SOCK_RAW
case SOCKETPOOL_SOCK_RAW:
#endif
ret = lwip_raw_udp_receive(socket, (byte *)buf, len, NULL, NULL, &_errno);
ret = lwip_raw_udp_receive(socket, (byte *)buf, len, NULL, &_errno);
break;
}
if (ret == (unsigned)-1) {
@ -1143,7 +1177,7 @@ mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *socket,
const char *host, size_t hostlen, uint32_t port, const uint8_t *buf, uint32_t len) {
int _errno;
ip_addr_t ip;
socketpool_resolve_host_raise(socket->pool, host, &ip);
socketpool_resolve_host_raise(host, &ip);
mp_uint_t ret = 0;
switch (socket->type) {

View file

@ -35,7 +35,7 @@ typedef struct _lwip_socket_obj_t {
} connection;
} incoming;
mp_obj_t callback;
byte peer[4];
ip_addr_t peer;
mp_uint_t peer_port;
mp_uint_t timeout;
uint16_t recv_offset;

View file

@ -5,10 +5,12 @@
// SPDX-License-Identifier: MIT
#include "shared-bindings/socketpool/SocketPool.h"
#include "common-hal/socketpool/__init__.h"
#include "common-hal/socketpool/Socket.h"
#include "shared/runtime/interrupt_char.h"
#include "py/runtime.h"
#include "shared-bindings/wifi/__init__.h"
#include "shared-bindings/ipaddress/__init__.h"
#include "lwip/dns.h"
#include "lwip/inet.h"
@ -21,72 +23,10 @@ void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *sel
// common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking.
typedef struct _getaddrinfo_state_t {
volatile int status;
volatile ip_addr_t ipaddr;
} getaddrinfo_state_t;
static void lwip_getaddrinfo_cb(const char *name, const ip_addr_t *ipaddr, void *arg) {
getaddrinfo_state_t *state = arg;
if (ipaddr != NULL) {
state->status = 1;
state->ipaddr = *ipaddr;
} else {
// error
state->status = -2;
}
}
static int socketpool_resolve_host(socketpool_socketpool_obj_t *self, const char *host, ip_addr_t *addr) {
getaddrinfo_state_t state;
state.status = 0;
MICROPY_PY_LWIP_ENTER
err_t ret = dns_gethostbyname(host, (ip_addr_t *)&state.ipaddr, lwip_getaddrinfo_cb, &state);
MICROPY_PY_LWIP_EXIT
switch (ret) {
case ERR_OK:
// cached
state.status = 1;
break;
case ERR_INPROGRESS:
while (state.status == 0) {
RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
break;
}
}
break;
default:
state.status = ret;
}
if (state.status < 0) {
return state.status;
// TODO: CPython raises gaierror, we raise with native lwIP negative error
// values, to differentiate from normal errno's at least in such way.
mp_raise_OSError(state.status);
}
*addr = state.ipaddr;
return 0;
}
void socketpool_resolve_host_raise(socketpool_socketpool_obj_t *self, const char *host, ip_addr_t *addr) {
int result = socketpool_resolve_host(self, host, addr);
if (result < 0) {
printf("socket_resolve_host() returned %d\n", result);
common_hal_socketpool_socketpool_raise_gaierror_noname();
mp_raise_OSError(-result);
}
}
mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_obj_t *self, const char *host) {
static mp_obj_t common_hal_socketpool_socketpool_gethostbyname_raise(socketpool_socketpool_obj_t *self, const char *host) {
ip_addr_t addr;
socketpool_resolve_host_raise(self, host, &addr);
socketpool_resolve_host_raise(host, &addr);
char ip_str[IP4ADDR_STRLEN_MAX];
inet_ntoa_r(addr, ip_str, IP4ADDR_STRLEN_MAX);
@ -94,6 +34,23 @@ mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_ob
return ip_obj;
}
mp_obj_t common_hal_socketpool_socketpool_gethostbyname_raise(socketpool_socketpool_obj_t *self, const char *host) {
return common_hal_socketpool_socketpool_gethostbyname(self, host);
mp_obj_t common_hal_socketpool_getaddrinfo_raise(socketpool_socketpool_obj_t *self, const char *host, int port, int family, int type, int proto, int flags) {
mp_obj_t ip_str;
if (strlen(host) > 0 && ipaddress_parse_ipv4address(host, strlen(host), NULL)) {
ip_str = mp_obj_new_str(host, strlen(host));
} else {
ip_str = common_hal_socketpool_socketpool_gethostbyname_raise(self, host);
}
mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL));
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(SOCKETPOOL_AF_INET);
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCKETPOOL_SOCK_STREAM);
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
mp_obj_tuple_t *sockaddr = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
sockaddr->items[0] = ip_str;
sockaddr->items[1] = MP_OBJ_NEW_SMALL_INT(port);
tuple->items[4] = MP_OBJ_FROM_PTR(sockaddr);
return mp_obj_new_list(1, (mp_obj_t *)&tuple);
}

View file

@ -13,5 +13,3 @@
typedef struct {
mp_obj_base_t base;
} socketpool_socketpool_obj_t;
void socketpool_resolve_host_raise(socketpool_socketpool_obj_t *self, const char *host, ip_addr_t *addr);

View file

@ -4,10 +4,78 @@
//
// SPDX-License-Identifier: MIT
#include "shared-bindings/socketpool/__init__.h"
#include "py/runtime.h"
#include "shared/runtime/interrupt_char.h"
#include "shared-bindings/socketpool/__init__.h"
#include "shared-bindings/socketpool/SocketPool.h"
#include "shared-bindings/wifi/__init__.h"
#include "common-hal/socketpool/__init__.h"
#include "lwip/dns.h"
#include "lwip/inet.h"
#include "common-hal/socketpool/Socket.h"
void socketpool_user_reset(void) {
socket_user_reset();
}
typedef struct _getaddrinfo_state_t {
volatile int status;
volatile ip_addr_t ipaddr;
} getaddrinfo_state_t;
static void lwip_getaddrinfo_cb(const char *name, const ip_addr_t *ipaddr, void *arg) {
getaddrinfo_state_t *state = arg;
if (ipaddr != NULL) {
state->status = 1;
state->ipaddr = *ipaddr;
} else {
// error
state->status = -2;
}
}
static int socketpool_resolve_host(const char *host, ip_addr_t *addr) {
getaddrinfo_state_t state;
state.status = 0;
MICROPY_PY_LWIP_ENTER
err_t ret = dns_gethostbyname(host, (ip_addr_t *)&state.ipaddr, lwip_getaddrinfo_cb, &state);
MICROPY_PY_LWIP_EXIT
switch (ret) {
case ERR_OK:
// cached
state.status = 1;
break;
case ERR_INPROGRESS:
while (state.status == 0) {
RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
break;
}
}
break;
default:
state.status = ret;
}
if (state.status < 0) {
return state.status;
}
*addr = state.ipaddr;
return 0;
}
void socketpool_resolve_host_raise(const char *host, ip_addr_t *addr) {
int result = socketpool_resolve_host(host, addr);
if (result < 0) {
printf("socket_resolve_host() returned %d\n", result);
common_hal_socketpool_socketpool_raise_gaierror_noname();
mp_raise_OSError(-result);
}
}

View file

@ -5,3 +5,8 @@
// SPDX-License-Identifier: MIT
#pragma once
#include "lwip/ip_addr.h"
mp_obj_t socketpool_ip_addr_to_str(const ip_addr_t *addr);
void socketpool_resolve_host_raise(const char *host, ip_addr_t *addr);

View file

@ -21,6 +21,7 @@
#include "shared-bindings/wifi/AuthMode.h"
#include "shared-bindings/time/__init__.h"
#include "shared-module/ipaddress/__init__.h"
#include "common-hal/socketpool/__init__.h"
#include "lwip/sys.h"
#include "lwip/dns.h"
@ -405,8 +406,15 @@ void common_hal_wifi_radio_set_ipv4_dns(wifi_radio_obj_t *self, mp_obj_t ipv4_dn
dns_setserver(0, &addr);
}
void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self) {
dhcp_start(NETIF_STA);
void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self, bool ipv4, bool ipv6) {
if (ipv4) {
dhcp_start(NETIF_STA);
} else {
dhcp_stop(NETIF_STA);
}
if (ipv6) {
mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_ipv6);
}
}
void common_hal_wifi_radio_stop_dhcp_client(wifi_radio_obj_t *self) {
@ -481,7 +489,11 @@ ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr)
mp_int_t common_hal_wifi_radio_ping(wifi_radio_obj_t *self, mp_obj_t ip_address, mp_float_t timeout) {
ping_time = sys_now();
ip_addr_t ping_addr;
ipaddress_ipaddress_to_lwip(ip_address, &ping_addr);
if (mp_obj_is_str(ip_address)) {
socketpool_resolve_host_raise(mp_obj_str_get_str(ip_address), &ping_addr);
} else {
ipaddress_ipaddress_to_lwip(ip_address, &ping_addr);
}
struct raw_pcb *ping_pcb;
MICROPY_PY_LWIP_ENTER
@ -522,3 +534,47 @@ void common_hal_wifi_radio_gc_collect(wifi_radio_obj_t *self) {
// Only bother to scan the actual object references.
gc_collect_ptr(self->current_scan);
}
mp_obj_t common_hal_wifi_radio_get_addresses(wifi_radio_obj_t *self) {
if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) != CYW43_LINK_UP) {
return mp_const_empty_tuple;
}
mp_obj_t args[] = {
socketpool_ip_addr_to_str(&NETIF_STA->ip_addr),
};
return mp_obj_new_tuple(1, args);
}
mp_obj_t common_hal_wifi_radio_get_addresses_ap(wifi_radio_obj_t *self) {
if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_AP) != CYW43_LINK_UP) {
return mp_const_empty_tuple;
}
mp_obj_t args[] = {
socketpool_ip_addr_to_str(&NETIF_AP->ip_addr),
};
return mp_obj_new_tuple(MP_ARRAY_SIZE(args), args);
}
mp_obj_t common_hal_wifi_radio_get_dns(wifi_radio_obj_t *self) {
const ip_addr_t *dns_addr = dns_getserver(0);
if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) != CYW43_LINK_UP || dns_addr->addr == 0) {
return mp_const_empty_tuple;
}
mp_obj_t args[] = {
socketpool_ip_addr_to_str(dns_addr),
};
return mp_obj_new_tuple(MP_ARRAY_SIZE(args), args);
}
void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addrs_obj) {
mp_int_t len = mp_obj_get_int(mp_obj_len(dns_addrs_obj));
mp_arg_validate_length_max(len, 1, MP_QSTR_dns);
ip_addr_t addr;
if (len == 0) {
addr.addr = IPADDR_NONE;
} else {
mp_obj_t dns_addr_obj = mp_obj_subscr(dns_addrs_obj, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL);
socketpool_resolve_host_raise(dns_addr_obj, &addr);
}
dns_setserver(0, &addr);
}

View file

@ -195,7 +195,7 @@ mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) {
MP_HAL_RETRY_SYSCALL(ret, write(STDOUT_FILENO, str, len), {});
mp_uint_t written = ret < 0 ? 0 : ret;
// CIRCUITPY-CHANGE: need to conditionalize MICROPY_PY_OS_DUPTERM
#if MICROPY_PY_OS_DUPTERM int dupterm_res = mp_os_dupterm_tx_strn(str, len);
#if MICROPY_PY_OS_DUPTERM int dupterm_res = mp_os_dupterm_tx_strn(str, len);
if (dupterm_res >= 0) {
written = MIN((mp_uint_t)dupterm_res, written);
}

View file

@ -97,11 +97,11 @@ STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected,
mp_arg_error_terse_mismatch();
#elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL
(void)f;
// CIRCUITPY-CHANGE: more specifc mp_raise routine
// CIRCUITPY-CHANGE: more specific mp_raise routine
mp_raise_TypeError_varg(
MP_ERROR_TEXT("function takes %d positional arguments but %d were given"), expected, given);
#elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
// CIRCUITPY-CHANGE: more specifc mp_raise routine
// CIRCUITPY-CHANGE: more specific mp_raise routine
mp_raise_TypeError_varg(
MP_ERROR_TEXT("%q() takes %d positional arguments but %d were given"),
mp_obj_fun_get_name(MP_OBJ_FROM_PTR(f)), expected, given);
@ -283,7 +283,7 @@ STATIC void mp_setup_code_state_helper(mp_code_state_t *code_state, size_t n_arg
if (elem != NULL) {
code_state_state[n_state - 1 - n_pos_args - i] = elem->value;
} else {
// CIRCUITPY-CHANGE: more specifc mp_raise routine
// CIRCUITPY-CHANGE: more specific mp_raise routine
mp_raise_TypeError_varg(
MP_ERROR_TEXT("function missing required keyword argument '%q'"),
MP_OBJ_QSTR_VALUE(arg_names[n_pos_args + i]));

View file

@ -51,7 +51,7 @@ size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) {
switch (val_type) {
case 'b':
case 'B':
// CIRCUITPY-CHANGE: x code: padding
// CIRCUITPY-CHANGE: x code: padding
case 'x':
size = 1;
break;
@ -71,7 +71,7 @@ size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) {
case 'Q':
size = 8;
break;
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
#if MICROPY_NONSTANDARD_TYPECODES
case 'P':
case 'O':
@ -99,7 +99,7 @@ size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) {
case BYTEARRAY_TYPECODE:
case 'b':
case 'B':
// CIRCUITPY-CHANGE: x code: padding
// CIRCUITPY-CHANGE: x code: padding
case 'x':
align = size = 1;
break;
@ -123,7 +123,7 @@ size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) {
align = alignof(long long);
size = sizeof(long long);
break;
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
#if MICROPY_NONSTANDARD_TYPECODES
case 'P':
case 'O':
@ -190,7 +190,7 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, size_t index) {
case 'd':
return mp_obj_new_float_from_d(((double *)p)[index]);
#endif
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
#if MICROPY_NONSTANDARD_TYPECODES
// Extension to CPython: array of objects
case 'O':
@ -248,7 +248,7 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte *
long long val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p);
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
if (MICROPY_NONSTANDARD_TYPECODES && (val_type == 'O')) {
return (mp_obj_t)(mp_uint_t)val;
#if MICROPY_NONSTANDARD_TYPECODES
@ -322,7 +322,7 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p
mp_uint_t val;
switch (val_type) {
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
#if MICROPY_NONSTANDARD_TYPECODES
case 'O':
val = (mp_uint_t)val_in;
@ -397,7 +397,7 @@ void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_
((double *)p)[index] = mp_obj_get_float_to_d(val_in);
break;
#endif
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
#if MICROPY_NONSTANDARD_TYPECODES
// Extension to CPython: array of objects
case 'O':
@ -469,7 +469,7 @@ void mp_binary_set_val_array_from_int(char typecode, void *p, size_t index, mp_i
((double *)p)[index] = (double)val;
break;
#endif
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
// CIRCUITPY-CHANGE: non-standard typecodes can be turned off
#if MICROPY_NONSTANDARD_TYPECODES
// Extension to CPython: array of pointers
case 'P':

View file

@ -77,7 +77,7 @@ STATIC void mp_help_add_from_names(mp_obj_t list, const char *name) {
}
#endif
// CIRCUITPY-CHANGE: move extern to top level to prevent warnings
// CIRCUITPY-CHANGE: move extern to top level to prevent warnings
#if MICROPY_MODULE_FROZEN
extern const char mp_frozen_names[];
#endif

View file

@ -496,6 +496,9 @@ CFLAGS += -DCIRCUITPY_SKIP_SAFE_MODE_WAIT=$(CIRCUITPY_SKIP_SAFE_MODE_WAIT)
CIRCUITPY_SOCKETPOOL ?= $(CIRCUITPY_WIFI)
CFLAGS += -DCIRCUITPY_SOCKETPOOL=$(CIRCUITPY_SOCKETPOOL)
CIRCUITPY_SOCKETPOOL_IPV6 ?= 0
CFLAGS += -DCIRCUITPY_SOCKETPOOL_IPV6=$(CIRCUITPY_SOCKETPOOL_IPV6)
CIRCUITPY_SSL ?= $(CIRCUITPY_WIFI)
CFLAGS += -DCIRCUITPY_SSL=$(CIRCUITPY_SSL)

View file

@ -453,7 +453,6 @@ def print_qstr_data(qcfgs, qstrs, translations):
print("// {} bytes worth of qstr".format(total_qstr_size))
def do_work(infiles):
# CIRCUITPY-CHANGE: include translations
qcfgs, qstrs, translations = parse_input_headers_with_translations(infiles)

View file

@ -740,7 +740,7 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_IndentationError), MP_ROM_PTR(&mp_type_IndentationError) },
{ MP_ROM_QSTR(MP_QSTR_IndexError), MP_ROM_PTR(&mp_type_IndexError) },
{ MP_ROM_QSTR(MP_QSTR_KeyboardInterrupt), MP_ROM_PTR(&mp_type_KeyboardInterrupt) },
// CIRCUITPY-CHANGE: add ReloadException
// CIRCUITPY-CHANGE: add ReloadException
{ MP_ROM_QSTR(MP_QSTR_ReloadException), MP_ROM_PTR(&mp_type_ReloadException) },
{ MP_ROM_QSTR(MP_QSTR_KeyError), MP_ROM_PTR(&mp_type_KeyError) },
{ MP_ROM_QSTR(MP_QSTR_LookupError), MP_ROM_PTR(&mp_type_LookupError) },
@ -748,7 +748,7 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_NameError), MP_ROM_PTR(&mp_type_NameError) },
{ MP_ROM_QSTR(MP_QSTR_NotImplementedError), MP_ROM_PTR(&mp_type_NotImplementedError) },
{ MP_ROM_QSTR(MP_QSTR_OSError), MP_ROM_PTR(&mp_type_OSError) },
// CIRCUITPY-CHANGE: add TimeoutEror ConnectionError, BrokenPipeError
// CIRCUITPY-CHANGE: add TimeoutEror ConnectionError, BrokenPipeError
{ MP_ROM_QSTR(MP_QSTR_TimeoutError), MP_ROM_PTR(&mp_type_TimeoutError) },
{ MP_ROM_QSTR(MP_QSTR_ConnectionError), MP_ROM_PTR(&mp_type_ConnectionError) },
{ MP_ROM_QSTR(MP_QSTR_BrokenPipeError), MP_ROM_PTR(&mp_type_BrokenPipeError) },

View file

@ -39,6 +39,11 @@
#include "extmod/modplatform.h"
#include "genhdr/mpversion.h"
// CIRCUITPY-CHANGE
#if CIRCUITPY_WARNINGS
#include "shared-module/warnings/__init__.h"
#endif
#if MICROPY_PY_SYS_SETTRACE
#include "py/objmodule.h"
#include "py/profile.h"
@ -166,6 +171,11 @@ STATIC mp_obj_t mp_sys_exit(size_t n_args, const mp_obj_t *args) {
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj, 0, 1, mp_sys_exit);
STATIC mp_obj_t mp_sys_print_exception(size_t n_args, const mp_obj_t *args) {
// CIRCUITPY-CHANGE
#if CIRCUITPY_WARNINGS
warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q moved from %q to %q"), MP_QSTR_print_exception, MP_QSTR_sys, MP_QSTR_traceback);
#endif
#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
void *stream_obj = &mp_sys_stdout_obj;
if (n_args > 1) {

View file

@ -549,8 +549,8 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
case 'p':
case 'P': // don't bother to handle upcase for 'P'
// Use unsigned long int to work on both ILP32 and LP64 systems
// CIRCUITPY-CHANGE: print 0x prefix
#if SUPPORT_INT_BASE_PREFIX
// CIRCUITPY-CHANGE: print 0x prefix
#if SUPPORT_INT_BASE_PREFIX
chrs += mp_print_int(print, va_arg(args, unsigned long int), 0, 16, 'a', flags | PF_FLAG_SHOW_PREFIX, fill, width);
#else
print->print_strn(print->data, "0x", 2);

View file

@ -76,7 +76,7 @@ NORETURN void nlr_jump(void *val) {
"ret \n"
:
: "r" (top)
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
: "memory"
);

View file

@ -78,7 +78,7 @@ NORETURN void nlr_jump(void *val) {
"nop \n"
:
: "r" (top)
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
: "memory"
);
MP_UNREACHABLE

View file

@ -114,7 +114,7 @@ NORETURN void nlr_jump(void *val) {
"blr ;"
:
: "r" (&top->regs)
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
: "memory"
);

View file

@ -134,7 +134,7 @@ NORETURN void nlr_jump(void *val) {
"bx lr \n" // return
: // output operands
: "r" (top) // input operands
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
: "memory" // clobbered registers
);

View file

@ -124,7 +124,7 @@ NORETURN void nlr_jump(void *val) {
"ret \n" // return
: // output operands
: "r" (top) // input operands
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
: "memory" // clobbered registers
);

View file

@ -97,7 +97,7 @@ NORETURN void nlr_jump(void *val) {
"ret \n" // return
: // output operands
: "r" (top) // input operands
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
: "memory" // clobbered registers
);

View file

@ -75,7 +75,7 @@ NORETURN void nlr_jump(void *val) {
"ret.n \n" // return
: // output operands
: "r" (top) // input operands
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
// CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126
: "memory" // clobbered registers
);

View file

@ -247,8 +247,8 @@ mp_obj_t MICROPY_WRAP_MP_LOAD_GLOBAL(mp_load_global)(qstr qst) {
#if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
mp_raise_msg(&mp_type_NameError, MP_ERROR_TEXT("name not defined"));
#else
// CIRCUITPY-CHANGE: slight message change
mp_raise_msg_varg(&mp_type_NameError, MP_ERROR_TEXT("name '%q' is not defined"), qst);
// CIRCUITPY-CHANGE: slight message change
mp_raise_msg_varg(&mp_type_NameError, MP_ERROR_TEXT("name '%q' is not defined"), qst);
#endif
}
}

View file

@ -36,7 +36,6 @@
//| ``reference_voltage`` to read the configured setting.
//| (TODO) Provide mechanism to read CPU Temperature."""
//|
//| def __init__(self, pin: microcontroller.Pin, *, sample_rate: int) -> None:
//| """Create a `BufferedIn` on the given pin and given sample rate.
//|
@ -96,47 +95,53 @@ static mp_obj_t analogbufio_bufferedin___exit__(size_t n_args, const mp_obj_t *a
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(analogbufio_bufferedin___exit___obj, 4, 4, analogbufio_bufferedin___exit__);
//| def readinto(self, buffer: WriteableBuffer) -> int:
//| def readinto(self, buffer: WriteableBuffer, loop: bool = False) -> int:
//| """Fills the provided buffer with ADC voltage values.
//|
//| ADC values will be read into the given buffer at the supplied sample_rate.
//| Depending on the buffer typecode, 'B', 'H', samples are 8-bit byte-arrays or
//| 16-bit half-words and are always unsigned.
//| The ADC most significant bits of the ADC are kept. (See
//| https://docs.circuitpython.org/en/latest/docs/library/array.html)
//| (See https://docs.circuitpython.org/en/latest/docs/library/array.html)
//| For 8-bit samples, the most significant bits of the 12-bit ADC values are kept.
//| For 16-bit samples, if loop=False, the 12-bit ADC values are scaled up to fill the 16 bit range.
//| If loop=True, ADC values are stored without scaling.
//|
//| :param ~circuitpython_typing.WriteableBuffer buffer: buffer: A buffer for samples"""
//| :param ~circuitpython_typing.WriteableBuffer buffer: buffer: A buffer for samples
//| :param ~bool loop: loop: Set to true for continuous conversions, False to fill buffer once then stop
//| """
//| ...
//|
static mp_obj_t analogbufio_bufferedin_obj_readinto(mp_obj_t self_in, mp_obj_t buffer_obj) {
analogbufio_bufferedin_obj_t *self = MP_OBJ_TO_PTR(self_in);
static mp_obj_t analogbufio_bufferedin_obj_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buffer, ARG_loop };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED, {} },
{ MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
};
analogbufio_bufferedin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_obj_t buffer = args[ARG_buffer].u_obj;
// Buffer defined and allocated by user
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buffer_obj, &bufinfo, MP_BUFFER_READ);
mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ);
uint8_t bytes_per_sample = 1;
// Bytes Per Sample
if (bufinfo.typecode == 'H') {
bytes_per_sample = 2;
} else if (bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE) {
mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be a bytearray or array of type 'H' or 'B'"), MP_QSTR_buffer);
}
mp_uint_t captured = common_hal_analogbufio_bufferedin_readinto(self, bufinfo.buf, bufinfo.len, bytes_per_sample);
mp_uint_t captured = common_hal_analogbufio_bufferedin_readinto(self, bufinfo.buf, bufinfo.len, bytes_per_sample, args[ARG_loop].u_bool);
return MP_OBJ_NEW_SMALL_INT(captured);
}
MP_DEFINE_CONST_FUN_OBJ_2(analogbufio_bufferedin_readinto_obj, analogbufio_bufferedin_obj_readinto);
MP_DEFINE_CONST_FUN_OBJ_KW(analogbufio_bufferedin_readinto_obj, 1, analogbufio_bufferedin_obj_readinto);
static const mp_rom_map_elem_t analogbufio_bufferedin_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&analogbufio_bufferedin_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&analogbufio_bufferedin_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&analogbufio_bufferedin___exit___obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&analogbufio_bufferedin_readinto_obj)},
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&analogbufio_bufferedin_readinto_obj)},
};
static MP_DEFINE_CONST_DICT(analogbufio_bufferedin_locals_dict, analogbufio_bufferedin_locals_dict_table);

View file

@ -14,4 +14,4 @@ extern const mp_obj_type_t analogbufio_bufferedin_type;
void common_hal_analogbufio_bufferedin_construct(analogbufio_bufferedin_obj_t *self, const mcu_pin_obj_t *pin, uint32_t sample_rate);
void common_hal_analogbufio_bufferedin_deinit(analogbufio_bufferedin_obj_t *self);
bool common_hal_analogbufio_bufferedin_deinited(analogbufio_bufferedin_obj_t *self);
uint32_t common_hal_analogbufio_bufferedin_readinto(analogbufio_bufferedin_obj_t *self, uint8_t *buffer, uint32_t len, uint8_t bytes_per_sample);
uint32_t common_hal_analogbufio_bufferedin_readinto(analogbufio_bufferedin_obj_t *self, uint8_t *buffer, uint32_t len, uint8_t bytes_per_sample, bool loop);

View file

@ -17,7 +17,12 @@
//| """A raw audio sample buffer in memory"""
//|
//| def __init__(
//| self, buffer: ReadableBuffer, *, channel_count: int = 1, sample_rate: int = 8000
//| self,
//| buffer: ReadableBuffer,
//| *,
//| channel_count: int = 1,
//| sample_rate: int = 8000,
//| single_buffer: bool = True
//| ) -> None:
//| """Create a RawSample based on the given buffer of values. If channel_count is more than
//| 1 then each channel's samples should alternate. In other words, for a two channel buffer, the
@ -27,34 +32,58 @@
//| :param ~circuitpython_typing.ReadableBuffer buffer: A buffer with samples
//| :param int channel_count: The number of channels in the buffer
//| :param int sample_rate: The desired playback sample rate
//| :param bool single_buffer: Selects single buffered or double buffered transfer mode. This affects
//| what happens if the sample buffer is changed while the sample is playing.
//| In single buffered transfers, a change in buffer contents will not affect active playback.
//| In double buffered transfers, changed buffer contents will
//| be played back when the transfer reaches the next half-buffer point.
//|
//| Simple 8ksps 440 Hz sin wave::
//| Playing 8ksps 440 Hz and 880 Hz sine waves::
//|
//| import audiocore
//| import audioio
//| import board
//| import analogbufio
//| import array
//| import time
//| import audiocore
//| import audiopwmio
//| import board
//| import math
//| import time
//|
//| # Generate one period of sine wav.
//| # Generate one period of sine wave.
//| length = 8000 // 440
//| sine_wave = array.array("h", [0] * length)
//| for i in range(length):
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15))
//| pwm = audiopwmio.PWMAudioOut(left_channel=board.D12, right_channel=board.D13)
//|
//| dac = audioio.AudioOut(board.SPEAKER)
//| sine_wave = audiocore.RawSample(sine_wave)
//| dac.play(sine_wave, loop=True)
//| # Play single-buffered
//| sample = audiocore.RawSample(sine_wave)
//| pwm.play(sample, loop=True)
//| time.sleep(3)
//| # changing the wave has no effect
//| for i in range(length):
//| sine_wave[i] = int(math.sin(math.pi * 4 * i / length) * (2 ** 15))
//| time.sleep(3)
//| pwm.stop()
//| time.sleep(1)
//| dac.stop()"""
//|
//| # Play double-buffered
//| sample = audiocore.RawSample(sine_wave, single_buffer=False)
//| pwm.play(sample, loop=True)
//| time.sleep(3)
//| # changing the wave takes effect almost immediately
//| for i in range(length):
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15))
//| time.sleep(3)
//| pwm.stop()
//| pwm.deinit()"""
//| ...
static mp_obj_t audioio_rawsample_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
enum { ARG_buffer, ARG_channel_count, ARG_sample_rate };
enum { ARG_buffer, ARG_channel_count, ARG_sample_rate, ARG_single_buffer };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL } },
{ MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1 } },
{ MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} },
{ MP_QSTR_single_buffer, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@ -69,9 +98,12 @@ static mp_obj_t audioio_rawsample_make_new(const mp_obj_type_t *type, size_t n_a
} else if (bufinfo.typecode != 'b' && bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE) {
mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be a bytearray or array of type 'h', 'H', 'b', or 'B'"), MP_QSTR_buffer);
}
if (!args[ARG_single_buffer].u_bool && bufinfo.len % (bytes_per_sample * args[ARG_channel_count].u_int * 2) != 0) {
mp_raise_ValueError_varg(MP_ERROR_TEXT("Length of %q must be an even multiple of channel_count * type_size"), MP_QSTR_buffer);
}
common_hal_audioio_rawsample_construct(self, ((uint8_t *)bufinfo.buf), bufinfo.len,
bytes_per_sample, signed_samples, args[ARG_channel_count].u_int,
args[ARG_sample_rate].u_int);
args[ARG_sample_rate].u_int, args[ARG_single_buffer].u_bool);
return MP_OBJ_FROM_PTR(self);
}

View file

@ -12,7 +12,7 @@ extern const mp_obj_type_t audioio_rawsample_type;
void common_hal_audioio_rawsample_construct(audioio_rawsample_obj_t *self,
uint8_t *buffer, uint32_t len, uint8_t bytes_per_sample, bool samples_signed,
uint8_t channel_count, uint32_t sample_rate);
uint8_t channel_count, uint32_t sample_rate, bool single_buffer);
void common_hal_audioio_rawsample_deinit(audioio_rawsample_obj_t *self);
bool common_hal_audioio_rawsample_deinited(audioio_rawsample_obj_t *self);

View file

@ -57,14 +57,10 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socketpool_socket___exit___obj, 4, 4,
//| Returns a tuple of (new_socket, remote_address)"""
static mp_obj_t _socketpool_socket_accept(mp_obj_t self_in) {
socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
uint8_t ip[4];
uint32_t port;
socketpool_socket_obj_t *sock = common_hal_socketpool_socket_accept(self, ip, &port);
mp_obj_t tuple_contents[2];
tuple_contents[0] = MP_OBJ_FROM_PTR(sock);
tuple_contents[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
tuple_contents[0] = MP_OBJ_FROM_PTR(common_hal_socketpool_socket_accept(self, &tuple_contents[1]));
return mp_obj_new_tuple(2, tuple_contents);
}
static MP_DEFINE_CONST_FUN_OBJ_1(socketpool_socket_accept_obj, _socketpool_socket_accept);
@ -158,13 +154,9 @@ static mp_obj_t socketpool_socket_recvfrom_into(mp_obj_t self_in, mp_obj_t data_
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_WRITE);
byte ip[4];
uint32_t port;
mp_int_t ret = common_hal_socketpool_socket_recvfrom_into(self,
(byte *)bufinfo.buf, bufinfo.len, ip, &port);
mp_obj_t tuple_contents[2];
tuple_contents[0] = mp_obj_new_int_from_uint(ret);
tuple_contents[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
tuple_contents[0] = mp_obj_new_int_from_uint(common_hal_socketpool_socket_recvfrom_into(self,
(byte *)bufinfo.buf, bufinfo.len, &tuple_contents[1]));
return mp_obj_new_tuple(2, tuple_contents);
}
static MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_recvfrom_into_obj, socketpool_socket_recvfrom_into);

View file

@ -10,7 +10,7 @@
extern const mp_obj_type_t socketpool_socket_type;
socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_t *port);
socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out);
size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self, const char *host, size_t hostlen, uint32_t port);
void common_hal_socketpool_socket_close(socketpool_socket_obj_t *self);
void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self, const char *host, size_t hostlen, uint32_t port);
@ -20,7 +20,7 @@ mp_uint_t common_hal_socketpool_socket_get_timeout(socketpool_socket_obj_t *self
mp_int_t common_hal_socketpool_socket_get_type(socketpool_socket_obj_t *self);
bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *self, int backlog);
mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *self,
uint8_t *buf, uint32_t len, uint8_t *ip, uint32_t *port);
uint8_t *buf, uint32_t len, mp_obj_t *peer_out);
mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len);
mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len);
mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *self,
@ -31,7 +31,7 @@ bool common_hal_socketpool_readable(socketpool_socket_obj_t *self);
bool common_hal_socketpool_writable(socketpool_socket_obj_t *self);
// Non-allocating versions for internal use.
int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_t *port, socketpool_socket_obj_t *accepted);
int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, socketpool_socket_obj_t *accepted);
void socketpool_socket_close(socketpool_socket_obj_t *self);
int socketpool_socket_send(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len);
int socketpool_socket_recv_into(socketpool_socket_obj_t *self,

View file

@ -142,28 +142,14 @@ static mp_obj_t socketpool_socketpool_getaddrinfo(size_t n_args, const mp_obj_t
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
const char *host = mp_obj_str_get_str(args[ARG_host].u_obj);
mp_int_t port = args[ARG_port].u_int;
mp_obj_t ip_str = mp_const_none;
if (strlen(host) > 0 && ipaddress_parse_ipv4address(host, strlen(host), NULL)) {
ip_str = args[ARG_host].u_obj;
}
if (ip_str == mp_const_none) {
ip_str = common_hal_socketpool_socketpool_gethostbyname_raise(self, host);
}
mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL));
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(SOCKETPOOL_AF_INET);
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCKETPOOL_SOCK_STREAM);
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
mp_obj_tuple_t *sockaddr = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
sockaddr->items[0] = ip_str;
sockaddr->items[1] = MP_OBJ_NEW_SMALL_INT(port);
tuple->items[4] = MP_OBJ_FROM_PTR(sockaddr);
return mp_obj_new_list(1, (mp_obj_t *)&tuple);
return common_hal_socketpool_getaddrinfo_raise(
self,
mp_obj_str_get_str(args[ARG_host].u_obj),
args[ARG_port].u_int,
args[ARG_family].u_int,
args[ARG_type].u_int,
args[ARG_proto].u_int,
args[ARG_flags].u_int);
}
static MP_DEFINE_CONST_FUN_OBJ_KW(socketpool_socketpool_getaddrinfo_obj, 1, socketpool_socketpool_getaddrinfo);
@ -207,15 +193,6 @@ MP_DEFINE_CONST_OBJ_TYPE(
locals_dict, &socketpool_socketpool_locals_dict
);
MP_WEAK
mp_obj_t common_hal_socketpool_socketpool_gethostbyname_raise(socketpool_socketpool_obj_t *self, const char *host) {
mp_obj_t ip_str = common_hal_socketpool_socketpool_gethostbyname(self, host);
if (ip_str == mp_const_none) {
common_hal_socketpool_socketpool_raise_gaierror_noname();
}
return ip_str;
}
MP_WEAK NORETURN
void common_hal_socketpool_socketpool_raise_gaierror_noname(void) {
vstr_t vstr;

View file

@ -19,12 +19,6 @@ void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *sel
socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_t *self,
socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type, int proto);
mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_obj_t *self,
const char *host);
// raises an exception instead of returning mp_const_none in the case of error
mp_obj_t common_hal_socketpool_socketpool_gethostbyname_raise(socketpool_socketpool_obj_t *self,
const char *host);
// Non-allocating version for internal use. These sockets are not registered and, therefore, not
// closed automatically.
bool socketpool_socket(socketpool_socketpool_obj_t *self,
@ -32,3 +26,5 @@ bool socketpool_socket(socketpool_socketpool_obj_t *self,
int proto, socketpool_socket_obj_t *sock);
NORETURN void common_hal_socketpool_socketpool_raise_gaierror_noname(void);
mp_obj_t common_hal_socketpool_getaddrinfo_raise(socketpool_socketpool_obj_t *self, const char *host, int port, int family, int type, int proto, int flags);

View file

@ -18,6 +18,21 @@
//|
//| For more information about the `socket` module, see the CPython documentation:
//| https://docs.python.org/3/library/socket.html
//|
//| .. jinja
//|
//| .. raw:: html
//|
//| <p>
//| <details>
//| <summary>AF_INET6 (IPv6) supported on these boards</summary>
//| <ul>
//| {% for board in support_matrix_reverse["socketpool.socketpool.AF_INET6"] %}
//| <li> {{ board }}
//| {% endfor %}
//| </ul>
//| </details>
//| </p>
//| """
static const mp_rom_map_elem_t socketpool_globals_table[] = {

View file

@ -596,6 +596,26 @@ static mp_obj_t wifi_radio_set_ipv4_address_ap(size_t n_args, const mp_obj_t *po
}
static MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_set_ipv4_address_ap_obj, 1, wifi_radio_set_ipv4_address_ap);
//| addresses: Sequence[str]
//| """Address(es) of the station when connected to an access point. Empty sequence when not connected. (read-only)"""
static mp_obj_t _wifi_radio_get_addresses(mp_obj_t self) {
return common_hal_wifi_radio_get_addresses(self);
}
MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_addresses_obj, _wifi_radio_get_addresses);
MP_PROPERTY_GETTER(wifi_radio_addresses_obj,
(mp_obj_t)&wifi_radio_get_addresses_obj);
//| addresses_ap: Sequence[str]
//| """Address(es) of the access point when enabled. Empty sequence when disabled. (read-only)"""
static mp_obj_t _wifi_radio_get_addresses_ap(mp_obj_t self) {
return common_hal_wifi_radio_get_addresses_ap(self);
}
MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_addresses_ap_obj, _wifi_radio_get_addresses_ap);
MP_PROPERTY_GETTER(wifi_radio_addresses_ap_obj,
(mp_obj_t)&wifi_radio_get_addresses_ap_obj);
//| ipv4_address: Optional[ipaddress.IPv4Address]
//| """IP v4 Address of the station when connected to an access point. None otherwise. (read-only)"""
static mp_obj_t _wifi_radio_get_ipv4_address(mp_obj_t self) {
@ -634,6 +654,24 @@ MP_PROPERTY_GETSET(wifi_radio_ipv4_dns_obj,
(mp_obj_t)&wifi_radio_get_ipv4_dns_obj,
(mp_obj_t)&wifi_radio_set_ipv4_dns_obj);
//| dns: Sequence[str]
//| """Address of the DNS server to be used."""
static mp_obj_t wifi_radio_get_dns(mp_obj_t self) {
return common_hal_wifi_radio_get_dns(self);
}
MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_dns_obj, wifi_radio_get_dns);
static mp_obj_t wifi_radio_set_dns(mp_obj_t self, mp_obj_t dns_addr) {
common_hal_wifi_radio_set_dns(self, dns_addr);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(wifi_radio_set_dns_obj, wifi_radio_set_dns);
MP_PROPERTY_GETSET(wifi_radio_dns_obj,
(mp_obj_t)&wifi_radio_get_dns_obj,
(mp_obj_t)&wifi_radio_set_dns_obj);
//| ap_info: Optional[Network]
//| """Network object containing BSSID, SSID, authmode, channel, country and RSSI when connected to an access point. None otherwise."""
static mp_obj_t wifi_radio_get_ap_info(mp_obj_t self) {
@ -655,14 +693,29 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_stations_ap_obj, wifi_radio_get_station
MP_PROPERTY_GETTER(wifi_radio_stations_ap_obj,
(mp_obj_t)&wifi_radio_get_stations_ap_obj);
//| def start_dhcp(self) -> None:
//| """Starts the station DHCP client."""
//| def start_dhcp(self, *, ipv4: bool = True, ipv6: bool = False) -> None:
//| """Starts the station DHCP client.
//|
//| By default, calling this function starts DHCP for IPv4 networks but not
//| IPv6 networks. When the the ``ipv4`` and ``ipv6`` arguments are `False`
//| then the corresponding DHCP client is stopped if it was active.
//| """
//| ...
static mp_obj_t wifi_radio_start_dhcp_client(mp_obj_t self) {
common_hal_wifi_radio_start_dhcp_client(self);
static mp_obj_t wifi_radio_start_dhcp_client(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_ipv4, ARG_ipv6 };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_ipv4, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = MP_ROM_TRUE } },
{ MP_QSTR_ipv6, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = MP_ROM_FALSE } },
};
wifi_radio_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
common_hal_wifi_radio_start_dhcp_client(self, args[ARG_ipv4].u_bool, args[ARG_ipv6].u_bool);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_start_dhcp_client_obj, wifi_radio_start_dhcp_client);
static MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_start_dhcp_client_obj, 1, wifi_radio_start_dhcp_client);
//| def stop_dhcp(self) -> None:
//| """Stops the station DHCP client. Needed to assign a static IP address."""
@ -772,6 +825,10 @@ static const mp_rom_map_elem_t wifi_radio_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_set_ipv4_address), MP_ROM_PTR(&wifi_radio_set_ipv4_address_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_ipv4_address_ap), MP_ROM_PTR(&wifi_radio_set_ipv4_address_ap_obj) },
{ MP_ROM_QSTR(MP_QSTR_addresses), MP_ROM_PTR(&wifi_radio_addresses_obj) },
{ MP_ROM_QSTR(MP_QSTR_addresses_ap), MP_ROM_PTR(&wifi_radio_addresses_ap_obj) },
{ MP_ROM_QSTR(MP_QSTR_dns), MP_ROM_PTR(&wifi_radio_dns_obj) },
{ MP_ROM_QSTR(MP_QSTR_ping), MP_ROM_PTR(&wifi_radio_ping_obj) },
};

View file

@ -86,7 +86,7 @@ extern void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self);
extern bool common_hal_wifi_radio_get_ap_active(wifi_radio_obj_t *self);
extern mp_obj_t common_hal_wifi_radio_get_stations_ap(wifi_radio_obj_t *self);
extern void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self);
extern void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self, bool ipv4, bool ipv6);
extern void common_hal_wifi_radio_stop_dhcp_client(wifi_radio_obj_t *self);
extern void common_hal_wifi_radio_start_dhcp_server(wifi_radio_obj_t *self);
extern void common_hal_wifi_radio_stop_dhcp_server(wifi_radio_obj_t *self);
@ -105,6 +105,12 @@ uint32_t wifi_radio_get_ipv4_address(wifi_radio_obj_t *self);
extern mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self);
extern mp_obj_t common_hal_wifi_radio_get_ipv4_address_ap(wifi_radio_obj_t *self);
mp_obj_t common_hal_wifi_radio_get_addresses(wifi_radio_obj_t *self);
mp_obj_t common_hal_wifi_radio_get_addresses_ap(wifi_radio_obj_t *self);
extern mp_obj_t common_hal_wifi_radio_get_dns(wifi_radio_obj_t *self);
extern void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addr);
extern void common_hal_wifi_radio_set_ipv4_address(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway, mp_obj_t ipv4_dns_addr);
extern void common_hal_wifi_radio_set_ipv4_address_ap(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway);

View file

@ -13,8 +13,9 @@
//| """
//| The `wifi` module provides necessary low-level functionality for managing
//| wifi connections. Use `socketpool` for communicating over the network."""
//|
//| wifi connections. Use `socketpool` for communicating over the network.
//| """
//| radio: Radio
//| """Wifi radio used to manage both station and AP modes.
//| This object is the sole instance of `wifi.Radio`."""

View file

@ -2,6 +2,8 @@
//
// SPDX-FileCopyrightText: Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
//
// SPDX-FileCopyrightText: Copyright (c) 2024 Tim Chinowsky
//
// SPDX-License-Identifier: MIT
#include "shared-bindings/audiocore/RawSample.h"
@ -16,13 +18,17 @@ void common_hal_audioio_rawsample_construct(audioio_rawsample_obj_t *self,
uint8_t bytes_per_sample,
bool samples_signed,
uint8_t channel_count,
uint32_t sample_rate) {
uint32_t sample_rate,
bool single_buffer) {
self->buffer = buffer;
self->bits_per_sample = bytes_per_sample * 8;
self->samples_signed = samples_signed;
self->len = len;
self->channel_count = channel_count;
self->sample_rate = sample_rate;
self->single_buffer = single_buffer;
self->buffer_index = 0;
}
void common_hal_audioio_rawsample_deinit(audioio_rawsample_obj_t *self) {
@ -56,19 +62,33 @@ audioio_get_buffer_result_t audioio_rawsample_get_buffer(audioio_rawsample_obj_t
uint8_t channel,
uint8_t **buffer,
uint32_t *buffer_length) {
*buffer_length = self->len;
if (single_channel_output) {
*buffer = self->buffer + (channel % self->channel_count) * (self->bits_per_sample / 8);
if (self->single_buffer) {
*buffer_length = self->len;
if (single_channel_output) {
*buffer = self->buffer + (channel % self->channel_count) * (self->bits_per_sample / 8);
} else {
*buffer = self->buffer;
}
return GET_BUFFER_DONE;
} else {
*buffer = self->buffer;
*buffer_length = self->len / 2;
if (single_channel_output) {
*buffer = self->buffer + (channel % self->channel_count) * (self->bits_per_sample / 8) + \
self->len / 2 * self->buffer_index;
} else {
*buffer = self->buffer + self->len / 2 * self->buffer_index;
}
self->buffer_index = 1 - self->buffer_index;
return GET_BUFFER_DONE;
}
return GET_BUFFER_DONE;
}
void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t *self, bool single_channel_output,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing) {
*single_buffer = true;
*single_buffer = self->single_buffer;
*samples_signed = self->samples_signed;
*max_buffer_length = self->len;
if (single_channel_output) {

View file

@ -18,6 +18,8 @@ typedef struct {
bool samples_signed;
uint8_t channel_count;
uint32_t sample_rate;
bool single_buffer;
uint8_t buffer_index;
} audioio_rawsample_obj_t;

View file

@ -46,7 +46,7 @@
#include "shared/runtime/pyexec.h"
#include "genhdr/mpversion.h"
// CIRCUITPY-CHANGE: atexit suport
// CIRCUITPY-CHANGE: atexit support
#if CIRCUITPY_ATEXIT
#include "shared-module/atexit/__init__.h"
#endif
@ -193,7 +193,7 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input
if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(exception_obj)), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) {
// at the moment, the value of SystemExit is unused
ret = pyexec_system_exit;
// CIRCUITPY-CHANGE
// CIRCUITPY-CHANGE
#if CIRCUITPY_ALARM
} else if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(exception_obj)), MP_OBJ_FROM_PTR(&mp_type_DeepSleepRequest))) {
ret = PYEXEC_DEEP_SLEEP;

View file

@ -338,7 +338,11 @@ bool supervisor_start_web_workflow(void) {
#endif
if (common_hal_socketpool_socket_get_closed(&listening)) {
#if CIRCUITPY_SOCKETPOOL_IPV6
socketpool_socket(&pool, SOCKETPOOL_AF_INET6, SOCKETPOOL_SOCK_STREAM, 0, &listening);
#else
socketpool_socket(&pool, SOCKETPOOL_AF_INET, SOCKETPOOL_SOCK_STREAM, 0, &listening);
#endif
common_hal_socketpool_socket_settimeout(&listening, 0);
// Bind to any ip. (Not checking for failures)
common_hal_socketpool_socket_bind(&listening, "", 0, web_api_port);
@ -1592,12 +1596,10 @@ void supervisor_web_workflow_background(void *data) {
if ((!common_hal_socketpool_socket_get_connected(&active) ||
(!active_request.in_progress && !active_request.new_socket)) &&
!common_hal_socketpool_socket_get_closed(&listening)) {
uint32_t ip;
uint32_t port;
if (!common_hal_socketpool_socket_get_closed(&active)) {
common_hal_socketpool_socket_close(&active);
}
int newsoc = socketpool_socket_accept(&listening, (uint8_t *)&ip, &port, &active);
int newsoc = socketpool_socket_accept(&listening, NULL, &active);
if (newsoc == -EBADF) {
common_hal_socketpool_socket_close(&listening);
break;

View file

@ -177,7 +177,7 @@ internal_bench/bytebuf:
## Test key/certificates
SSL/TLS tests in `multi_net` and `net_inet` use a
SSL/TLS tests in `multi_net` and `net_inet` use a
self-signed key/cert pair that is randomly generated and to be used for
testing/demonstration only. You should always generate your own key/cert.

View file

@ -0,0 +1,23 @@
import analogbufio
import array
import audiocore
import audiopwmio
import board
samples = 100
buffer = array.array("H", [0x0000] * samples)
adc = analogbufio.BufferedIn(board.A0, sample_rate=100000)
adc.readinto(buffer)
print("Sample,Print 1, Print 2,Print 3, Print 4")
for i in range(4):
for j in range(samples):
print(j, "," * (i + 1), buffer[j])
adc.readinto(buffer, loop=True)
print("Sample,Print 1, Print 2,Print 3, Print 4")
for i in range(4):
for j in range(samples):
print(j, "," * (i + 1), buffer[j])

View file

@ -0,0 +1,67 @@
import audiocore
import audiopwmio
import audiomixer
import board
import array
import time
import math
CHANNELS = 2
RATE = 8000
SAMPLE_TYPE = "H"
OFFSET = 2**15 - 1
BUFFER_SIZE = 640
SINGLE_BUFFER = True
LOOP = True
# (frequency, amp_left, amp_right)
VOICES = ((200, 1, 0), (400, 0, 1), (100, 1, 1))
def play(
voices=VOICES,
channels=CHANNELS,
rate=RATE,
sample_type=SAMPLE_TYPE,
offset=OFFSET,
buffer_size=BUFFER_SIZE,
single_buffer=SINGLE_BUFFER,
loop=LOOP,
):
waves = []
samples = []
for v in voices:
print(v)
sample_length = int(rate // v[0])
wave = array.array(sample_type, [offset] * sample_length * channels)
for i in range(0, sample_length):
if channels == 1:
wave[i] = int(
math.sin(math.pi * 2 * i / sample_length) * v[1] * (2**15 - 1) + offset
)
else:
wave[2 * i] = int(
math.sin(math.pi * 2 * i / sample_length) * v[1] * (2**15 - 1) + offset
)
wave[2 * i + 1] = int(
math.sin(math.pi * 2 * i / sample_length) * v[2] * (2**15 - 1) + offset
)
waves.append(wave)
samples.append(
audiocore.RawSample(
wave, sample_rate=rate, channel_count=channels, single_buffer=single_buffer
)
)
mixer = audiomixer.Mixer(
voice_count=len(voices),
sample_rate=rate,
channel_count=channels,
bits_per_sample=16,
samples_signed=False,
buffer_size=buffer_size,
)
pwm = audiopwmio.PWMAudioOut(left_channel=board.D12, right_channel=board.D13)
pwm.play(mixer)
for i in range(len(samples)):
mixer.voice[i].play(samples[i], loop=loop)
mixer.voice[i].level = 0.5

View file

@ -72,6 +72,7 @@ EXCLUSIONS = [
"ports/raspberrypi/lwip_src",
]
# CIRCUITPY-CHANGE
# None of the standard Python path matching routines implement the matching
# we want, which is most like git's "pathspec" version of globs.
@ -142,6 +143,7 @@ def relative_filename(arg):
def list_files(args):
return sorted(arg for arg in args if path_rx.match(relative_filename(arg)))
# CIRCUITPY-CHANGE: handle inline documentation
def fixup_c(filename):
# Read file.