Merge pull request #49 from amirgon/update_micropython_v1.18

Update micropython v1.18

Related: https://github.com/lvgl/lv_binding_micropython/issues/203
This commit is contained in:
Amir Gonnen 2022-01-28 23:27:31 +02:00 committed by GitHub
commit f61da15cc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
802 changed files with 28662 additions and 7484 deletions

18
.github/workflows/ports.yml vendored Normal file
View File

@ -0,0 +1,18 @@
name: Build ports metadata
on:
push:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'tools/**'
- ports/**
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build ports download metadata
run: mkdir boards && ./tools/autobuild/build-downloads.py . ./boards

View File

@ -24,13 +24,13 @@ jobs:
- name: Build - name: Build
run: source tools/ci.sh && ci_esp32_build run: source tools/ci.sh && ci_esp32_build
build_idf43: build_idf44:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Initialize lv_bindings submodule - name: Initialize lv_bindings submodule
run: git submodule update --init --recursive lib/lv_bindings run: git submodule update --init --recursive lib/lv_bindings
- name: Install packages - name: Install packages
run: source tools/ci.sh && ci_esp32_idf43_setup run: source tools/ci.sh && ci_esp32_idf44_setup
- name: Build - name: Build
run: source tools/ci.sh && ci_esp32_build run: source tools/ci.sh && ci_esp32_build

1
.gitignore vendored
View File

@ -58,6 +58,7 @@ __pycache__/
GNUmakefile GNUmakefile
user.props user.props
ports/javascript/node_modules ports/javascript/node_modules
.vscode/
# Generated rst files # Generated rst files
###################### ######################

3
.gitmodules vendored
View File

@ -26,12 +26,13 @@
[submodule "lib/asf4"] [submodule "lib/asf4"]
path = lib/asf4 path = lib/asf4
url = https://github.com/adafruit/asf4 url = https://github.com/adafruit/asf4
branch = circuitpython
[submodule "lib/tinyusb"] [submodule "lib/tinyusb"]
path = lib/tinyusb path = lib/tinyusb
url = https://github.com/hathach/tinyusb url = https://github.com/hathach/tinyusb
[submodule "lib/mynewt-nimble"] [submodule "lib/mynewt-nimble"]
path = lib/mynewt-nimble path = lib/mynewt-nimble
url = https://github.com/apache/mynewt-nimble.git url = https://github.com/micropython/mynewt-nimble.git
[submodule "lib/btstack"] [submodule "lib/btstack"]
path = lib/btstack path = lib/btstack
url = https://github.com/bluekitchen/btstack.git url = https://github.com/bluekitchen/btstack.git

View File

@ -11,6 +11,8 @@ tasks:
make -C ports/unix VARIANT=dev DEBUG=1 submodules make -C ports/unix VARIANT=dev DEBUG=1 submodules
make -j $(nproc) -C mpy-cross VARIANT=dev DEBUG=1 make -j $(nproc) -C mpy-cross VARIANT=dev DEBUG=1
make -j $(nproc) -C ports/unix VARIANT=dev DEBUG=1 make -j $(nproc) -C ports/unix VARIANT=dev DEBUG=1
source tools/ci.sh && ci_esp32_idf44_setup
source tools/ci.sh && ci_esp32_build
command: | command: |
xrandr --fb 500x500 # Fix resolution for LVGL screens which are smaller xrandr --fb 500x500 # Fix resolution for LVGL screens which are smaller
ports/unix/micropython-dev -i lib/lv_bindings/examples/advanced_demo.py ports/unix/micropython-dev -i lib/lv_bindings/examples/advanced_demo.py

View File

@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2013-2021 Damien P. George Copyright (c) 2013-2022 Damien P. George
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -66,7 +66,7 @@ master_doc = 'index'
# General information about the project. # General information about the project.
project = 'MicroPython' project = 'MicroPython'
copyright = '- The MicroPython Documentation is Copyright © 2014-2021, Damien P. George, Paul Sokolovsky, and contributors' copyright = '- The MicroPython Documentation is Copyright © 2014-2022, Damien P. George, Paul Sokolovsky, and contributors'
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
@ -74,7 +74,7 @@ copyright = '- The MicroPython Documentation is Copyright © 2014-2021, Damien P
# #
# We don't follow "The short X.Y version" vs "The full version, including alpha/beta/rc tags" # We don't follow "The short X.Y version" vs "The full version, including alpha/beta/rc tags"
# breakdown, so use the same version identifier for both to avoid confusion. # breakdown, so use the same version identifier for both to avoid confusion.
version = release = '1.17' version = release = '1.18'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View File

@ -16,4 +16,3 @@ live in the main MicroPython repository.
cmodules.rst cmodules.rst
natmod.rst natmod.rst

View File

@ -4,7 +4,7 @@ Getting Started
=============== ===============
This guide covers a step-by-step process on setting up version control, obtaining and building This guide covers a step-by-step process on setting up version control, obtaining and building
a copy of the source code for a port, building the documentation, running tests, and a description of the a copy of the source code for a port, building the documentation, running tests, and a description of the
directory structure of the MicroPython code base. directory structure of the MicroPython code base.
Source control with git Source control with git
@ -16,7 +16,7 @@ code is pulled and pushed to and from the main repository. Install the respectiv
of Git for your operating system to follow through the rest of the steps. of Git for your operating system to follow through the rest of the steps.
.. note:: .. note::
For a reference on the installation instructions, please refer to For a reference on the installation instructions, please refer to
the `Git installation instructions <https://git-scm.com/book/en/v2/Getting-Started-Installing-Git>`_. the `Git installation instructions <https://git-scm.com/book/en/v2/Getting-Started-Installing-Git>`_.
Learn about the basic git commands in this `Git Handbook <https://guides.github.com/introduction/git-handbook/>`_ Learn about the basic git commands in this `Git Handbook <https://guides.github.com/introduction/git-handbook/>`_
or any other sources on the internet. or any other sources on the internet.
@ -58,12 +58,12 @@ MicroPython repository.
After the above configuration, your setup should be similar to this: After the above configuration, your setup should be similar to this:
.. code-block:: bash .. code-block:: bash
$ git remote -v $ git remote -v
origin https://github.com/<your-user-name>/micropython (fetch) origin https://github.com/<your-user-name>/micropython (fetch)
origin https://github.com/<your-user-name>/micropython (push) origin https://github.com/<your-user-name>/micropython (push)
upstream https://github.com/micropython/micropython (fetch) upstream https://github.com/micropython/micropython (fetch)
upstream https://github.com/micropython/micropython (push) upstream https://github.com/micropython/micropython (push)
You should now have a copy of the source code. By default, you are pointing You should now have a copy of the source code. By default, you are pointing
to the master branch. To prepare for further development, it is recommended to the master branch. To prepare for further development, it is recommended
@ -73,7 +73,7 @@ to work on a development branch.
$ git checkout -b dev-branch $ git checkout -b dev-branch
You can give it any name. You will have to compile MicroPython whenever you change You can give it any name. You will have to compile MicroPython whenever you change
to a different branch. to a different branch.
Compile and build the code Compile and build the code
@ -140,8 +140,8 @@ If it built successfully, you should see a message similar to this:
.. code-block:: bash .. code-block:: bash
LINK mpy-cross LINK mpy-cross
text data bss dec hex filename text data bss dec hex filename
279328 776 880 280984 44998 mpy-cross 279328 776 880 280984 44998 mpy-cross
.. note:: .. note::
@ -181,8 +181,8 @@ If MicroPython built correctly, you should see the following:
.. code-block:: bash .. code-block:: bash
LINK micropython LINK micropython
text data bss dec hex filename text data bss dec hex filename
412033 5680 2496 420209 66971 micropython 412033 5680 2496 420209 66971 micropython
Now run it: Now run it:
@ -215,7 +215,7 @@ as detailed in the :ref:`required_dependencies` section, then build:
$ make submodules $ make submodules
$ make $ make
Please refer to the `stm32 documentation <https://github.com/micropython/micropython/tree/master/ports/stm32>`_ Please refer to the `stm32 documentation <https://github.com/micropython/micropython/tree/master/ports/stm32>`_
for more details on flashing the firmware. for more details on flashing the firmware.
.. note:: .. note::
@ -259,7 +259,7 @@ Build the docs:
$ make html $ make html
Open ``docs/build/html/index.html`` in your browser to view the docs locally. Refer to the Open ``docs/build/html/index.html`` in your browser to view the docs locally. Refer to the
documentation on `importing your documentation documentation on `importing your documentation
<https://docs.readthedocs.io/en/stable/intro/import-guide.html>`_ to use Read the Docs. <https://docs.readthedocs.io/en/stable/intro/import-guide.html>`_ to use Read the Docs.

View File

@ -5,7 +5,7 @@ This chapter covers a tour of MicroPython from the perspective of a developer, c
to MicroPython. It acts as a comprehensive resource on the implementation details of MicroPython to MicroPython. It acts as a comprehensive resource on the implementation details of MicroPython
for both novice and expert contributors. for both novice and expert contributors.
Development around MicroPython usually involves modifying the core runtime, porting or Development around MicroPython usually involves modifying the core runtime, porting or
maintaining a new library. This guide describes at great depth, the implementation maintaining a new library. This guide describes at great depth, the implementation
details of MicroPython including a getting started guide, compiler internals, porting details of MicroPython including a getting started guide, compiler internals, porting
MicroPython to a new platform and implementing a core MicroPython library. MicroPython to a new platform and implementing a core MicroPython library.
@ -24,4 +24,3 @@ MicroPython to a new platform and implementing a core MicroPython library.
publiccapi.rst publiccapi.rst
extendingmicropython.rst extendingmicropython.rst
porting.rst porting.rst

View File

@ -53,8 +53,6 @@ The basic MicroPython firmware is implemented in the main port file, e.g ``main.
mp_stack_ctrl_init(); mp_stack_ctrl_init();
gc_init(heap, heap + sizeof(heap)); gc_init(heap, heap + sizeof(heap));
mp_init(); mp_init();
mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), 0);
mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0);
// Start a normal REPL; will exit when ctrl-D is entered on a blank line. // Start a normal REPL; will exit when ctrl-D is entered on a blank line.
pyexec_friendly_repl(); pyexec_friendly_repl();

View File

@ -59,7 +59,7 @@ Processing happens in the following stages:
information. Note that this step only uses files that have changed, which information. Note that this step only uses files that have changed, which
means that ``qstr.i.last`` will only contain data from files that have means that ``qstr.i.last`` will only contain data from files that have
changed since the last compile. changed since the last compile.
2. ``qstr.split`` is an empty file created after running ``makeqstrdefs.py split`` 2. ``qstr.split`` is an empty file created after running ``makeqstrdefs.py split``
on qstr.i.last. It's just used as a dependency to indicate that the step ran. on qstr.i.last. It's just used as a dependency to indicate that the step ran.
This script outputs one file per input C file, ``genhdr/qstr/...file.c.qstr``, This script outputs one file per input C file, ``genhdr/qstr/...file.c.qstr``,

View File

@ -3,8 +3,21 @@
MicroPython differences from CPython MicroPython differences from CPython
==================================== ====================================
The operations listed in this section produce conflicting results in MicroPython when compared to standard Python. MicroPython implements Python 3.4 and some select features of Python 3.5 and
MicroPython implements Python 3.4 and some select features of Python 3.5. above. The sections below describe the current status of these features.
.. toctree::
../differences/python_35.rst
../differences/python_36.rst
../differences/python_37.rst
../differences/python_38.rst
../differences/python_39.rst
For the features of Python that are implemented by MicroPython, there are
sometimes differences in their behaviour compared to standard Python. The
operations listed in the sections below produce conflicting results in
MicroPython when compared to standard Python.
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2

View File

@ -0,0 +1,181 @@
.. _python_35:
Python 3.5
==========
Below is a list of finalised/accepted PEPs for Python 3.5 grouped into their impact to MicroPython.
+----------------------------------------------------------------------------------------------------------+---------------+
| **Extensions to the syntax:** | **Status** |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 448 <https://www.python.org/dev/peps/pep-0448/>`_ | additional unpacking generalizations | |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 465 <https://www.python.org/dev/peps/pep-0465/>`_ | a new matrix multiplication operator | Completed |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 492 <https://www.python.org/dev/peps/pep-0492/>`_ | coroutines with async and await syntax | Completed |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| **Extensions and changes to runtime:** |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 461 <https://www.python.org/dev/peps/pep-0461/>`_ | % formatting for binary strings | Completed |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 475 <https://www.python.org/dev/peps/pep-0475/>`_ | retrying system calls that fail with EINTR | Completed |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 479 <https://www.python.org/dev/peps/pep-0479/>`_ | change StopIteration handling inside generators | Completed |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| **Standard library changes:** |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 471 <https://www.python.org/dev/peps/pep-0471/>`_ | os.scandir() | |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 485 <https://www.python.org/dev/peps/pep-0485/>`_ | math.isclose(), a function for testing | Completed |
| | approximate equality | |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| **Miscellaneous changes:** |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 441 <https://www.python.org/dev/peps/pep-0441/>`_ | improved Python zip application support | |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 486 <https://www.python.org/dev/peps/pep-0486/>`_ | make the Python Laucher aware of virtual | |
| | environments | |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 484 <https://www.python.org/dev/peps/pep-0484/>`_ | type hints (advisory only) | In Progress |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 488 <https://www.python.org/dev/peps/pep-0488/>`_ | elimination of PYO files | Not relevant |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 489 <https://www.python.org/dev/peps/pep-0489/>`_ | redesigning extension module loading | |
+--------------------------------------------------------+-------------------------------------------------+---------------+
Other Language Changes:
+-----------------------------------------------------------------------------------------------------------+---------------+
| Added the *namereplace* error handlers. The *backslashreplace* error handlers now work with decoding and | |
| translating. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| Property docstrings are now writable. This is especially useful for collections.namedtuple() docstrings | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| Circular imports involving relative imports are now supported. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
New Modules:
* `typing <https://docs.python.org/3/whatsnew/3.5.html#typing>`_
* `zipzap <https://docs.python.org/3/whatsnew/3.5.html#zipapp>`_
Changes to built-in modules:
+-----------------------------------------------------------------------------------------------------------+---------------+
| `collections <https://docs.python.org/3/whatsnew/3.5.html#collections>`_ |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The *OrderedDict* class is now implemented in C, which makes it 4 to 100 times faster. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| *OrderedDict.items()* , *OrderedDict.keys()* , *OrderedDict.values()* views now support reversed() | |
| iteration. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The deque class now defines *index()*, *insert()*, and *copy()*, and supports the + and * operators. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| Docstrings produced by namedtuple() can now be updated. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The UserString class now implements the *__getnewargs__()*, *__rmod__()*, *casefold()*, *format_map()*, | |
| *isprintable()*, and *maketrans()* methods to match the corresponding methods of str. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| `heapq <https://docs.python.org/3/whatsnew/3.5.html#heapq>`_ |
+-----------------------------------------------------------------------------------------------------------+---------------+
| Element comparison in *merge()* can now be customized by passing a key function in a new optional key | |
| keyword argument, and a new optional *reverse* keyword argument can be used to reverse element comparison | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| `io <https://docs.python.org/3/whatsnew/3.5.html#io>`_ |
+-----------------------------------------------------------------------------------------------------------+---------------+
| A new *BufferedIOBase.readinto1()* method, that uses at most one call to the underlying raw stream's | |
| *RawIOBase.read()* or *RawIOBase.readinto()* methods | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| `json <https://docs.python.org/3/whatsnew/3.5.html#json>`_ | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| JSON decoder now raises JSONDecodeError instead of ValueError to provide better context information about | |
| the error. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| `math <https://docs.python.org/3/whatsnew/3.5.html#math>`_ |
+-----------------------------------------------------------------------------------------------------------+---------------+
| Two new constants have been added to the math module: *inf* and *nan*. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| A new function *isclose()* provides a way to test for approximate equality. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| A new *gcd()* function has been added. The *fractions.gcd()* function is now deprecated. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| `os <https://docs.python.org/3/whatsnew/3.5.html#os>`_ |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The new *scandir()* function returning an iterator of DirEntry objects has been added. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The *urandom()* function now uses the *getrandom()* syscall on Linux 3.17 or newer, and *getentropy()* on | |
| OpenBSD 5.6 and newer, removing the need to use /dev/urandom and avoiding failures due to potential file | |
| descriptor exhaustion. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| New *get_blocking()* and *set_blocking()* functions allow getting and setting a file descriptor's blocking| |
| mode (O_NONBLOCK.) | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| There is a new *os.path.commonpath()* function returning the longest common sub-path of each passed | |
| pathname | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| `re <https://docs.python.org/3/whatsnew/3.5.html#re>`_ | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| References and conditional references to groups with fixed length are now allowed in lookbehind assertions| |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The number of capturing groups in regular expressions is no longer limited to 100. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The *sub()* and *subn()* functions now replace unmatched groups with empty strings instead of raising an | |
| exception. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The *re.error* exceptions have new attributes, msg, pattern, pos, lineno, and colno, that provide better | |
| context information about the error | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| `socket <https://docs.python.org/3/whatsnew/3.5.html#socket>`_ |
+-----------------------------------------------------------------------------------------------------------+---------------+
| Functions with timeouts now use a monotonic clock, instead of a system clock. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| A new *socket.sendfile()* method allows sending a file over a socket by using the high-performance | |
| *os.sendfile()* function on UNIX, resulting in uploads being from 2 to 3 times faster than when using | |
| plain *socket.send()* | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The *socket.sendall()* method no longer resets the socket timeout every time bytes are received or sent. | |
| The socket timeout is now the maximum total duration to send all data. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The backlog argument of the *socket.listen()* method is now optional. By default it is set to SOMAXCONN or| |
| to 128, whichever is less. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| `ssl <https://docs.python.org/3/whatsnew/3.5.html#ssl>`_ |
+-----------------------------------------------------------------------------------------------------------+---------------+
| Memory BIO Support | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| Application-Layer Protocol Negotiation Support | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| There is a new *SSLSocket.version()* method to query the actual protocol version in use. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The SSLSocket class now implements a *SSLSocket.sendfile()* method. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The *SSLSocket.send()* method now raises either the *ssl.SSLWantReadError* or *ssl.SSLWantWriteError* | |
| exception on a non-blocking socket if the operation would block. Previously, it would return 0. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The *cert_time_to_seconds()* function now interprets the input time as UTC and not as local time, per RFC | |
| 5280. Additionally, the return value is always an int. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| New *SSLObject.shared_ciphers()* and *SSLSocket.shared_ciphers()* methods return the list of ciphers sent | |
| by the client during the handshake. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The *SSLSocket.do_handshake()*, *SSLSocket.read()*, *SSLSocket.shutdown()*, and *SSLSocket.write()* | |
| methods of the SSLSocket class no longer reset the socket timeout every time bytes are received or sent. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The *match_hostname()* function now supports matching of IP addresses. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| `sys <https://docs.python.org/3/whatsnew/3.5.html#sys>`_ |
+-----------------------------------------------------------------------------------------------------------+---------------+
| A new *set_coroutine_wrapper()* function allows setting a global hook that will be called whenever a | |
| coroutine object is created by an async def function. A corresponding *get_coroutine_wrapper()* can be | |
| used to obtain a currently set wrapper. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| A new *is_finalizing()* function can be used to check if the Python interpreter is shutting down. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| `time <https://docs.python.org/3/whatsnew/3.5.html#time>`_ |
+-----------------------------------------------------------------------------------------------------------+---------------+
| The *monotonic()* function is now always available | |
+-----------------------------------------------------------------------------------------------------------+---------------+

View File

@ -0,0 +1,191 @@
.. _python_36:
Python 3.6
==========
Python 3.6 beta 1 was released on 12 Sep 2016, and a summary of the new features can be found here:
+-----------------------------------------------------------------------------------------------------------+--------------+
| **New Syntax Features:** | **Status** |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 498 <https://www.python.org/dev/peps/pep-0498/>`_ | Literal String Formatting | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 515 <https://www.python.org/dev/peps/pep-0515/>`_ | Underscores in Numeric Literals | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 525 <https://www.python.org/dev/peps/pep-0525/>`_ | Asynchronous Generators | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 526 <https://www.python.org/dev/peps/pep-0526/>`_ | Syntax for Variable Annotations (provisional) | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 530 <https://www.python.org/dev/peps/pep-0530/>`_ | Asynchronous Comprehensions | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| **New Built-in Features:** |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 468 <https://www.python.org/dev/peps/pep-0468/>`_ | Preserving the order of *kwargs* in a function | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 487 <https://www.python.org/dev/peps/pep-0487/>`_ | Simpler customization of class creation | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 520 <https://www.python.org/dev/peps/pep-0520/>`_ | Preserving Class Attribute Definition Order | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| **Standard Library Changes:** |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 495 <https://www.python.org/dev/peps/pep-0495/>`_ | Local Time Disambiguation | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 506 <https://www.python.org/dev/peps/pep-0506/>`_ | Adding A Secrets Module To The Standard Library | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 519 <https://www.python.org/dev/peps/pep-0519/>`_ | Adding a file system path protocol | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| **CPython internals:** |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 509 <https://www.python.org/dev/peps/pep-0509/>`_ | Add a private version to dict | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 523 <https://www.python.org/dev/peps/pep-0523/>`_ | Adding a frame evaluation API to CPython | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| **Linux/Window Changes** |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 524 <https://www.python.org/dev/peps/pep-0524/>`_ | Make os.urandom() blocking on Linux | |
| | (during system startup) | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 528 <https://www.python.org/dev/peps/pep-0528/>`_ | Change Windows console encoding to UTF-8 | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
| `PEP 529 <https://www.python.org/dev/peps/pep-0529/>`_ | Change Windows filesystem encoding to UTF-8 | |
+--------------------------------------------------------+--------------------------------------------------+--------------+
Other Language Changes:
+-------------------------------------------------------------------------------------------------------------+---------------+
| A *global* or *nonlocal* statement must now textually appear before the first use of the affected name in | |
| the same scope. Previously this was a SyntaxWarning. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| It is now possible to set a special method to None to indicate that the corresponding operation is not | |
| available. For example, if a class sets *__iter__()* to *None* , the class is not iterable. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Long sequences of repeated traceback lines are now abbreviated as *[Previous line repeated {count} more | |
| times]* | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Import now raises the new exception *ModuleNotFoundError* when it cannot find a module. Code that currently | |
| checks for ImportError (in try-except) will still work. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Class methods relying on zero-argument *super()* will now work correctly when called from metaclass methods | |
| during class creation. | |
+-------------------------------------------------------------------------------------------------------------+---------------+
Changes to built-in modules:
+--------------------------------------------------------------------------------------------------------------+----------------+
| `array <https://docs.python.org/3.6/whatsnew/3.6.html#array>`_ | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| Exhausted iterators of *array.array* will now stay exhausted even if the iterated array is extended. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `binascii <https://docs.python.org/3.6/whatsnew/3.6.html#binascii>`_ | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The b2a_base64() function now accepts an optional newline keyword argument to control whether the newline | |
| character is appended to the return value | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `cmath <https://docs.python.org/3.6/whatsnew/3.6.html#cmath>`_ | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The new cmath.tau (τ) constant has been added | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| New constants: *cmath.inf* and *cmath.nan* to match *math.inf* and *math.nan* , and also *cmath.infj* and | |
| *cmath.nanj* to match the format used by complex repr | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `collections <https://docs.python.org/3.6/whatsnew/3.6.html#collections>`_ |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The new Collection abstract base class has been added to represent sized iterable container classes | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The new *Reversible* abstract base class represents iterable classes that also provide the *__reversed__()* | |
| method. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The new *AsyncGenerator* abstract base class represents asynchronous generators. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The *namedtuple()* function now accepts an optional keyword argument module, which, when specified, is used | |
| for the *__module__* attribute of the returned named tuple class. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The verbose and rename arguments for *namedtuple()* are now keyword-only. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| Recursive *collections.deque* instances can now be pickled. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `hashlib <https://docs.python.org/3.6/whatsnew/3.6.html#hashlib>`_ |
+--------------------------------------------------------------------------------------------------------------+----------------+
| BLAKE2 hash functions were added to the module. *blake2b()* and *blake2s()* are always available and support | |
| the full feature set of BLAKE2. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The SHA-3 hash functions *sha3_224()*, *sha3_256()*, *sha3_384()*, *sha3_512()*, and *SHAKE* hash functions | |
| *shake_128()* and *shake_256()* were added. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The password-based key derivation function *scrypt()* is now available with OpenSSL 1.1.0 and newer. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `json <https://docs.python.org/3.6/whatsnew/3.6.html#json>`_ |
+--------------------------------------------------------------------------------------------------------------+----------------+
| *json.load()* and *json.loads()* now support binary input. Encoded JSON should be represented using either | |
| UTF-8, UTF-16, or UTF-32. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `math <https://docs.python.org/3.6/whatsnew/3.6.html#math>`_ |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The new math.tau (τ) constant has been added | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `os <https://docs.python.org/3.6/whatsnew/3.6.html#os>`_ |
+--------------------------------------------------------------------------------------------------------------+----------------+
| A new *close()* method allows explicitly closing a *scandir()* iterator. The *scandir()* iterator now | |
| supports the context manager protocol. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| On Linux, *os.urandom()* now blocks until the system urandom entropy pool is initialized to increase the | |
| security. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The Linux *getrandom()* syscall (get random bytes) is now exposed as the new *os.getrandom()* function. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `re <https://docs.python.org/3.6/whatsnew/3.6.html#re>`_ |
+--------------------------------------------------------------------------------------------------------------+----------------+
| Added support of modifier spans in regular expressions. Examples: *'(?i:p)ython'* matches 'python' and | |
| 'Python', but not 'PYTHON'; *'(?i)g(?-i:v)r'* matches *'GvR'* and *'gvr'*, but not *'GVR'* . | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| Match object groups can be accessed by *__getitem__*, which is equivalent to *group()*. So *mo['name']* is | |
| now equivalent to *mo.group('name')*. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| Match objects now support index-like objects as group indices. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `socket <https://docs.python.org/3.6/whatsnew/3.6.html#socket>`_ |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The *ioctl()* function now supports the *SIO_LOOPBACK_FAST_PATH* control code. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The *getsockopt()* constants *SO_DOMAIN* , *SO_PROTOCOL*, *SO_PEERSEC* , and *SO_PASSSEC* are now supported. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The *setsockopt()* now supports the *setsockopt(level, optname, None, optlen: int)* form. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The socket module now supports the address family *AF_ALG* to interface with Linux Kernel crypto API. | |
| *ALG_*, *SOL_ALG* and *sendmsg_afalg()* were added. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| New Linux constants *TCP_USER_TIMEOUT* and *TCP_CONGESTION* were added. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `ssl <https://docs.python.org/3.6/whatsnew/3.6.html#ssl>`_ |
+--------------------------------------------------------------------------------------------------------------+----------------+
| ssl supports OpenSSL 1.1.0. The minimum recommend version is 1.0.2. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| 3DES has been removed from the default cipher suites and ChaCha20 Poly1305 cipher suites have been added. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| *SSLContext* has better default configuration for options and ciphers. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| SSL session can be copied from one client-side connection to another with the new *SSLSession* class. TLS | |
| session resumption can speed up the initial handshake, reduce latency and improve performance. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The new *get_ciphers()* method can be used to get a list of enabled ciphers in order of cipher priority. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| All constants and flags have been converted to *IntEnum* and *IntFlags*. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| Server and client-side specific TLS protocols for *SSLContext* were added. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| Added *SSLContext.post_handshake_auth* to enable and *ssl.SSLSocket.verify_client_post_handshake()* to | |
| initiate TLS 1.3 post-handshake authentication. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `struct <https://docs.python.org/3.6/whatsnew/3.6.html#struct>`_ | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| now supports IEEE 754 half-precision floats via the 'e' format specifier. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `sys <https://docs.python.org/3.6/whatsnew/3.6.html#sys>`_ | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The new *getfilesystemencodeerrors()* function returns the name of the error mode used to convert between | |
| Unicode filenames and bytes filenames. | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `zlib <https://docs.python.org/3.6/whatsnew/3.6.html#zlib>`_ | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The *compress()* and *decompress()* functions now accept keyword arguments | |
+--------------------------------------------------------------------------------------------------------------+----------------+

View File

@ -0,0 +1,95 @@
.. _python_37:
Python 3.7
==========
New Features:
+--------------------------------------------------------+--------------------------------------------------+----------------+
| **Features:** | **Status** |
+--------------------------------------------------------+--------------------------------------------------+----------------+
| `PEP 538 <https://www.python.org/dev/peps/pep-0538/>`_ | Coercing the legacy C locale to a UTF-8 based | |
| | locale | |
+--------------------------------------------------------+--------------------------------------------------+----------------+
| `PEP 539 <https://www.python.org/dev/peps/pep-0539/>`_ | A New C-API for Thread-Local Storage in CPython | |
+--------------------------------------------------------+--------------------------------------------------+----------------+
| `PEP 540 <https://www.python.org/dev/peps/pep-0540/>`_ | UTF-8 mode | |
+--------------------------------------------------------+--------------------------------------------------+----------------+
| `PEP 552 <https://www.python.org/dev/peps/pep-0552/>`_ | Deterministic pyc | |
+--------------------------------------------------------+--------------------------------------------------+----------------+
| `PEP 553 <https://www.python.org/dev/peps/pep-0553/>`_ | Built-in breakpoint() | |
+--------------------------------------------------------+--------------------------------------------------+----------------+
| `PEP 557 <https://www.python.org/dev/peps/pep-0557/>`_ | Data Classes | |
+--------------------------------------------------------+--------------------------------------------------+----------------+
| `PEP 560 <https://www.python.org/dev/peps/pep-0560/>`_ | Core support for typing module and generic types | |
+--------------------------------------------------------+--------------------------------------------------+----------------+
| `PEP 562 <https://www.python.org/dev/peps/pep-0562/>`_ | Module __getattr__ and __dir__ | Partially done |
+--------------------------------------------------------+--------------------------------------------------+----------------+
| `PEP 563 <https://www.python.org/dev/peps/pep-0563/>`_ | Postponed Evaluation of Annotations | |
+--------------------------------------------------------+--------------------------------------------------+----------------+
| `PEP 564 <https://www.python.org/dev/peps/pep-0564/>`_ | Time functions with nanosecond resolution | |
+--------------------------------------------------------+--------------------------------------------------+----------------+
| `PEP 565 <https://www.python.org/dev/peps/pep-0565/>`_ | Show DeprecationWarning in __main__ | |
+--------------------------------------------------------+--------------------------------------------------+----------------+
| `PEP 567 <https://www.python.org/dev/peps/pep-0567/>`_ | Context Variables | |
+--------------------------------------------------------+--------------------------------------------------+----------------+
Other Language Changes:
+----------------------------------------------------------------------------------------------------------+----------------+
| async and await are now reserved keywords | Completed |
+----------------------------------------------------------------------------------------------------------+----------------+
| dict objects must preserve insertion-order | |
+----------------------------------------------------------------------------------------------------------+----------------+
| More than 255 arguments can now be passed to a function; a function can now have more than 255 parameters| |
+----------------------------------------------------------------------------------------------------------+----------------+
| bytes.fromhex() and bytearray.fromhex() now ignore all ASCII whitespace, not only spaces | |
+----------------------------------------------------------------------------------------------------------+----------------+
| str, bytes, and bytearray gained support for the new isascii() method, which can be used to test if a | |
| string or bytes contain only the ASCII characters | |
+----------------------------------------------------------------------------------------------------------+----------------+
| ImportError now displays module name and module __file__ path whenfrom ... import ... fails | |
+----------------------------------------------------------------------------------------------------------+----------------+
| Circular imports involving absolute imports with binding a submodule to a name are now supported | |
+----------------------------------------------------------------------------------------------------------+----------------+
| object.__format__(x, '') is now equivalent to str(x) rather than format(str(self), '') | |
+----------------------------------------------------------------------------------------------------------+----------------+
| In order to better support dynamic creation of stack traces, types.TracebackType can now be instantiated | |
| from Python code, and the tb_next attribute on tracebacks is now writable | |
+----------------------------------------------------------------------------------------------------------+----------------+
| When using the -m switch, sys.path[0] is now eagerly expanded to the full starting directory path, rather| |
| than being left as the empty directory (which allows imports from the current working directory at the | |
| time when an import occurs) | |
+----------------------------------------------------------------------------------------------------------+----------------+
| The new -X importtime option or the PYTHONPROFILEIMPORTTIME environment variable can be used to show the | |
| timing of each module import | |
+----------------------------------------------------------------------------------------------------------+----------------+
Changes to built-in modules:
+------------------------------------------------------------------------------------------------------------+----------------+
| `asyncio <https://docs.python.org/3/whatsnew/3.7.html#asyncio>`_ | |
+------------------------------------------------------------------------------------------------------------+----------------+
| asyncio (many, may need a separate ticket) | |
+------------------------------------------------------------------------------------------------------------+----------------+
| `gc <https://docs.python.org/3/whatsnew/3.7.html#gc>`_ | |
+------------------------------------------------------------------------------------------------------------+----------------+
| New features include *gc.freeze()*, *gc.unfreeze()*, *gc-get_freeze_count* | |
+------------------------------------------------------------------------------------------------------------+----------------+
| `math <https://docs.python.org/3/whatsnew/3.7.html#math>`_ | |
+------------------------------------------------------------------------------------------------------------+----------------+
| math.remainder() added to implement IEEE 754-style remainder | |
+------------------------------------------------------------------------------------------------------------+----------------+
| `re <https://docs.python.org/3/whatsnew/3.7.html#re>`_ | |
+------------------------------------------------------------------------------------------------------------+----------------+
| A number of tidy up features including better support for splitting on empty strings and copy support for | |
| compiled expressions and match objects | |
+------------------------------------------------------------------------------------------------------------+----------------+
| `sys <https://docs.python.org/3/whatsnew/3.7.html#sys>`_ | |
+------------------------------------------------------------------------------------------------------------+----------------+
| sys.breakpointhook() added. sys.get(/set)_coroutine_origin_tracking_depth() added | |
+------------------------------------------------------------------------------------------------------------+----------------+
| `time <https://docs.python.org/3/whatsnew/3.7.html#time>`_ | |
+------------------------------------------------------------------------------------------------------------+----------------+
| Mostly updates to support nanosecond resolution in PEP564, see above | |
+------------------------------------------------------------------------------------------------------------+----------------+

View File

@ -0,0 +1,118 @@
.. _python_38:
Python 3.8
==========
Python 3.8.0 (final) was released on the 14 October 2019. The Features for 3.8
are defined in `PEP 569 <https://www.python.org/dev/peps/pep-0569/#id9>`_ and
a detailed description of the changes can be found in What's New in `Python
3.8. <https://docs.python.org/3/whatsnew/3.8.html>`_
+--------------------------------------------------------+---------------------------------------------------+---------------+
| **Features:** | Status |
+--------------------------------------------------------+---------------------------------------------------+---------------+
| `PEP 570 <https://www.python.org/dev/peps/pep-0570/>`_ | Positional-only arguments | |
+--------------------------------------------------------+---------------------------------------------------+---------------+
| `PEP 572 <https://www.python.org/dev/peps/pep-0572/>`_ | Assignment Expressions | |
+--------------------------------------------------------+---------------------------------------------------+---------------+
| `PEP 574 <https://www.python.org/dev/peps/pep-0574/>`_ | Pickle protocol 5 with out-of-band data | |
+--------------------------------------------------------+---------------------------------------------------+---------------+
| `PEP 578 <https://www.python.org/dev/peps/pep-0578/>`_ | Runtime audit hooks | |
+--------------------------------------------------------+---------------------------------------------------+---------------+
| `PEP 587 <https://www.python.org/dev/peps/pep-0587/>`_ | Python Initialization Configuration | |
+--------------------------------------------------------+---------------------------------------------------+---------------+
| `PEP 590 <https://www.python.org/dev/peps/pep-0590/>`_ | Vectorcall: a fast calling protocol for CPython | |
+--------------------------------------------------------+---------------------------------------------------+---------------+
| **Miscellaneous** |
+------------------------------------------------------------------------------------------------------------+---------------+
| f-strings support = for self-documenting expressions and debugging | Completed |
+------------------------------------------------------------------------------------------------------------+---------------+
Other Language Changes:
+------------------------------------------------------------------------------------------------------------+-------------+
| A *continue* statement was illegal in the *finally* clause due to a problem with the implementation. In | Completed |
| Python 3.8 this restriction was lifted | |
+------------------------------------------------------------------------------------------------------------+-------------+
| The *bool*, *int* , and *fractions.Fraction* types now have an *as_integer_ratio()* method like that found | |
| in *float* and *decimal.Decimal* | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Constructors of *int*, *float* and *complex* will now use the *__index__()* special method, if available | |
| and the corresponding method *__int__()*, *__float__()* or *__complex__()* is not available | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Added support of *\N{name}* escapes in regular expressions | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Dict and dictviews are now iterable in reversed insertion order using *reversed()* | |
+------------------------------------------------------------------------------------------------------------+-------------+
| The syntax allowed for keyword names in function calls was further restricted. In particular, | |
| f((keyword)=arg) is no longer allowed | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Generalized iterable unpacking in yield and return statements no longer requires enclosing parentheses | |
+------------------------------------------------------------------------------------------------------------+-------------+
| When a comma is missed in code such as [(10, 20) (30, 40)], the compiler displays a SyntaxWarning with a | |
| helpful suggestion | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Arithmetic operations between subclasses of *datetime.date* or *datetime.datetime* and *datetime.timedelta*| |
| objects now return an instance of the subclass, rather than the base class | |
+------------------------------------------------------------------------------------------------------------+-------------+
| When the Python interpreter is interrupted by *Ctrl-C (SIGINT)* and the resulting *KeyboardInterrupt* | |
| exception is not caught, the Python process now exits via a SIGINT signal or with the correct exit code | |
| such that the calling process can detect that it died due to a *Ctrl-C* | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Some advanced styles of programming require updating the *types.CodeType* object for an existing function | |
+------------------------------------------------------------------------------------------------------------+-------------+
| For integers, the three-argument form of the pow() function now permits the exponent to be negative in the | |
| case where the base is relatively prime to the modulus | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Dict comprehensions have been synced-up with dict literals so that the key is computed first and the value | |
| second | |
+------------------------------------------------------------------------------------------------------------+-------------+
| The *object.__reduce__()* method can now return a tuple from two to six elements long | |
+------------------------------------------------------------------------------------------------------------+-------------+
Changes to built-in modules:
+------------------------------------------------------------------------------------------------------------+-------------+
| `asyncio` |
+------------------------------------------------------------------------------------------------------------+-------------+
| *asyncio.run()* has graduated from the provisional to stable API | Completed |
+------------------------------------------------------------------------------------------------------------+-------------+
| Running *python -m asyncio* launches a natively async REPL | |
+------------------------------------------------------------------------------------------------------------+-------------+
| The exception *asyncio.CancelledError* now inherits from *BaseException* rather than *Exception* and no | Completed |
| longer inherits from *concurrent.futures.CancelledError* | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Added *asyncio.Task.get_coro()* for getting the wrapped coroutine within an *asyncio.Task* | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Asyncio tasks can now be named, either by passing the name keyword argument to *asyncio.create_task()* or | |
| the *create_task()* event loop method, or by calling the *set_name()* method on the task object | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Added support for Happy Eyeballs to *asyncio.loop.create_connection()*. To specify the behavior, two new | |
| parameters have been added: *happy_eyeballs_delay* and interleave. | |
+------------------------------------------------------------------------------------------------------------+-------------+
| `gc` |
+------------------------------------------------------------------------------------------------------------+-------------+
| *get_objects()* can now receive an optional generation parameter indicating a generation to get objects | |
| from. (Note, though, that while *gc* is a built-in, *get_objects()* is not implemented for MicroPython) | |
+------------------------------------------------------------------------------------------------------------+-------------+
| `math` |
+------------------------------------------------------------------------------------------------------------+-------------+
| Added new function *math.dist()* for computing Euclidean distance between two points | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Expanded the *math.hypot()* function to handle multiple dimensions | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Added new function, *math.prod()*, as analogous function to *sum()* that returns the product of a "start" | |
| value (default: 1) times an iterable of numbers | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Added two new combinatoric functions *math.perm()* and *math.comb()* | |
+------------------------------------------------------------------------------------------------------------+-------------+
| Added a new function *math.isqrt()* for computing accurate integer square roots without conversion to | |
| floating point | |
+------------------------------------------------------------------------------------------------------------+-------------+
| The function *math.factorial()* no longer accepts arguments that are not int-like | Completed |
+------------------------------------------------------------------------------------------------------------+-------------+
| `sys` |
+------------------------------------------------------------------------------------------------------------+-------------+
| Add new *sys.unraisablehook()* function which can be overridden to control how "unraisable exceptions" | |
| are handled | |
+------------------------------------------------------------------------------------------------------------+-------------+

View File

@ -0,0 +1,121 @@
.. _python_39:
Python 3.9
==========
Python 3.9.0 (final) was released on the 5th October 2020. The Features for 3.9 are
defined in `PEP 596 <https://www.python.org/dev/peps/pep-0596/#features-for-3-9>`_
and a detailed description of the changes can be found in
`What's New in Python 3.9 <https://docs.python.org/3/whatsnew/3.9.html>`_
+--------------------------------------------------------+----------------------------------------------------+--------------+
| **Features:** | | **Status** |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 573 <https://www.python.org/dev/peps/pep-0573/>`_ | fast access to module state from methods of C | |
| | extension types | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 584 <https://www.python.org/dev/peps/pep-0584/>`_ | union operators added to dict | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 585 <https://www.python.org/dev/peps/pep-0584/>`_ | type hinting generics in standard collections | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 593 <https://www.python.org/dev/peps/pep-0593/>`_ | flexible function and variable annotations | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 602 <https://www.python.org/dev/peps/pep-0602/>`_ | CPython adopts an annual release cycle. Instead of | |
| | annual, aiming for two month release cycle | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 614 <https://www.python.org/dev/peps/pep-0614/>`_ | relaxed grammar restrictions on decorators | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 615 <https://www.python.org/dev/peps/pep-0615/>`_ | the IANA Time Zone Database is now present in the | |
| | standard library in the zoneinfo module | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 616 <https://www.python.org/dev/peps/pep-0616/>`_ | string methods to remove prefixes and suffixes | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
| `PEP 617 <https://www.python.org/dev/peps/pep-0617/>`_ | CPython now uses a new parser based on PEG | |
+--------------------------------------------------------+----------------------------------------------------+--------------+
Other Language Changes:
+-------------------------------------------------------------------------------------------------------------+---------------+
| *__import__()* now raises *ImportError* instead of *ValueError* | Completed |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Python now gets the absolute path of the script filename specified on the command line (ex: *python3* | |
| *script.py*): the *__file__* attribute of the *__main__* module became an absolute path, rather than a | |
| relative path | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| By default, for best performance, the errors argument is only checked at the first encoding/decoding error | |
| and the encoding argument is sometimes ignored for empty strings | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| *"".replace("", s, n)* now returns *s* instead of an empty string for all non-zero n. It is now consistent | |
| with *"".replace("", s)* | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Any valid expression can now be used as a decorator. Previously, the grammar was much more restrictive | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Parallel running of *aclose()* / *asend()* / *athrow()* is now prohibited, and *ag_running* now reflects | |
| the actual running status of the async generator | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Unexpected errors in calling the *__iter__* method are no longer masked by TypeError in the in operator and | |
| functions contains(), indexOf() and countOf() of the operator module | |
+-------------------------------------------------------------------------------------------------------------+---------------+
| Unparenthesized lambda expressions can no longer be the expression part in an if clause in comprehensions | |
| and generator expressions | |
+-------------------------------------------------------------------------------------------------------------+---------------+
Changes to built-in modules:
+---------------------------------------------------------------------------------------------------------------+---------------+
| `asyncio` |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Due to significant security concerns, the reuse_address parameter of *asyncio.loop.create_datagram_endpoint()*| |
| is no longer supported | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Added a new coroutine *shutdown_default_executor()* that schedules a shutdown for the default executor that | |
| waits on the *ThreadPoolExecutor* to finish closing. Also, *asyncio.run()* has been updated to use the new | |
| coroutine. | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Added *asyncio.PidfdChildWatcher*, a Linux-specific child watcher implementation that polls process file | |
| descriptors | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| added a new *coroutine asyncio.to_thread()* | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| When cancelling the task due to a timeout, *asyncio.wait_for()* will now wait until the cancellation is | |
| complete also in the case when timeout is <= 0, like it does with positive timeouts | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| *asyncio* now raises *TyperError* when calling incompatible methods with an *ssl.SSLSocket* socket | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `gc` |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Garbage collection does not block on resurrected objects | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Added a new function *gc.is_finalized()* to check if an object has been finalized by the garbage collector | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `math` |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Expanded the *math.gcd()* function to handle multiple arguments. Formerly, it only supported two arguments | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Added *math.lcm()*: return the least common multiple of specified arguments | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Added *math.nextafter()*: return the next floating-point value after x towards y | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Added *math.ulp()*: return the value of the least significant bit of a float | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `os` |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Exposed the Linux-specific *os.pidfd_open()* and *os.P_PIDFD* | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| The *os.unsetenv()* function is now also available on Windows | Completed |
+---------------------------------------------------------------------------------------------------------------+---------------+
| The *os.putenv()* and *os.unsetenv()* functions are now always available | Completed |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Added *os.waitstatus_to_exitcode()* function: convert a wait status to an exit code | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `random` |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Added a new *random.Random.randbytes* method: generate random bytes | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| `sys` |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Added a new *sys.platlibdir* attribute: name of the platform-specific library directory | |
+---------------------------------------------------------------------------------------------------------------+---------------+
| Previously, *sys.stderr* was block-buffered when non-interactive. Now stderr defaults to always being | |
| line-buffered | |
+---------------------------------------------------------------------------------------------------------------+---------------+

View File

@ -16,7 +16,7 @@ working with this board it may be useful to get an overview of the microcontroll
:maxdepth: 1 :maxdepth: 1
general.rst general.rst
tutorial/intro.rst tutorial/index.rst
Installing MicroPython Installing MicroPython
---------------------- ----------------------
@ -218,20 +218,48 @@ range from 1Hz to 40MHz but there is a tradeoff; as the base frequency
*increases* the duty resolution *decreases*. See *increases* the duty resolution *decreases*. See
`LED Control <https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/ledc.html>`_ `LED Control <https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/ledc.html>`_
for more details. for more details.
Currently the duty cycle has to be in the range of 0-1023.
Use the ``machine.PWM`` class:: Use the :ref:`machine.PWM <machine.PWM>` class::
from machine import Pin, PWM from machine import Pin, PWM
pwm0 = PWM(Pin(0)) # create PWM object from a pin pwm0 = PWM(Pin(0)) # create PWM object from a pin
pwm0.freq() # get current frequency freq = pwm0.freq() # get current frequency (default 5kHz)
pwm0.freq(1000) # set frequency pwm0.freq(1000) # set PWM frequency from 1Hz to 40MHz
pwm0.duty() # get current duty cycle
pwm0.duty(200) # set duty cycle
pwm0.deinit() # turn off PWM on the pin
pwm2 = PWM(Pin(2), freq=20000, duty=512) # create and configure in one go duty = pwm0.duty() # get current duty cycle, range 0-1023 (default 512, 50%)
pwm0.duty(256) # set duty cycle from 0 to 1023 as a ratio duty/1023, (now 25%)
duty_u16 = pwm0.duty_u16() # get current duty cycle, range 0-65535
pwm0.duty_u16(2**16*3//4) # set duty cycle from 0 to 65535 as a ratio duty_u16/65535, (now 75%)
duty_ns = pwm0.duty_ns() # get current pulse width in ns
pwm0.duty_ns(250_000) # set pulse width in nanoseconds from 0 to 1_000_000_000/freq, (now 25%)
pwm0.deinit() # turn off PWM on the pin
pwm2 = PWM(Pin(2), freq=20000, duty=512) # create and configure in one go
print(pwm2) # view PWM settings
ESP chips have different hardware peripherals:
===================================================== ======== ======== ========
Hardware specification ESP32 ESP32-S2 ESP32-C3
----------------------------------------------------- -------- -------- --------
Number of groups (speed modes) 2 1 1
Number of timers per group 4 4 4
Number of channels per group 8 8 6
----------------------------------------------------- -------- -------- --------
Different PWM frequencies (groups * timers) 8 4 4
Total PWM channels (Pins, duties) (groups * channels) 16 8 6
===================================================== ======== ======== ========
A maximum number of PWM channels (Pins) are available on the ESP32 - 16 channels,
but only 8 different PWM frequencies are available, the remaining 8 channels must
have the same frequency. On the other hand, 16 independent PWM duty cycles are
possible at the same frequency.
See more examples in the :ref:`esp32_pwm` tutorial.
ADC (analog to digital conversion) ADC (analog to digital conversion)
---------------------------------- ----------------------------------
@ -391,14 +419,14 @@ I2S bus
See :ref:`machine.I2S <machine.I2S>`. :: See :ref:`machine.I2S <machine.I2S>`. ::
from machine import I2S, Pin from machine import I2S, Pin
i2s = I2S(0, sck=Pin(13), ws=Pin(14), sd=Pin(34), mode=I2S.TX, bits=16, format=I2S.STEREO, rate=44100, ibuf=40000) # create I2S object i2s = I2S(0, sck=Pin(13), ws=Pin(14), sd=Pin(34), mode=I2S.TX, bits=16, format=I2S.STEREO, rate=44100, ibuf=40000) # create I2S object
i2s.write(buf) # write buffer of audio samples to I2S device i2s.write(buf) # write buffer of audio samples to I2S device
i2s = I2S(1, sck=Pin(33), ws=Pin(25), sd=Pin(32), mode=I2S.RX, bits=16, format=I2S.MONO, rate=22050, ibuf=40000) # create I2S object i2s = I2S(1, sck=Pin(33), ws=Pin(25), sd=Pin(32), mode=I2S.RX, bits=16, format=I2S.MONO, rate=22050, ibuf=40000) # create I2S object
i2s.readinto(buf) # fill buffer with audio samples from I2S device i2s.readinto(buf) # fill buffer with audio samples from I2S device
The I2S class is currently available as a Technical Preview. During the preview period, feedback from The I2S class is currently available as a Technical Preview. During the preview period, feedback from
users is encouraged. Based on this feedback, the I2S class API and implementation may be changed. users is encouraged. Based on this feedback, the I2S class API and implementation may be changed.
ESP32 has two I2S buses with id=0 and id=1 ESP32 has two I2S buses with id=0 and id=1
@ -481,7 +509,7 @@ The RMT is ESP32-specific and allows generation of accurate digital pulses with
r = esp32.RMT(0, pin=Pin(18), clock_div=8) r = esp32.RMT(0, pin=Pin(18), clock_div=8)
r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8) r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8)
# The channel resolution is 100ns (1/(source_freq/clock_div)). # The channel resolution is 100ns (1/(source_freq/clock_div)).
r.write_pulses((1, 20, 2, 40), start=0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns r.write_pulses((1, 20, 2, 40), 0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns
OneWire driver OneWire driver
-------------- --------------
@ -545,6 +573,9 @@ For low-level driving of a NeoPixel::
400kHz) devices by passing ``timing=0`` when constructing the 400kHz) devices by passing ``timing=0`` when constructing the
``NeoPixel`` object. ``NeoPixel`` object.
The low-level driver uses an RMT channel by default. To configure this see
`RMT.bitstream_channel`.
APA102 (DotStar) uses a different driver as it has an additional clock pin. APA102 (DotStar) uses a different driver as it has an additional clock pin.
Capacitive touch Capacitive touch

View File

@ -0,0 +1,23 @@
.. _esp32_tutorial:
MicroPython tutorial for ESP32
==============================
This tutorial is intended to get you started using MicroPython on the ESP32
system-on-a-chip. If it is your first time it is recommended to follow the
tutorial through in the order below. Otherwise the sections are mostly self
contained, so feel free to skip to those that interest you.
The tutorial does not assume that you know Python, but it also does not attempt
to explain any of the details of the Python language. Instead it provides you
with commands that are ready to run, and hopes that you will gain a bit of
Python knowledge along the way. To learn more about Python itself please refer
to `<https://www.python.org>`__.
.. toctree::
:maxdepth: 1
:numbered:
intro.rst
pwm.rst
peripheral_access.rst

View File

@ -34,8 +34,8 @@ Please refer to the documentation for your board for further details.
Getting the firmware Getting the firmware
-------------------- --------------------
The first thing you need to do is download the most recent MicroPython firmware The first thing you need to do is download the most recent MicroPython firmware
.bin file to load onto your ESP32 device. You can download it from the .bin file to load onto your ESP32 device. You can download it from the
`MicroPython downloads page <https://micropython.org/download#esp32>`_. `MicroPython downloads page <https://micropython.org/download#esp32>`_.
From here, you have 3 main choices: From here, you have 3 main choices:

View File

@ -0,0 +1,44 @@
Accessing peripherals directly via registers
============================================
The ESP32's peripherals can be controlled via direct register reads and writes.
This requires reading the datasheet to know what registers to use and what
values to write to them. The following example shows how to turn on and change
the prescaler of the MCPWM0 peripheral.
.. code-block:: python3
from micropython import const
from machine import mem32
# Define the register addresses that will be used.
DR_REG_DPORT_BASE = const(0x3FF00000)
DPORT_PERIP_CLK_EN_REG = const(DR_REG_DPORT_BASE + 0x0C0)
DPORT_PERIP_RST_EN_REG = const(DR_REG_DPORT_BASE + 0x0C4)
DPORT_PWM0_CLK_EN = const(1 << 17)
MCPWM0 = const(0x3FF5E000)
MCPWM1 = const(0x3FF6C000)
# Enable CLK and disable RST.
print(hex(mem32[DPORT_PERIP_CLK_EN_REG] & 0xffffffff))
print(hex(mem32[DPORT_PERIP_RST_EN_REG] & 0xffffffff))
mem32[DPORT_PERIP_CLK_EN_REG] |= DPORT_PWM0_CLK_EN
mem32[DPORT_PERIP_RST_EN_REG] &= ~DPORT_PWM0_CLK_EN
print(hex(mem32[DPORT_PERIP_CLK_EN_REG] & 0xffffffff))
print(hex(mem32[DPORT_PERIP_RST_EN_REG] & 0xffffffff))
# Change the MCPWM0 prescaler.
print(hex(mem32[MCPWM0])) # read PWM_CLK_CFG_REG (reset value = 0)
mem32[MCPWM0] = 0x55 # change PWM_CLK_PRESCALE
print(hex(mem32[MCPWM0])) # read PWM_CLK_CFG_REG
Note that before a peripheral can be used its clock must be enabled and it must
be taken out of reset. In the above example the following registers are used
for this:
- ``DPORT_PERI_CLK_EN_REG``: used to enable a peripheral clock
- ``DPORT_PERI_RST_EN_REG``: used to reset (or take out of reset) a peripheral
The MCPWM0 peripheral is in bit position 17 of the above two registers, hence
the value of ``DPORT_PWM0_CLK_EN``.

115
docs/esp32/tutorial/pwm.rst Normal file
View File

@ -0,0 +1,115 @@
.. _esp32_pwm:
Pulse Width Modulation
======================
Pulse width modulation (PWM) is a way to get an artificial analog output on a
digital pin. It achieves this by rapidly toggling the pin from low to high.
There are two parameters associated with this: the frequency of the toggling,
and the duty cycle. The duty cycle is defined to be how long the pin is high
compared with the length of a single period (low plus high time). Maximum
duty cycle is when the pin is high all of the time, and minimum is when it is
low all of the time.
* More comprehensive example with all 16 PWM channels and 8 timers::
from machine import Pin, PWM
try:
f = 100 # Hz
d = 1024 // 16 # 6.25%
pins = (15, 2, 4, 16, 18, 19, 22, 23, 25, 26, 27, 14 , 12, 13, 32, 33)
pwms = []
for i, pin in enumerate(pins):
pwms.append(PWM(Pin(pin), freq=f * (i // 2 + 1), duty= 1023 if i==15 else d * (i + 1)))
print(pwms[i])
finally:
for pwm in pwms:
try:
pwm.deinit()
except:
pass
Output is::
PWM(Pin(15), freq=100, duty=64, resolution=10, mode=0, channel=0, timer=0)
PWM(Pin(2), freq=100, duty=128, resolution=10, mode=0, channel=1, timer=0)
PWM(Pin(4), freq=200, duty=192, resolution=10, mode=0, channel=2, timer=1)
PWM(Pin(16), freq=200, duty=256, resolution=10, mode=0, channel=3, timer=1)
PWM(Pin(18), freq=300, duty=320, resolution=10, mode=0, channel=4, timer=2)
PWM(Pin(19), freq=300, duty=384, resolution=10, mode=0, channel=5, timer=2)
PWM(Pin(22), freq=400, duty=448, resolution=10, mode=0, channel=6, timer=3)
PWM(Pin(23), freq=400, duty=512, resolution=10, mode=0, channel=7, timer=3)
PWM(Pin(25), freq=500, duty=576, resolution=10, mode=1, channel=0, timer=0)
PWM(Pin(26), freq=500, duty=640, resolution=10, mode=1, channel=1, timer=0)
PWM(Pin(27), freq=600, duty=704, resolution=10, mode=1, channel=2, timer=1)
PWM(Pin(14), freq=600, duty=768, resolution=10, mode=1, channel=3, timer=1)
PWM(Pin(12), freq=700, duty=832, resolution=10, mode=1, channel=4, timer=2)
PWM(Pin(13), freq=700, duty=896, resolution=10, mode=1, channel=5, timer=2)
PWM(Pin(32), freq=800, duty=960, resolution=10, mode=1, channel=6, timer=3)
PWM(Pin(33), freq=800, duty=1023, resolution=10, mode=1, channel=7, timer=3)
* Example of a smooth frequency change::
from utime import sleep
from machine import Pin, PWM
F_MIN = 500
F_MAX = 1000
f = F_MIN
delta_f = 1
p = PWM(Pin(5), f)
print(p)
while True:
p.freq(f)
sleep(10 / F_MIN)
f += delta_f
if f >= F_MAX or f <= F_MIN:
delta_f = -delta_f
See PWM wave at Pin(5) with an oscilloscope.
* Example of a smooth duty change::
from utime import sleep
from machine import Pin, PWM
DUTY_MAX = 2**16 - 1
duty_u16 = 0
delta_d = 16
p = PWM(Pin(5), 1000, duty_u16=duty_u16)
print(p)
while True:
p.duty_u16(duty_u16)
sleep(1 / 1000)
duty_u16 += delta_d
if duty_u16 >= DUTY_MAX:
duty_u16 = DUTY_MAX
delta_d = -delta_d
elif duty_u16 <= 0:
duty_u16 = 0
delta_d = -delta_d
See PWM wave at Pin(5) with an oscilloscope.
Note: the Pin.OUT mode does not need to be specified. The channel is initialized
to PWM mode internally once for each Pin that is passed to the PWM constructor.
The following code is wrong::
pwm = PWM(Pin(5, Pin.OUT), freq=1000, duty=512) # Pin(5) in PWM mode here
pwm = PWM(Pin(5, Pin.OUT), freq=500, duty=256) # Pin(5) in OUT mode here, PWM is off
Use this code instead::
pwm = PWM(Pin(5), freq=1000, duty=512)
pwm.init(freq=500, duty=256)

View File

@ -41,8 +41,8 @@ Please refer to the documentation for your board for further details.
Getting the firmware Getting the firmware
-------------------- --------------------
The first thing you need to do is download the most recent MicroPython firmware The first thing you need to do is download the most recent MicroPython firmware
.bin file to load onto your ESP8266 device. You can download it from the .bin file to load onto your ESP8266 device. You can download it from the
`MicroPython downloads page <http://micropython.org/download#esp8266>`_. `MicroPython downloads page <http://micropython.org/download#esp8266>`_.
From here, you have 3 main choices From here, you have 3 main choices
@ -64,7 +64,7 @@ such, only daily builds for 512kb modules are provided.
Deploying the firmware Deploying the firmware
---------------------- ----------------------
Once you have the MicroPython firmware (compiled code), you need to load it onto Once you have the MicroPython firmware (compiled code), you need to load it onto
your ESP8266 device. There are two main steps to do this: first you your ESP8266 device. There are two main steps to do this: first you
need to put your device in boot-loader mode, and second you need to copy across need to put your device in boot-loader mode, and second you need to copy across
the firmware. The exact procedure for these steps is highly dependent on the the firmware. The exact procedure for these steps is highly dependent on the

View File

@ -66,8 +66,8 @@ Subclassing FrameBuffer provides support for graphics primitives::
display.hline(0, 8, 4, 1) # draw horizontal line x=0, y=8, width=4, colour=1 display.hline(0, 8, 4, 1) # draw horizontal line x=0, y=8, width=4, colour=1
display.vline(0, 8, 4, 1) # draw vertical line x=0, y=8, height=4, colour=1 display.vline(0, 8, 4, 1) # draw vertical line x=0, y=8, height=4, colour=1
display.line(0, 0, 127, 63, 1) # draw a line from 0,0 to 127,63 display.line(0, 0, 127, 63, 1) # draw a line from 0,0 to 127,63
display.rect(10, 10, 107, 43, 1) # draw a rectangle outline 10,10 to 107,43, colour=1 display.rect(10, 10, 107, 43, 1) # draw a rectangle outline 10,10 to 117,53, colour=1
display.fill_rect(10, 10, 107, 43, 1) # draw a solid rectangle 10,10 to 107,43, colour=1 display.fill_rect(10, 10, 107, 43, 1) # draw a solid rectangle 10,10 to 117,53, colour=1
display.text('Hello World', 0, 0, 1) # draw some text at x=0, y=0, colour=1 display.text('Hello World', 0, 0, 1) # draw some text at x=0, y=0, colour=1
display.scroll(20, 0) # scroll 20 pixels to the right display.scroll(20, 0) # scroll 20 pixels to the right

View File

@ -49,7 +49,7 @@ Configuration
- ``'mac'``: The current address in use, depending on the current address mode. - ``'mac'``: The current address in use, depending on the current address mode.
This returns a tuple of ``(addr_type, addr)``. This returns a tuple of ``(addr_type, addr)``.
See :meth:`gatts_write <BLE.gap_scan>` for details about address type. See :meth:`gatts_write <BLE.gatts_write>` for details about address type.
This may only be queried while the interface is currently active. This may only be queried while the interface is currently active.
@ -359,13 +359,27 @@ Central Role
A central device can connect to peripherals that it has discovered using the observer role (see :meth:`gap_scan<BLE.gap_scan>`) or with a known address. A central device can connect to peripherals that it has discovered using the observer role (see :meth:`gap_scan<BLE.gap_scan>`) or with a known address.
.. method:: BLE.gap_connect(addr_type, addr, scan_duration_ms=2000, /) .. method:: BLE.gap_connect(addr_type, addr, scan_duration_ms=2000, min_conn_interval_us=None, max_conn_interval_us=None, /)
Connect to a peripheral. Connect to a peripheral.
See :meth:`gap_scan <BLE.gap_scan>` for details about address types. See :meth:`gap_scan <BLE.gap_scan>` for details about address types.
On success, the ``_IRQ_PERIPHERAL_CONNECT`` event will be raised. To cancel an outstanding connection attempt early, call
``gap_connect(None)``.
On success, the ``_IRQ_PERIPHERAL_CONNECT`` event will be raised. If
cancelling a connection attempt, the ``_IRQ_PERIPHERAL_DISCONNECT`` event
will be raised.
The device will wait up to *scan_duration_ms* to receive an advertising
payload from the device.
The connection interval can be configured in **micro**\ seconds using either
or both of *min_conn_interval_us* and *max_conn_interval_us*. Otherwise a
default interval will be chosen, typically between 30000 and 50000
microseconds. A shorter interval will increase throughput, at the expense
of power usage.
Peripheral Role Peripheral Role

View File

@ -4,7 +4,7 @@
.. module:: esp .. module:: esp
:synopsis: functions related to the ESP8266 and ESP32 :synopsis: functions related to the ESP8266 and ESP32
The ``esp`` module contains specific functions related to both the ESP8266 and The ``esp`` module contains specific functions related to both the ESP8266 and
ESP32 modules. Some functions are only available on one or the other of these ESP32 modules. Some functions are only available on one or the other of these
ports. ports.

View File

@ -250,6 +250,17 @@ For more details see Espressif's `ESP-IDF RMT documentation.
new sequence of pulses. Looping sequences longer than 126 pulses is not new sequence of pulses. Looping sequences longer than 126 pulses is not
supported by the hardware. supported by the hardware.
.. staticmethod:: RMT.bitstream_channel([value])
Select which RMT channel is used by the `machine.bitstream` implementation.
*value* can be ``None`` or a valid RMT channel number. The default RMT
channel is the highest numbered one.
Passing in ``None`` disables the use of RMT and instead selects a bit-banging
implementation for `machine.bitstream`.
Passing in no argument will not change the channel. This function returns
the current channel number.
Ultra-Low-Power co-processor Ultra-Low-Power co-processor
---------------------------- ----------------------------

View File

@ -19,11 +19,11 @@ For example::
import framebuf import framebuf
# FrameBuffer needs 2 bytes for every RGB565 pixel # FrameBuffer needs 2 bytes for every RGB565 pixel
fbuf = framebuf.FrameBuffer(bytearray(10 * 100 * 2), 10, 100, framebuf.RGB565) fbuf = framebuf.FrameBuffer(bytearray(100 * 10 * 2), 100, 10, framebuf.RGB565)
fbuf.fill(0) fbuf.fill(0)
fbuf.text('MicroPython!', 0, 0, 0xffff) fbuf.text('MicroPython!', 0, 0, 0xffff)
fbuf.hline(0, 10, 96, 0xffff) fbuf.hline(0, 9, 96, 0xffff)
Constructors Constructors
------------ ------------

View File

@ -23,7 +23,7 @@ Functions
Pop the first item from the ``heap``, and return it. Raise ``IndexError`` if Pop the first item from the ``heap``, and return it. Raise ``IndexError`` if
``heap`` is empty. ``heap`` is empty.
The returned item will be the smallest item in the ``heap``. The returned item will be the smallest item in the ``heap``.
.. function:: heapify(x) .. function:: heapify(x)

View File

@ -65,6 +65,7 @@ library.
json.rst json.rst
math.rst math.rst
os.rst os.rst
random.rst
re.rst re.rst
select.rst select.rst
socket.rst socket.rst
@ -119,6 +120,7 @@ The following libraries are specific to the pyboard.
:maxdepth: 2 :maxdepth: 2
pyb.rst pyb.rst
stm.rst
lcd160cr.rst lcd160cr.rst

View File

@ -313,7 +313,7 @@ Advanced commands
specified by :meth:`LCD160CR.set_spi_win`, starting from the top-left corner. specified by :meth:`LCD160CR.set_spi_win`, starting from the top-left corner.
The `framebuf <framebuf.html>`_ module can be used to construct frame buffers The `framebuf <framebuf.html>`_ module can be used to construct frame buffers
and provides drawing primitives. Using a frame buffer will improve and provides drawing primitives. Using a frame buffer will improve
performance of animations when compared to drawing directly to the screen. performance of animations when compared to drawing directly to the screen.
.. method:: LCD160CR.set_scroll(on) .. method:: LCD160CR.set_scroll(on)

View File

@ -27,13 +27,13 @@ Constructors
Create an ADC object associated with the given pin. Create an ADC object associated with the given pin.
This allows you to then read analog values on that pin. This allows you to then read analog values on that pin.
For more info check the `pinout and alternate functions For more info check the `pinout and alternate functions
table. <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_ table. <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
.. warning:: .. warning::
ADC pin input range is 0-1.4V (being 1.8V the absolute maximum that it ADC pin input range is 0-1.4V (being 1.8V the absolute maximum that it
can withstand). When GP2, GP3, GP4 or GP5 are remapped to the can withstand). When GP2, GP3, GP4 or GP5 are remapped to the
ADC block, 1.8 V is the maximum. If these pins are used in digital mode, ADC block, 1.8 V is the maximum. If these pins are used in digital mode,
then the maximum allowed input is 3.6V. then the maximum allowed input is 3.6V.
Methods Methods

View File

@ -4,91 +4,91 @@
class I2S -- Inter-IC Sound bus protocol class I2S -- Inter-IC Sound bus protocol
======================================== ========================================
I2S is a synchronous serial protocol used to connect digital audio devices. I2S is a synchronous serial protocol used to connect digital audio devices.
At the physical level, a bus consists of 3 lines: SCK, WS, SD. At the physical level, a bus consists of 3 lines: SCK, WS, SD.
The I2S class supports controller operation. Peripheral operation is not supported. The I2S class supports controller operation. Peripheral operation is not supported.
The I2S class is currently available as a Technical Preview. During the preview period, feedback from The I2S class is currently available as a Technical Preview. During the preview period, feedback from
users is encouraged. Based on this feedback, the I2S class API and implementation may be changed. users is encouraged. Based on this feedback, the I2S class API and implementation may be changed.
I2S objects can be created and initialized using:: I2S objects can be created and initialized using::
from machine import I2S from machine import I2S
from machine import Pin from machine import Pin
# ESP32 # ESP32
sck_pin = Pin(14) # Serial clock output sck_pin = Pin(14) # Serial clock output
ws_pin = Pin(13) # Word clock output ws_pin = Pin(13) # Word clock output
sd_pin = Pin(12) # Serial data output sd_pin = Pin(12) # Serial data output
or or
# PyBoards # PyBoards
sck_pin = Pin("Y6") # Serial clock output sck_pin = Pin("Y6") # Serial clock output
ws_pin = Pin("Y5") # Word clock output ws_pin = Pin("Y5") # Word clock output
sd_pin = Pin("Y8") # Serial data output sd_pin = Pin("Y8") # Serial data output
audio_out = I2S(2, audio_out = I2S(2,
sck=sck_pin, ws=ws_pin, sd=sd_pin, sck=sck_pin, ws=ws_pin, sd=sd_pin,
mode=I2S.TX, mode=I2S.TX,
bits=16, bits=16,
format=I2S.MONO, format=I2S.MONO,
rate=44100, rate=44100,
ibuf=20000) ibuf=20000)
audio_in = I2S(2, audio_in = I2S(2,
sck=sck_pin, ws=ws_pin, sd=sd_pin, sck=sck_pin, ws=ws_pin, sd=sd_pin,
mode=I2S.RX, mode=I2S.RX,
bits=32, bits=32,
format=I2S.STEREO, format=I2S.STEREO,
rate=22050, rate=22050,
ibuf=20000) ibuf=20000)
3 modes of operation are supported: 3 modes of operation are supported:
- blocking - blocking
- non-blocking - non-blocking
- uasyncio - uasyncio
blocking:: blocking::
num_written = audio_out.write(buf) # blocks until buf emptied num_written = audio_out.write(buf) # blocks until buf emptied
num_read = audio_in.readinto(buf) # blocks until buf filled num_read = audio_in.readinto(buf) # blocks until buf filled
non-blocking:: non-blocking::
audio_out.irq(i2s_callback) # i2s_callback is called when buf is emptied audio_out.irq(i2s_callback) # i2s_callback is called when buf is emptied
num_written = audio_out.write(buf) # returns immediately num_written = audio_out.write(buf) # returns immediately
audio_in.irq(i2s_callback) # i2s_callback is called when buf is filled audio_in.irq(i2s_callback) # i2s_callback is called when buf is filled
num_read = audio_in.readinto(buf) # returns immediately num_read = audio_in.readinto(buf) # returns immediately
uasyncio:: uasyncio::
swriter = uasyncio.StreamWriter(audio_out) swriter = uasyncio.StreamWriter(audio_out)
swriter.write(buf) swriter.write(buf)
await swriter.drain() await swriter.drain()
sreader = uasyncio.StreamReader(audio_in) sreader = uasyncio.StreamReader(audio_in)
num_read = await sreader.readinto(buf) num_read = await sreader.readinto(buf)
Constructor Constructor
----------- -----------
.. class:: I2S(id, *, sck, ws, sd, mode, bits, format, rate, ibuf) .. class:: I2S(id, *, sck, ws, sd, mode, bits, format, rate, ibuf)
Construct an I2S object of the given id: Construct an I2S object of the given id:
- ``id`` identifies a particular I2S bus. - ``id`` identifies a particular I2S bus.
``id`` is board and port specific: ``id`` is board and port specific:
- PYBv1.0/v1.1: has one I2S bus with id=2. - PYBv1.0/v1.1: has one I2S bus with id=2.
- PYBD-SFxW: has two I2S buses with id=1 and id=2. - PYBD-SFxW: has two I2S buses with id=1 and id=2.
- ESP32: has two I2S buses with id=0 and id=1. - ESP32: has two I2S buses with id=0 and id=1.
Keyword-only parameters that are supported on all ports: Keyword-only parameters that are supported on all ports:
- ``sck`` is a pin object for the serial clock line - ``sck`` is a pin object for the serial clock line
- ``ws`` is a pin object for the word select line - ``ws`` is a pin object for the word select line
- ``sd`` is a pin object for the serial data line - ``sd`` is a pin object for the serial data line
@ -97,9 +97,9 @@ Constructor
- ``format`` specifies channel format, STEREO or MONO - ``format`` specifies channel format, STEREO or MONO
- ``rate`` specifies audio sampling rate (samples/s) - ``rate`` specifies audio sampling rate (samples/s)
- ``ibuf`` specifies internal buffer length (bytes) - ``ibuf`` specifies internal buffer length (bytes)
For all ports, DMA runs continuously in the background and allows user applications to perform other operations while For all ports, DMA runs continuously in the background and allows user applications to perform other operations while
sample data is transfered between the internal buffer and the I2S peripheral unit. sample data is transfered between the internal buffer and the I2S peripheral unit.
Increasing the size of the internal buffer has the potential to increase the time that user applications can perform non-I2S operations Increasing the size of the internal buffer has the potential to increase the time that user applications can perform non-I2S operations
before underflow (e.g. ``write`` method) or overflow (e.g. ``readinto`` method). before underflow (e.g. ``write`` method) or overflow (e.g. ``readinto`` method).
@ -109,37 +109,37 @@ Methods
.. method:: I2S.init(sck, ...) .. method:: I2S.init(sck, ...)
see Constructor for argument descriptions see Constructor for argument descriptions
.. method:: I2S.deinit() .. method:: I2S.deinit()
Deinitialize the I2S bus Deinitialize the I2S bus
.. method:: I2S.readinto(buf) .. method:: I2S.readinto(buf)
Read audio samples into the buffer specified by ``buf``. ``buf`` must support the buffer protocol, such as bytearray or array. Read audio samples into the buffer specified by ``buf``. ``buf`` must support the buffer protocol, such as bytearray or array.
"buf" byte ordering is little-endian. For Stereo format, left channel sample precedes right channel sample. For Mono format, "buf" byte ordering is little-endian. For Stereo format, left channel sample precedes right channel sample. For Mono format,
the left channel sample data is used. the left channel sample data is used.
Returns number of bytes read Returns number of bytes read
.. method:: I2S.write(buf) .. method:: I2S.write(buf)
Write audio samples contained in ``buf``. ``buf`` must support the buffer protocol, such as bytearray or array. Write audio samples contained in ``buf``. ``buf`` must support the buffer protocol, such as bytearray or array.
"buf" byte ordering is little-endian. For Stereo format, left channel sample precedes right channel sample. For Mono format, "buf" byte ordering is little-endian. For Stereo format, left channel sample precedes right channel sample. For Mono format,
the sample data is written to both the right and left channels. the sample data is written to both the right and left channels.
Returns number of bytes written Returns number of bytes written
.. method:: I2S.irq(handler) .. method:: I2S.irq(handler)
Set a callback. ``handler`` is called when ``buf`` is emptied (``write`` method) or becomes full (``readinto`` method). Set a callback. ``handler`` is called when ``buf`` is emptied (``write`` method) or becomes full (``readinto`` method).
Setting a callback changes the ``write`` and ``readinto`` methods to non-blocking operation. Setting a callback changes the ``write`` and ``readinto`` methods to non-blocking operation.
``handler`` is called in the context of the MicroPython scheduler. ``handler`` is called in the context of the MicroPython scheduler.
.. staticmethod:: I2S.shift(buf, bits, shift)
bitwise shift of all samples contained in ``buf``. ``bits`` specifies sample size in bits. ``shift`` specifies the number of bits to shift each sample. .. staticmethod:: I2S.shift(*, buf, bits, shift)
Positive for left shift, negative for right shift.
bitwise shift of all samples contained in ``buf``. ``bits`` specifies sample size in bits. ``shift`` specifies the number of bits to shift each sample.
Positive for left shift, negative for right shift.
Typically used for volume control. Each bit shift changes sample volume by 6dB. Typically used for volume control. Each bit shift changes sample volume by 6dB.
Constants Constants
--------- ---------

View File

@ -77,3 +77,34 @@ Methods
With no arguments the pulse width in nanoseconds is returned. With no arguments the pulse width in nanoseconds is returned.
With a single *value* argument the pulse width is set to that value. With a single *value* argument the pulse width is set to that value.
Limitations of PWM
------------------
* Not all frequencies can be generated with absolute accuracy due to
the discrete nature of the computing hardware. Typically the PWM frequency
is obtained by dividing some integer base frequency by an integer divider.
For example, if the base frequency is 80MHz and the required PWM frequency is
300kHz the divider must be a non-integer number 80000000 / 300000 = 266.67.
After rounding the divider is set to 267 and the PWM frequency will be
80000000 / 267 = 299625.5 Hz, not 300kHz. If the divider is set to 266 then
the PWM frequency will be 80000000 / 266 = 300751.9 Hz, but again not 300kHz.
* The duty cycle has the same discrete nature and its absolute accuracy is not
achievable. On most hardware platforms the duty will be applied at the next
frequency period. Therefore, you should wait more than "1/frequency" before
measuring the duty.
* The frequency and the duty cycle resolution are usually interdependent.
The higher the PWM frequency the lower the duty resolution which is available,
and vice versa. For example, a 300kHz PWM frequency can have a duty cycle
resolution of 8 bit, not 16-bit as may be expected. In this case, the lowest
8 bits of *duty_u16* are insignificant. So::
pwm=PWM(Pin(13), freq=300_000, duty_u16=2**16//2)
and::
pwm=PWM(Pin(13), freq=300_000, duty_u16=2**16//2 + 255)
will generate PWM with the same 50% duty cycle.

View File

@ -74,6 +74,8 @@ Constructors
- ``Pin.ALT_OPEN_DRAIN`` - The Same as ``Pin.ALT``, but the pin is configured as - ``Pin.ALT_OPEN_DRAIN`` - The Same as ``Pin.ALT``, but the pin is configured as
open-drain. Not all ports implement this mode. open-drain. Not all ports implement this mode.
- ``Pin.ANALOG`` - Pin is configured for analog input, see the :class:`ADC` class.
- ``pull`` specifies if the pin has a (weak) pull resistor attached, and can be - ``pull`` specifies if the pin has a (weak) pull resistor attached, and can be
one of: one of:
@ -247,6 +249,7 @@ not all constants are available on all ports.
Pin.OPEN_DRAIN Pin.OPEN_DRAIN
Pin.ALT Pin.ALT
Pin.ALT_OPEN_DRAIN Pin.ALT_OPEN_DRAIN
Pin.ANALOG
Selects the pin mode. Selects the pin mode.

View File

@ -32,7 +32,7 @@ Constructors
.. class:: SD(id,... ) .. class:: SD(id,... )
Create a SD card object. See ``init()`` for parameters if initialization. Create a SD card object. See ``init()`` for parameters if initialization.
Methods Methods
------- -------

View File

@ -50,7 +50,7 @@ vary from platform to platform.
- *mosi* can be used to specify an SPI mosi pin. - *mosi* can be used to specify an SPI mosi pin.
- *cs* can be used to specify an SPI chip select pin. - *cs* can be used to specify an SPI chip select pin.
- *freq* selects the SD/MMC interface frequency in Hz (only supported on the ESP32). - *freq* selects the SD/MMC interface frequency in Hz (only supported on the ESP32).
Implementation-specific details Implementation-specific details

View File

@ -19,6 +19,42 @@ Software SPI is implemented by bit-banging and can be used on any pin but
is not as efficient. These classes have the same methods available and is not as efficient. These classes have the same methods available and
differ primarily in the way they are constructed. differ primarily in the way they are constructed.
Example usage::
from machine import SPI, Pin
spi = SPI(0, baudrate=400000) # Create SPI peripheral 0 at frequency of 400kHz.
# Depending on the use case, extra parameters may be required
# to select the bus characteristics and/or pins to use.
cs = Pin(4, mode=Pin.OUT, value=1) # Create chip-select on pin 4.
try:
cs(0) # Select peripheral.
spi.write(b"12345678") # Write 8 bytes, and don't care about received data.
finally:
cs(1) # Deselect peripheral.
try:
cs(0) # Select peripheral.
rxdata = spi.read(8, 0x42) # Read 8 bytes while writing 0x42 for each byte.
finally:
cs(1) # Deselect peripheral.
rxdata = bytearray(8)
try:
cs(0) # Select peripheral.
spi.readinto(rxdata, 0x42) # Read 8 bytes inplace while writing 0x42 for each byte.
finally:
cs(1) # Deselect peripheral.
txdata = b"12345678"
rxdata = bytearray(len(txdata))
try:
cs(0) # Select peripheral.
spi.write_readinto(txdata, rxdata) # Simultaneously write and read bytes.
finally:
cs(1) # Deselect peripheral.
Constructors Constructors
------------ ------------

View File

@ -27,11 +27,12 @@ instead of this class.
Constructors Constructors
------------ ------------
.. class:: Timer(id, ...) .. class:: Timer(id, /, ...)
Construct a new timer object of the given id. Id of -1 constructs a Construct a new timer object of the given ``id``. ``id`` of -1 constructs a
virtual timer (if supported by a board). virtual timer (if supported by a board).
``id`` shall not be passed as a keyword argument.
See ``init`` for parameters of initialisation. See ``init`` for parameters of initialisation.
Methods Methods
@ -41,8 +42,14 @@ Methods
Initialise the timer. Example:: Initialise the timer. Example::
tim.init(period=100) # periodic with 100ms period def mycallback(t):
tim.init(mode=Timer.ONE_SHOT, period=1000) # one shot firing after 1000ms pass
# periodic with 100ms period
tim.init(period=100, callback=mycallback)
# one shot firing after 1000ms
tim.init(mode=Timer.ONE_SHOT, period=1000, callback=mycallback)
Keyword arguments: Keyword arguments:
@ -53,6 +60,14 @@ Methods
- ``Timer.PERIODIC`` - The timer runs periodically at the configured - ``Timer.PERIODIC`` - The timer runs periodically at the configured
frequency of the channel. frequency of the channel.
- ``period`` - The timer period, in milliseconds.
- ``callback`` - The callable to call upon expiration of the timer period.
The callback must take one argument, which is passed the Timer object.
The ``callback`` argument shall be specified. Otherwise an exception
will occurr upon timer expiration:
``TypeError: 'NoneType' object isn't callable``
.. method:: Timer.deinit() .. method:: Timer.deinit()
Deinitialises the timer. Stops the timer, and disables the timer peripheral. Deinitialises the timer. Stops the timer, and disables the timer peripheral.

View File

@ -50,9 +50,9 @@ Methods
- ``mode`` can be one of: - ``mode`` can be one of:
- ``TimerWiPy.ONE_SHOT`` - The timer runs once until the configured - ``TimerWiPy.ONE_SHOT`` - The timer runs once until the configured
period of the channel expires. period of the channel expires.
- ``TimerWiPy.PERIODIC`` - The timer runs periodically at the configured - ``TimerWiPy.PERIODIC`` - The timer runs periodically at the configured
frequency of the channel. frequency of the channel.
- ``TimerWiPy.PWM`` - Output a PWM signal on a pin. - ``TimerWiPy.PWM`` - Output a PWM signal on a pin.
@ -74,7 +74,7 @@ Methods
The operating mode is is the one configured to the Timer object that was used to The operating mode is is the one configured to the Timer object that was used to
create the channel. create the channel.
- ``channel`` if the width of the timer is 16-bit, then must be either ``TIMER.A``, ``TIMER.B``. - ``channel`` if the width of the timer is 16-bit, then must be either ``TIMER.A``, ``TIMER.B``.
If the width is 32-bit then it **must be** ``TIMER.A | TIMER.B``. If the width is 32-bit then it **must be** ``TIMER.A | TIMER.B``.
Keyword only arguments: Keyword only arguments:

View File

@ -64,7 +64,7 @@ Methods
- *timeout_char* specifies the time to wait between characters (in ms). - *timeout_char* specifies the time to wait between characters (in ms).
- *invert* specifies which lines to invert. - *invert* specifies which lines to invert.
- *flow* specifies which hardware flow control signals to use. The value - *flow* specifies which hardware flow control signals to use. The value
is a bitmask. is a bitmask.
- ``0`` will ignore hardware flow control signals. - ``0`` will ignore hardware flow control signals.
- ``UART.RTS`` will enable receive flow control by using the RTS output pin to - ``UART.RTS`` will enable receive flow control by using the RTS output pin to

View File

@ -24,7 +24,7 @@ Constructors
Create a WDT object and start it. The timeout must be given in milliseconds. Create a WDT object and start it. The timeout must be given in milliseconds.
Once it is running the timeout cannot be changed and the WDT cannot be stopped either. Once it is running the timeout cannot be changed and the WDT cannot be stopped either.
Notes: On the esp32 the minimum timeout is 1 second. On the esp8266 a timeout Notes: On the esp32 the minimum timeout is 1 second. On the esp8266 a timeout
cannot be specified, it is determined by the underlying system. cannot be specified, it is determined by the underlying system.

View File

@ -203,7 +203,7 @@ Classes
machine.UART.rst machine.UART.rst
machine.SPI.rst machine.SPI.rst
machine.I2C.rst machine.I2C.rst
machine.I2S.rst machine.I2S.rst
machine.RTC.rst machine.RTC.rst
machine.Timer.rst machine.Timer.rst
machine.WDT.rst machine.WDT.rst

View File

@ -314,6 +314,12 @@ that the block device supports the extended interface.
``ioctl(6, ...)`` must also be intercepted. The need for others is ``ioctl(6, ...)`` must also be intercepted. The need for others is
hardware dependent. hardware dependent.
Prior to any call to ``writeblocks(block, ...)`` littlefs issues
``ioctl(6, block)``. This enables a device driver to erase the block
prior to a write if the hardware requires it. Alternatively a driver
might intercept ``ioctl(6, block)`` and return 0 (success). In this case
the driver assumes responsibility for detecting the need for erasure.
Unless otherwise stated ``ioctl(op, arg)`` can return ``None``. Unless otherwise stated ``ioctl(op, arg)`` can return ``None``.
Consequently an implementation can ignore unused values of ``op``. Where Consequently an implementation can ignore unused values of ``op``. Where
``op`` is intercepted, the return value for operations 4 and 5 are as ``op`` is intercepted, the return value for operations 4 and 5 are as

View File

@ -120,7 +120,7 @@ Methods
- *value* if not None will set the port output value before enabling the pin. - *value* if not None will set the port output value before enabling the pin.
- *alt* can be used when mode is ``Pin.AF_PP`` or ``Pin.AF_OD`` to set the - *alt* can be used when mode is ``Pin.AF_PP`` or ``Pin.AF_OD`` to set the
index or name of one of the alternate functions associated with a pin. index or name of one of the alternate functions associated with a pin.
This arg was previously called *af* which can still be used if needed. This arg was previously called *af* which can still be used if needed.
Returns: ``None``. Returns: ``None``.

82
docs/library/random.rst Normal file
View File

@ -0,0 +1,82 @@
:mod:`random` -- generate random numbers
========================================
.. module:: random
:synopsis: random numbers
This module implements a pseudo-random number generator (PRNG).
|see_cpython_module| :mod:`python:random` .
.. note::
The following notation is used for intervals:
- () are open interval brackets and do not include their endpoints.
For example, (0, 1) means greater than 0 and less than 1.
In set notation: (0, 1) = {x | 0 < x < 1}.
- [] are closed interval brackets which include all their limit points.
For example, [0, 1] means greater than or equal to 0 and less than
or equal to 1.
In set notation: [0, 1] = {x | 0 <= x <= 1}.
.. note::
The :func:`randrange`, :func:`randint` and :func:`choice` functions are only
available if the ``MICROPY_PY_URANDOM_EXTRA_FUNCS`` configuration option is
enabled.
Functions for integers
----------------------
.. function:: getrandbits(n)
Return an integer with *n* random bits (0 <= n <= 32).
.. function:: randint(a, b)
Return a random integer in the range [*a*, *b*].
.. function:: randrange(stop)
randrange(start, stop)
randrange(start, stop[, step])
The first form returns a random integer from the range [0, *stop*).
The second form returns a random integer from the range [*start*, *stop*).
The third form returns a random integer from the range [*start*, *stop*) in
steps of *step*. For instance, calling ``randrange(1, 10, 2)`` will
return odd numbers between 1 and 9 inclusive.
Functions for floats
--------------------
.. function:: random()
Return a random floating point number in the range [0.0, 1.0).
.. function:: uniform(a, b)
Return a random floating point number N such that *a* <= N <= *b* for *a* <= *b*,
and *b* <= N <= *a* for *b* < *a*.
Other Functions
---------------
.. function:: seed(n=None, /)
Initialise the random number generator module with the seed *n* which should
be an integer. When no argument (or ``None``) is passed in it will (if
supported by the port) initialise the PRNG with a true random number
(usually a hardware generated random number).
The ``None`` case only works if ``MICROPY_PY_URANDOM_SEED_INIT_FUNC`` is
enabled by the port, otherwise it raises ``ValueError``.
.. function:: choice(sequence)
Chooses and returns one item at random from *sequence* (tuple, list or
any object that supports the subscript operation).

View File

@ -58,7 +58,7 @@ For running PIO programs, see :class:`rp2.StateMachine`.
combined into a single 8-word FIFO for one direction only. The options combined into a single 8-word FIFO for one direction only. The options
are `PIO.JOIN_NONE`, `PIO.JOIN_RX` and `PIO.JOIN_TX`. are `PIO.JOIN_NONE`, `PIO.JOIN_RX` and `PIO.JOIN_TX`.
.. function:: asm_pio_encode(instr, sideset_count) .. function:: asm_pio_encode(instr, sideset_count, sideset_opt=False)
Assemble a single PIO instruction. You usually want to use `asm_pio()` Assemble a single PIO instruction. You usually want to use `asm_pio()`
instead. instead.
@ -72,6 +72,158 @@ For running PIO programs, see :class:`rp2.StateMachine`.
an error assembling a PIO program. an error assembling a PIO program.
PIO assembly language instructions
----------------------------------
PIO state machines are programmed in a custom assembly language with nine core
PIO-machine instructions. In MicroPython, PIO assembly routines are written as
a Python function with the decorator ``@rp2.asm_pio()``, and they use Python
syntax. Such routines support standard Python variables and arithmetic, as well
as the following custom functions that encode PIO instructions and direct the
assembler. See sec 3.4 of the RP2040 datasheet for further details.
wrap_target()
Specify the location where execution continues after program wrapping.
By default this is the start of the PIO routine.
wrap()
Specify the location where the program finishes and wraps around.
If this directive is not used then it is added automatically at the end of
the PIO routine. Wrapping does not cost any execution cycles.
label(label)
Define a label called *label* at the current location. *label* can be a
string or integer.
word(instr, label=None)
Insert an arbitrary 16-bit word in the assembled output.
- *instr*: the 16-bit value
- *label*: if given, look up the label and logical-or the label's value with
*instr*
jmp(...)
This instruction takes two forms:
jmp(label)
- *label*: label to jump to unconditionally
jmp(cond, label)
- *cond*: the condition to check, one of:
- ``not_x``, ``not_y``: true if register is zero
- ``x_dec``, ``y_dec``: true if register is non-zero, and do post
decrement
- ``x_not_y``: true if X is not equal to Y
- ``pin``: true if the input pin is set
- ``not_osre``: true if OSR is not empty (hasn't reached its
threshold)
- *label*: label to jump to if condition is true
wait(polarity, src, index)
Block, waiting for high/low on a pin or IRQ line.
- *polarity*: 0 or 1, whether to wait for a low or high value
- *src*: one of: ``gpio`` (absolute pin), ``pin`` (pin relative to
StateMachine's ``in_base`` argument), ``irq``
- *index*: 0-31, the index for *src*
in_(src, bit_count)
Shift data in from *src* to ISR.
- *src*: one of: ``pins``, ``x``, ``y``, ``null``, ``isr``, ``osr``
- *bit_count*: number of bits to shift in (1-32)
out(dest, bit_count)
Shift data out from OSR to *dest*.
- *dest*: one of: ``pins``, ``x``, ``y``, ``pindirs``, ``pc``, ``isr``,
``exec``
- *bit_count*: number of bits to shift out (1-32)
push(...)
Push ISR to the RX FIFO, then clear ISR to zero.
This instruction takes the following forms:
- push()
- push(block)
- push(noblock)
- push(iffull)
- push(iffull, block)
- push(iffull, noblock)
If ``block`` is used then the instruction stalls if the RX FIFO is full.
The default is to block. If ``iffull`` is used then it only pushes if the
input shift count has reached its threshold.
pull(...)
Pull from the TX FIFO into OSR.
This instruction takes the following forms:
- pull()
- pull(block)
- pull(noblock)
- pull(ifempty)
- pull(ifempty, block)
- pull(ifempty, noblock)
If ``block`` is used then the instruction stalls if the TX FIFO is empty.
The default is to block. If ``ifempty`` is used then it only pulls if the
output shift count has reached its threshold.
mov(dest, src)
Move into *dest* the value from *src*.
- *dest*: one of: ``pins``, ``x``, ``y``, ``exec``, ``pc``, ``isr``, ``osr``
- *src*: one of: ``pins``, ``x``, ``y``, ``null``, ``status``, ``isr``,
``osr``; this argument can be optionally modified by wrapping it in
``invert()`` or ``reverse()`` (but not both together)
irq(...)
Set or clear an IRQ flag.
This instruction takes two forms:
irq(index)
- *index*: 0-7, or ``rel(0)`` to ``rel(7)``
irq(mode, index)
- *mode*: one of: ``block``, ``clear``
- *index*: 0-7, or ``rel(0)`` to ``rel(7)``
If ``block`` is used then the instruction stalls until the flag is cleared
by another entity. If ``clear`` is used then the flag is cleared instead of
being set. Relative IRQ indices add the state machine ID to the IRQ index
with modulo-4 addition. IRQs 0-3 are visible from to the processor, 4-7 are
internal to the state machines.
set(dest, data)
Set *dest* with the value *data*.
- *dest*: ``pins``, ``x``, ``y``, ``pindirs``
- *data*: value (0-31)
nop()
This is a pseudoinstruction that assembles to ``mov(y, y)`` and has no side
effect.
.side(value)
This is a modifier which can be applied to any instruction, and is used to
control side-set pin values.
- *value*: the value (bits) to output on the side-set pins
.delay(value)
This is a modifier which can be applied to any instruction, and specifies
how many cycles to delay for after the instruction executes.
- *value*: cycles to delay, 0-31 (maximum value reduced if side-set pins are
used)
[value]
This is a modifier and is equivalent to ``.delay(value)``.
Classes Classes
------- -------

104
docs/library/stm.rst Normal file
View File

@ -0,0 +1,104 @@
.. currentmodule:: stm
:mod:`stm` --- functionality specific to STM32 MCUs
===================================================
.. module:: stm
:synopsis: functionality specific to STM32 MCUs
This module provides functionality specific to STM32 microcontrollers, including
direct access to peripheral registers.
Memory access
-------------
The module exposes three objects used for raw memory access.
.. data:: mem8
Read/write 8 bits of memory.
.. data:: mem16
Read/write 16 bits of memory.
.. data:: mem32
Read/write 32 bits of memory.
Use subscript notation ``[...]`` to index these objects with the address of
interest.
These memory objects can be used in combination with the peripheral register
constants to read and write registers of the MCU hardware peripherals, as well
as all other areas of address space.
Peripheral register constants
-----------------------------
The module defines constants for registers which are generated from CMSIS header
files, and the constants available depend on the microcontroller series that is
being compiled for. Examples of some constants include:
.. data:: GPIOA
Base address of the GPIOA peripheral.
.. data:: GPIOB
Base address of the GPIOB peripheral.
.. data:: GPIO_BSRR
Offset of the GPIO bit set/reset register.
.. data:: GPIO_IDR
Offset of the GPIO input data register.
.. data:: GPIO_ODR
Offset of the GPIO output data register.
Constants that are named after a peripheral, like ``GPIOA``, are the absolute
address of that peripheral. Constants that have a prefix which is the name of a
peripheral, like ``GPIO_BSRR``, are relative offsets of the register. Accessing
peripheral registers requires adding the absolute base address of the peripheral
and the relative register offset. For example ``GPIOA + GPIO_BSRR`` is the
full, absolute address of the ``GPIOA->BSRR`` register.
Example use:
.. code-block:: python3
# set PA2 high
stm.mem32[stm.GPIOA + stm.GPIO_BSRR] = 1 << 2
# read PA3
value = (stm.mem32[stm.GPIOA + stm.GPIO_IDR] >> 3) & 1
Functions specific to STM32WBxx MCUs
------------------------------------
These functions are available on STM32WBxx microcontrollers, and interact with
the second CPU, the RF core.
.. function:: rfcore_status()
Returns the status of the second CPU as an integer (the first word of device
info table).
.. function:: rfcore_fw_version(id)
Get the version of the firmware running on the second CPU. Pass in 0 for
*id* to get the FUS version, and 1 to get the WS version.
Returns a 5-tuple with the full version number.
.. function:: rfcore_sys_hci(ogf, ocf, data, timeout_ms=0)
Execute a HCI command on the SYS channel. The execution is synchronous.
Returns a bytes object with the result of the SYS command.

View File

@ -43,6 +43,15 @@ Functions
positional; further arguments are not supported. CPython-compatible positional; further arguments are not supported. CPython-compatible
``traceback`` module can be found in `micropython-lib`. ``traceback`` module can be found in `micropython-lib`.
.. function:: settrace(tracefunc)
Enable tracing of bytecode execution. For details see the `CPython
documentaion <https://docs.python.org/3/library/sys.html#sys.settrace>`_.
This function requires a custom MicroPython build as it is typically not
present in pre-built firmware (due to it affecting performance). The relevant
configuration option is *MICROPY_PY_SYS_SETTRACE*.
Constants Constants
--------- ---------
@ -106,6 +115,14 @@ Constants
A mutable list of directories to search for imported modules. A mutable list of directories to search for imported modules.
.. admonition:: Difference to CPython
:class: attention
On MicroPython, an entry with the value ``".frozen"`` will indicate that import
should search :term:`frozen modules <frozen module>` at that point in the search.
If no frozen module is found then search will *not* look for a directory called
``.frozen``, instead it will continue with the next entry in ``sys.path``.
.. data:: platform .. data:: platform
The platform that MicroPython is running on. For OS/RTOS ports, this is The platform that MicroPython is running on. For OS/RTOS ports, this is

View File

@ -68,11 +68,13 @@ Additional functions
.. function:: wait_for(awaitable, timeout) .. function:: wait_for(awaitable, timeout)
Wait for the *awaitable* to complete, but cancel it if it takes longer Wait for the *awaitable* to complete, but cancel it if it takes longer
that *timeout* seconds. If *awaitable* is not a task then a task will be than *timeout* seconds. If *awaitable* is not a task then a task will be
created from it. created from it.
If a timeout occurs, it cancels the task and raises ``asyncio.TimeoutError``: If a timeout occurs, it cancels the task and raises ``asyncio.TimeoutError``:
this should be trapped by the caller. this should be trapped by the caller. The task receives
``asyncio.CancelledError`` which may be ignored or trapped using ``try...except``
or ``try...finally`` to run cleanup code.
Returns the return value of *awaitable*. Returns the return value of *awaitable*.
@ -106,8 +108,9 @@ class Task
.. method:: Task.cancel() .. method:: Task.cancel()
Cancel the task by injecting a ``CancelledError`` into it. The task may Cancel the task by injecting ``asyncio.CancelledError`` into it. The task may
or may not ignore this exception. ignore this exception. Cleanup code may be run by trapping it, or via
``try ... finally``.
class Event class Event
----------- -----------

View File

@ -5,7 +5,7 @@ REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" ( if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build set SPHINXBUILD=sphinx-build
) )
set BUILDDIR=_build set BUILDDIR=build
set SPHINXOPTS=-W --keep-going set SPHINXOPTS=-W --keep-going
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% .

View File

@ -225,20 +225,20 @@ I2S bus
See :ref:`machine.I2S <machine.I2S>`. :: See :ref:`machine.I2S <machine.I2S>`. ::
from machine import I2S, Pin from machine import I2S, Pin
i2s = I2S(2, sck=Pin('Y6'), ws=Pin('Y5'), sd=Pin('Y8'), mode=I2S.TX, bits=16, format=I2S.STEREO, rate=44100, ibuf=40000) # create I2S object i2s = I2S(2, sck=Pin('Y6'), ws=Pin('Y5'), sd=Pin('Y8'), mode=I2S.TX, bits=16, format=I2S.STEREO, rate=44100, ibuf=40000) # create I2S object
i2s.write(buf) # write buffer of audio samples to I2S device i2s.write(buf) # write buffer of audio samples to I2S device
i2s = I2S(1, sck=Pin('X5'), ws=Pin('X6'), sd=Pin('Y4'), mode=I2S.RX, bits=16, format=I2S.MONO, rate=22050, ibuf=40000) # create I2S object i2s = I2S(1, sck=Pin('X5'), ws=Pin('X6'), sd=Pin('Y4'), mode=I2S.RX, bits=16, format=I2S.MONO, rate=22050, ibuf=40000) # create I2S object
i2s.readinto(buf) # fill buffer with audio samples from I2S device i2s.readinto(buf) # fill buffer with audio samples from I2S device
The I2S class is currently available as a Technical Preview. During the preview period, feedback from The I2S class is currently available as a Technical Preview. During the preview period, feedback from
users is encouraged. Based on this feedback, the I2S class API and implementation may be changed. users is encouraged. Based on this feedback, the I2S class API and implementation may be changed.
PYBv1.0/v1.1 has one I2S bus with id=2. PYBv1.0/v1.1 has one I2S bus with id=2.
PYBD-SFxW has two I2S buses with id=1 and id=2. PYBD-SFxW has two I2S buses with id=1 and id=2.
I2S is shared with SPI. I2S is shared with SPI.
CAN bus (controller area network) CAN bus (controller area network)
--------------------------------- ---------------------------------

View File

@ -29,7 +29,7 @@ We will start by using the accelerometer to turn on a light if it is not flat. :
while True: while True:
x = accel.x() x = accel.x()
if abs(x) > SENSITIVITY: if abs(x) > SENSITIVITY:
light.on() light.on()
else: else:
light.off() light.off()
@ -61,7 +61,7 @@ use the ``y()`` value and more LEDs we can turn the pyboard into a spirit level.
while True: while True:
x = accel.x() x = accel.x()
if x > SENSITIVITY: if x > SENSITIVITY:
xlights[0].on() xlights[0].on()
xlights[1].off() xlights[1].off()
elif x < -SENSITIVITY: elif x < -SENSITIVITY:
@ -72,7 +72,7 @@ use the ``y()`` value and more LEDs we can turn the pyboard into a spirit level.
xlights[1].off() xlights[1].off()
y = accel.y() y = accel.y()
if y > SENSITIVITY: if y > SENSITIVITY:
ylights[0].on() ylights[0].on()
ylights[1].off() ylights[1].off()
elif y < -SENSITIVITY: elif y < -SENSITIVITY:

View File

@ -47,7 +47,7 @@ Here, n keeps track of the current LED and every time the loop is executed we cy
One problem you might find is that if you stop the script and then start it again that the LEDs are stuck on from the previous run, ruining our carefully choreographed disco. We can fix this by turning all the LEDs off when we initialise the script and then using a try/finally block. When you press CTRL-C, MicroPython generates a VCPInterrupt exception. Exceptions normally mean something has gone wrong and you can use a try: command to "catch" an exception. In this case it is just the user interrupting the script, so we don't need to catch the error but just tell MicroPython what to do when we exit. The finally block does this, and we use it to make sure all the LEDs are off. The full code is:: One problem you might find is that if you stop the script and then start it again that the LEDs are stuck on from the previous run, ruining our carefully choreographed disco. We can fix this by turning all the LEDs off when we initialise the script and then using a try/finally block. When you press CTRL-C, MicroPython generates a VCPInterrupt exception. Exceptions normally mean something has gone wrong and you can use a try: command to "catch" an exception. In this case it is just the user interrupting the script, so we don't need to catch the error but just tell MicroPython what to do when we exit. The finally block does this, and we use it to make sure all the LEDs are off. The full code is::
leds = [pyb.LED(i) for i in range(1,5)] leds = [pyb.LED(i) for i in range(1,5)]
for l in leds: for l in leds:
l.off() l.off()
n = 0 n = 0

View File

@ -73,7 +73,7 @@ indicate that you should type the text after it at the prompt. In the end, once
you have entered the text ``print("hello pyboard!")`` and pressed Enter, the output you have entered the text ``print("hello pyboard!")`` and pressed Enter, the output
on your screen should look like it does above. on your screen should look like it does above.
If you already know some python you can now try some basic commands here. If you already know some python you can now try some basic commands here.
If any of this is not working you can try either a hard reset or a soft reset; If any of this is not working you can try either a hard reset or a soft reset;
see below. see below.

View File

@ -21,7 +21,7 @@ To enter safe mode, do the following steps:
4. The LEDs will then cycle green to orange to green+orange and back again. 4. The LEDs will then cycle green to orange to green+orange and back again.
5. Keep holding down USR until *only the orange LED is lit*, and then let 5. Keep holding down USR until *only the orange LED is lit*, and then let
go of the USR switch. go of the USR switch.
6. The orange LED should flash quickly 4 times, and then turn off. 6. The orange LED should flash quickly 4 times, and then turn off.
7. You are now in safe mode. 7. You are now in safe mode.
In safe mode, the ``boot.py`` and ``main.py`` files are not executed, and so In safe mode, the ``boot.py`` and ``main.py`` files are not executed, and so

View File

@ -8,8 +8,8 @@ To do this we must first edit the ``boot.py`` file to change the USB
configuration. If you have not yet touched your ``boot.py`` file then it configuration. If you have not yet touched your ``boot.py`` file then it
will look something like this:: will look something like this::
# boot.py -- run on boot-up # boot.py -- run on boot to configure USB and filesystem
# can run arbitrary Python, but best to keep it minimal # Put app code in main.py
import pyb import pyb
#pyb.main('main.py') # main script to run after this one #pyb.main('main.py') # main script to run after this one

View File

@ -3,7 +3,7 @@ Hints and tips
The following are some examples of the use of the inline assembler and some The following are some examples of the use of the inline assembler and some
information on how to work around its limitations. In this document the term information on how to work around its limitations. In this document the term
"assembler function" refers to a function declared in Python with the "assembler function" refers to a function declared in Python with the
``@micropython.asm_thumb`` decorator, whereas "subroutine" refers to assembler ``@micropython.asm_thumb`` decorator, whereas "subroutine" refers to assembler
code called from within an assembler function. code called from within an assembler function.
@ -106,8 +106,8 @@ function can return multiple values by assigning them to array elements.
Assembler functions have no means of determining the length of an array: Assembler functions have no means of determining the length of an array:
this will need to be passed to the function. this will need to be passed to the function.
This use of arrays can be extended to enable more than three arrays to be used. This use of arrays can be extended to enable more than three arrays to be used.
This is done using indirection: the ``uctypes`` module supports ``addressof()`` This is done using indirection: the ``uctypes`` module supports ``addressof()``
which will return the address of an array passed as its argument. Thus you can which will return the address of an array passed as its argument. Thus you can
populate an integer array with the addresses of other arrays: populate an integer array with the addresses of other arrays:

View File

@ -144,7 +144,7 @@ store constant data:
As in the string example, at runtime a reference to the arbitrarily large As in the string example, at runtime a reference to the arbitrarily large
integer is assigned to the variable ``bar``. That reference occupies a integer is assigned to the variable ``bar``. That reference occupies a
single machine word. single machine word.
It might be expected that tuples of integers could be employed for the purpose It might be expected that tuples of integers could be employed for the purpose
of storing constant data with minimal RAM use. With the current compiler this of storing constant data with minimal RAM use. With the current compiler this

View File

@ -219,15 +219,6 @@ resistant to filesystem corruption.
situations, for details see `littlefs issue 347`_ and situations, for details see `littlefs issue 347`_ and
`littlefs issue 295`_. `littlefs issue 295`_.
Note: It can be still be accessed over USB MSC using the `littlefs FUSE
driver`_. Note that you must use the ``-b=4096`` option to override the block
size.
.. _littlefs FUSE driver: https://github.com/ARMmbed/littlefs-fuse/tree/master/littlefs
.. _Littlefs: https://github.com/ARMmbed/littlefs
.. _littlefs issue 295: https://github.com/ARMmbed/littlefs/issues/295
.. _littlefs issue 347: https://github.com/ARMmbed/littlefs/issues/347
To format the entire flash using littlefs v2:: To format the entire flash using littlefs v2::
# ESP8266 and ESP32 # ESP8266 and ESP32
@ -243,6 +234,27 @@ To format the entire flash using littlefs v2::
os.mount(pyb.Flash(start=0), '/flash') os.mount(pyb.Flash(start=0), '/flash')
os.chdir('/flash') os.chdir('/flash')
A littlefs filesystem can be still be accessed on a PC over USB MSC using the
`littlefs FUSE driver`_. Note that you must specify both the ``--block_size``
and ``--block_count`` options to override the defaults. For example (after
building the littlefs-fuse executable)::
$ ./lfs --block_size=4096 --block_count=512 -o allow_other /dev/sdb1 mnt
This will allow the board's littlefs filesystem to be accessed at the ``mnt``
directory. To get the correct values of ``block_size`` and ``block_count`` use::
import pyb
f = pyb.Flash(start=0)
f.ioctl(1, 1) # initialise flash in littlefs raw-block mode
block_count = f.ioctl(4, 0)
block_size = f.ioctl(5, 0)
.. _littlefs FUSE driver: https://github.com/littlefs-project/littlefs-fuse
.. _Littlefs: https://github.com/littlefs-project/littlefs
.. _littlefs issue 295: https://github.com/littlefs-project/littlefs/issues/295
.. _littlefs issue 347: https://github.com/littlefs-project/littlefs/issues/347
Hybrid (STM32) Hybrid (STM32)
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~

View File

@ -21,10 +21,12 @@ implementation and the best practices to use them.
glossary.rst glossary.rst
repl.rst repl.rst
mpremote.rst
mpyfiles.rst mpyfiles.rst
isr_rules.rst isr_rules.rst
speed_python.rst speed_python.rst
constrained.rst constrained.rst
manifest.rst
packages.rst packages.rst
asm_thumb2_index.rst asm_thumb2_index.rst
filesystem.rst filesystem.rst

145
docs/reference/manifest.rst Normal file
View File

@ -0,0 +1,145 @@
MicroPython manifest files
==========================
When building firmware for a device the following components are included in
the compilation process:
- the core MicroPython virtual machine and runtime
- port-specific system code and drivers to interface with the
microcontroller/device that the firmware is targeting
- standard built-in modules, like ``sys``
- extended built-in modules, like ``json`` and ``machine``
- extra modules written in C/C++
- extra modules written in Python
All the modules included in the firmware are available via ``import`` from
Python code. The extra modules written in Python that are included in a build
(the last point above) are called *frozen modules*, and are specified by a
``manifest.py`` file. Changing this manifest requires rebuilding the firmware.
It's also possible to add additional modules to the filesystem of the device
once it is up and running. Adding and removing modules to/from the filesystem
does not require rebuilding the firmware so is a simpler process than rebuilding
firmware. The benefit of using a manifest is that frozen modules are more
efficient: they are faster to import and take up less RAM once imported.
MicroPython manifest files are Python files and can contain arbitrary Python
code. There are also a set of commands (predefined functions) which are used
to specify the Python source files to include. These commands are described
below.
Freezing source code
--------------------
.. function:: freeze(path, script=None, opt=0)
Freeze the input specified by *path*, automatically determining its type. A
``.py`` script will be compiled to a ``.mpy`` first then frozen, and a
``.mpy`` file will be frozen directly.
*path* must be a directory, which is the base directory to begin searching
for files. When importing the resulting frozen modules, the name of the
module will start after *path*, i.e. *path* is excluded from the module
name.
If *path* is relative, it is resolved to the current ``manifest.py``. Use
``$(MPY_DIR)``, ``$(MPY_LIB_DIR)``, ``$(PORT_DIR)``, ``$(BOARD_DIR)`` if you
need to access specific paths.
If *script* is None, all files in *path* will be frozen.
If *script* is an iterable then ``freeze()`` is called on all items of the
iterable (with the same *path* and *opt* passed through).
If *script* is a string then it specifies the file or directory to freeze,
and can include extra directories before the file or last directory. The
file or directory will be searched for in *path*. If *script* is a
directory then all files in that directory will be frozen.
*opt* is the optimisation level to pass to mpy-cross when compiling ``.py``
to ``.mpy``.
.. function:: freeze_as_str(path)
Freeze the given *path* and all ``.py`` scripts within it as a string, which
will be compiled upon import.
.. function:: freeze_as_mpy(path, script=None, opt=0)
Freeze the input by first compiling the ``.py`` scripts to ``.mpy`` files,
then freezing the resulting ``.mpy`` files. See ``freeze()`` for further
details on the arguments.
.. function:: freeze_mpy(path, script=None, opt=0)
Freeze the input, which must be ``.mpy`` files that are frozen directly.
See ``freeze()`` for further details on the arguments.
Including other manifest files
------------------------------
.. function:: include(manifest, **kwargs)
Include another manifest.
The *manifest* argument can be a string (filename) or an iterable of
strings.
Relative paths are resolved with respect to the current manifest file.
Optional *kwargs* can be provided which will be available to the included
script via the *options* variable.
For example:
.. code-block:: python3
include("path.py", extra_features=True)
then in path.py:
.. code-block:: python3
options.defaults(standard_features=True)
# freeze minimal modules.
if options.standard_features:
# freeze standard modules.
if options.extra_features:
# freeze extra modules.
Examples
--------
To freeze a single file which is available as ``import mydriver``, use:
.. code-block:: python3
freeze(".", "mydriver.py")
To freeze a set of files which are available as ``import test1`` and
``import test2``, and which are compiled with optimisation level 3, use:
.. code-block:: python3
freeze("/path/to/tests", ("test1.py", "test2.py"), opt=3)
To freeze a module which can be imported as ``import mymodule``, use:
.. code-block:: python3
freeze(
"../relative/path",
(
"mymodule/__init__.py",
"mymodule/core.py",
"mymodule/extra.py",
),
)
To include a manifest from the MicroPython repository, use:
.. code-block:: python3
include("$(MPY_DIR)/extmod/uasyncio/manifest.py")

196
docs/reference/mpremote.rst Normal file
View File

@ -0,0 +1,196 @@
MicroPython remote control: mpremote
====================================
The ``mpremote`` command line tool provides an integrated set of utilities to
remotely interact with and automate a MicroPython device over a serial
connection.
To use mpremote install it via ``pip``:
.. code-block:: bash
$ pip install mpremote
The simplest way to use this tool is just by invoking it without any arguments:
.. code-block:: bash
mpremote
This command automatically detects and connects to the first available serial
device and provides an interactive REPL. Serial ports are opened in exclusive
mode, so running a second (or third, etc) instance of ``mpremote`` will connect
to subsequent serial devices, if any are available.
Commands
--------
For REPL access, running ``mpremote`` without any arguments is usually all that
is needed. ``mpremote`` also supports a set of commands given at the command
line which will perform various actions on remote MicroPython devices.
The full list of supported commands are:
- connect to a specified device via a device-name shortcut:
.. code-block:: bash
$ mpremote <device-shortcut>
- connect to specified device via name:
.. code-block:: bash
$ mpremote connect <device>
``<device>`` may be one of:
- ``list``: list available devices
- ``auto``: connect to the first available device
- ``id:<serial>``: connect to the device with USB serial number
``<serial>`` (the second entry in the output from the ``connect list``
command)
- ``port:<path>``: connect to the device with the given path
- any valid device name/path, to connect to that device
- disconnect current device:
.. code-block:: bash
$ mpremote disconnect
- enter the REPL on the connected device:
.. code-block:: bash
$ mpremote repl [options]
Options are:
- ``--capture <file>``, to capture output of the REPL session to the given
file
- ``--inject-code <string>``, to specify characters to inject at the REPL when
Ctrl-J is pressed
- ``--inject-file <file>``, to specify a file to inject at the REPL when
Ctrl-K is pressed
- evaluate and print the result of a Python expression:
.. code-block:: bash
$ mpremote eval <string>
- execute the given Python code:
.. code-block:: bash
$ mpremote exec <string>
- run a script from the local filesystem:
.. code-block:: bash
$ mpremote run <file>
- execute filesystem commands on the device:
.. code-block:: bash
$ mpremote fs <command>
``<command>`` may be:
- ``cat <file..>`` to show the contents of a file or files on the device
- ``ls`` to list the current directory
- ``ls <dirs...>`` to list the given directories
- ``cp [-r] <src...> <dest>`` to copy files; use ":" as a prefix to specify
a file on the device
- ``rm <src...>`` to remove files on the device
- ``mkdir <dirs...>`` to create directories on the device
- ``rmdir <dirs...>`` to remove directories on the device
- mount the local directory on the remote device:
.. code-block:: bash
$ mpremote mount <local-dir>
Multiple commands can be specified and they will be run sequentially.
Connection and disconnection will be done automatically at the start and end of
the execution of the tool, if such commands are not explicitly given. Automatic
connection will search for the first available serial device. If no action is
specified then the REPL will be entered.
Shortcuts
---------
Shortcuts can be defined using the macro system. Built-in shortcuts are::
- ``devs``: list available devices (shortcut for ``connect list``)
- ``a0``, ``a1``, ``a2``, ``a3``: connect to /dev/ttyACM?
- ``u0``, ``u1``, ``u2``, ``u3``: connect to /dev/ttyUSB?
- ``c0``, ``c1``, ``c2``, ``c3``: connect to COM?
- ``cat``, ``ls``, ``cp``, ``rm``, ``mkdir``, ``rmdir``, ``df``: filesystem
commands
- ``reset``: reset the device
- ``bootloader``: make the device enter its bootloader
Any user configuration, including user-defined shortcuts, can be placed in the file
``.config/mpremote/config.py``. For example:
.. code-block:: python3
commands = {
"c33": "connect id:334D335C3138",
"bl": "bootloader",
"double x=4": "eval x*2", # x is an argument, with default 4
"wl_scan": ["exec", """
import network
wl = network.WLAN()
wl.active(1)
for ap in wl.scan():
print(ap)
""",],
"test": ["mount", ".", "exec", "import test"],
}
Examples
--------
.. code-block:: bash
mpremote
mpremote a1
mpremote connect /dev/ttyUSB0 repl
mpremote ls
mpremote a1 ls
mpremote exec "import micropython; micropython.mem_info()"
mpremote eval 1/2 eval 3/4
mpremote mount .
mpremote mount . exec "import local_script"
mpremote ls
mpremote cat boot.py
mpremote cp :main.py .
mpremote cp main.py :
mpremote cp -r dir/ :

View File

@ -66,8 +66,6 @@ If importing an .mpy file fails then try the following:
print('mpy flags:', end='') print('mpy flags:', end='')
if arch: if arch:
print(' -march=' + arch, end='') print(' -march=' + arch, end='')
if sys_mpy & 0x100:
print(' -mcache-lookup-bc', end='')
if not sys_mpy & 0x200: if not sys_mpy & 0x200:
print(' -mno-unicode', end='') print(' -mno-unicode', end='')
print() print()

View File

@ -36,7 +36,7 @@ Algorithms
~~~~~~~~~~ ~~~~~~~~~~
The most important aspect of designing any routine for performance is ensuring that The most important aspect of designing any routine for performance is ensuring that
the best algorithm is employed. This is a topic for textbooks rather than for a the best algorithm is employed. This is a topic for textbooks rather than for a
MicroPython guide but spectacular performance gains can sometimes be achieved MicroPython guide but spectacular performance gains can sometimes be achieved
by adopting algorithms known for their efficiency. by adopting algorithms known for their efficiency.
@ -210,7 +210,7 @@ no adaptation (but see below). It is invoked by means of a function decorator:
buf = self.linebuf # Cached object buf = self.linebuf # Cached object
# code # code
There are certain limitations in the current implementation of the native code emitter. There are certain limitations in the current implementation of the native code emitter.
* Context managers are not supported (the ``with`` statement). * Context managers are not supported (the ``with`` statement).
* Generators are not supported. * Generators are not supported.
@ -222,7 +222,7 @@ increase in compiled code size.
The Viper code emitter The Viper code emitter
---------------------- ----------------------
The optimisations discussed above involve standards-compliant Python code. The The optimisations discussed above involve standards-compliant Python code. The
Viper code emitter is not fully compliant. It supports special Viper native data types Viper code emitter is not fully compliant. It supports special Viper native data types
in pursuit of performance. Integer processing is non-compliant because it uses machine in pursuit of performance. Integer processing is non-compliant because it uses machine
words: arithmetic on 32 bit hardware is performed modulo 2**32. words: arithmetic on 32 bit hardware is performed modulo 2**32.
@ -237,7 +237,7 @@ bit manipulations. It is invoked using a decorator:
def foo(self, arg: int) -> int: def foo(self, arg: int) -> int:
# code # code
As the above fragment illustrates it is beneficial to use Python type hints to assist the Viper optimiser. As the above fragment illustrates it is beneficial to use Python type hints to assist the Viper optimiser.
Type hints provide information on the data types of arguments and of the return value; these Type hints provide information on the data types of arguments and of the return value; these
are a standard Python language feature formally defined here `PEP0484 <https://www.python.org/dev/peps/pep-0484/>`_. are a standard Python language feature formally defined here `PEP0484 <https://www.python.org/dev/peps/pep-0484/>`_.
Viper supports its own set of types namely ``int``, ``uint`` (unsigned integer), ``ptr``, ``ptr8``, Viper supports its own set of types namely ``int``, ``uint`` (unsigned integer), ``ptr``, ``ptr8``,

View File

@ -22,9 +22,9 @@ QFN-56 SMD package. The key features include:
firmware from either the external flash memory or USB bus into internal SRAM) firmware from either the external flash memory or USB bus into internal SRAM)
* QSPI bus controller, which * QSPI bus controller, which
supports up to 16 MB of external Flash memory supports up to 16 MB of external Flash memory
* On-chip programmable LDO togenerate core voltage * On-chip programmable LDO to generate core voltage
* 2 on-chip PLLs to generate USB and core clocks * 2 on-chip PLLs to generate USB and core clocks
* 30 GPIOpins, of which 4 can optionally be used as analog inputs * 30 GPIO pins, of which 4 can optionally be used as analog inputs
The peripherals include: The peripherals include:

View File

@ -92,6 +92,37 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
p4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor p4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
p5 = Pin(5, Pin.OUT, value=1) # set pin high on creation p5 = Pin(5, Pin.OUT, value=1) # set pin high on creation
Programmable IO (PIO)
---------------------
PIO is useful to build low-level IO interfaces from scratch. See the :mod:`rp2` module
for detailed explaination of the assembly instructions.
Example using PIO to blink an LED at 1Hz::
from machine import Pin
import rp2
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def blink_1hz():
# Cycles: 1 + 7 + 32 * (30 + 1) = 1000
set(pins, 1)
set(x, 31) [6]
label("delay_high")
nop() [29]
jmp(x_dec, "delay_high")
# Cycles: 1 + 7 + 32 * (30 + 1) = 1000
set(pins, 0)
set(x, 31) [6]
label("delay_low")
nop() [29]
jmp(x_dec, "delay_low")
# Create and start a StateMachine with blink_1hz, outputting on Pin(25)
sm = rp2.StateMachine(0, blink_1hz, freq=2000, set_base=Pin(25))
sm.active(1)
UART (serial bus) UART (serial bus)
----------------- -----------------
@ -219,6 +250,26 @@ has the same methods as software I2C above::
i2c = I2C(0) # default assignment: scl=Pin(9), sda=Pin(8) i2c = I2C(0) # default assignment: scl=Pin(9), sda=Pin(8)
i2c = I2C(1, scl=Pin(3), sda=Pin(2), freq=400_000) i2c = I2C(1, scl=Pin(3), sda=Pin(2), freq=400_000)
I2S bus
-------
See :ref:`machine.I2S <machine.I2S>`. ::
from machine import I2S, Pin
i2s = I2S(0, sck=Pin(16), ws=Pin(17), sd=Pin(18), mode=I2S.TX, bits=16, format=I2S.STEREO, rate=44100, ibuf=40000) # create I2S object
i2s.write(buf) # write buffer of audio samples to I2S device
i2s = I2S(1, sck=Pin(0), ws=Pin(1), sd=Pin(2), mode=I2S.RX, bits=16, format=I2S.MONO, rate=22050, ibuf=40000) # create I2S object
i2s.readinto(buf) # fill buffer with audio samples from I2S device
The ``ws`` pin number must be one greater than the ``sck`` pin number.
The I2S class is currently available as a Technical Preview. During the preview period, feedback from
users is encouraged. Based on this feedback, the I2S class API and implementation may be changed.
Two I2S buses are supported with id=0 and id=1.
Real time clock (RTC) Real time clock (RTC)
--------------------- ---------------------

View File

@ -4,3 +4,8 @@ Getting started with MicroPython on the RP2xxx
============================================== ==============================================
Let's get started! Let's get started!
.. toctree::
:maxdepth: 1
pio.rst

123
docs/rp2/tutorial/pio.rst Normal file
View File

@ -0,0 +1,123 @@
Programmable IO
===============
The RP2040 has hardware support for standard communication protocols like I2C,
SPI and UART. For protocols where there is no hardware support, or where there
is a requirement of custom I/O behaviour, Programmable Input Output (PIO) comes
into play. Also, some MicroPython applications make use of a technique called
bit banging in which pins are rapidly turned on and off to transmit data. This
can make the entire process slow as the processor concentrates on bit banging
rather than executing other logic. However, PIO allows bit banging to happen
in the background while the CPU is executing the main work.
Along with the two central Cortex-M0+ processing cores, the RP2040 has two PIO
blocks each of which has four independent state machines. These state machines
can transfer data to/from other entities using First-In-First-Out (FIFO) buffers,
which allow the state machine and main processor to work independently yet also
synchronise their data. Each FIFO has four words (each of 32 bits) which can be
linked to the DMA to transfer larger amounts of data.
All PIO instructions follow a common pattern::
<instruction> .side(<side_set_value>) [<delay_value>]
The side-set ``.side(...)`` and delay ``[...]`` parts are both optional, and if
specified allow the instruction to perform more than one operation. This keeps
PIO programs small and efficient.
There are nine instructions which perform the following tasks:
- ``jmp()`` transfers control to a different part of the code
- ``wait()`` pauses until a particular action happens
- ``in_()`` shifts the bits from a source (scratch register or set of pins) to the
input shift register
- ``out()`` shifts the bits from the output shift register to a destination
- ``push()`` sends data to the RX FIFO
- ``pull()`` receives data from the TX FIFO
- ``mov()`` moves data from a source to a destination
- ``irq()`` sets or clears an IRQ flag
- ``set()`` writes a literal value to a destination
The instruction modifiers are:
- ``.side()`` sets the side-set pins at the start of the instruction
- ``[]`` delays for a certain number of cycles after execution of the instruction
There are also directives:
- ``wrap_target()`` specifies where the program execution will get continued from
- ``wrap()`` specifies the instruction where the control flow of the program will
get wrapped from
- ``label()`` sets a label for use with ``jmp()`` instructions
- ``word()`` emits a raw 16-bit value which acts as an instruction in the program
An example
----------
Take the ``pio_1hz.py`` example for a simple understanding of how to use the PIO
and state machines. Below is the code for reference.
.. code-block:: python3
# Example using PIO to blink an LED and raise an IRQ at 1Hz.
import time
from machine import Pin
import rp2
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def blink_1hz():
# Cycles: 1 + 1 + 6 + 32 * (30 + 1) = 1000
irq(rel(0))
set(pins, 1)
set(x, 31) [5]
label("delay_high")
nop() [29]
jmp(x_dec, "delay_high")
# Cycles: 1 + 7 + 32 * (30 + 1) = 1000
set(pins, 0)
set(x, 31) [6]
label("delay_low")
nop() [29]
jmp(x_dec, "delay_low")
# Create the StateMachine with the blink_1hz program, outputting on Pin(25).
sm = rp2.StateMachine(0, blink_1hz, freq=2000, set_base=Pin(25))
# Set the IRQ handler to print the millisecond timestamp.
sm.irq(lambda p: print(time.ticks_ms()))
# Start the StateMachine.
sm.active(1)
This creates an instance of class :class:`rp2.StateMachine` which runs the
``blink_1hz`` program at 2000Hz, and connects to pin 25. The ``blink_1hz``
program uses the PIO to blink an LED connected to this pin at 1Hz, and also
raises an IRQ as the LED turns on. This IRQ then calls the ``lambda`` function
which prints out a millisecond timestamp.
The ``blink_1hz`` program is a PIO assembler routine. It connects to a single
pin which is configured as an output and starts out low. The instructions do
the following:
- ``irq(rel(0))`` raises the IRQ associated with the state machine.
- The LED is turned on via the ``set(pins, 1)`` instruction.
- The value 31 is put into register X, and then there is a delay for 5 more
cycles, specified by the ``[5]``.
- The ``nop() [29]`` instruction waits for 30 cycles.
- The ``jmp(x_dec, "delay_high")`` will keep looping to the ``delay_high`` label
as long as the register X is non-zero, and will also post-decrement X. Since
X starts with the value 31 this jump will happen 31 times, so the ``nop() [29]``
runs 32 times in total (note there is also one instruction cycle taken by the
``jmp`` for each of these 32 loops).
- ``set(pins, 0)`` will turn the LED off by setting pin 25 low.
- Another 32 loops of ``nop() [29]`` and ``jmp(...)`` will execute.
- Because ``wrap_target()`` and ``wrap()`` are not specified, their default will
be used and execution of the program will wrap around from the bottom to the
top. This wrapping does not cost any execution cycles.
The entire routine takes exactly 2000 cycles of the state machine. Setting the
frequency of the state machine to 2000Hz makes the LED blink at 1Hz.

View File

@ -154,7 +154,7 @@ See :ref:`machine.RTC <machine.RTC>` ::
pass pass
# do some non blocking operations # do some non blocking operations
# warning printing on an irq via telnet is not # warning printing on an irq via telnet is not
# possible, only via UART # possible, only via UART
# create a RTC alarm that expires after 5 seconds # create a RTC alarm that expires after 5 seconds
rtc.alarm(time=5000, repeat=False) rtc.alarm(time=5000, repeat=False)
@ -179,7 +179,7 @@ See :ref:`machine.SD <machine.SD>`. ::
sd = SD() sd = SD()
os.mount(sd, '/sd') os.mount(sd, '/sd')
WLAN (WiFi) WLAN (WiFi)
----------- -----------
See :ref:`network.WLAN <network.WLAN>` and :mod:`machine`. :: See :ref:`network.WLAN <network.WLAN>` and :mod:`machine`. ::

View File

@ -1,10 +1,10 @@
Reset and boot modes Reset and boot modes
==================== ====================
There are soft resets and hard resets. There are soft resets and hard resets.
- A soft reset simply clears the state of the MicroPython virtual machine, - A soft reset simply clears the state of the MicroPython virtual machine,
but leaves hardware peripherals unaffected. To do a soft reset, simply press but leaves hardware peripherals unaffected. To do a soft reset, simply press
**Ctrl+D** on the REPL, or within a script do:: **Ctrl+D** on the REPL, or within a script do::
import sys import sys

View File

@ -5,7 +5,7 @@ Timers can be used for a great variety of tasks, calling a function periodically
counting events, and generating a PWM signal are among the most common use cases. counting events, and generating a PWM signal are among the most common use cases.
Each timer consists of two 16-bit channels and this channels can be tied together to Each timer consists of two 16-bit channels and this channels can be tied together to
form one 32-bit timer. The operating mode needs to be configured per timer, but then form one 32-bit timer. The operating mode needs to be configured per timer, but then
the period (or the frequency) can be independently configured on each channel. the period (or the frequency) can be independently configured on each channel.
By using the callback method, the timer event can call a Python function. By using the callback method, the timer event can call a Python function.
Example usage to toggle an LED at a fixed frequency:: Example usage to toggle an LED at a fixed frequency::

View File

@ -13,9 +13,9 @@ You can check the current mode (which is always ``WLAN.AP`` after power up)::
>>> wlan.mode() >>> wlan.mode()
.. warning:: .. warning::
When you change the WLAN mode following the instructions below, your WLAN When you change the WLAN mode following the instructions below, your WLAN
connection to the WiPy will be broken. This means you will not be able connection to the WiPy will be broken. This means you will not be able
to run these commands interactively over the WLAN. to run these commands interactively over the WLAN.
There are two ways around this:: There are two ways around this::

View File

@ -31,8 +31,8 @@ With your serial program open (PuTTY, screen, picocom, etc) you may see a
blank screen with a flashing cursor. Press Enter (or reset the board) and blank screen with a flashing cursor. Press Enter (or reset the board) and
you should be presented with the following text:: you should be presented with the following text::
*** Booting Zephyr OS build v2.6.0-rc1-416-g3056c5ec30ad *** *** Booting Zephyr OS build zephyr-v2.7.0 ***
MicroPython v2.6.0-rc1-416-g3056c5ec30 on 2021-06-24; zephyr-frdm_k64f with mk64f12 MicroPython v1.17-288-gb695f5a70-dirty on 2022-01-03; zephyr-frdm_k64f with mk64f12
Type "help()" for more information. Type "help()" for more information.
>>> >>>

View File

@ -1,9 +1,15 @@
# DHT11/DHT22 driver for MicroPython on ESP8266 # DHT11/DHT22 driver for MicroPython on ESP8266
# MIT license; Copyright (c) 2016 Damien P. George # MIT license; Copyright (c) 2016 Damien P. George
try: import sys
if sys.platform.startswith("esp"):
from esp import dht_readinto from esp import dht_readinto
except: elif sys.platform == "mimxrt":
from mimxrt import dht_readinto
elif sys.platform == "rp2":
from rp2 import dht_readinto
else:
from pyb import dht_readinto from pyb import dht_readinto

View File

@ -0,0 +1,234 @@
"""
LSM6DSOX STMicro driver for MicroPython based on LSM9DS1:
Source repo: https://github.com/hoihu/projects/tree/master/raspi-hat
The MIT License (MIT)
Copyright (c) 2021 Damien P. George
Copyright (c) 2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Basic example usage:
import time
from lsm6dsox import LSM6DSOX
from machine import Pin, I2C
lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12)))
while (True):
print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.read_accel()))
print('Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.read_gyro()))
print("")
time.sleep_ms(100)
"""
import array
from micropython import const
class LSM6DSOX:
_CTRL3_C = const(0x12)
_CTRL1_XL = const(0x10)
_CTRL8_XL = const(0x17)
_CTRL9_XL = const(0x18)
_CTRL2_G = const(0x11)
_CTRL7_G = const(0x16)
_OUTX_L_G = const(0x22)
_OUTX_L_XL = const(0x28)
_MLC_STATUS = const(0x38)
_DEFAULT_ADDR = const(0x6A)
_WHO_AM_I_REG = const(0x0F)
_FUNC_CFG_ACCESS = const(0x01)
_FUNC_CFG_BANK_USER = const(0)
_FUNC_CFG_BANK_HUB = const(1)
_FUNC_CFG_BANK_EMBED = const(2)
_MLC0_SRC = const(0x70)
_MLC_INT1 = const(0x0D)
_TAP_CFG0 = const(0x56)
_EMB_FUNC_EN_A = const(0x04)
_EMB_FUNC_EN_B = const(0x05)
def __init__(
self,
i2c,
address=_DEFAULT_ADDR,
gyro_odr=104,
accel_odr=104,
gyro_scale=2000,
accel_scale=4,
ucf=None,
):
"""Initalizes Gyro and Accelerator.
accel_odr: (0, 1.6Hz, 3.33Hz, 6.66Hz, 12.5Hz, 26Hz, 52Hz, 104Hz, 208Hz, 416Hz, 888Hz)
gyro_odr: (0, 1.6Hz, 3.33Hz, 6.66Hz, 12.5Hz, 26Hz, 52Hz, 104Hz, 208Hz, 416Hz, 888Hz)
gyro_scale: (245dps, 500dps, 1000dps, 2000dps)
accel_scale: (+/-2g, +/-4g, +/-8g, +-16g)
ucf: MLC program to load.
"""
self.i2c = i2c
self.address = address
# check the id of the Accelerometer/Gyro
if self.__read_reg(_WHO_AM_I_REG) != 108:
raise OSError("No LSM6DS device was found at address 0x%x" % (self.address))
# allocate scratch buffer for efficient conversions and memread op's
self.scratch_int = array.array("h", [0, 0, 0])
SCALE_GYRO = {250: 0, 500: 1, 1000: 2, 2000: 3}
SCALE_ACCEL = {2: 0, 4: 2, 8: 3, 16: 1}
# XL_HM_MODE = 0 by default. G_HM_MODE = 0 by default.
ODR = {
0: 0x00,
1.6: 0x08,
3.33: 0x09,
6.66: 0x0A,
12.5: 0x01,
26: 0x02,
52: 0x03,
104: 0x04,
208: 0x05,
416: 0x06,
888: 0x07,
}
gyro_odr = round(gyro_odr, 2)
accel_odr = round(accel_odr, 2)
# Sanity checks
if not gyro_odr in ODR:
raise ValueError("Invalid sampling rate: %d" % accel_odr)
if not gyro_scale in SCALE_GYRO:
raise ValueError("invalid gyro scaling: %d" % gyro_scale)
if not accel_odr in ODR:
raise ValueError("Invalid sampling rate: %d" % accel_odr)
if not accel_scale in SCALE_ACCEL:
raise ValueError("invalid accelerometer scaling: %d" % accel_scale)
# Soft-reset the device.
self.reset()
# Load and configure MLC if UCF file is provided
if ucf != None:
self.load_mlc(ucf)
# Set Gyroscope datarate and scale.
# Note output from LPF2 second filtering stage is selected. See Figure 18.
self.__write_reg(_CTRL1_XL, (ODR[accel_odr] << 4) | (SCALE_ACCEL[accel_scale] << 2) | 2)
# Enable LPF2 and HPF fast-settling mode, ODR/4
self.__write_reg(_CTRL8_XL, 0x09)
# Set Gyroscope datarate and scale.
self.__write_reg(_CTRL2_G, (ODR[gyro_odr] << 4) | (SCALE_GYRO[gyro_scale] << 2) | 0)
self.gyro_scale = 32768 / gyro_scale
self.accel_scale = 32768 / accel_scale
def __read_reg(self, reg, size=1):
buf = self.i2c.readfrom_mem(self.address, reg, size)
if size == 1:
return int(buf[0])
return [int(x) for x in buf]
def __write_reg(self, reg, val):
self.i2c.writeto_mem(self.address, reg, bytes([val]))
def reset(self):
self.__write_reg(_CTRL3_C, self.__read_reg(_CTRL3_C) | 0x1)
for i in range(0, 10):
if (self.__read_reg(_CTRL3_C) & 0x01) == 0:
return
time.sleep_ms(10)
raise OSError("Failed to reset LSM6DS device.")
def set_mem_bank(self, bank):
cfg = self.__read_reg(_FUNC_CFG_ACCESS) & 0x3F
self.__write_reg(_FUNC_CFG_ACCESS, cfg | (bank << 6))
def set_embedded_functions(self, enable, emb_ab=None):
self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
if enable:
self.__write_reg(_EMB_FUNC_EN_A, emb_ab[0])
self.__write_reg(_EMB_FUNC_EN_B, emb_ab[1])
else:
emb_a = self.__read_reg(_EMB_FUNC_EN_A)
emb_b = self.__read_reg(_EMB_FUNC_EN_B)
self.__write_reg(_EMB_FUNC_EN_A, (emb_a & 0xC7))
self.__write_reg(_EMB_FUNC_EN_B, (emb_b & 0xE6))
emb_ab = (emb_a, emb_b)
self.set_mem_bank(_FUNC_CFG_BANK_USER)
return emb_ab
def load_mlc(self, ucf):
# Load MLC config from file
with open(ucf, "r") as ucf_file:
for l in ucf_file:
if l.startswith("Ac"):
v = [int(v, 16) for v in l.strip().split(" ")[1:3]]
self.__write_reg(v[0], v[1])
emb_ab = self.set_embedded_functions(False)
# Disable I3C interface
self.__write_reg(_CTRL9_XL, self.__read_reg(_CTRL9_XL) | 0x01)
# Enable Block Data Update
self.__write_reg(_CTRL3_C, self.__read_reg(_CTRL3_C) | 0x40)
# Route signals on interrupt pin 1
self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
self.__write_reg(_MLC_INT1, self.__read_reg(_MLC_INT1) & 0x01)
self.set_mem_bank(_FUNC_CFG_BANK_USER)
# Configure interrupt pin mode
self.__write_reg(_TAP_CFG0, self.__read_reg(_TAP_CFG0) | 0x41)
self.set_embedded_functions(True, emb_ab)
def read_mlc_output(self):
buf = None
if self.__read_reg(_MLC_STATUS) & 0x1:
self.__read_reg(0x1A, size=12)
self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
buf = self.__read_reg(_MLC0_SRC, 8)
self.set_mem_bank(_FUNC_CFG_BANK_USER)
return buf
def read_gyro(self):
"""Returns gyroscope vector in degrees/sec."""
mv = memoryview(self.scratch_int)
f = self.gyro_scale
self.i2c.readfrom_mem_into(self.address, _OUTX_L_G, mv)
return (mv[0] / f, mv[1] / f, mv[2] / f)
def read_accel(self):
"""Returns acceleration vector in gravity units (9.81m/s^2)."""
mv = memoryview(self.scratch_int)
f = self.accel_scale
self.i2c.readfrom_mem_into(self.address, _OUTX_L_XL, mv)
return (mv[0] / f, mv[1] / f, mv[2] / f)

View File

@ -0,0 +1,13 @@
# LSM6DSOX Basic Example.
import time
from lsm6dsox import LSM6DSOX
from machine import Pin, I2C
lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12)))
while True:
print("Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}".format(*lsm.read_accel()))
print("Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}".format(*lsm.read_gyro()))
print("")
time.sleep_ms(100)

View File

@ -0,0 +1,48 @@
# LSM6DSOX IMU MLC (Machine Learning Core) Example.
# Download the raw UCF file, copy to storage and reset.
# NOTE: The pre-trained models (UCF files) for the examples can be found here:
# https://github.com/STMicroelectronics/STMems_Machine_Learning_Core/tree/master/application_examples/lsm6dsox
import time
from lsm6dsox import LSM6DSOX
from machine import Pin, I2C
INT_MODE = True # Run in interrupt mode.
INT_FLAG = False # Set True on interrupt.
def imu_int_handler(pin):
global INT_FLAG
INT_FLAG = True
if INT_MODE == True:
int_pin = Pin(24)
int_pin.irq(handler=imu_int_handler, trigger=Pin.IRQ_RISING)
i2c = I2C(0, scl=Pin(13), sda=Pin(12))
# Vibration detection example
UCF_FILE = "lsm6dsox_vibration_monitoring.ucf"
UCF_LABELS = {0: "no vibration", 1: "low vibration", 2: "high vibration"}
# NOTE: Selected data rate and scale must match the MLC data rate and scale.
lsm = LSM6DSOX(i2c, gyro_odr=26, accel_odr=26, gyro_scale=2000, accel_scale=4, ucf=UCF_FILE)
# Head gestures example
# UCF_FILE = "lsm6dsox_head_gestures.ucf"
# UCF_LABELS = {0:"Nod", 1:"Shake", 2:"Stationary", 3:"Swing", 4:"Walk"}
# NOTE: Selected data rate and scale must match the MLC data rate and scale.
# lsm = LSM6DSOX(i2c, gyro_odr=26, accel_odr=26, gyro_scale=250, accel_scale=2, ucf=UCF_FILE)
print("MLC configured...")
while True:
if INT_MODE:
if INT_FLAG:
INT_FLAG = False
print(UCF_LABELS[lsm.read_mlc_output()[0]])
else:
buf = lsm.read_mlc_output()
if buf != None:
print(UCF_LABELS[buf[0]])

View File

@ -36,10 +36,14 @@ class NeoPixel:
def fill(self, v): def fill(self, v):
b = self.buf b = self.buf
for i in range(self.bpp): l = len(self.buf)
bpp = self.bpp
for i in range(bpp):
c = v[i] c = v[i]
for j in range(self.ORDER[i], len(self.buf), self.bpp): j = self.ORDER[i]
while j < l:
b[j] = c b[j] = c
j += bpp
def write(self): def write(self):
# BITSTREAM_TYPE_HIGH_LOW = 0 # BITSTREAM_TYPE_HIGH_LOW = 0

View File

@ -0,0 +1,39 @@
/*
* This file is part of the OpenMV project, https://openmv.io.
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
* Copyright (c) 2013-2021 Kwabena W. Agyeman <kwagyeman@openmv.io>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* NINA-W10 driver BSP.
*/
#ifndef MICROPY_INCLUDED_DRIVERS_NINAW10_NINA_BSP_H
#define MICROPY_INCLUDED_DRIVERS_NINAW10_NINA_BSP_H
int nina_bsp_init(void);
int nina_bsp_deinit(void);
int nina_bsp_read_irq(void);
int nina_bsp_spi_slave_select(uint32_t timeout);
int nina_bsp_spi_slave_deselect(void);
int nina_bsp_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t size);
#endif // MICROPY_INCLUDED_DRIVERS_NINAW10_NINA_BSP_H

