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:
commit
f61da15cc3
18
.github/workflows/ports.yml
vendored
Normal file
18
.github/workflows/ports.yml
vendored
Normal 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
|
||||||
4
.github/workflows/ports_esp32.yml
vendored
4
.github/workflows/ports_esp32.yml
vendored
@ -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
1
.gitignore
vendored
@ -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
3
.gitmodules
vendored
@ -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
|
||||||
|
|||||||
2
.gitpod
2
.gitpod
@ -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
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@ -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
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
@ -16,4 +16,3 @@ live in the main MicroPython repository.
|
|||||||
|
|
||||||
cmodules.rst
|
cmodules.rst
|
||||||
natmod.rst
|
natmod.rst
|
||||||
|
|
||||||
@ -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.
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
@ -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();
|
||||||
|
|||||||
@ -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``,
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
181
docs/differences/python_35.rst
Normal file
181
docs/differences/python_35.rst
Normal 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 | |
|
||||||
|
+-----------------------------------------------------------------------------------------------------------+---------------+
|
||||||
191
docs/differences/python_36.rst
Normal file
191
docs/differences/python_36.rst
Normal 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 | |
|
||||||
|
+--------------------------------------------------------------------------------------------------------------+----------------+
|
||||||
95
docs/differences/python_37.rst
Normal file
95
docs/differences/python_37.rst
Normal 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 | |
|
||||||
|
+------------------------------------------------------------------------------------------------------------+----------------+
|
||||||
118
docs/differences/python_38.rst
Normal file
118
docs/differences/python_38.rst
Normal 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 | |
|
||||||
|
+------------------------------------------------------------------------------------------------------------+-------------+
|
||||||
121
docs/differences/python_39.rst
Normal file
121
docs/differences/python_39.rst
Normal 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 | |
|
||||||
|
+---------------------------------------------------------------------------------------------------------------+---------------+
|
||||||
@ -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
|
||||||
|
|||||||
23
docs/esp32/tutorial/index.rst
Normal file
23
docs/esp32/tutorial/index.rst
Normal 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
|
||||||
@ -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:
|
||||||
|
|
||||||
|
|||||||
44
docs/esp32/tutorial/peripheral_access.rst
Normal file
44
docs/esp32/tutorial/peripheral_access.rst
Normal 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
115
docs/esp32/tutorial/pwm.rst
Normal 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)
|
||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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.
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|||||||
@ -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
|
||||||
------------
|
------------
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
@ -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.
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
-------
|
-------
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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.
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
82
docs/library/random.rst
Normal 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).
|
||||||
@ -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
104
docs/library/stm.rst
Normal 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.
|
||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
-----------
|
-----------
|
||||||
|
|||||||
@ -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% .
|
||||||
|
|||||||
@ -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)
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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:
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|||||||
@ -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
145
docs/reference/manifest.rst
Normal 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
196
docs/reference/mpremote.rst
Normal 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/ :
|
||||||
@ -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()
|
||||||
|
|||||||
@ -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``,
|
||||||
|
|||||||
@ -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:
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|||||||
@ -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
123
docs/rp2/tutorial/pio.rst
Normal 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.
|
||||||
@ -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`. ::
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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::
|
||||||
|
|||||||
@ -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::
|
||||||
|
|||||||
@ -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.
|
||||||
>>>
|
>>>
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
234
drivers/lsm6dsox/lsm6dsox.py
Normal file
234
drivers/lsm6dsox/lsm6dsox.py
Normal 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)
|
||||||
13
drivers/lsm6dsox/lsm6dsox_basic.py
Normal file
13
drivers/lsm6dsox/lsm6dsox_basic.py
Normal 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)
|
||||||
48
drivers/lsm6dsox/lsm6dsox_mlc.py
Normal file
48
drivers/lsm6dsox/lsm6dsox_mlc.py
Normal 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]])
|
||||||
@ -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
|
||||||
|
|||||||
39
drivers/ninaw10/nina_bsp.h
Normal file
39
drivers/ninaw10/nina_bsp.h
Normal 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
|
||||||
150
drivers/ninaw10/nina_bt_hci.c
Normal file
150
drivers/ninaw10/nina_bt_hci.c
Normal 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
|
||||||
139
drivers/ninaw10/nina_wifi_bsp.c
Normal file
139
drivers/ninaw10/nina_wifi_bsp.c
Normal 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
|
||||||
931
drivers/ninaw10/nina_wifi_drv.c
Normal file
931
drivers/ninaw10/nina_wifi_drv.c
Normal 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
|
||||||
120
drivers/ninaw10/nina_wifi_drv.h
Normal file
120
drivers/ninaw10/nina_wifi_drv.h
Normal 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
|
||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
143
extmod/machine_pwm.c
Normal 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
55
extmod/machine_pwm.h
Normal 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
|
||||||
@ -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
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
@ -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
|
||||||
@ -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
146
extmod/moduplatform.c
Normal 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
|
||||||
@ -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
|
||||||
|
|||||||
@ -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
Loading…
x
Reference in New Issue
Block a user