View File

@ -0,0 +1,150 @@
/*
* This file is part of the OpenMV project, https://openmv.io.
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
* Copyright (c) 2013-2021 Kwabena W. Agyeman <kwagyeman@openmv.io>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* NINA-W10 Bluetooth HCI driver.
*/
#include "py/mphal.h"
#if MICROPY_PY_BLUETOOTH && MICROPY_PY_NETWORK_NINAW10
#include <stdio.h>
#include <string.h>
#include "py/runtime.h"
#include "extmod/mpbthci.h"
#define HCI_COMMAND_PACKET (0x01)
#define HCI_ACLDATA_PACKET (0x02)
#define HCI_EVENT_PACKET (0x04)
#define HCI_COMMAND_COMPLETE (0x0e)
#define HCI_COMMAND_TIMEOUT (3000)
#define OGF_LINK_CTL (0x01)
#define OGF_HOST_CTL (0x03)
#define OCF_SET_EVENT_MASK (0x0001)
#define OCF_RESET (0x0003)
#define error_printf(...) mp_printf(&mp_plat_print, "nina_bt_hci.c: " __VA_ARGS__)
#define debug_printf(...) // mp_printf(&mp_plat_print, "nina_bt_hci.c: " __VA_ARGS__)
// Provided by the port, and also possibly shared with the stack.
extern uint8_t mp_bluetooth_hci_cmd_buf[4 + 256];
static int nina_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *param_buf) {
uint8_t *buf = mp_bluetooth_hci_cmd_buf;
buf[0] = HCI_COMMAND_PACKET;
buf[1] = ocf;
buf[2] = ogf << 2 | ocf >> 8;
buf[3] = param_len;
if (param_len) {
memcpy(buf + 4, param_buf, param_len);
}
debug_printf("HCI Command: %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);
mp_bluetooth_hci_uart_write(buf, 4 + param_len);
// Receive HCI event packet, initially reading 3 bytes (HCI Event, Event code, Plen).
for (mp_uint_t start = mp_hal_ticks_ms(), size = 3, i = 0; i < size;) {
while (!mp_bluetooth_hci_uart_any()) {
MICROPY_EVENT_POLL_HOOK
// Timeout.
if ((mp_hal_ticks_ms() - start) > HCI_COMMAND_TIMEOUT) {
error_printf("timeout waiting for HCI packet\n");
return -1;
}
}
buf[i] = mp_bluetooth_hci_uart_readchar();
// There seems to be a sync issue with this fw/module.
if (i == 0 && buf[0] == 0xFF) {
continue;
}
// Check for packet type.
if (i == 0 && buf[0] != HCI_EVENT_PACKET) {
error_printf("unexpected HCI packet: %02x\n", buf[0]);
return -1;
}
// Sanity check the packet parameters length.
if (i == 2 && ((size += buf[2]) > sizeof(mp_bluetooth_hci_cmd_buf))) {
error_printf("unexpected event packet length: %d\n", size);
return -1;
}
i++;
}
// We're only looking for command complete events.
if (buf[1] != HCI_COMMAND_COMPLETE || buf[4] != ocf || buf[5] != (ogf << 2 | ocf >> 8)) {
error_printf("response mismatch: %02x %02x\n", buf[4], buf[5]);
return -1;
}
// Log event.
debug_printf("HCI Event packet: %02x %02x %02x %02x %02x %02x %02x\n",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
// Status code.
return buf[6];
}
int mp_bluetooth_hci_controller_init(void) {
// This is called immediately after the UART is initialised during stack initialisation.
mp_hal_pin_output(MICROPY_HW_NINA_GPIO1);
mp_hal_pin_output(MICROPY_HW_NINA_RESET);
mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 0);
mp_hal_pin_write(MICROPY_HW_NINA_RESET, 0);
mp_hal_delay_ms(100);
mp_hal_pin_write(MICROPY_HW_NINA_RESET, 1);
mp_hal_delay_ms(750);
// The UART must be re-initialize here because the GPIO1/RX pin is used initially
// to reset the module in Bluetooth mode. This will change back the pin to UART RX.
mp_bluetooth_hci_uart_init(0, 0);
// Send reset command
return nina_hci_cmd(OGF_HOST_CTL, OCF_RESET, 0, NULL);
// It seems that nothing else is needed for now.
}
int mp_bluetooth_hci_controller_deinit(void) {
// Reset module
mp_hal_pin_output(MICROPY_HW_NINA_RESET);
mp_hal_pin_write(MICROPY_HW_NINA_RESET, 0);
return 0;
}
#endif

View File

@ -0,0 +1,139 @@
/*
* This file is part of the OpenMV project, https://openmv.io.
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
* Copyright (c) 2013-2021 Kwabena W. Agyeman <kwagyeman@openmv.io>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* NINA-W10 driver BSP implementation.
*/
#include "py/mphal.h"
#if MICROPY_PY_NETWORK_NINAW10
#include <stdint.h>
#include <string.h>
#include "py/runtime.h"
#include "modmachine.h"
#include "extmod/machine_spi.h"
#include "mpconfigboard.h"
#include "nina_bsp.h"
#include "nina_wifi_drv.h"
#if NINA_DEBUG
#define debug_printf(...) mp_printf(&mp_plat_print, __VA_ARGS__)
#else
#define debug_printf(...)
#endif
int nina_bsp_init(void) {
mp_hal_pin_output(MICROPY_HW_NINA_GPIO1);
mp_hal_pin_input(MICROPY_HW_NINA_ACK);
mp_hal_pin_output(MICROPY_HW_NINA_RESET);
mp_hal_pin_output(MICROPY_HW_NINA_GPIO0);
// Reset module in WiFi mode
mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 1);
mp_hal_pin_write(MICROPY_HW_NINA_GPIO0, 1);
mp_hal_pin_write(MICROPY_HW_NINA_RESET, 0);
mp_hal_delay_ms(100);
mp_hal_pin_write(MICROPY_HW_NINA_RESET, 1);
mp_hal_delay_ms(750);
mp_hal_pin_write(MICROPY_HW_NINA_GPIO0, 0);
mp_hal_pin_input(MICROPY_HW_NINA_GPIO0);
// Initialize SPI.
mp_obj_t args[] = {
MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_ID),
MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_BAUDRATE),
};
MP_STATE_PORT(mp_wifi_spi) = machine_spi_type.make_new((mp_obj_t)&machine_spi_type, 2, 0, args);
return 0;
}
int nina_bsp_deinit(void) {
mp_hal_pin_output(MICROPY_HW_NINA_GPIO1);
mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 1);
mp_hal_pin_output(MICROPY_HW_NINA_RESET);
mp_hal_pin_write(MICROPY_HW_NINA_RESET, 0);
mp_hal_delay_ms(100);
mp_hal_pin_output(MICROPY_HW_NINA_GPIO0);
mp_hal_pin_write(MICROPY_HW_NINA_GPIO0, 1);
return 0;
}
int nina_bsp_read_irq(void) {
return mp_hal_pin_read(MICROPY_HW_NINA_GPIO0);
}
int nina_bsp_spi_slave_select(uint32_t timeout) {
// Wait for ACK to go low.
for (mp_uint_t start = mp_hal_ticks_ms(); mp_hal_pin_read(MICROPY_HW_NINA_ACK) == 1; mp_hal_delay_ms(1)) {
if ((mp_hal_ticks_ms() - start) >= timeout) {
return -1;
}
}
// Chip select.
mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 0);
// Wait for ACK to go high.
for (mp_uint_t start = mp_hal_ticks_ms(); mp_hal_pin_read(MICROPY_HW_NINA_ACK) == 0; mp_hal_delay_ms(1)) {
if ((mp_hal_ticks_ms() - start) >= 100) {
mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 1);
return -1;
}
}
return 0;
}
int nina_bsp_spi_slave_deselect(void) {
mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 1);
return 0;
}
int nina_bsp_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t size) {
mp_obj_t mp_wifi_spi = MP_STATE_PORT(mp_wifi_spi);
((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer(mp_wifi_spi, size, tx_buf, rx_buf);
#if NINA_DEBUG
for (int i = 0; i < size; i++) {
if (tx_buf) {
debug_printf("0x%x ", tx_buf[i]);
} else {
debug_printf("0x%x ", rx_buf[i]);
}
}
#endif
return 0;
}
#endif // MICROPY_PY_NETWORK_NINAW10

View File

@ -0,0 +1,931 @@
/*
* This file is part of the OpenMV project, https://openmv.io.
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
* Copyright (c) 2013-2021 Kwabena W. Agyeman <kwagyeman@openmv.io>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* NINA-W10 WiFi driver.
*/
#include "py/mphal.h"
#if MICROPY_PY_NETWORK_NINAW10
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "nina_bsp.h"
#include "nina_wifi_drv.h"
#define SPI_ACK (1)
#define SPI_ERR (0xFF)
#define NO_SOCKET_AVAIL (255)
#define CMD_START (0xE0)
#define CMD_END (0xEE)
#define CMD_ERROR (0xEF)
#define CMD_REPLY (1 << 7)
#define ARG_8BITS (1)
#define ARG_16BITS (2)
#define ARG_STR(x) {strlen(x), (const void *)x}
#define ARG_BYTE(x) {1, (uint8_t [1]) {x}}
#define ARG_SHORT(x) {2, (uint16_t [1]) {x}}
#define ARG_WORD(x) {4, (uint32_t [1]) {x}}
#define NINA_ARGS(...) (nina_args_t []) {__VA_ARGS__}
#define NINA_VALS(...) (nina_vals_t []) {__VA_ARGS__}
#define NINA_SSELECT_TIMEOUT (10000)
#define NINA_RESPONSE_TIMEOUT (1000)
#define NINA_CONNECT_TIMEOUT (10000)
#if NINA_DEBUG
#define debug_printf(...) mp_printf(&mp_plat_print, __VA_ARGS__)
#else
#define debug_printf(...)
#endif
#ifndef __REVSH
#define __REVSH(x) ((((uint16_t)x) << 8) | (((uint16_t)x) >> 8))
#endif
typedef struct {
uint16_t size;
const void *data;
} nina_args_t;
typedef struct {
uint16_t *size;
void *data;
} nina_vals_t;
typedef enum {
// STA mode commands.
NINA_CMD_CONNECT_OPEN = 0x10,
NINA_CMD_CONNECT_WEP = 0x11,
NINA_CMD_CONNECT_WPA = 0x12,
NINA_CMD_GET_SSID = 0x23,
NINA_CMD_GET_BSSID = 0x24,
NINA_CMD_GET_RSSI = 0x25,
NINA_CMD_GET_ENCRYPT = 0x26,
// AP mode commands.
NINA_CMD_START_AP_OPEN = 0x18,
NINA_CMD_START_AP_WEP = 0x19,
// AP mode scan commands.
NINA_CMD_AP_START_SCAN = 0x36,
NINA_CMD_AP_SCAN_RESULT = 0x27,
NINA_CMD_AP_GET_RSSI = 0x32,
NINA_CMD_AP_GET_ENCRYPT = 0x33,
NINA_CMD_AP_GET_BSSID = 0x3C,
NINA_CMD_AP_GET_CHANNEL = 0x3D,
// Disonnect/status commands.
NINA_CMD_DISCONNECT = 0x30,
NINA_CMD_CONN_STATUS = 0x20,
// Interface config commands.
NINA_CMD_SET_IF_CONFIG = 0x14,
NINA_CMD_GET_IF_CONFIG = 0x21,
NINA_CMD_SET_DNS_CONFIG = 0x15,
// Hostname/Resolv commands.
NINA_CMD_SET_HOSTNAME = 0x16,
NINA_CMD_HOST_BY_NAME = 0x34,
NINA_CMD_GET_HOST_BY_NAME = 0x35,
// Misc commands.
NINA_CMD_SET_POWER = 0x17,
NINA_CMD_PING = 0x3E,
NINA_CMD_GET_TIME = 0x3B,
NINA_CMD_GET_FW_VERSION = 0x37,
NINA_CMD_DEBUG_MODE = 0x1A,
NINA_CMD_TEMP_SENSOR = 0x1B,
NINA_CMD_GET_MAC_ADDR = 0x22,
// Sockets commands.
NINA_CMD_SOCKET_OPEN = 0x3F,
NINA_CMD_SOCKET_CLOSE = 0x2E,
NINA_CMD_SOCKET_CONNECT = 0x2D,
NINA_CMD_SOCKET_ACCEPT = 0x2B,
NINA_CMD_SOCKET_BIND = 0x28,
NINA_CMD_SOCKET_STATE = 0x2F,
NINA_CMD_SOCKET_REMOTE_ADDR = 0x3A,
// TCP commands
NINA_CMD_TCP_SEND = 0x44,
NINA_CMD_TCP_RECV = 0x45,
NINA_CMD_TCP_ACK = 0x2A,
// UDP commands.
NINA_CMD_UDP_SEND = 0x46,
NINA_CMD_UDP_RECV = 0x45,
NINA_CMD_UDP_ACK = 0x39,
// Pin control commands.
NINA_CMD_SET_PIN_MODE = 0x50,
NINA_CMD_SET_DIGITAL_WRITE = 0x51,
NINA_CMD_GET_DIGITAL_READ = 0x53,
NINA_CMD_SET_ANALOG_WRITE = 0x52,
NINA_CMD_GET_ANALOG_READ = 0x54,
// File send/recv commands.
NINA_CMD_CMD_WRITE_FILE = 0x60,
NINA_CMD_CMD_READ_FILE = 0x61,
NINA_CMD_CMD_DELETE_FILE = 0x62,
NINA_CMD_CMD_EXISTS_FILE = 0x63,
NINA_CMD_CMD_DOWNLOAD_FILE = 0x64,
// OTA upgrade commands.
NINA_CMD_CMD_APPLY_OTA = 0x65,
NINA_CMD_CMD_RENAME_FILE = 0x66,
NINA_CMD_CMD_DOWNLOAD_OTA = 0x67,
} nina_cmd_t;
typedef enum {
NINA_STATUS_IDLE = 0,
NINA_STATUS_NO_SSID_AVAIL,
NINA_STATUS_SCAN_COMPLETED,
NINA_STATUS_CONNECTED,
NINA_STATUS_CONNECT_FAILED,
NINA_STATUS_CONNECTION_LOST,
NINA_STATUS_DISCONNECTED,
NINA_STATUS_AP_LISTENING,
NINA_STATUS_AP_CONNECTED,
NINA_STATUS_AP_FAILED
} nina_status_t;
typedef enum {
SOCKET_STATE_CLOSED = 0,
SOCKET_STATE_LISTEN,
SOCKET_STATE_SYN_SENT,
SOCKET_STATE_SYN_RCVD,
SOCKET_STATE_ESTABLISHED,
SOCKET_STATE_FIN_WAIT_1,
SOCKET_STATE_FIN_WAIT_2,
SOCKET_STATE_CLOSE_WAIT,
SOCKET_STATE_CLOSING,
SOCKET_STATE_LAST_ACK,
SOCKET_STATE_TIME_WAIT
} nina_sock_state_t;
static uint8_t nina_bsp_spi_read_byte(void) {
uint8_t byte = 0;
nina_bsp_spi_transfer(NULL, &byte, 1);
return byte;
}
static int nina_wait_for_cmd(uint8_t cmd, uint32_t timeout) {
uint8_t buf = 0;
for (mp_uint_t start = mp_hal_ticks_ms(); ;) {
buf = nina_bsp_spi_read_byte();
if (buf == CMD_ERROR || buf == cmd
|| ((mp_hal_ticks_ms() - start) >= timeout)) {
break;
}
mp_hal_delay_ms(1);
}
return (buf == cmd) ? 0 : -1;
}
static int nina_send_command(uint32_t cmd, uint32_t nargs, uint32_t width, nina_args_t *args) {
int ret = -1;
uint32_t length = 4; // 3 bytes header + 1 end byte
debug_printf("nina_send_command (cmd 0x%x nargs %d width %d): ", cmd, nargs, width);
if (nina_bsp_spi_slave_select(NINA_SSELECT_TIMEOUT) != 0) {
return -1;
}
// Send command header.
uint8_t cmdbuf_hdr[3] = {CMD_START, cmd, nargs};
if (nina_bsp_spi_transfer(cmdbuf_hdr, NULL, sizeof(cmdbuf_hdr)) != 0) {
goto error_out;
}
// Send command arg(s).
for (uint32_t i = 0; i < nargs; i++) {
// Send size MSB first if 2 bytes.
uint16_t size = (width == ARG_8BITS) ? args[i].size : __REVSH(args[i].size);
// Send arg length.
if (nina_bsp_spi_transfer((uint8_t *)&size, NULL, width) != 0) {
goto error_out;
}
// Send arg value.
if (nina_bsp_spi_transfer(args[i].data, NULL, args[i].size) != 0) {
goto error_out;
}
length += args[i].size + width;
}
// Send END byte + padding to multiple of 4.
uint8_t cmdbuf_end[4] = {CMD_END, 0xFF, 0xFF, 0xFF};
if (nina_bsp_spi_transfer(cmdbuf_end, NULL, 1 + (length % 4)) != 0) {
goto error_out;
}
// All good
ret = 0;
error_out:
debug_printf("\n");
nina_bsp_spi_slave_deselect();
return ret;
}
static int nina_read_response(uint32_t cmd, uint32_t nvals, uint32_t width, nina_vals_t *vals) {
int ret = -1;
debug_printf("nina_read_response(cmd 0x%x nvals %d width %d): ", cmd, nvals, width);
// Read reply
if (nina_bsp_spi_slave_select(NINA_SSELECT_TIMEOUT) != 0) {
return -1;
}
// Wait for CMD_START
if (nina_wait_for_cmd(CMD_START, NINA_RESPONSE_TIMEOUT) != 0) {
goto error_out;
}
// Should return CMD + REPLY flag.
if (nina_bsp_spi_read_byte() != (cmd | CMD_REPLY)) {
goto error_out;
}
// Sanity check the number of returned values.
// NOTE: This is to handle the special case for the scan command.
uint32_t rvals = nina_bsp_spi_read_byte();
if (nvals > rvals) {
nvals = rvals;
}
// Read return value(s).
for (uint32_t i = 0; i < nvals; i++) {
// Read return value size.
uint16_t bytes = nina_bsp_spi_read_byte();
if (width == ARG_16BITS) {
bytes = (bytes << 8) | nina_bsp_spi_read_byte();
}
// Check the val fits the buffer.
if (*(vals[i].size) < bytes) {
goto error_out;
}
// Read the returned value.
if (nina_bsp_spi_transfer(NULL, vals[i].data, bytes) != 0) {
goto error_out;
}
// Set the size.
*(vals[i].size) = bytes;
}
if (nina_bsp_spi_read_byte() != CMD_END) {
goto error_out;
}
// All good
ret = 0;
error_out:
debug_printf("\n");
nina_bsp_spi_slave_deselect();
return ret;
}
static int nina_send_command_read_ack(uint32_t cmd, uint32_t nargs, uint32_t width, nina_args_t *args) {
uint16_t size = 1;
uint8_t rval = SPI_ERR;
if (nina_send_command(cmd, nargs, width, args) != 0 ||
nina_read_response(cmd, 1, ARG_8BITS, NINA_VALS({&size, &rval})) != 0) {
return -1;
}
return rval;
}
static int nina_send_command_read_vals(uint32_t cmd, uint32_t nargs,
uint32_t argsw, nina_args_t *args, uint32_t nvals, uint32_t valsw, nina_vals_t *vals) {
if (nina_send_command(cmd, nargs, argsw, args) != 0 ||
nina_read_response(cmd, nvals, valsw, vals) != 0) {
return -1;
}
return 0;
}
static void nina_fix_mac_addr(uint8_t *mac) {
for (int i = 0; i < 3; i++) {
uint8_t b = mac[i];
mac[i] = mac[5 - i];
mac[5 - i] = b;
}
}
int nina_init(void) {
// Initialize the BSP.
nina_bsp_init();
return 0;
}
int nina_deinit(void) {
return nina_bsp_deinit();
}
static int nina_connection_status() {
return nina_send_command_read_ack(NINA_CMD_CONN_STATUS, 0, ARG_8BITS, NULL);
}
static int nina_socket_status(uint8_t fd) {
return nina_send_command_read_ack(NINA_CMD_SOCKET_STATE,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)));
}
static int nina_server_socket_status(uint8_t fd) {
return nina_send_command_read_ack(NINA_CMD_SOCKET_STATE & 0xF9,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)));
}
int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel) {
uint8_t status = NINA_STATUS_CONNECT_FAILED;
if (key == NULL && security != NINA_SEC_OPEN) {
return -1;
}
switch (security) {
case NINA_SEC_OPEN:
if (nina_send_command_read_ack(NINA_CMD_CONNECT_OPEN,
1, ARG_8BITS, NINA_ARGS(ARG_STR(ssid))) != SPI_ACK) {
return -1;
}
break;
case NINA_SEC_WEP:
if (nina_send_command_read_ack(NINA_CMD_CONNECT_WEP,
2, ARG_8BITS, NINA_ARGS(ARG_STR(ssid), ARG_STR(key))) != SPI_ACK) {
return -1;
}
break;
case NINA_SEC_WPA_PSK:
if (nina_send_command_read_ack(NINA_CMD_CONNECT_WPA,
3, ARG_8BITS, NINA_ARGS(ARG_STR(ssid), ARG_BYTE(0), ARG_STR(key))) != SPI_ACK) {
return -1;
}
break;
default:
return -1;
}
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
status = nina_connection_status();
if ((status != NINA_STATUS_IDLE) && (status != NINA_STATUS_NO_SSID_AVAIL) && (status != NINA_STATUS_SCAN_COMPLETED)) {
break;
}
if ((mp_hal_ticks_ms() - start) >= NINA_CONNECT_TIMEOUT) {
break;
}
}
return (status == NINA_STATUS_CONNECTED) ? 0 : -1;
}
int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t channel) {
uint8_t status = NINA_STATUS_AP_FAILED;
if ((key == NULL && security != NINA_SEC_OPEN) ||
(security != NINA_SEC_OPEN && security != NINA_SEC_WEP)) {
return -1;
}
switch (security) {
case NINA_SEC_OPEN:
if (nina_send_command_read_ack(NINA_CMD_START_AP_OPEN,
2, ARG_8BITS, NINA_ARGS(ARG_STR(ssid), ARG_BYTE(channel))) != SPI_ACK) {
return -1;
}
break;
case NINA_SEC_WEP:
if (nina_send_command_read_ack(NINA_CMD_START_AP_WEP,
3, ARG_8BITS, NINA_ARGS(ARG_STR(ssid), ARG_STR(key), ARG_BYTE(channel))) != SPI_ACK) {
return -1;
}
break;
default:
return -1;
}
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
status = nina_connection_status();
if ((status != NINA_STATUS_IDLE) && (status != NINA_STATUS_NO_SSID_AVAIL) && (status != NINA_STATUS_SCAN_COMPLETED)) {
break;
}
if ((mp_hal_ticks_ms() - start) >= NINA_CONNECT_TIMEOUT) {
break;
}
}
return (status == NINA_STATUS_AP_LISTENING) ? 0 : -1;
}
int nina_disconnect(void) {
if (nina_send_command_read_ack(NINA_CMD_DISCONNECT,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF))) != SPI_ACK) {
return -1;
}
return 0;
}
int nina_isconnected(void) {
int status = nina_connection_status();
if (status == -1) {
return -1;
}
return status == NINA_STATUS_CONNECTED;
}
int nina_connected_sta(uint32_t *sta_ip) {
return -1;
}
int nina_wait_for_sta(uint32_t *sta_ip, uint32_t timeout) {
return NINA_ERROR_TIMEOUT;
}
int nina_ifconfig(nina_ifconfig_t *ifconfig, bool set) {
uint16_t ip_len = NINA_IPV4_ADDR_LEN;
uint16_t sub_len = NINA_IPV4_ADDR_LEN;
uint16_t gw_len = NINA_IPV4_ADDR_LEN;
uint16_t dns_len = NINA_IPV4_ADDR_LEN;
if (set) {
if (nina_send_command_read_ack(NINA_CMD_SET_IF_CONFIG,
4, ARG_8BITS,
NINA_ARGS(
ARG_BYTE(3), // Valid number of args.
{ip_len, ifconfig->ip_addr},
{gw_len, ifconfig->gateway_addr},
{sub_len, ifconfig->subnet_addr})) != 0) {
return -1;
}
uint8_t dns2[4] = {8, 8, 8, 8};
if (nina_send_command_read_ack(NINA_CMD_SET_DNS_CONFIG,
3, ARG_8BITS,
NINA_ARGS(
ARG_BYTE(1), // Valid number of args.
{dns_len, ifconfig->dns_addr},
{dns_len, dns2})) != SPI_ACK) {
return -1;
}
} else {
if (nina_send_command_read_vals(NINA_CMD_GET_IF_CONFIG,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF)),
3, ARG_8BITS,
NINA_VALS(
{&ip_len, ifconfig->ip_addr},
{&sub_len, ifconfig->subnet_addr},
{&gw_len, ifconfig->gateway_addr})) != 0) {
return -1;
}
// No command to get DNS ?
memcpy(ifconfig->dns_addr, ifconfig->gateway_addr, NINA_IPV4_ADDR_LEN);
}
return 0;
}
int nina_netinfo(nina_netinfo_t *netinfo) {
uint16_t rssi_len = 4;
uint16_t sec_len = 1;
uint16_t ssid_len = NINA_MAX_SSID_LEN;
uint16_t bssid_len = NINA_MAC_ADDR_LEN;
if (nina_send_command_read_vals(NINA_CMD_GET_RSSI,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF)),
1, ARG_8BITS, NINA_VALS({&rssi_len, &netinfo->rssi})) != 0) {
return -1;
}
if (nina_send_command_read_vals(NINA_CMD_GET_ENCRYPT,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF)),
1, ARG_8BITS, NINA_VALS({&sec_len, &netinfo->security})) != 0) {
return -1;
}
if (nina_send_command_read_vals(NINA_CMD_GET_SSID,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF)),
1, ARG_8BITS, NINA_VALS({&ssid_len, &netinfo->ssid})) != 0) {
return -1;
}
// Null terminate SSID.
netinfo->ssid[MIN((NINA_MAX_SSID_LEN - 1), ssid_len)] = 0;
if (nina_send_command_read_vals(NINA_CMD_GET_BSSID,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF)),
1, ARG_8BITS, NINA_VALS({&bssid_len, &netinfo->bssid})) != 0) {
return -1;
}
// The MAC address is read in reverse from the firmware.
nina_fix_mac_addr(netinfo->bssid);
return 0;
}
int nina_scan(nina_scan_callback_t scan_callback, void *arg, uint32_t timeout) {
uint16_t sizes[NINA_MAX_NETWORK_LIST];
char ssids[NINA_MAX_NETWORK_LIST][NINA_MAX_SSID_LEN];
nina_vals_t vals[NINA_MAX_NETWORK_LIST];
// Initialize the values list.
for (int i = 0; i < NINA_MAX_NETWORK_LIST; i++) {
sizes[i] = NINA_MAX_SSID_LEN - 1;
memset(ssids[i], 0, NINA_MAX_SSID_LEN);
vals[i].size = &sizes[i];
vals[i].data = ssids[i];
}
if (nina_send_command_read_ack(NINA_CMD_AP_START_SCAN,
0, ARG_8BITS, NULL) != SPI_ACK) {
return -1;
}
for (mp_uint_t start = mp_hal_ticks_ms(); ;) {
if (nina_send_command_read_vals(NINA_CMD_AP_SCAN_RESULT,
0, ARG_8BITS, NULL,
NINA_MAX_NETWORK_LIST, ARG_8BITS, vals) != 0) {
return -1;
}
if (ssids[0][0] != 0) {
// Found at least 1 network.
break;
}
if (timeout && (mp_hal_ticks_ms() - start) >= timeout) {
// Timeout, no networks.
return NINA_ERROR_TIMEOUT;
}
mp_hal_delay_ms(100);
}
for (int i = 0; i < NINA_MAX_NETWORK_LIST; i++) {
uint16_t rssi_len = 4;
uint16_t sec_len = 1;
uint16_t chan_len = 1;
uint16_t bssid_len = NINA_MAC_ADDR_LEN;
nina_scan_result_t scan_result;
if (ssids[i][0] == 0) {
break;
}
// Set AP SSID
strncpy(scan_result.ssid, ssids[i], NINA_MAX_SSID_LEN);
// Read AP RSSI
if (nina_send_command_read_vals(NINA_CMD_AP_GET_RSSI,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(i)),
1, ARG_8BITS, NINA_VALS({&rssi_len, &scan_result.rssi})) != 0) {
return -1;
}
// Read AP encryption type
if (nina_send_command_read_vals(NINA_CMD_AP_GET_ENCRYPT,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(i)),
1, ARG_8BITS, NINA_VALS({&sec_len, &scan_result.security})) != 0) {
return -1;
}
// Read AP channel
if (nina_send_command_read_vals(NINA_CMD_AP_GET_CHANNEL,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(i)),
1, ARG_8BITS, NINA_VALS({&chan_len, &scan_result.channel})) != 0) {
return -1;
}
// Read AP bssid
if (nina_send_command_read_vals(NINA_CMD_AP_GET_BSSID,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(i)),
1, ARG_8BITS, NINA_VALS({&bssid_len, scan_result.bssid})) != 0) {
return -1;
}
// The MAC address is read in reverse from the firmware.
nina_fix_mac_addr(scan_result.bssid);
scan_callback(&scan_result, arg);
}
return 0;
}
int nina_get_rssi(void) {
uint16_t size = 4;
int32_t rssi = 0;
if (nina_send_command_read_vals(NINA_CMD_GET_RSSI,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF)),
1, ARG_8BITS, NINA_VALS({&size, &rssi})) != 0) {
return -1;
}
return rssi;
}
int nina_fw_version(uint8_t *fw_ver) {
uint16_t size = NINA_FW_VER_LEN;
if (nina_send_command_read_vals(NINA_CMD_GET_FW_VERSION,
0, ARG_8BITS, NULL,
1, ARG_8BITS, NINA_VALS({&size, fw_ver})) != 0) {
return -1;
}
return 0;
}
int nina_set_hostname(const char *hostname) {
if (nina_send_command_read_ack(NINA_CMD_SET_HOSTNAME,
1, ARG_8BITS, NINA_ARGS(ARG_STR(hostname))) != SPI_ACK) {
return -1;
}
return 0;
}
int nina_gethostbyname(const char *name, uint8_t *out_ip) {
uint16_t size = 4;
if (nina_send_command_read_ack(NINA_CMD_HOST_BY_NAME,
1, ARG_8BITS, NINA_ARGS(ARG_STR(name))) != SPI_ACK) {
return -1;
}
if (nina_send_command_read_vals(NINA_CMD_GET_HOST_BY_NAME,
0, ARG_8BITS, NULL,
1, ARG_8BITS, NINA_VALS({&size, out_ip})) != 0) {
return -1;
}
return 0;
}
int nina_socket_socket(uint8_t type) {
uint16_t size = 1;
uint8_t sock = 0;
if (nina_send_command_read_vals(NINA_CMD_SOCKET_OPEN,
0, ARG_8BITS, NULL,
1, ARG_8BITS, NINA_VALS({&size, &sock})) != 0) {
return -1;
}
return sock;
}
int nina_socket_close(int fd) {
if (fd > 0 && fd < 255) {
if (nina_send_command_read_ack(NINA_CMD_SOCKET_CLOSE,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd))) != SPI_ACK) {
return -1;
}
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
if (nina_socket_status(fd) == SOCKET_STATE_CLOSED) {
break;
}
if ((mp_hal_ticks_ms() - start) >= 5000) {
return NINA_ERROR_TIMEOUT;
}
}
}
return 0;
}
int nina_socket_bind(int fd, uint8_t *ip, uint16_t port, int type) {
if (nina_send_command_read_ack(NINA_CMD_SOCKET_BIND,
3, ARG_8BITS,
NINA_ARGS(
ARG_SHORT(__REVSH(port)),
ARG_BYTE(fd),
ARG_BYTE(type))) != SPI_ACK) {
return -1;
}
// Only TCP sockets' states should be checked.
if (type == NINA_SOCKET_TYPE_TCP &&
nina_server_socket_status(fd) != SOCKET_STATE_LISTEN) {
return -1;
}
return 0;
}
int nina_socket_listen(int fd, uint32_t backlog) {
return 0; // No listen ?
}
int nina_socket_accept(int fd, uint8_t *ip, uint16_t *port, int *fd_out, uint32_t timeout) {
uint16_t size = 2;
uint16_t sock = NO_SOCKET_AVAIL;
if (nina_server_socket_status(fd) != SOCKET_STATE_LISTEN) {
return -1;
}
for (mp_uint_t start = mp_hal_ticks_ms(); sock == 0 || sock == NO_SOCKET_AVAIL; mp_hal_delay_ms(10)) {
if (nina_send_command_read_vals(NINA_CMD_SOCKET_ACCEPT,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)),
1, ARG_8BITS, NINA_VALS({&size, &sock})) != 0) {
return -1;
}
if (timeout && (mp_hal_ticks_ms() - start) >= timeout) {
return NINA_ERROR_TIMEOUT;
}
}
uint16_t port_len = 2;
uint16_t ip_len = NINA_IPV4_ADDR_LEN;
if (nina_send_command_read_vals(NINA_CMD_SOCKET_REMOTE_ADDR,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(sock)),
2, ARG_8BITS, NINA_VALS({&ip_len, ip}, {&port_len, port})) != 0) {
return -1;
}
*fd_out = sock;
*port = __REVSH(*port);
return 0;
}
int nina_socket_connect(int fd, uint8_t *ip, uint16_t port, uint32_t timeout) {
if (nina_send_command_read_ack(NINA_CMD_SOCKET_CONNECT,
4, ARG_8BITS,
NINA_ARGS(
ARG_WORD((*(uint32_t *)ip)),
ARG_SHORT(__REVSH(port)),
ARG_BYTE(fd),
ARG_BYTE(NINA_SOCKET_TYPE_TCP))) != SPI_ACK) {
return -1;
}
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
int state = nina_socket_status(fd);
if (state == -1) {
return -1;
}
if (state == SOCKET_STATE_ESTABLISHED) {
break;
}
if (timeout && (mp_hal_ticks_ms() - start) >= timeout) {
return NINA_ERROR_TIMEOUT;
}
}
return 0;
}
int nina_socket_send(int fd, const uint8_t *buf, uint32_t len, uint32_t timeout) {
uint16_t size = 2;
uint16_t bytes = 0;
if (nina_socket_status(fd) != SOCKET_STATE_ESTABLISHED) {
return -1;
}
if (nina_send_command_read_vals(NINA_CMD_TCP_SEND,
2, ARG_16BITS, NINA_ARGS(ARG_BYTE(fd), {len, buf}),
1, ARG_8BITS, NINA_VALS({&size, &bytes})) != 0 || bytes <= 0) {
return -1;
}
for (mp_uint_t start = mp_hal_ticks_ms(); ;) {
int resp = nina_send_command_read_ack(NINA_CMD_TCP_ACK,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)));
if (resp == -1) {
return -1;
}
if (resp == SPI_ACK) {
break;
}
if (timeout && (mp_hal_ticks_ms() - start) >= timeout) {
return NINA_ERROR_TIMEOUT;
}
mp_hal_delay_ms(1);
}
return bytes;
}
int nina_socket_recv(int fd, uint8_t *buf, uint32_t len, uint32_t timeout) {
uint16_t bytes = 0;
if (nina_socket_status(fd) != SOCKET_STATE_ESTABLISHED) {
return -1;
}
for (mp_uint_t start = mp_hal_ticks_ms(); bytes == 0; mp_hal_delay_ms(1)) {
bytes = len;
if (nina_send_command_read_vals(NINA_CMD_TCP_RECV,
2, ARG_16BITS, NINA_ARGS(ARG_BYTE(fd), ARG_SHORT(bytes)),
1, ARG_16BITS, NINA_VALS({&bytes, buf})) != 0) {
return -1;
}
if (timeout && (mp_hal_ticks_ms() - start) >= timeout) {
return NINA_ERROR_TIMEOUT;
}
}
return bytes;
}
// Check from the upper layer if the socket is bound, if not then auto-bind it first.
int nina_socket_sendto(int fd, const uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t port, uint32_t timeout) {
// TODO do we need to split the packet somewhere?
if (nina_send_command_read_ack(NINA_CMD_SOCKET_CONNECT,
4, ARG_8BITS,
NINA_ARGS(
ARG_WORD((*(uint32_t *)ip)),
ARG_SHORT(__REVSH(port)),
ARG_BYTE(fd),
ARG_BYTE(NINA_SOCKET_TYPE_UDP))) != SPI_ACK) {
return -1;
}
// Buffer length and socket number are passed as 16bits.
if (nina_send_command_read_ack(NINA_CMD_UDP_SEND,
2, ARG_16BITS, NINA_ARGS(ARG_BYTE(fd), {len, buf})) != SPI_ACK) {
return -1;
}
if (nina_send_command_read_ack(NINA_CMD_UDP_ACK,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd))) != SPI_ACK) {
return -1;
}
return 0;
}
// Check from the upper layer if the socket is bound, if not then auto-bind it first.
int nina_socket_recvfrom(int fd, uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t *port, uint32_t timeout) {
uint16_t bytes = 0;
uint16_t port_len = 2;
uint16_t ip_len = NINA_IPV4_ADDR_LEN;
for (mp_uint_t start = mp_hal_ticks_ms(); bytes == 0; mp_hal_delay_ms(1)) {
bytes = len;
if (nina_send_command_read_vals(NINA_CMD_UDP_RECV,
2, ARG_16BITS, NINA_ARGS(ARG_BYTE(fd), ARG_SHORT(bytes)),
1, ARG_16BITS, NINA_VALS({&bytes, buf})) != 0) {
return -1;
}
if (timeout && (mp_hal_ticks_ms() - start) >= timeout) {
return NINA_ERROR_TIMEOUT;
}
}
if (nina_send_command_read_vals(NINA_CMD_SOCKET_REMOTE_ADDR,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)),
2, ARG_8BITS, NINA_VALS({&ip_len, ip}, {&port_len, port})) != 0) {
return -1;
}
return bytes;
}
int nina_socket_setsockopt(int fd, uint32_t level, uint32_t opt, const void *optval, uint32_t optlen) {
return -1;
}
#endif // MICROPY_PY_NINAW10

View File

@ -0,0 +1,120 @@
/*
* This file is part of the OpenMV project, https://openmv.io.
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
* Copyright (c) 2013-2021 Kwabena W. Agyeman <kwagyeman@openmv.io>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* NINA-W10 WiFi driver.
*/
#ifndef MICROPY_INCLUDED_DRIVERS_NINAW10_NINA_WIFI_DRV_H
#define MICROPY_INCLUDED_DRIVERS_NINAW10_NINA_WIFI_DRV_H
#define NINA_FW_VER_LEN (6)
#define NINA_IPV4_ADDR_LEN (4)
#define NINA_MAC_ADDR_LEN (6)
#define NINA_MAX_SSID_LEN (32)
#define NINA_MAX_WEP_LEN (13)
#define NINA_MAX_WPA_LEN (63)
#define NINA_MAX_NETWORK_LIST (10)
#define NINA_MAX_SOCKET (10)
#define NINA_FW_VER_MAJOR (1)
#define NINA_FW_VER_MINOR (4)
#define NINA_FW_VER_PATCH (8)
#define NINA_FW_VER_MAJOR_OFFS (0)
#define NINA_FW_VER_MINOR_OFFS (2)
#define NINA_FW_VER_PATCH_OFFS (4)
typedef enum {
NINA_SEC_INVALID = 0,
NINA_SEC_OPEN,
NINA_SEC_WPA_PSK,
NINA_SEC_WEP
} nina_security_t;
typedef enum {
NINA_SOCKET_TYPE_TCP = 0,
NINA_SOCKET_TYPE_UDP,
NINA_SOCKET_TYPE_TLS,
NINA_SOCKET_TYPE_UDP_MULTICAST,
NINA_SOCKET_TYPE_TLS_BEARSSL
} nina_socket_type_t;
typedef enum {
NINA_ERROR_IO = -1,
NINA_ERROR_TIMEOUT = -2,
} nina_error_t;
typedef struct {
uint8_t ip_addr[NINA_IPV4_ADDR_LEN];
uint8_t subnet_addr[NINA_IPV4_ADDR_LEN];
uint8_t gateway_addr[NINA_IPV4_ADDR_LEN];
uint8_t dns_addr[NINA_IPV4_ADDR_LEN];
} nina_ifconfig_t;
typedef struct {
int32_t rssi;
uint8_t security;
uint8_t channel;
uint8_t bssid[NINA_MAC_ADDR_LEN];
char ssid[NINA_MAX_SSID_LEN];
} nina_scan_result_t;
typedef struct {
int32_t rssi;
uint8_t security;
char ssid[NINA_MAX_SSID_LEN];
uint8_t bssid[NINA_MAC_ADDR_LEN];
} nina_netinfo_t;
typedef int (*nina_scan_callback_t)(nina_scan_result_t *, void *);
int nina_init(void);
int nina_deinit(void);
int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel);
int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t channel);
int nina_disconnect(void);
int nina_isconnected(void);
int nina_connected_sta(uint32_t *sta_ip);
int nina_wait_for_sta(uint32_t *sta_ip, uint32_t timeout);
int nina_ifconfig(nina_ifconfig_t *ifconfig, bool set);
int nina_netinfo(nina_netinfo_t *netinfo);
int nina_scan(nina_scan_callback_t scan_callback, void *arg, uint32_t timeout);
int nina_get_rssi(void);
int nina_fw_version(uint8_t *fw_ver);
int nina_set_hostname(const char *name);
int nina_gethostbyname(const char *name, uint8_t *out_ip);
int nina_socket_socket(uint8_t type);
int nina_socket_close(int fd);
int nina_socket_bind(int fd, uint8_t *ip, uint16_t port, int type);
int nina_socket_listen(int fd, uint32_t backlog);
int nina_socket_accept(int fd, uint8_t *ip, uint16_t *port, int *fd_out, uint32_t timeout);
int nina_socket_connect(int fd, uint8_t *ip, uint16_t port, uint32_t timeout);
int nina_socket_send(int fd, const uint8_t *buf, uint32_t len, uint32_t timeout);
int nina_socket_recv(int fd, uint8_t *buf, uint32_t len, uint32_t timeout);
int nina_socket_sendto(int fd, const uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t port, uint32_t timeout);
int nina_socket_recvfrom(int fd, uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t *port, uint32_t timeout);
int nina_socket_setsockopt(int fd, uint32_t level, uint32_t opt, const void *optval, uint32_t optlen);
#endif // MICROPY_INCLUDED_DRIVERS_NINAW10_NINA_WIFI_DRV_H

View File

@ -45,7 +45,6 @@
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
#define MICROPY_STREAMS_NON_BLOCK (0) #define MICROPY_STREAMS_NON_BLOCK (0)
#define MICROPY_OPT_COMPUTED_GOTO (0) #define MICROPY_OPT_COMPUTED_GOTO (0)
#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0)
#define MICROPY_CAN_OVERRIDE_BUILTINS (0) #define MICROPY_CAN_OVERRIDE_BUILTINS (0)
#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0)
#define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_CPYTHON_COMPAT (0)

View File

@ -1265,13 +1265,13 @@ int mp_bluetooth_gap_scan_stop(void) {
return 0; return 0;
} }
int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms) { int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms, int32_t min_conn_interval_us, int32_t max_conn_interval_us) {
DEBUG_printf("mp_bluetooth_gap_peripheral_connect\n"); DEBUG_printf("mp_bluetooth_gap_peripheral_connect\n");
uint16_t conn_scan_interval = 60000 / 625; uint16_t conn_scan_interval = 60000 / 625;
uint16_t conn_scan_window = 30000 / 625; uint16_t conn_scan_window = 30000 / 625;
uint16_t conn_interval_min = 10000 / 1250; uint16_t conn_interval_min = (min_conn_interval_us ? min_conn_interval_us : 10000) / 1250;
uint16_t conn_interval_max = 30000 / 1250; uint16_t conn_interval_max = (max_conn_interval_us ? max_conn_interval_us : 30000) / 1250;
uint16_t conn_latency = 4; uint16_t conn_latency = 4;
uint16_t supervision_timeout = duration_ms / 10; // default = 720 uint16_t supervision_timeout = duration_ms / 10; // default = 720
uint16_t min_ce_length = 10000 / 625; uint16_t min_ce_length = 10000 / 625;
@ -1284,6 +1284,11 @@ int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr,
return btstack_error_to_errno(gap_connect(btstack_addr, addr_type)); return btstack_error_to_errno(gap_connect(btstack_addr, addr_type));
} }
int mp_bluetooth_gap_peripheral_connect_cancel(void) {
DEBUG_printf("mp_bluetooth_gap_peripheral_connect_cancel\n");
return btstack_error_to_errno(gap_connect_cancel());
}
#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT

View File

@ -10,11 +10,13 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_EXTMOD_DIR}/machine_i2c.c ${MICROPY_EXTMOD_DIR}/machine_i2c.c
${MICROPY_EXTMOD_DIR}/machine_mem.c ${MICROPY_EXTMOD_DIR}/machine_mem.c
${MICROPY_EXTMOD_DIR}/machine_pulse.c ${MICROPY_EXTMOD_DIR}/machine_pulse.c
${MICROPY_EXTMOD_DIR}/machine_pwm.c
${MICROPY_EXTMOD_DIR}/machine_signal.c ${MICROPY_EXTMOD_DIR}/machine_signal.c
${MICROPY_EXTMOD_DIR}/machine_spi.c ${MICROPY_EXTMOD_DIR}/machine_spi.c
${MICROPY_EXTMOD_DIR}/modbluetooth.c ${MICROPY_EXTMOD_DIR}/modbluetooth.c
${MICROPY_EXTMOD_DIR}/modbtree.c ${MICROPY_EXTMOD_DIR}/modbtree.c
${MICROPY_EXTMOD_DIR}/modframebuf.c ${MICROPY_EXTMOD_DIR}/modframebuf.c
${MICROPY_EXTMOD_DIR}/modnetwork.c
${MICROPY_EXTMOD_DIR}/modonewire.c ${MICROPY_EXTMOD_DIR}/modonewire.c
${MICROPY_EXTMOD_DIR}/moduasyncio.c ${MICROPY_EXTMOD_DIR}/moduasyncio.c
${MICROPY_EXTMOD_DIR}/modubinascii.c ${MICROPY_EXTMOD_DIR}/modubinascii.c
@ -23,9 +25,11 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_EXTMOD_DIR}/moduhashlib.c ${MICROPY_EXTMOD_DIR}/moduhashlib.c
${MICROPY_EXTMOD_DIR}/moduheapq.c ${MICROPY_EXTMOD_DIR}/moduheapq.c
${MICROPY_EXTMOD_DIR}/modujson.c ${MICROPY_EXTMOD_DIR}/modujson.c
${MICROPY_EXTMOD_DIR}/moduplatform.c
${MICROPY_EXTMOD_DIR}/modurandom.c ${MICROPY_EXTMOD_DIR}/modurandom.c
${MICROPY_EXTMOD_DIR}/modure.c ${MICROPY_EXTMOD_DIR}/modure.c
${MICROPY_EXTMOD_DIR}/moduselect.c ${MICROPY_EXTMOD_DIR}/moduselect.c
${MICROPY_EXTMOD_DIR}/modusocket.c
${MICROPY_EXTMOD_DIR}/modussl_axtls.c ${MICROPY_EXTMOD_DIR}/modussl_axtls.c
${MICROPY_EXTMOD_DIR}/modussl_mbedtls.c ${MICROPY_EXTMOD_DIR}/modussl_mbedtls.c
${MICROPY_EXTMOD_DIR}/modutimeq.c ${MICROPY_EXTMOD_DIR}/modutimeq.c

View File

@ -33,7 +33,7 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "extmod/machine_i2c.h" #include "extmod/machine_i2c.h"
#if MICROPY_PY_MACHINE_I2C #if MICROPY_PY_MACHINE_SOFTI2C
typedef mp_machine_soft_i2c_obj_t machine_i2c_obj_t; typedef mp_machine_soft_i2c_obj_t machine_i2c_obj_t;
@ -240,9 +240,13 @@ int mp_machine_soft_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t n
return transfer_ret; return transfer_ret;
} }
#endif // MICROPY_PY_MACHINE_SOFTI2C
/******************************************************************************/ /******************************************************************************/
// Generic helper functions // Generic helper functions
#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C
// For use by ports that require a single buffer of data for a read/write transfer // For use by ports that require a single buffer of data for a read/write transfer
int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) { int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) {
size_t len; size_t len;
@ -628,9 +632,13 @@ STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = {
}; };
MP_DEFINE_CONST_DICT(mp_machine_i2c_locals_dict, machine_i2c_locals_dict_table); MP_DEFINE_CONST_DICT(mp_machine_i2c_locals_dict, machine_i2c_locals_dict_table);
#endif // MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C
/******************************************************************************/ /******************************************************************************/
// Implementation of soft I2C // Implementation of soft I2C
#if MICROPY_PY_MACHINE_SOFTI2C
STATIC void mp_machine_soft_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void mp_machine_soft_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_machine_soft_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_machine_soft_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "SoftI2C(scl=" MP_HAL_PIN_FMT ", sda=" MP_HAL_PIN_FMT ", freq=%u)", mp_printf(print, "SoftI2C(scl=" MP_HAL_PIN_FMT ", sda=" MP_HAL_PIN_FMT ", freq=%u)",
@ -711,4 +719,4 @@ const mp_obj_type_t mp_machine_soft_i2c_type = {
.locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict, .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict,
}; };
#endif // MICROPY_PY_MACHINE_I2C #endif // MICROPY_PY_MACHINE_SOFTI2C

143
extmod/machine_pwm.c Normal file
View File

@ -0,0 +1,143 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020-2021 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#if MICROPY_PY_MACHINE_PWM
#include "extmod/machine_pwm.h"
#ifdef MICROPY_PY_MACHINE_PWM_INCLUDEFILE
#include MICROPY_PY_MACHINE_PWM_INCLUDEFILE
#endif
#if MICROPY_PY_MACHINE_PWM_INIT
STATIC mp_obj_t machine_pwm_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_machine_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pwm_init_obj, 1, machine_pwm_init);
#endif
// PWM.deinit()
STATIC mp_obj_t machine_pwm_deinit(mp_obj_t self_in) {
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_machine_pwm_deinit(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pwm_deinit_obj, machine_pwm_deinit);
// PWM.freq([value])
STATIC mp_obj_t machine_pwm_freq(size_t n_args, const mp_obj_t *args) {
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (n_args == 1) {
// Get frequency.
return mp_machine_pwm_freq_get(self);
} else {
// Set the frequency.
mp_int_t freq = mp_obj_get_int(args[1]);
mp_machine_pwm_freq_set(self, freq);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_freq_obj, 1, 2, machine_pwm_freq);
#if MICROPY_PY_MACHINE_PWM_DUTY
// PWM.duty([duty])
STATIC mp_obj_t machine_pwm_duty(size_t n_args, const mp_obj_t *args) {
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (n_args == 1) {
// Get duty cycle.
return mp_machine_pwm_duty_get(self);
} else {
// Set duty cycle.
mp_int_t duty = mp_obj_get_int(args[1]);
mp_machine_pwm_duty_set(self, duty);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_duty_obj, 1, 2, machine_pwm_duty);
#endif
#if MICROPY_PY_MACHINE_PWM_DUTY_U16_NS
// PWM.duty_u16([value])
STATIC mp_obj_t machine_pwm_duty_u16(size_t n_args, const mp_obj_t *args) {
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (n_args == 1) {
// Get duty cycle.
return mp_machine_pwm_duty_get_u16(self);
} else {
// Set duty cycle.
mp_int_t duty_u16 = mp_obj_get_int(args[1]);
mp_machine_pwm_duty_set_u16(self, duty_u16);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_duty_u16_obj, 1, 2, machine_pwm_duty_u16);
// PWM.duty_ns([value])
STATIC mp_obj_t machine_pwm_duty_ns(size_t n_args, const mp_obj_t *args) {
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (n_args == 1) {
// Get duty cycle.
return mp_machine_pwm_duty_get_ns(self);
} else {
// Set duty cycle.
mp_int_t duty_ns = mp_obj_get_int(args[1]);
mp_machine_pwm_duty_set_ns(self, duty_ns);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_duty_ns_obj, 1, 2, machine_pwm_duty_ns);
#endif
STATIC const mp_rom_map_elem_t machine_pwm_locals_dict_table[] = {
#if MICROPY_PY_MACHINE_PWM_INIT
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pwm_init_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_pwm_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_pwm_freq_obj) },
#if MICROPY_PY_MACHINE_PWM_DUTY
{ MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&machine_pwm_duty_obj) },
#endif
#if MICROPY_PY_MACHINE_PWM_DUTY_U16_NS
{ MP_ROM_QSTR(MP_QSTR_duty_u16), MP_ROM_PTR(&machine_pwm_duty_u16_obj) },
{ MP_ROM_QSTR(MP_QSTR_duty_ns), MP_ROM_PTR(&machine_pwm_duty_ns_obj) },
#endif
};
STATIC MP_DEFINE_CONST_DICT(machine_pwm_locals_dict, machine_pwm_locals_dict_table);
const mp_obj_type_t machine_pwm_type = {
{ &mp_type_type },
.name = MP_QSTR_PWM,
.print = mp_machine_pwm_print,
.make_new = mp_machine_pwm_make_new,
.locals_dict = (mp_obj_dict_t *)&machine_pwm_locals_dict,
};
#endif // MICROPY_PY_MACHINE_PWM

55
extmod/machine_pwm.h Normal file
View File

@ -0,0 +1,55 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PWM_H
#define MICROPY_INCLUDED_EXTMOD_MACHINE_PWM_H
#include "py/obj.h"
// A port must provide this type, but it's otherwise opaque.
typedef struct _machine_pwm_obj_t machine_pwm_obj_t;
// This PWM class is implemented by machine_pwm.c.
extern const mp_obj_type_t machine_pwm_type;
// A port must provide implementations of these low-level PWM functions, either as global
// linker symbols, or included directly if MICROPY_PY_MACHINE_PWM_INCLUDEFILE is defined.
#ifndef MICROPY_PY_MACHINE_PWM_INCLUDEFILE
void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
void mp_machine_pwm_deinit(machine_pwm_obj_t *self);
mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self);
void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq);
mp_obj_t mp_machine_pwm_duty_get(machine_pwm_obj_t *self);
void mp_machine_pwm_duty_set(machine_pwm_obj_t *self, mp_int_t duty);
mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self);
void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16);
mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self);
void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns);
#endif
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_PWM_H

View File

@ -30,8 +30,6 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "extmod/machine_spi.h" #include "extmod/machine_spi.h"
#if MICROPY_PY_MACHINE_SPI
// if a port didn't define MSB/LSB constants then provide them // if a port didn't define MSB/LSB constants then provide them
#ifndef MICROPY_PY_MACHINE_SPI_MSB #ifndef MICROPY_PY_MACHINE_SPI_MSB
#define MICROPY_PY_MACHINE_SPI_MSB (0) #define MICROPY_PY_MACHINE_SPI_MSB (0)
@ -41,6 +39,8 @@
/******************************************************************************/ /******************************************************************************/
// MicroPython bindings for generic machine.SPI // MicroPython bindings for generic machine.SPI
#if MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI
STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]); mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)s->type->protocol; mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)s->type->protocol;
@ -115,12 +115,15 @@ STATIC const mp_rom_map_elem_t machine_spi_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_MSB) }, { MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_MSB) },
{ MP_ROM_QSTR(MP_QSTR_LSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_LSB) }, { MP_ROM_QSTR(MP_QSTR_LSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_LSB) },
}; };
MP_DEFINE_CONST_DICT(mp_machine_spi_locals_dict, machine_spi_locals_dict_table); MP_DEFINE_CONST_DICT(mp_machine_spi_locals_dict, machine_spi_locals_dict_table);
#endif // MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI
/******************************************************************************/ /******************************************************************************/
// Implementation of soft SPI // Implementation of soft SPI
#if MICROPY_PY_MACHINE_SOFTSPI
STATIC uint32_t baudrate_from_delay_half(uint32_t delay_half) { STATIC uint32_t baudrate_from_delay_half(uint32_t delay_half) {
#ifdef MICROPY_HW_SOFTSPI_MIN_DELAY #ifdef MICROPY_HW_SOFTSPI_MIN_DELAY
if (delay_half == MICROPY_HW_SOFTSPI_MIN_DELAY) { if (delay_half == MICROPY_HW_SOFTSPI_MIN_DELAY) {
@ -258,4 +261,4 @@ const mp_obj_type_t mp_machine_soft_spi_type = {
.locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict, .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict,
}; };
#endif // MICROPY_PY_MACHINE_SPI #endif // MICROPY_PY_MACHINE_SOFTSPI

View File

@ -215,7 +215,9 @@ STATIC mp_int_t bluetooth_uuid_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bu
return 0; return 0;
} }
#if !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS && MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE #if !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS
#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
STATIC void ringbuf_put_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid) { STATIC void ringbuf_put_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid) {
assert(ringbuf_free(ringbuf) >= (size_t)uuid->type + 1); assert(ringbuf_free(ringbuf) >= (size_t)uuid->type + 1);
ringbuf_put(ringbuf, uuid->type); ringbuf_put(ringbuf, uuid->type);
@ -223,7 +225,9 @@ STATIC void ringbuf_put_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid)
ringbuf_put(ringbuf, uuid->data[i]); ringbuf_put(ringbuf, uuid->data[i]);
} }
} }
#endif
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
STATIC void ringbuf_get_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid) { STATIC void ringbuf_get_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid) {
assert(ringbuf_avail(ringbuf) >= 1); assert(ringbuf_avail(ringbuf) >= 1);
uuid->type = ringbuf_get(ringbuf); uuid->type = ringbuf_get(ringbuf);
@ -232,7 +236,9 @@ STATIC void ringbuf_get_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid)
uuid->data[i] = ringbuf_get(ringbuf); uuid->data[i] = ringbuf_get(ringbuf);
} }
} }
#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE #endif
#endif // !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS
const mp_obj_type_t mp_type_bluetooth_uuid = { const mp_obj_type_t mp_type_bluetooth_uuid = {
{ &mp_type_type }, { &mp_type_type },
@ -630,6 +636,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_gatts_register_services_obj, blue
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
STATIC mp_obj_t bluetooth_ble_gap_connect(size_t n_args, const mp_obj_t *args) { STATIC mp_obj_t bluetooth_ble_gap_connect(size_t n_args, const mp_obj_t *args) {
if (n_args == 2) {
if (args[1] == mp_const_none) {
int err = mp_bluetooth_gap_peripheral_connect_cancel();
return bluetooth_handle_errno(err);
}
mp_raise_TypeError(MP_ERROR_TEXT("invalid addr"));
}
uint8_t addr_type = mp_obj_get_int(args[1]); uint8_t addr_type = mp_obj_get_int(args[1]);
mp_buffer_info_t bufinfo = {0}; mp_buffer_info_t bufinfo = {0};
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
@ -637,14 +650,22 @@ STATIC mp_obj_t bluetooth_ble_gap_connect(size_t n_args, const mp_obj_t *args) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid addr")); mp_raise_ValueError(MP_ERROR_TEXT("invalid addr"));
} }
mp_int_t scan_duration_ms = MP_BLUETOOTH_CONNECT_DEFAULT_SCAN_DURATION_MS; mp_int_t scan_duration_ms = MP_BLUETOOTH_CONNECT_DEFAULT_SCAN_DURATION_MS;
if (n_args == 4) { mp_int_t min_conn_interval_us = 0;
mp_int_t max_conn_interval_us = 0;
if (n_args >= 4 && args[3] != mp_const_none) {
scan_duration_ms = mp_obj_get_int(args[3]); scan_duration_ms = mp_obj_get_int(args[3]);
} }
if (n_args >= 5 && args[4] != mp_const_none) {
min_conn_interval_us = mp_obj_get_int(args[4]);
}
if (n_args >= 6 && args[5] != mp_const_none) {
max_conn_interval_us = mp_obj_get_int(args[5]);
}
int err = mp_bluetooth_gap_peripheral_connect(addr_type, bufinfo.buf, scan_duration_ms); int err = mp_bluetooth_gap_peripheral_connect(addr_type, bufinfo.buf, scan_duration_ms, min_conn_interval_us, max_conn_interval_us);
return bluetooth_handle_errno(err); return bluetooth_handle_errno(err);
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_connect_obj, 3, 4, bluetooth_ble_gap_connect); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_connect_obj, 2, 6, bluetooth_ble_gap_connect);
STATIC mp_obj_t bluetooth_ble_gap_scan(size_t n_args, const mp_obj_t *args) { STATIC mp_obj_t bluetooth_ble_gap_scan(size_t n_args, const mp_obj_t *args) {
// Default is indefinite scan, with the NimBLE "background scan" interval and window. // Default is indefinite scan, with the NimBLE "background scan" interval and window.

View File

@ -370,10 +370,14 @@ int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_
int mp_bluetooth_gap_scan_stop(void); int mp_bluetooth_gap_scan_stop(void);
// Connect to a found peripheral. // Connect to a found peripheral.
int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms); int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms, int32_t min_conn_interval_us, int32_t max_conn_interval_us);
// Cancel in-progress connection to a peripheral.
int mp_bluetooth_gap_peripheral_connect_cancel(void);
#endif #endif
#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
// Find all primary services on the connected peripheral. // Find all primary services on the connected peripheral.
int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle, const mp_obj_bluetooth_uuid_t *uuid); int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle, const mp_obj_bluetooth_uuid_t *uuid);

View File

@ -32,55 +32,16 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "shared/netutils/netutils.h" #include "shared/netutils/netutils.h"
#include "systick.h"
#include "pendsv.h"
#include "modnetwork.h" #include "modnetwork.h"
#if MICROPY_PY_NETWORK #if MICROPY_PY_NETWORK
#if MICROPY_PY_LWIP #if MICROPY_PY_LWIP
#include "lwip/netif.h" #include "lwip/netif.h"
#include "lwip/timeouts.h" #include "lwip/timeouts.h"
#include "lwip/dns.h" #include "lwip/dns.h"
#include "lwip/dhcp.h" #include "lwip/dhcp.h"
#include "lwip/apps/mdns.h" #include "lwip/apps/mdns.h"
#include "extmod/network_cyw43.h"
#include "drivers/cyw43/cyw43.h"
// Poll lwIP every 128ms
#define LWIP_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & 0x7f) == 0)
u32_t sys_now(void) {
return mp_hal_ticks_ms();
}
STATIC void pyb_lwip_poll(void) {
#if MICROPY_PY_WIZNET5K
// Poll the NIC for incoming data
wiznet5k_poll();
#endif
// Run the lwIP internal updates
sys_check_timeouts();
}
void mod_network_lwip_poll_wrapper(uint32_t ticks_ms) {
if (LWIP_TICK(ticks_ms)) {
pendsv_schedule_dispatch(PENDSV_DISPATCH_LWIP, pyb_lwip_poll);
}
#if MICROPY_PY_NETWORK_CYW43
if (cyw43_poll) {
if (cyw43_sleep != 0) {
if (--cyw43_sleep == 0) {
pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll);
}
}
}
#endif
}
#endif #endif
/// \module network - network configuration /// \module network - network configuration
@ -124,28 +85,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route);
STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) }, { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) },
#if defined(MICROPY_HW_ETH_MDC)
{ MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&network_lan_type) },
#endif
#if MICROPY_PY_NETWORK_CYW43
{ MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mp_network_cyw43_type) },
#endif
#if MICROPY_PY_WIZNET5K
{ MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) },
#endif
#if MICROPY_PY_CC3K
{ MP_ROM_QSTR(MP_QSTR_CC3K), MP_ROM_PTR(&mod_network_nic_type_cc3k) },
#endif
{ MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) }, { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) },
// Defined per port in mpconfigport.h
MICROPY_PORT_NETWORK_INTERFACES
// Constants // Constants
#if MICROPY_PY_NETWORK_CYW43 { MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(MOD_NETWORK_STA_IF) },
{ MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(CYW43_ITF_STA)}, { MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(MOD_NETWORK_AP_IF) },
{ MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(CYW43_ITF_AP)},
#endif
}; };
STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table); STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);

View File

@ -23,8 +23,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_STM32_MODNETWORK_H #ifndef MICROPY_INCLUDED_MODNETWORK_H
#define MICROPY_INCLUDED_STM32_MODNETWORK_H #define MICROPY_INCLUDED_MODNETWORK_H
#define MOD_NETWORK_IPADDR_BUF_SIZE (4) #define MOD_NETWORK_IPADDR_BUF_SIZE (4)
@ -35,18 +35,13 @@
#define MOD_NETWORK_SOCK_DGRAM (2) #define MOD_NETWORK_SOCK_DGRAM (2)
#define MOD_NETWORK_SOCK_RAW (3) #define MOD_NETWORK_SOCK_RAW (3)
#define MOD_NETWORK_STA_IF (0)
#define MOD_NETWORK_AP_IF (1)
#if MICROPY_PY_LWIP #if MICROPY_PY_LWIP
struct netif; struct netif;
extern const mp_obj_type_t network_lan_type;
extern const mp_obj_type_t mod_network_nic_type_wiznet5k;
void mod_network_lwip_poll_wrapper(uint32_t ticks_ms); void mod_network_lwip_poll_wrapper(uint32_t ticks_ms);
mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args); mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args);
void wiznet5k_poll(void);
#else #else
struct _mod_network_socket_obj_t; struct _mod_network_socket_obj_t;
@ -77,24 +72,23 @@ typedef struct _mod_network_socket_obj_t {
mp_obj_base_t base; mp_obj_base_t base;
mp_obj_t nic; mp_obj_t nic;
mod_network_nic_type_t *nic_type; mod_network_nic_type_t *nic_type;
union { uint32_t domain : 5;
struct { uint32_t type : 5;
uint8_t domain; uint32_t proto : 5;
uint8_t type; uint32_t bound : 1;
int8_t fileno; int32_t fileno : 16;
} u_param; #if MICROPY_PY_USOCKET_EXTENDED_STATE
mp_uint_t u_state; // Extended socket state for NICs/ports that need it.
}; int32_t timeout;
void *state;
#endif
} mod_network_socket_obj_t; } mod_network_socket_obj_t;
extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k; #endif // MICROPY_PY_LWIP
extern const mod_network_nic_type_t mod_network_nic_type_cc3k;
#endif
void mod_network_init(void); void mod_network_init(void);
void mod_network_deinit(void); void mod_network_deinit(void);
void mod_network_register_nic(mp_obj_t nic); void mod_network_register_nic(mp_obj_t nic);
mp_obj_t mod_network_find_nic(const uint8_t *ip); mp_obj_t mod_network_find_nic(const uint8_t *ip);
#endif // MICROPY_INCLUDED_STM32_MODNETWORK_H #endif // MICROPY_INCLUDED_MODNETWORK_H

View File

@ -30,6 +30,8 @@
#include "py/obj.h" #include "py/obj.h"
#include "py/mphal.h" #include "py/mphal.h"
#if MICROPY_PY_ONEWIRE
/******************************************************************************/ /******************************************************************************/
// Low-level 1-Wire routines // Low-level 1-Wire routines
@ -160,3 +162,5 @@ const mp_obj_module_t mp_module_onewire = {
.base = { &mp_type_module }, .base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&onewire_module_globals, .globals = (mp_obj_dict_t *)&onewire_module_globals,
}; };
#endif // MICROPY_PY_ONEWIRE

146
extmod/moduplatform.c Normal file
View File

@ -0,0 +1,146 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "py/runtime.h"
#include "py/objtuple.h"
#include "py/objstr.h"
#include "py/mphal.h"
#include "genhdr/mpversion.h"
#if MICROPY_PY_UPLATFORM
// platform - Access to underlying platform's identifying data
// TODO: Add more architectures, compilers and libraries.
// See: https://sourceforge.net/p/predef/wiki/Home/
#if defined(__ARM_ARCH)
#define PLATFORM_ARCH "arm"
#elif defined(__x86_64__) || defined(_WIN64)
#define PLATFORM_ARCH "x86_64"
#elif defined(__i386__) || defined(_M_IX86)
#define PLATFORM_ARCH "x86"
#elif defined(__xtensa__) || defined(_M_IX86)
#define PLATFORM_ARCH "xtensa"
#else
#define PLATFORM_ARCH ""
#endif
#if defined(__GNUC__)
#define PLATFORM_COMPILER \
"GCC " \
MP_STRINGIFY(__GNUC__) "." \
MP_STRINGIFY(__GNUC_MINOR__) "." \
MP_STRINGIFY(__GNUC_PATCHLEVEL__)
#elif defined(__ARMCC_VERSION)
#define PLATFORM_COMPILER \
"ARMCC " \
MP_STRINGIFY((__ARMCC_VERSION / 1000000)) "." \
MP_STRINGIFY((__ARMCC_VERSION / 10000 % 100)) "." \
MP_STRINGIFY((__ARMCC_VERSION % 10000))
#elif defined(_MSC_VER)
#if defined(_WIN64)
#define COMPILER_BITS "64 bit"
#elif defined(_M_IX86)
#define COMPILER_BITS "32 bit"
#else
#define COMPILER_BITS ""
#endif
#define PLATFORM_COMPILER \
"MSC v." MP_STRINGIFY(_MSC_VER) " " COMPILER_BITS
#else
#define PLATFORM_COMPILER ""
#endif
#if defined(__GLIBC__)
#define PLATFORM_LIBC_LIB "glibc"
#define PLATFORM_LIBC_VER \
MP_STRINGIFY(__GLIBC__) "." \
MP_STRINGIFY(__GLIBC_MINOR__)
#elif defined(__NEWLIB__)
#define PLATFORM_LIBC_LIB "newlib"
#define PLATFORM_LIBC_VER _NEWLIB_VERSION
#else
#define PLATFORM_LIBC_LIB ""
#define PLATFORM_LIBC_VER ""
#endif
#if defined(__linux)
#define PLATFORM_SYSTEM "Linux"
#elif defined(__unix__)
#define PLATFORM_SYSTEM "Unix"
#elif defined(__CYGWIN__)
#define PLATFORM_SYSTEM "Cygwin"
#elif defined(_WIN32)
#define PLATFORM_SYSTEM "Windows"
#else
#define PLATFORM_SYSTEM "MicroPython"
#endif
#ifndef MICROPY_PLATFORM_VERSION
#define MICROPY_PLATFORM_VERSION ""
#endif
STATIC const MP_DEFINE_STR_OBJ(info_platform_obj, PLATFORM_SYSTEM "-" MICROPY_VERSION_STRING "-" \
PLATFORM_ARCH "-" MICROPY_PLATFORM_VERSION "-with-" PLATFORM_LIBC_LIB "" PLATFORM_LIBC_VER);
STATIC const MP_DEFINE_STR_OBJ(info_python_compiler_obj, PLATFORM_COMPILER);
STATIC const MP_DEFINE_STR_OBJ(info_libc_lib_obj, PLATFORM_LIBC_LIB);
STATIC const MP_DEFINE_STR_OBJ(info_libc_ver_obj, PLATFORM_LIBC_VER);
STATIC const mp_rom_obj_tuple_t info_libc_tuple_obj = {
{&mp_type_tuple}, 2, {MP_ROM_PTR(&info_libc_lib_obj), MP_ROM_PTR(&info_libc_ver_obj)}
};
STATIC mp_obj_t platform_platform(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
return MP_OBJ_FROM_PTR(&info_platform_obj);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(platform_platform_obj, 0, platform_platform);
STATIC mp_obj_t platform_python_compiler(void) {
return MP_OBJ_FROM_PTR(&info_python_compiler_obj);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(platform_python_compiler_obj, platform_python_compiler);
STATIC mp_obj_t platform_libc_ver(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
return MP_OBJ_FROM_PTR(&info_libc_tuple_obj);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(platform_libc_ver_obj, 0, platform_libc_ver);
STATIC const mp_rom_map_elem_t modplatform_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uplatform) },
{ MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_platform_obj) },
{ MP_ROM_QSTR(MP_QSTR_python_compiler), MP_ROM_PTR(&platform_python_compiler_obj) },
{ MP_ROM_QSTR(MP_QSTR_libc_ver), MP_ROM_PTR(&platform_libc_ver_obj) },
};
STATIC MP_DEFINE_CONST_DICT(modplatform_globals, modplatform_globals_table);
const mp_obj_module_t mp_module_uplatform = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&modplatform_globals,
};
#endif // MICROPY_PY_UPLATFORM

View File

@ -454,11 +454,16 @@ const mp_obj_module_t mp_module_ure = {
// only if module is enabled by config setting. // only if module is enabled by config setting.
#define re1_5_fatal(x) assert(!x) #define re1_5_fatal(x) assert(!x)
#include "lib/re1.5/compilecode.c" #include "lib/re1.5/compilecode.c"
#if MICROPY_PY_URE_DEBUG
#include "lib/re1.5/dumpcode.c"
#endif
#include "lib/re1.5/recursiveloop.c" #include "lib/re1.5/recursiveloop.c"
#include "lib/re1.5/charclass.c" #include "lib/re1.5/charclass.c"
#if MICROPY_PY_URE_DEBUG
// Make sure the output print statements go to the same output as other Python output.
#define printf(...) mp_printf(&mp_plat_print, __VA_ARGS__)
#include "lib/re1.5/dumpcode.c"
#undef printf
#endif
#endif // MICROPY_PY_URE #endif // MICROPY_PY_URE

View File

@ -35,7 +35,7 @@
#include "shared/netutils/netutils.h" #include "shared/netutils/netutils.h"
#include "modnetwork.h" #include "modnetwork.h"
#if MICROPY_PY_USOCKET && !MICROPY_PY_LWIP #if MICROPY_PY_NETWORK && MICROPY_PY_USOCKET && !MICROPY_PY_LWIP
/******************************************************************************/ /******************************************************************************/
// socket class // socket class
@ -51,19 +51,26 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t
s->base.type = &socket_type; s->base.type = &socket_type;
s->nic = MP_OBJ_NULL; s->nic = MP_OBJ_NULL;
s->nic_type = NULL; s->nic_type = NULL;
s->u_param.domain = MOD_NETWORK_AF_INET; s->domain = MOD_NETWORK_AF_INET;
s->u_param.type = MOD_NETWORK_SOCK_STREAM; s->type = MOD_NETWORK_SOCK_STREAM;
s->u_param.fileno = -1; s->proto = 0;
s->bound = false;
s->fileno = -1;
if (n_args >= 1) { if (n_args >= 1) {
s->u_param.domain = mp_obj_get_int(args[0]); s->domain = mp_obj_get_int(args[0]);
if (n_args >= 2) { if (n_args >= 2) {
s->u_param.type = mp_obj_get_int(args[1]); s->type = mp_obj_get_int(args[1]);
if (n_args >= 4) { if (n_args >= 4) {
s->u_param.fileno = mp_obj_get_int(args[3]); s->fileno = mp_obj_get_int(args[3]);
} }
} }
} }
#if MICROPY_PY_USOCKET_EXTENDED_STATE
s->timeout = 0;
s->state = NULL;
#endif
return MP_OBJ_FROM_PTR(s); return MP_OBJ_FROM_PTR(s);
} }
@ -78,6 +85,13 @@ STATIC void socket_select_nic(mod_network_socket_obj_t *self, const byte *ip) {
if (self->nic_type->socket(self, &_errno) != 0) { if (self->nic_type->socket(self, &_errno) != 0) {
mp_raise_OSError(_errno); mp_raise_OSError(_errno);
} }
#if MICROPY_PY_USOCKET_EXTENDED_STATE
// if a timeout was set before binding a NIC, call settimeout to reset it
if (self->timeout != 0 && self->nic_type->settimeout(self, self->timeout, &_errno) != 0) {
mp_raise_OSError(_errno);
}
#endif
} }
} }
@ -137,6 +151,17 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
socket2->nic = MP_OBJ_NULL; socket2->nic = MP_OBJ_NULL;
socket2->nic_type = NULL; socket2->nic_type = NULL;
// set the same address family, socket type and protocol as parent
socket2->domain = self->domain;
socket2->type = self->type;
socket2->proto = self->proto;
socket2->bound = false;
socket2->fileno = -1;
#if MICROPY_PY_USOCKET_EXTENDED_STATE
socket2->timeout = 0;
socket2->state = NULL;
#endif
// accept incoming connection // accept incoming connection
uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE];
mp_uint_t port; mp_uint_t port;
@ -310,10 +335,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_s
// otherwise, timeout is in seconds // otherwise, timeout is in seconds
STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->nic == MP_OBJ_NULL) {
// not connected
mp_raise_OSError(MP_ENOTCONN);
}
mp_uint_t timeout; mp_uint_t timeout;
if (timeout_in == mp_const_none) { if (timeout_in == mp_const_none) {
timeout = -1; timeout = -1;
@ -324,9 +345,19 @@ STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
timeout = 1000 * mp_obj_get_int(timeout_in); timeout = 1000 * mp_obj_get_int(timeout_in);
#endif #endif
} }
int _errno; if (self->nic == MP_OBJ_NULL) {
if (self->nic_type->settimeout(self, timeout, &_errno) != 0) { #if MICROPY_PY_USOCKET_EXTENDED_STATE
mp_raise_OSError(_errno); // store the timeout in the socket state until a NIC is bound
self->timeout = timeout;
#else
// not connected
mp_raise_OSError(MP_ENOTCONN);
#endif
} else {
int _errno;
if (self->nic_type->settimeout(self, timeout, &_errno) != 0) {
mp_raise_OSError(_errno);
}
} }
return mp_const_none; return mp_const_none;
} }
@ -356,10 +387,41 @@ STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) },
{ MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) }, { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) },
{ MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
}; };
STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
mp_uint_t socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->nic == MP_OBJ_NULL) {
return MP_STREAM_ERROR;
}
mp_int_t ret = self->nic_type->recv(self, (byte *)buf, size, errcode);
if (ret < 0) {
ret = MP_STREAM_ERROR;
*errcode = -(*errcode); // expects a positive error code
}
return ret;
}
mp_uint_t socket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->nic == MP_OBJ_NULL) {
return MP_STREAM_ERROR;
}
mp_int_t ret = self->nic_type->send(self, buf, size, errcode);
if (ret < 0) {
ret = MP_STREAM_ERROR;
*errcode = -(*errcode); // expects a positive error code
}
return ret;
}
mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (request == MP_STREAM_CLOSE) { if (request == MP_STREAM_CLOSE) {
@ -380,6 +442,8 @@ mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *
} }
STATIC const mp_stream_p_t socket_stream_p = { STATIC const mp_stream_p_t socket_stream_p = {
.read = socket_read,
.write = socket_write,
.ioctl = socket_ioctl, .ioctl = socket_ioctl,
.is_text = false, .is_text = false,
}; };
@ -477,4 +541,4 @@ const mp_obj_module_t mp_module_usocket = {
.globals = (mp_obj_dict_t *)&mp_module_usocket_globals, .globals = (mp_obj_dict_t *)&mp_module_usocket_globals,
}; };
#endif // MICROPY_PY_USOCKET && !MICROPY_PY_LWIP #endif // MICROPY_PY_NETWORK && MICROPY_PY_USOCKET && !MICROPY_PY_LWIP

Some files were not shown because too many files have changed in this diff Show More