Merge tag 'v1.19.1' into update_micropython_v1.19

Bug fix for esp32 SoftI2C

This is a bug fix release.  The changes are:

- extmod/machine_i2c: only use WRITE1 option if transfer supports it

  This fixes the machine.SoftI2C.readfrom_mem() method on esp32, so it
  writes the address to read from.
This commit is contained in:
Amir Gonnen 2022-06-26 00:39:56 +03:00
commit 38c5106a9d
1260 changed files with 61660 additions and 11294 deletions

View File

@ -1,3 +1,15 @@
#all: Reformat remaining C code that doesn't have a space after a comma.
5b700b0af90591d6b1a2c087bb8de6b7f1bfdd2d
# ports: Reformat more C and Python source code.
5c32111fa0e31e451b0f1666bdf926be2fdfd82c
# all: Update Python formatting to latest Black version 22.1.0.
ab2923dfa1174dc177f0a90cb00a7e4ff87958d2
# all: Update Python formatting to latest Black version 21.12b0.
3770fab33449a5dadf8eb06edfae0767e75320a6
# tools/gen-cpydiff.py: Fix formatting of doc strings for new Black.
0f78c36c5aa458a954eed39a46942209107a553e

25
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,25 @@
---
name: Bug report
about: Report an issue
title: ''
labels: bug
assignees: ''
---
* Remove all placeholder text below before submitting.
* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, please see the MicroPython Forum -- https://forum.micropython.org/
* In your issue, please include a clear and concise description of what the bug is, the expected output, and how to replicate it.
* If this issue involves external hardware, please include links to relevant datasheets and schematics.
* If you are seeing code being executed incorrectly, please provide a minimal example and expected output (e.g. comparison to CPython).
* For build issues, please include full details of your environment, compiler versions, command lines, and build output.
* Please provide as much information as possible about the version of MicroPython you're running, such as:
- firmware file name
- git commit hash and port/board
- version information shown in the REPL (hit Ctrl-B to see the startup message)

11
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: MicroPython Forum
url: https://forum.micropython.org/
about: Community discussion about all things MicroPython. This is the best place to start if you have questions about using MicroPython or getting started with MicroPython development.
- name: MicroPython Documentation
url: https://docs.micropython.org/
about: Documentation for using and working with MicroPython and libraries.
- name: MicroPython Downloads
url: https://micropython.org/download/
about: Pre-built firmware and information for most supported boards.

16
.github/ISSUE_TEMPLATE/documentation.md vendored Normal file
View File

@ -0,0 +1,16 @@
---
name: Documentation issue
about: Report areas of the documentation or examples that need improvement
title: 'docs: '
labels: documentation
assignees: ''
---
* Remove all placeholder text below before submitting.
* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, please see the MicroPython Forum -- https://forum.micropython.org/
* Describe what was missing from the documentation and/or what was incorrect/incomplete.
* If possible, please link to the relevant page on https://docs.micropython.org/

View File

@ -0,0 +1,24 @@
---
name: Feature request
about: Request a feature or improvement
title: ''
labels: enhancement
assignees: ''
---
* Remove all placeholder text below before submitting.
* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, please see the MicroPython Forum -- https://forum.micropython.org/
* Describe the feature you'd like to see added to MicroPython. In particular, what does this feature enable and why is it useful. MicroPython aims to strike a balance between functionality and code size, so please consider whether this feature can be optionally enabled and whether it can be provided in other ways (e.g. pure-Python library).
* For core Python features, where possible please include a link to the relevant PEP.
* For new architectures / ports / boards, please provide links to relevant documentation, specifications, and toolchains. Any information about the popularity and unique features about this hardware would also be useful.
* For features for existing ports (e.g. new peripherals or microcontroller features), please describe which port(s) it applies too, and whether this is could be an extension to the machine API or a port-specific module?
* For drivers (e.g. for external hardware), please link to datasheets and/or existing drivers from other sources.
* Who do you expect will implement the feature you are requesting? Would you be willing to sponsor this work?

16
.github/ISSUE_TEMPLATE/security.md vendored Normal file
View File

@ -0,0 +1,16 @@
---
name: Security report
about: Report a security issue or vunerability in MicroPython
title: ''
labels: security
assignees: ''
---
* Remove all placeholder text before submitting the new issue.
* If you need to raise this issue privately with the MicroPython team, please email contact@micropython.org instead.
* Include a clear and concise description of what the security issue is.
* What does this issue allow an attacker to do?

View File

@ -1,18 +0,0 @@
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

230
.github/workflows/ports_unix.yml vendored Normal file
View File

@ -0,0 +1,230 @@
name: unix port
on:
push:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'lib/**'
- 'examples/**'
- 'ports/unix/**'
- 'tests/**'
jobs:
minimal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: source tools/ci.sh && ci_unix_minimal_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_minimal_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
reproducible:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build with reproducible date
run: source tools/ci.sh && ci_unix_minimal_build
env:
SOURCE_DATE_EPOCH: 1234567890
- name: Check reproducible build date
run: echo | ports/unix/micropython-minimal -i | grep 'on 2009-02-13;'
standard:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: source tools/ci.sh && ci_unix_standard_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_standard_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
dev:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: source tools/ci.sh && ci_unix_dev_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_dev_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install packages
run: source tools/ci.sh && ci_unix_coverage_setup
- name: Build
run: source tools/ci.sh && ci_unix_coverage_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_coverage_run_tests
- name: Test merging .mpy files
run: source tools/ci.sh && ci_unix_coverage_run_mpy_merge_tests
- name: Build native mpy modules
run: source tools/ci.sh && ci_native_mpy_modules_build
- name: Test importing .mpy generated by mpy_ld.py
run: source tools/ci.sh && ci_unix_coverage_run_native_mpy_tests
- name: Run gcov coverage analysis
run: |
(cd ports/unix && gcov -o build-coverage/py ../../py/*.c || true)
(cd ports/unix && gcov -o build-coverage/extmod ../../extmod/*.c || true)
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
fail_ci_if_error: true
verbose: true
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
coverage_32bit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install packages
run: source tools/ci.sh && ci_unix_32bit_setup
- name: Build
run: source tools/ci.sh && ci_unix_coverage_32bit_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_coverage_32bit_run_tests
- name: Build native mpy modules
run: source tools/ci.sh && ci_native_mpy_modules_32bit_build
- name: Test importing .mpy generated by mpy_ld.py
run: source tools/ci.sh && ci_unix_coverage_32bit_run_native_mpy_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
nanbox:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install packages
run: source tools/ci.sh && ci_unix_32bit_setup
- name: Build
run: source tools/ci.sh && ci_unix_nanbox_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_nanbox_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
float:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: source tools/ci.sh && ci_unix_float_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_float_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
stackless_clang:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Install packages
run: source tools/ci.sh && ci_unix_clang_setup
- name: Build
run: source tools/ci.sh && ci_unix_stackless_clang_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_stackless_clang_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
float_clang:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Install packages
run: source tools/ci.sh && ci_unix_clang_setup
- name: Build
run: source tools/ci.sh && ci_unix_float_clang_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_float_clang_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
settrace:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: source tools/ci.sh && ci_unix_settrace_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_settrace_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
settrace_stackless:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: source tools/ci.sh && ci_unix_settrace_stackless_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_settrace_stackless_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
macos:
runs-on: macos-11.0
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.8'
- name: Build
run: source tools/ci.sh && ci_unix_macos_build
- name: Run tests
run: source tools/ci.sh && ci_unix_macos_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
qemu_mips:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install packages
run: source tools/ci.sh && ci_unix_qemu_mips_setup
- name: Build
run: source tools/ci.sh && ci_unix_qemu_mips_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_qemu_mips_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
qemu_arm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install packages
run: source tools/ci.sh && ci_unix_qemu_arm_setup
- name: Build
run: source tools/ci.sh && ci_unix_qemu_arm_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_qemu_arm_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures

10
.gitmodules vendored
View File

@ -13,7 +13,7 @@
[submodule "lib/stm32lib"]
path = lib/stm32lib
url = https://github.com/micropython/stm32lib
branch = work-F4-1.13.1+F7-1.5.0+L4-1.3.0
branch = work-F0-1.9.0+F4-1.16.0+F7-1.7.0+G4-1.3.0+H7-1.6.0+L0-1.11.2+L4-1.17.0+WB-1.10.0+WL-1.1.0
[submodule "lib/nrfx"]
path = lib/nrfx
url = https://github.com/NordicSemiconductor/nrfx.git
@ -45,3 +45,11 @@
[submodule "lib/pico-sdk"]
path = lib/pico-sdk
url = https://github.com/raspberrypi/pico-sdk.git
[submodule "lib/fsp"]
path = lib/fsp
url = https://github.com/renesas/fsp.git
[submodule "lib/wiznet"]
path = lib/wiznet5k
url = https://github.com/andrewleech/wiznet_ioLibrary_Driver.git
# Requires https://github.com/Wiznet/ioLibrary_Driver/pull/120
# url = https://github.com/Wiznet/ioLibrary_Driver.git

View File

@ -350,7 +350,7 @@ The STM32 version
The "stm32" port requires an ARM compiler, arm-none-eabi-gcc, and associated
bin-utils. For those using Arch Linux, you need arm-none-eabi-binutils,
arm-none-eabi-gcc and arm-none-eabi-newlib packages. Otherwise, try here:
https://launchpad.net/gcc-arm-embedded
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm
To build:

View File

@ -74,7 +74,7 @@ copyright = '- The MicroPython Documentation is Copyright © 2014-2022, Damien P
#
# 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.
version = release = '1.18'
version = release = '1.19.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View File

@ -221,23 +221,25 @@ as described above.
If a module is not enabled by default then the corresponding C preprocessor macro
must be enabled. This macro name can be found by searching for the ``MP_REGISTER_MODULE``
line in the module's source code (it usually appears at the end of the main source file).
The third argument to ``MP_REGISTER_MODULE`` is the macro name, and this must be set
to 1 using ``CFLAGS_EXTRA`` to make the module available. If the third argument is just
the number 1 then the module is enabled by default.
This macro should be surrounded by a ``#if X`` / ``#endif`` pair, and the configuration
option ``X`` must be set to 1 using ``CFLAGS_EXTRA`` to make the module available. If
there is no ``#if X`` / ``#endif`` pair then the module is enabled by default.
For example, the ``examples/usercmodule/cexample`` module is enabled by default so
has the following line in its source code:
.. code-block:: c
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, 1);
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule);
Alternatively, to make this module disabled by default but selectable through
a preprocessor configuration option, it would be:
.. code-block:: c
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, MODULE_CEXAMPLE_ENABLED);
#if MODULE_CEXAMPLE_ENABLED
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule);
#endif
In this case the module is enabled by adding ``CFLAGS_EXTRA=-DMODULE_CEXAMPLE_ENABLED=1``
to the ``make`` command, or editing ``mpconfigport.h`` or ``mpconfigboard.h`` to add

View File

@ -64,7 +64,7 @@ hypothetical new module ``subsystem`` in the file ``modsubsystem.c``:
.globals = (mp_obj_dict_t *)&mp_module_subsystem_globals,
};
MP_REGISTER_MODULE(MP_QSTR_subsystem, mp_module_subsystem, MICROPY_PY_SUBSYSTEM);
MP_REGISTER_MODULE(MP_QSTR_subsystem, mp_module_subsystem);
#endif

View File

@ -34,6 +34,7 @@ options for the ``ARCH`` variable, see below):
* ``x86`` (32 bit)
* ``x64`` (64 bit x86)
* ``armv6m`` (ARM Thumb, eg Cortex-M0)
* ``armv7m`` (ARM Thumb 2, eg Cortex-M3)
* ``armv7emsp`` (ARM Thumb 2, single precision float, eg Cortex-M4F, Cortex-M7)
* ``armv7emdp`` (ARM Thumb 2, double precision float, eg Cortex-M7)
@ -171,7 +172,7 @@ The file ``Makefile`` contains:
# Source files (.c or .py)
SRC = factorial.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
# Architecture to build for (x86, x64, armv6m, armv7m, xtensa, xtensawin)
ARCH = x64
# Include to get the rules for compiling and linking the module

View File

@ -146,6 +146,9 @@ The following is an example of an ``mpconfigport.h`` file:
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
// Enable u-modules to be imported with their standard name, like sys.
#define MICROPY_MODULE_WEAK_LINKS (1)
// Fine control over Python builtins, classes, modules, etc.
#define MICROPY_PY_ASYNC_AWAIT (0)
#define MICROPY_PY_BUILTINS_SET (0)
@ -277,12 +280,7 @@ To add a custom module like ``myport``, first add the module definition in a fil
.globals = (mp_obj_dict_t *)&myport_module_globals,
};
MP_REGISTER_MODULE(MP_QSTR_myport, myport_module, 1);
Note: the "1" as the third argument in ``MP_REGISTER_MODULE`` enables this new module
unconditionally. To allow it to be conditionally enabled, replace the "1" by
``MICROPY_PY_MYPORT`` and then add ``#define MICROPY_PY_MYPORT (1)`` in ``mpconfigport.h``
accordingly.
MP_REGISTER_MODULE(MP_QSTR_myport, myport_module);
You will also need to edit the Makefile to add ``modmyport.c`` to the ``SRC_C`` list, and
a new line adding the same file to ``SRC_QSTR`` (so qstrs are searched for in this new file),
@ -296,7 +294,7 @@ like this:
mphalport.c \
...
SRC_QSTR += modport.c
SRC_QSTR += modmyport.c
If all went correctly then, after rebuilding, you should be able to import the new module:

View File

@ -8,7 +8,7 @@ Below is a list of finalised/accepted PEPs for Python 3.5 grouped into their imp
+----------------------------------------------------------------------------------------------------------+---------------+
| **Extensions to the syntax:** | **Status** |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 448 <https://www.python.org/dev/peps/pep-0448/>`_ | additional unpacking generalizations | |
| `PEP 448 <https://www.python.org/dev/peps/pep-0448/>`_ | additional unpacking generalizations | Partial |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 465 <https://www.python.org/dev/peps/pep-0465/>`_ | a new matrix multiplication operator | Completed |
+--------------------------------------------------------+-------------------------------------------------+---------------+
@ -33,7 +33,7 @@ Below is a list of finalised/accepted PEPs for Python 3.5 grouped into their imp
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `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 | |
| `PEP 486 <https://www.python.org/dev/peps/pep-0486/>`_ | make the Python Launcher aware of virtual | Not relevant |
| | environments | |
+--------------------------------------------------------+-------------------------------------------------+---------------+
| `PEP 484 <https://www.python.org/dev/peps/pep-0484/>`_ | type hints (advisory only) | In Progress |
@ -97,7 +97,7 @@ Changes to built-in modules:
+-----------------------------------------------------------------------------------------------------------+---------------+
| `math <https://docs.python.org/3/whatsnew/3.5.html#math>`_ |
+-----------------------------------------------------------------------------------------------------------+---------------+
| Two new constants have been added to the math module: *inf* and *nan*. | |
| Two new constants have been added to the math module: *inf* and *nan*. | Completed |
+-----------------------------------------------------------------------------------------------------------+---------------+
| A new function *isclose()* provides a way to test for approximate equality. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
@ -140,7 +140,7 @@ Changes to built-in modules:
| 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| |
| The backlog argument of the *socket.listen()* method is now optional. By default it is set to SOMAXCONN or| Completed |
| to 128, whichever is less. | |
+-----------------------------------------------------------------------------------------------------------+---------------+
| `ssl <https://docs.python.org/3/whatsnew/3.5.html#ssl>`_ |

View File

@ -78,7 +78,7 @@ Changes to built-in modules:
+--------------------------------------------------------------------------------------------------------------+----------------+
| `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 | |
| The b2a_base64() function now accepts an optional newline keyword argument to control whether the newline | Completed |
| character is appended to the return value | |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `cmath <https://docs.python.org/3.6/whatsnew/3.6.html#cmath>`_ | |
@ -121,7 +121,7 @@ Changes to built-in modules:
+--------------------------------------------------------------------------------------------------------------+----------------+
| `math <https://docs.python.org/3.6/whatsnew/3.6.html#math>`_ |
+--------------------------------------------------------------------------------------------------------------+----------------+
| The new math.tau (τ) constant has been added | |
| The new math.tau (τ) constant has been added | Completed |
+--------------------------------------------------------------------------------------------------------------+----------------+
| `os <https://docs.python.org/3.6/whatsnew/3.6.html#os>`_ |
+--------------------------------------------------------------------------------------------------------------+----------------+

View File

@ -160,6 +160,7 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
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
p6 = Pin(6, Pin.OUT, drive=Pin.DRIVE_3) # set maximum drive strength
Available Pins are from the following ranges (inclusive): 0-19, 21-23, 25-27, 32-39.
These correspond to the actual GPIO pin numbers of ESP32 chip. Note that many
@ -167,6 +168,23 @@ end-user boards use their own adhoc pin numbering (marked e.g. D0, D1, ...).
For mapping between board logical pins and physical chip pins consult your board
documentation.
Four drive strengths are supported, using the ``drive`` keyword argument to the
``Pin()`` constructor or ``Pin.init()`` method, with different corresponding
safe maximum source/sink currents and approximate internal driver resistances:
- ``Pin.DRIVE_0``: 5mA / 130 ohm
- ``Pin.DRIVE_1``: 10mA / 60 ohm
- ``Pin.DRIVE_2``: 20mA / 30 ohm (default strength if not configured)
- ``Pin.DRIVE_3``: 40mA / 15 ohm
The ``hold=`` keyword argument to ``Pin()`` and ``Pin.init()`` will enable the
ESP32 "pad hold" feature. When set to ``True``, the pin configuration
(direction, pull resistors and output value) will be held and any further
changes (including changing the output level) will not be applied. Setting
``hold=False`` will immediately apply any outstanding pin configuration changes
and release the pin. Using ``hold=True`` while a pin is already held will apply
any configuration changes and then immediately reapply the hold.
Notes:
* Pins 1 and 3 are REPL UART TX and RX respectively
@ -176,8 +194,7 @@ Notes:
* Pins 34-39 are input only, and also do not have internal pull-up resistors
* The pull value of some pins can be set to ``Pin.PULL_HOLD`` to reduce power
consumption during deepsleep.
* See :ref:`Deep_sleep_Mode` for a discussion of pin behaviour during sleep
There's a higher-level abstraction :ref:`machine.Signal <machine.Signal>`
which can be used to invert a pin. Useful for illuminating active-low LEDs
@ -264,54 +281,99 @@ See more examples in the :ref:`esp32_pwm` tutorial.
ADC (analog to digital conversion)
----------------------------------
On the ESP32 ADC functionality is available on Pins 32-39. Note that, when
using the default configuration, input voltages on the ADC pin must be between
0.0v and 1.0v (anything above 1.0v will just read as 4095). Attenuation must
be applied in order to increase this usable voltage range.
On the ESP32, ADC functionality is available on pins 32-39 (ADC block 1) and
pins 0, 2, 4, 12-15 and 25-27 (ADC block 2).
Use the :ref:`machine.ADC <machine.ADC>` class::
from machine import ADC
adc = ADC(Pin(32)) # create ADC object on ADC pin
adc.read() # read value, 0-4095 across voltage range 0.0v - 1.0v
adc = ADC(pin) # create an ADC object acting on a pin
val = adc.read_u16() # read a raw analog value in the range 0-65535
val = adc.read_uv() # read an analog value in microvolts
adc.atten(ADC.ATTN_11DB) # set 11dB input attenuation (voltage range roughly 0.0v - 3.6v)
adc.width(ADC.WIDTH_9BIT) # set 9 bit return values (returned range 0-511)
adc.read() # read value using the newly configured attenuation and width
ADC block 2 is also used by WiFi and so attempting to read analog values from
block 2 pins when WiFi is active will raise an exception.
ESP32 specific ADC class method reference:
The internal ADC reference voltage is typically 1.1V, but varies slightly from
package to package. The ADC is less linear close to the reference voltage
(particularly at higher attenuations) and has a minimum measurement voltage
around 100mV, voltages at or below this will read as 0. To read voltages
accurately, it is recommended to use the ``read_uv()`` method (see below).
.. method:: ADC.atten(attenuation)
ESP32-specific ADC class method reference:
This method allows for the setting of the amount of attenuation on the
input of the ADC. This allows for a wider possible input voltage range,
at the cost of accuracy (the same number of bits now represents a wider
range). The possible attenuation options are:
.. class:: ADC(pin, *, atten)
- ``ADC.ATTN_0DB``: 0dB attenuation, gives a maximum input voltage
of 1.00v - this is the default configuration
- ``ADC.ATTN_2_5DB``: 2.5dB attenuation, gives a maximum input voltage
of approximately 1.34v
- ``ADC.ATTN_6DB``: 6dB attenuation, gives a maximum input voltage
of approximately 2.00v
- ``ADC.ATTN_11DB``: 11dB attenuation, gives a maximum input voltage
of approximately 3.6v
Return the ADC object for the specified pin. ESP32 does not support
different timings for ADC sampling and so the ``sample_ns`` keyword argument
is not supported.
To read voltages above the reference voltage, apply input attenuation with
the ``atten`` keyword argument. Valid values (and approximate linear
measurement ranges) are:
- ``ADC.ATTN_0DB``: No attenuation (100mV - 950mV)
- ``ADC.ATTN_2_5DB``: 2.5dB attenuation (100mV - 1250mV)
- ``ADC.ATTN_6DB``: 6dB attenuation (150mV - 1750mV)
- ``ADC.ATTN_11DB``: 11dB attenuation (150mV - 2450mV)
.. Warning::
Despite 11dB attenuation allowing for up to a 3.6v range, note that the
absolute maximum voltage rating for the input pins is 3.6v, and so going
near this boundary may be damaging to the IC!
Note that the absolute maximum voltage rating for input pins is 3.6V. Going
near to this boundary risks damage to the IC!
.. method:: ADC.width(width)
.. method:: ADC.read_uv()
This method allows for the setting of the number of bits to be utilised
and returned during ADC reads. Possible width options are:
This method uses the known characteristics of the ADC and per-package eFuse
values - set during manufacture - to return a calibrated input voltage
(before attenuation) in microvolts. The returned value has only millivolt
resolution (i.e., will always be a multiple of 1000 microvolts).
The calibration is only valid across the linear range of the ADC. In
particular, an input tied to ground will read as a value above 0 microvolts.
Within the linear range, however, more accurate and consistent results will
be obtained than using `read_u16()` and scaling the result with a constant.
The ESP32 port also supports the :ref:`machine.ADC <machine.ADCBlock>` API:
.. class:: ADCBlock(id, *, bits)
Return the ADC block object with the given ``id`` (1 or 2) and initialize
it to the specified resolution (9 to 12-bits depending on the ESP32 series)
or the highest supported resolution if not specified.
.. method:: ADCBlock.connect(pin)
ADCBlock.connect(channel)
ADCBlock.connect(channel, pin)
Return the ``ADC`` object for the specified ADC pin or channel number.
Arbitrary connection of ADC channels to GPIO is not supported and so
specifying a pin that is not connected to this block, or specifying a
mismatched channel and pin, will raise an exception.
Legacy methods:
.. method:: ADC.read()
This method returns the raw ADC value ranged according to the resolution of
the block, e.g., 0-4095 for 12-bit resolution.
.. method:: ADC.atten(atten)
Equivalent to ``ADC.init(atten=atten)``.
.. method:: ADC.width(bits)
Equivalent to ``ADC.block().init(bits=bits)``.
For compatibility, the ``ADC`` object also provides constants matching the
supported ADC resolutions:
- ``ADC.WIDTH_9BIT`` = 9
- ``ADC.WIDTH_10BIT`` = 10
- ``ADC.WIDTH_11BIT`` = 11
- ``ADC.WIDTH_12BIT`` = 12
- ``ADC.WIDTH_9BIT``: 9 bit data
- ``ADC.WIDTH_10BIT``: 10 bit data
- ``ADC.WIDTH_11BIT``: 11 bit data
- ``ADC.WIDTH_12BIT``: 12 bit data - this is the default configuration
Software SPI bus
----------------
@ -453,6 +515,8 @@ See :ref:`machine.WDT <machine.WDT>`. ::
wdt = WDT(timeout=5000)
wdt.feed()
.. _Deep_sleep_mode:
Deep-sleep mode
---------------
@ -472,15 +536,49 @@ Notes:
* Calling ``deepsleep()`` without an argument will put the device to sleep
indefinitely
* A software reset does not change the reset cause
* There may be some leakage current flowing through enabled internal pullups.
To further reduce power consumption it is possible to disable the internal pullups::
p1 = Pin(4, Pin.IN, Pin.PULL_HOLD)
Some ESP32 pins (0, 2, 4, 12-15, 25-27, 32-39) are connected to the RTC during
deep-sleep and can be used to wake the device with the ``wake_on_`` functions in
the :mod:`esp32` module. The output-capable RTC pins (all except 34-39) will
also retain their pull-up or pull-down resistor configuration when entering
deep-sleep.
After leaving deepsleep it may be necessary to un-hold the pin explicitly (e.g. if
it is an output pin) via::
If the pull resistors are not actively required during deep-sleep and are likely
to cause current leakage (for example a pull-up resistor is connected to ground
through a switch), then they should be disabled to save power before entering
deep-sleep mode::
p1 = Pin(4, Pin.OUT, None)
from machine import Pin, deepsleep
# configure input RTC pin with pull-up on boot
pin = Pin(2, Pin.IN, Pin.PULL_UP)
# disable pull-up and put the device to sleep for 10 seconds
pin.init(pull=None)
machine.deepsleep(10000)
Output-configured RTC pins will also retain their output direction and level in
deep-sleep if pad hold is enabled with the ``hold=True`` argument to
``Pin.init()``.
Non-RTC GPIO pins will be disconnected by default on entering deep-sleep.
Configuration of non-RTC pins - including output level - can be retained by
enabling pad hold on the pin and enabling GPIO pad hold during deep-sleep::
from machine import Pin, deepsleep
import esp32
opin = Pin(19, Pin.OUT, value=1, hold=True) # hold output level
ipin = Pin(21, Pin.IN, Pin.PULL_UP, hold=True) # hold pull-up
# enable pad hold in deep-sleep for non-RTC GPIO
esp32.gpio_deep_sleep_hold(True)
# put the device to sleep for 10 seconds
deepsleep(10000)
The pin configuration - including the pad hold - will be retained on wake from
sleep. See :ref:`Pins_and_GPIO` above for a further discussion of pad holding.
SD card
-------
@ -562,18 +660,14 @@ The APA106 driver extends NeoPixel, but internally uses a different colour order
ap = APA106(pin, 8)
r, g, b = ap[0]
For low-level driving of a NeoPixel::
import esp
esp.neopixel_write(pin, grb_buf, is800khz)
.. Warning::
By default ``NeoPixel`` is configured to control the more popular *800kHz*
units. It is possible to use alternative timing to control other (typically
400kHz) devices by passing ``timing=0`` when constructing the
``NeoPixel`` object.
The low-level driver uses an RMT channel by default. To configure this see
For low-level driving of a NeoPixel see `machine.bitstream`.
This 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.

View File

@ -374,17 +374,13 @@ Use the ``neopixel`` module::
np.write() # write data to all pixels
r, g, b = np[0] # get first pixel colour
For low-level driving of a NeoPixel::
import esp
esp.neopixel_write(pin, grb_buf, is800khz)
.. Warning::
By default ``NeoPixel`` is configured to control the more popular *800kHz*
units. It is possible to use alternative timing to control other (typically
400kHz) devices by passing ``timing=0`` when constructing the
``NeoPixel`` object.
For low-level driving of a NeoPixel see `machine.bitstream`.
APA102 driver
-------------

View File

@ -12,6 +12,8 @@ MicroPython documentation and references
esp8266/quickref.rst
esp32/quickref.rst
rp2/quickref.rst
mimxrt/quickref.rst
wipy/quickref.rst
unix/quickref.rst
zephyr/quickref.rst
renesas-ra/quickref.rst

View File

@ -31,8 +31,8 @@ Functions
Conforms to `RFC 2045 s.6.8 <https://tools.ietf.org/html/rfc2045#section-6.8>`_.
Returns a bytes object.
.. function:: b2a_base64(data)
.. function:: b2a_base64(data, *, newline=True)
Encode binary data in base64 format, as in `RFC 3548
<https://tools.ietf.org/html/rfc3548.html>`_. Returns the encoded data
followed by a newline character, as a bytes object.
followed by a newline character if newline is true, as a bytes object.

View File

@ -12,7 +12,7 @@ hold/accumulate various objects.
Classes
-------
.. function:: deque(iterable, maxlen[, flags])
.. class:: deque(iterable, maxlen[, flags])
Deques (double-ended queues) are a list-like container that support O(1)
appends and pops from either side of the deque. New deques are created
@ -57,7 +57,7 @@ Classes
print(t1.name)
assert t2.name == t2[1]
.. function:: OrderedDict(...)
.. class:: OrderedDict(...)
``dict`` type subclass which remembers and preserves the order of keys
added. When ordered dict is iterated over, keys/items are returned in

View File

@ -62,6 +62,21 @@ Functions
.. function:: flash_erase(sector_no)
.. function:: osdebug(level)
Turn esp os debugging messages on or off.
The *level* parameter sets the threshold for the log messages for all esp components.
The log levels are defined as constants:
* ``LOG_NONE`` -- No log output
* ``LOG_ERROR`` -- Critical errors, software module can not recover on its own
* ``LOG_WARN`` -- Error conditions from which recovery measures have been taken
* ``LOG_INFO`` -- Information messages which describe normal flow of events
* ``LOG_DEBUG`` -- Extra information which is not necessary for normal use (values, pointers, sizes, etc)
* ``LOG_VERBOSE`` -- Bigger chunks of debugging information, or frequent messages
which can potentially flood the output
.. function:: set_native_code_location(start, length)
**Note**: ESP8266 only

View File

@ -30,6 +30,11 @@ Functions
or a tuple/list of valid Pin objects. *level* should be ``esp32.WAKEUP_ALL_LOW``
or ``esp32.WAKEUP_ANY_HIGH``.
.. function:: gpio_deep_sleep_hold(enable)
Configure whether non-RTC GPIO pin configuration is retained during
deep-sleep mode for held pads. *enable* should be a boolean value.
.. function:: raw_temperature()
Read the raw value of the internal temperature sensor, returning an integer.
@ -68,17 +73,21 @@ Flash partitions
This class gives access to the partitions in the device's flash memory and includes
methods to enable over-the-air (OTA) updates.
.. class:: Partition(id)
.. class:: Partition(id, block_size=4096, /)
Create an object representing a partition. *id* can be a string which is the label
of the partition to retrieve, or one of the constants: ``BOOT`` or ``RUNNING``.
*block_size* specifies the byte size of an individual block.
.. classmethod:: Partition.find(type=TYPE_APP, subtype=0xff, label=None)
.. classmethod:: Partition.find(type=TYPE_APP, subtype=0xff, label=None, block_size=4096)
Find a partition specified by *type*, *subtype* and *label*. Returns a
(possibly empty) list of Partition objects. Note: ``subtype=0xff`` matches any subtype
and ``label=None`` matches any label.
*block_size* specifies the byte size of an individual block used by the returned
objects.
.. method:: Partition.info()
Returns a 6-tuple ``(type, subtype, addr, size, label, encrypted)``.

View File

@ -97,6 +97,13 @@ the following libraries.
network.rst
uctypes.rst
The following libraries provide drivers for hardware components.
.. toctree::
:maxdepth: 1
wm8960.rst
Port-specific libraries
-----------------------

View File

@ -8,28 +8,59 @@ The ADC class provides an interface to analog-to-digital convertors, and
represents a single endpoint that can sample a continuous voltage and
convert it to a discretised value.
For extra control over ADC sampling see :ref:`machine.ADCBlock <machine.ADCBlock>`.
Example usage::
import machine
from machine import ADC
adc = machine.ADC(pin) # create an ADC object acting on a pin
adc = ADC(pin) # create an ADC object acting on a pin
val = adc.read_u16() # read a raw analog value in the range 0-65535
val = adc.read_uv() # read an analog value in microvolts
Constructors
------------
.. class:: ADC(id)
.. class:: ADC(id, *, sample_ns, atten)
Access the ADC associated with a source identified by *id*. This
*id* may be an integer (usually specifying a channel number), a
:ref:`Pin <machine.Pin>` object, or other value supported by the
underlying machine.
If additional keyword-arguments are given then they will configure
various aspects of the ADC. If not given, these settings will take
previous or default values. The settings are:
- *sample_ns* is the sampling time in nanoseconds.
- *atten* specifies the input attenuation.
Methods
-------
.. method:: ADC.init(*, sample_ns, atten)
Apply the given settings to the ADC. Only those arguments that are
specified will be changed. See the ADC constructor above for what the
arguments are.
.. method:: ADC.block()
Return the :ref:`ADCBlock <machine.ADCBlock>` instance associated with
this ADC object.
This method only exists if the port supports the
:ref:`ADCBlock <machine.ADCBlock>` class.
.. method:: ADC.read_u16()
Take an analog reading and return an integer in the range 0-65535.
The return value represents the raw reading taken by the ADC, scaled
such that the minimum value is 0 and the maximum value is 65535.
.. method:: ADC.read_uv()
Take an analog reading and return an integer value with units of
microvolts. It is up to the particular port whether or not this value
is calibrated, and how calibration is done.

View File

@ -0,0 +1,58 @@
.. currentmodule:: machine
.. _machine.ADCBlock:
class ADCBlock -- control ADC peripherals
=========================================
The ADCBlock class provides access to an ADC peripheral which has a
number of channels that can be used to sample analog values. It allows
finer control over configuration of :ref:`machine.ADC <machine.ADC>`
objects, which do the actual sampling.
This class is not always available.
Example usage::
from machine import ADCBlock
block = ADCBlock(id, bits=12) # create an ADCBlock with 12-bit resolution
adc = block.connect(4, pin) # connect channel 4 to the given pin
val = adc.read_uv() # read an analog value
Constructors
------------
.. class:: ADCBlock(id, *, bits)
Access the ADC peripheral identified by *id*, which may be an integer
or string.
The *bits* argument, if given, sets the resolution in bits of the
conversion process. If not specified then the previous or default
resolution is used.
Methods
-------
.. method:: ADCBlock.init(*, bits)
Configure the ADC peripheral. *bits* will set the resolution of the
conversion process.
.. method:: ADCBlock.connect(channel)
ADCBlock.connect(source)
ADCBlock.connect(channel, source)
Connect up a channel on the ADC peripheral so it is ready for sampling,
and return an :ref:`ADC <machine.ADC>` object that represents that connection.
The *channel* argument must be an integer, and *source* must be an object
(for example a :ref:`Pin <machine.Pin>`) which can be connected up for sampling.
If only *channel* is given then it is configured for sampling.
If only *source* is given then that object is connected to a default
channel ready for sampling.
If both *channel* and *source* are given then they are connected together
and made ready for sampling.

View File

@ -57,7 +57,7 @@ Constructors
of *scl* and *sda* that cannot be changed.
.. _machine.SoftI2C:
.. class:: SoftI2C(scl, sda, *, freq=400000, timeout=255)
.. class:: SoftI2C(scl, sda, *, freq=400000, timeout=50000)
Construct a new software I2C object. The parameters are:

View File

@ -72,30 +72,34 @@ uasyncio::
sreader = uasyncio.StreamReader(audio_in)
num_read = await sreader.readinto(buf)
Some codec devices like the WM8960 or SGTL5000 require separate initialization
before they can operate with the I2S class. For these, separate drivers are
supplied, which also offer methods for controlling volume, audio processing and
other things. For these drivers see:
- :ref:`wm8960`
Constructor
-----------
.. class:: I2S(id, *, sck, ws, sd, mode, bits, format, rate, ibuf)
.. class:: I2S(id, *, sck, ws, sd, mck=None, mode, bits, format, rate, ibuf)
Construct an I2S object of the given id:
- ``id`` identifies a particular I2S bus.
``id`` is board and port specific:
- PYBv1.0/v1.1: has one I2S bus with 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.
- ``id`` identifies a particular I2S bus; it is board and port specific
Keyword-only parameters that are supported on all ports:
- ``sck`` is a pin object for the serial clock line
- ``ws`` is a pin object for the word select line
- ``sd`` is a pin object for the serial data line
- ``mck`` is a pin object for the master clock line;
master clock frequency is sampling rate * 256
- ``mode`` specifies receive or transmit
- ``bits`` specifies sample size (bits), 16 or 32
- ``format`` specifies channel format, STEREO or MONO
- ``rate`` specifies audio sampling rate (samples/s)
- ``rate`` specifies audio sampling rate (Hz);
this is the frequency of the ``ws`` signal
- ``ibuf`` specifies internal buffer length (bytes)
For all ports, DMA runs continuously in the background and allows user applications to perform other operations while

View File

@ -23,7 +23,7 @@ Example usage::
Constructors
------------
.. class:: PWM(dest, \*, freq, duty_u16, duty_ns)
.. class:: PWM(dest, *, freq, duty_u16, duty_ns)
Construct and return a new PWM object using the following parameters:
@ -42,7 +42,7 @@ Constructors
Methods
-------
.. method:: PWM.init(\*, freq, duty_u16, duty_ns)
.. method:: PWM.init(*, freq, duty_u16, duty_ns)
Modify settings for the PWM object. See the above constructor for details
about the parameters.
@ -78,6 +78,13 @@ Methods
With a single *value* argument the pulse width is set to that value.
Specific PWM class implementations
----------------------------------
The following concrete class(es) implement enhancements to the PWM class.
| :ref:`pyb.Timer for PyBoard <pyb.Timer>`
Limitations of PWM
------------------
@ -90,6 +97,11 @@ Limitations of PWM
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.
Some ports like the RP2040 one use a fractional divider, which allow a finer
granularity of the frequency at higher frequencies by switching the PWM
pulse duration between two adjacent values, such that the resulting average
frequency is more close to the intended one, at the cost of spectral purity.
* 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

View File

@ -42,7 +42,7 @@ Usage Model::
Constructors
------------
.. class:: Pin(id, mode=-1, pull=-1, *, value, drive, alt)
.. class:: Pin(id, mode=-1, pull=-1, *, value=None, drive=0, alt=-1)
Access the pin peripheral (GPIO pin) associated with the given ``id``. If
additional arguments are given in the constructor then they are used to initialise
@ -87,9 +87,9 @@ Constructors
output pin value if given, otherwise the state of the pin peripheral remains
unchanged.
- ``drive`` specifies the output power of the pin and can be one of: ``Pin.LOW_POWER``,
``Pin.MED_POWER`` or ``Pin.HIGH_POWER``. The actual current driving capabilities
are port dependent. Not all ports implement this argument.
- ``drive`` specifies the output power of the pin and can be one of: ``Pin.DRIVE_0``,
``Pin.DRIVE_1``, etc., increasing in drive strength. The actual current driving
capabilities are port dependent. Not all ports implement this argument.
- ``alt`` specifies an alternate function for the pin and the values it can take are
port dependent. This argument is valid only for ``Pin.ALT`` and ``Pin.ALT_OPEN_DRAIN``
@ -108,7 +108,7 @@ Constructors
Methods
-------
.. method:: Pin.init(mode=-1, pull=-1, *, value, drive, alt)
.. method:: Pin.init(mode=-1, pull=-1, *, value=None, drive=0, alt=-1)
Re-initialise the pin using the given parameters. Only those arguments that
are specified will be set. The rest of the pin peripheral state will remain
@ -260,11 +260,13 @@ not all constants are available on all ports.
Selects whether there is a pull up/down resistor. Use the value
``None`` for no pull.
.. data:: Pin.LOW_POWER
Pin.MED_POWER
Pin.HIGH_POWER
.. data:: Pin.DRIVE_0
Pin.DRIVE_1
Pin.DRIVE_2
Selects the pin drive strength.
Selects the pin drive strength. A port may define additional drive
constants with increasing number corresponding to increasing drive
strength.
.. data:: Pin.IRQ_FALLING
Pin.IRQ_RISING

View File

@ -122,3 +122,46 @@ You can set the pins used for SPI access by passing a tuple as the
*Note:* The current cc3200 SD card implementation names the this class
:class:`machine.SD` rather than :class:`machine.SDCard` .
mimxrt
``````
The SDCard module for the mimxrt port only supports access via dedicated SD/MMC
peripheral (USDHC) in 4-bit mode with 50MHz clock frequency exclusively.
Unfortunately the MIMXRT1011 controller does not support the USDHC peripheral.
Hence this controller does not feature the ``machine.SDCard`` module.
Due to the decision to only support 4-bit mode with 50MHz clock frequency the
interface has been simplified, and the constructor signature is:
.. class:: SDCard(slot=1)
:noindex:
The pins used for the USDHC peripheral have to be configured in ``mpconfigboard.h``.
Most of the controllers supported by the mimxrt port provide up to two USDHC
peripherals. Therefore the pin configuration is performed using the macro
``MICROPY_USDHCx`` with x being 1 or 2 respectively.
The following shows an example configuration for USDHC1::
#define MICROPY_USDHC1 \
{ \
.cmd = { GPIO_SD_B0_02_USDHC1_CMD}, \
.clk = { GPIO_SD_B0_03_USDHC1_CLK }, \
.cd_b = { GPIO_SD_B0_06_USDHC1_CD_B },\
.data0 = { GPIO_SD_B0_04_USDHC1_DATA0 },\
.data1 = { GPIO_SD_B0_05_USDHC1_DATA1 },\
.data2 = { GPIO_SD_B0_00_USDHC1_DATA2 },\
.data3 = { GPIO_SD_B0_01_USDHC1_DATA3 },\
}
If the card detect pin is not used (cb_b pin) then the respective entry has to be
filled with the following dummy value::
#define USDHC_DUMMY_PIN NULL , 0
Based on the definition of macro ``MICROPY_USDHC1`` and/or ``MICROPY_USDHC2``
the ``machine.SDCard`` module either supports one or two slots. If only one of
the defines is provided, calling ``machine.SDCard()`` or ``machine.SDCard(1)``
will return an instance using the respective USDHC peripheral. When both macros
are defined, calling ``machine.SDCard(2)`` returns an instance using USDHC2.

View File

@ -143,9 +143,11 @@ Constants
for initialising the SPI bus to controller; this is only used for the WiPy
.. data:: SPI.MSB
SoftSPI.MSB
set the first bit to be the most significant bit
.. data:: SPI.LSB
SoftSPI.LSB
set the first bit to be the least significant bit

View File

@ -63,6 +63,12 @@ Methods
- *timeout* specifies the time to wait for the first character (in ms).
- *timeout_char* specifies the time to wait between characters (in ms).
- *invert* specifies which lines to invert.
- ``0`` will not invert lines (idle state of both lines is logic high).
- ``UART.INV_TX`` will invert TX line (idle state of TX line now logic low).
- ``UART.INV_RX`` will invert RX line (idle state of RX line now logic low).
- ``UART.INV_TX | UART.INV_RX`` will invert both lines (idle state at logic low).
- *flow* specifies which hardware flow control signals to use. The value
is a bitmask.

View File

@ -31,7 +31,7 @@ Constructors
Methods
-------
.. method:: wdt.feed()
.. method:: WDT.feed()
Feed the WDT to prevent it from resetting the system. The application
should place this call in a sensible place ensuring that the WDT is

View File

@ -199,6 +199,7 @@ Classes
machine.Pin.rst
machine.Signal.rst
machine.ADC.rst
machine.ADCBlock.rst
machine.PWM.rst
machine.UART.rst
machine.SPI.rst

View File

@ -0,0 +1,93 @@
.. currentmodule:: network
.. _network.LAN:
class LAN -- control an Ethernet module
=======================================
This class allows you to control the Ethernet interface. The PHY hardware type is board-specific.
Example usage::
import network
nic = network.LAN(0)
print(nic.ifconfig())
# now use socket as usual
...
Constructors
------------
.. class:: LAN(id, *, phy_type=<board_default>, phy_addr=<board_default>, phy_clock=<board_default>)
Create a LAN driver object, initialise the LAN module using the given
PHY driver name, and return the LAN object.
Arguments are:
- *id* is the number of the Ethernet port, either 0 or 1.
- *phy_type* is the name of the PHY driver. For most board the on-board PHY has to be used and
is the default. Suitable values are port specific.
- *phy_addr* specifies the address of the PHY interface. As with *phy_type*, the hardwired value has
to be used for most boards and that value is the default.
- *phy_clock* specifies, whether the data clock is provided by the Ethernet controller or the PYH interface.
The default value is the one that matches the board. If set to ``True``, the clock is driven by the
Ethernet controller, otherwise by the PHY interface.
For example, with the Seeed Arch Mix board you can use::
nic = LAN(0, phy_type=LAN.PHY_LAN8720, phy_addr=2, phy_clock=False)
Methods
-------
.. method:: LAN.active([state])
With a parameter, it sets the interface active if *state* is true, otherwise it
sets it inactive.
Without a parameter, it returns the state.
.. method:: LAN.isconnected()
Returns ``True`` if the physical Ethernet link is connected and up.
Returns ``False`` otherwise.
.. method:: LAN.status()
Returns the LAN status.
.. method:: LAN.ifconfig([(ip, subnet, gateway, dns)])
Get/set IP address, subnet mask, gateway and DNS.
When called with no arguments, this method returns a 4-tuple with the above information.
To set the above values, pass a 4-tuple with the required information. For example::
nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
.. method:: LAN.config(config_parameters)
Sets or gets parameters of the LAN interface. The only parameter that can be
retrieved is the MAC address, using::
mac = LAN.config("mac")
The parameters that can be set are:
- ``trace=n`` sets trace levels; suitable values are:
- 2: trace TX
- 4: trace RX
- 8: full trace
- ``low_power=bool`` sets or clears low power mode, valid values being ``False``
or ``True``.
Specific LAN class implementations
----------------------------------
On the mimxrt port, suitable values for the *phy_type* constructor argument are:
``PHY_KSZ8081``, ``PHY_DP83825``, ``PHY_DP83848``, ``PHY_LAN8720``, ``PHY_RTL8211F``.

View File

@ -6,7 +6,7 @@ class WIZNET5K -- control WIZnet5x00 Ethernet modules
This class allows you to control WIZnet5x00 Ethernet adaptors based on
the W5200 and W5500 chipsets. The particular chipset that is supported
by the firmware is selected at compile-time via the MICROPY_PY_WIZNET5K
by the firmware is selected at compile-time via the MICROPY_PY_NETWORK_WIZNET5K
option.
Example usage::

View File

@ -132,4 +132,5 @@ Methods
password Access password (string)
dhcp_hostname The DHCP hostname to use
reconnects Number of reconnect attempts to make (integer, 0=none, -1=unlimited)
txpower Maximum transmit power in dBm (integer or float)
============= ===========

View File

@ -152,6 +152,7 @@ provide a way to control networking interfaces of various kinds.
network.WLANWiPy.rst
network.CC3K.rst
network.WIZNET5K.rst
network.LAN.rst
Network functions
=================

View File

@ -4,13 +4,12 @@
class CAN -- controller area network communication bus
======================================================
CAN implements the standard CAN communications protocol. At
the physical level it consists of 2 lines: RX and TX. Note that
to connect the pyboard to a CAN bus you must use a CAN transceiver
to convert the CAN logic signals from the pyboard to the correct
CAN implements support for classic CAN (available on F4, F7 MCUs) and CAN FD (H7 series) controllers.
At the physical level CAN bus consists of 2 lines: RX and TX. Note that to connect the pyboard to a
CAN bus you must use a CAN transceiver to convert the CAN logic signals from the pyboard to the correct
voltage levels on the bus.
Example usage (works without anything connected)::
Example usage for classic CAN controller in Loopback (transceiver-less) mode::
from pyb import CAN
can = CAN(1, CAN.LOOPBACK)
@ -18,6 +17,16 @@ Example usage (works without anything connected)::
can.send('message!', 123) # send a message with id 123
can.recv(0) # receive message on FIFO 0
Example usage for CAN FD controller with all of the possible options enabled::
# FD frame + BRS mode + Extended frame ID. 500 Kbit/s for arbitration phase, 1Mbit/s for data phase.
can = CAN(1, CAN.NORMAL, baudrate=500_000, brs_baudrate=1_000_000, sample_point=80)
can.setfilter(0, CAN.RANGE, 0, (0xFFF0, 0xFFFF))
can.send('a'*64, 0xFFFF, fdf=True, brs=True, extframe=True)
can.recv(0)
The following CAN module functions and their arguments are available
for both classic and FD CAN controllers, unless otherwise stated.
Constructors
------------
@ -35,43 +44,48 @@ Constructors
- ``CAN(1)`` is on ``YA``: ``(RX, TX) = (Y3, Y4) = (PB8, PB9)``
- ``CAN(2)`` is on ``YB``: ``(RX, TX) = (Y5, Y6) = (PB12, PB13)``
Class Methods
-------------
.. classmethod:: CAN.initfilterbanks(nr)
Reset and disable all filter banks and assign how many banks should be available for CAN(1).
STM32F405 has 28 filter banks that are shared between the two available CAN bus controllers.
This function configures how many filter banks should be assigned to each. *nr* is the number of banks
that will be assigned to CAN(1), the rest of the 28 are assigned to CAN(2).
At boot, 14 banks are assigned to each controller.
Methods
-------
.. method:: CAN.init(mode, extframe=False, prescaler=100, *, sjw=1, bs1=6, bs2=8, auto_restart=False, baudrate=0, sample_point=75)
.. method:: CAN.init(mode, prescaler=100, *, sjw=1, bs1=6, bs2=8, auto_restart=False, baudrate=0, sample_point=75,
num_filter_banks=14, brs_sjw=1, brs_bs1=8, brs_bs2=3, brs_baudrate=0, brs_sample_point=75)
Initialise the CAN bus with the given parameters:
- *mode* is one of: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK
- if *extframe* is True then the bus uses extended identifiers in the frames
(29 bits); otherwise it uses standard 11 bit identifiers
- *prescaler* is used to set the duration of 1 time quanta; the time quanta
will be the input clock (PCLK1, see :meth:`pyb.freq()`) divided by the prescaler
- *sjw* is the resynchronisation jump width in units of the time quanta;
it can be 1, 2, 3, 4
- *bs1* defines the location of the sample point in units of the time quanta;
it can be between 1 and 1024 inclusive
- *bs2* defines the location of the transmit point in units of the time quanta;
it can be between 1 and 16 inclusive
- *prescaler* is the value by which the CAN input clock is divided to generate the
nominal bit time quanta. The prescaler can be a value between 1 and 1024 inclusive
for classic CAN, and between 1 and 512 inclusive for CAN FD.
- *sjw* is the resynchronisation jump width in units of time quanta for nominal bits;
it can be a value between 1 and 4 inclusive for classic CAN, and between 1 and 128 inclusive for CAN FD.
- *bs1* defines the location of the sample point in units of the time quanta for nominal bits;
it can be a value between 1 and 16 inclusive for classic CAN, and between 2 and 256 inclusive for CAN FD.
- *bs2* defines the location of the transmit point in units of the time quanta for nominal bits;
it can be a value between 1 and 8 inclusive for classic CAN, and between 2 and 128 inclusive for CAN FD.
- *auto_restart* sets whether the controller will automatically try and restart
communications after entering the bus-off state; if this is disabled then
:meth:`~CAN.restart()` can be used to leave the bus-off state
- *baudrate* if a baudrate other than 0 is provided, this function will try to automatically
calculate a CAN bit-timing (overriding *prescaler*, *bs1* and *bs2*) that satisfies both
the baudrate and the desired *sample_point*.
- *sample_point* given in a percentage of the bit time, the *sample_point* specifies the position
of the last bit sample with respect to the whole bit time. The default *sample_point* is 75%.
calculate the CAN nominal bit time (overriding *prescaler*, *bs1* and *bs2*) that satisfies
both the baudrate and the desired *sample_point*.
- *sample_point* given in a percentage of the nominal bit time, the *sample_point* specifies the position
of the bit sample with respect to the whole nominal bit time. The default *sample_point* is 75%.
- *num_filter_banks* for classic CAN, this is the number of banks that will be assigned to CAN(1),
the rest of the 28 are assigned to CAN(2).
- *brs_prescaler* is the value by which the CAN FD input clock is divided to generate the
data bit time quanta. The prescaler can be a value between 1 and 32 inclusive.
- *brs_sjw* is the resynchronisation jump width in units of time quanta for data bits;
it can be a value between 1 and 16 inclusive
- *brs_bs1* defines the location of the sample point in units of the time quanta for data bits;
it can be a value between 1 and 32 inclusive
- *brs_bs2* defines the location of the transmit point in units of the time quanta for data bits;
it can be a value between 1 and 16 inclusive
- *brs_baudrate* if a baudrate other than 0 is provided, this function will try to automatically
calculate the CAN data bit time (overriding *brs_prescaler*, *brs_bs1* and *brs_bs2*) that satisfies
both the baudrate and the desired *brs_sample_point*.
- *brs_sample_point* given in a percentage of the data bit time, the *brs_sample_point* specifies the position
of the bit sample with respect to the whole data bit time. The default *brs_sample_point* is 75%.
The time quanta tq is the basic unit of time for the CAN bus. tq is the CAN
prescaler value divided by PCLK1 (the frequency of internal peripheral bus 1);
@ -140,17 +154,17 @@ Methods
- number of pending RX messages on fifo 0
- number of pending RX messages on fifo 1
.. method:: CAN.setfilter(bank, mode, fifo, params, *, rtr)
.. method:: CAN.setfilter(bank, mode, fifo, params, *, rtr, extframe=False)
Configure a filter bank:
- *bank* is the filter bank that is to be configured.
- *mode* is the mode the filter should operate in.
- *bank* is the classic CAN controller filter bank, or CAN FD filter index, to configure.
- *mode* is the mode the filter should operate in, see the tables below.
- *fifo* is which fifo (0 or 1) a message should be stored in, if it is accepted by this filter.
- *params* is an array of values the defines the filter. The contents of the array depends on the *mode* argument.
+-----------+---------------------------------------------------------+
|*mode* |contents of *params* array |
|*mode* |Contents of *params* array for classic CAN controller |
+===========+=========================================================+
|CAN.LIST16 |Four 16 bit ids that will be accepted |
+-----------+---------------------------------------------------------+
@ -165,10 +179,20 @@ Methods
|CAN.MASK32 |As with CAN.MASK16 but with only one 32 bit id/mask pair.|
+-----------+---------------------------------------------------------+
- *rtr* is an array of booleans that states if a filter should accept a
remote transmission request message. If this argument is not given
then it defaults to ``False`` for all entries. The length of the array
depends on the *mode* argument.
+-----------+---------------------------------------------------------+
|*mode* |Contents of *params* array for CAN FD controller |
+===========+=========================================================+
|CAN.RANGE |Two ids that represent a range of accepted ids. |
+-----------+---------------------------------------------------------+
|CAN.DUAL |Two ids that will be accepted. For example (1, 2) |
+-----------+---------------------------------------------------------+
|CAN.MASK |One filter ID and a mask. For example (0x111, 0x7FF) |
+-----------+---------------------------------------------------------+
- *rtr* For classic CAN controllers, this is an array of booleans that states if
a filter should accept a remote transmission request message. If this argument
is not given then it defaults to ``False`` for all entries. The length of the
array depends on the *mode* argument. For CAN FD, this argument is ignored.
+-----------+----------------------+
|*mode* |length of *rtr* array |
@ -182,11 +206,17 @@ Methods
|CAN.MASK32 |1 |
+-----------+----------------------+
.. method:: CAN.clearfilter(bank)
- *extframe* If True the frame will have an extended identifier (29 bits),
otherwise a standard identifier (11 bits) is used.
.. method:: CAN.clearfilter(bank, extframe=False)
Clear and disables a filter bank:
- *bank* is the filter bank that is to be cleared.
- *bank* is the classic CAN controller filter bank, or CAN FD filter index, to clear.
- *extframe* For CAN FD controllers, if True, clear an extended filter (configured with extframe=True),
otherwise the clear a standard identifier (configured with extframe=False).
.. method:: CAN.any(fifo)
@ -200,21 +230,22 @@ Methods
- *list* is an optional list object to be used as the return value
- *timeout* is the timeout in milliseconds to wait for the receive.
Return value: A tuple containing four values.
Return value: A tuple containing five values.
- The id of the message.
- A boolean that indicates if the message ID is standard or extended.
- A boolean that indicates if the message is an RTR message.
- The FMI (Filter Match Index) value.
- An array containing the data.
If *list* is ``None`` then a new tuple will be allocated, as well as a new
bytes object to contain the data (as the fourth element in the tuple).
bytes object to contain the data (as the fifth element in the tuple).
If *list* is not ``None`` then it should be a list object with a least four
elements. The fourth element should be a memoryview object which is created
If *list* is not ``None`` then it should be a list object with a least five
elements. The fifth element should be a memoryview object which is created
from either a bytearray or an array of type 'B' or 'b', and this array must
have enough room for at least 8 bytes. The list object will then be
populated with the first three return values above, and the memoryview object
populated with the first four return values above, and the memoryview object
will be resized inplace to the size of the data and filled in with that data.
The same list and memoryview objects can be reused in subsequent calls to
this method, providing a way of receiving data without using the heap.
@ -225,7 +256,7 @@ Methods
# No heap memory is allocated in the following call
can.recv(0, lst)
.. method:: CAN.send(data, id, *, timeout=0, rtr=False)
.. method:: CAN.send(data, id, *, timeout=0, rtr=False, extframe=False, fdf=False, brs=False)
Send a message on the bus:
@ -236,6 +267,13 @@ Methods
a remote transmission request. If *rtr* is True then only the length
of *data* is used to fill in the DLC slot of the frame; the actual
bytes in *data* are unused.
- *extframe* if True the frame will have an extended identifier (29 bits),
otherwise a standard identifier (11 bits) is used.
- *fdf* for CAN FD controllers, if set to True, the frame will have an FD
frame format, which supports data payloads up to 64 bytes.
- *brs* for CAN FD controllers, if set to True, the bitrate switching mode
is enabled, in which the data phase is transmitted at a differet bitrate.
See :meth:`CAN.init` for the data bit timing configuration parameters.
If timeout is 0 the message is placed in a buffer in one of three hardware
buffers and the method returns immediately. If all three buffers are in use
@ -302,4 +340,10 @@ Constants
CAN.LIST32
CAN.MASK32
The operation mode of a filter used in :meth:`~CAN.setfilter()`.
The operation mode of a filter used in :meth:`~CAN.setfilter()` for classic CAN.
.. data:: CAN.DUAL
CAN.RANGE
CAN.MASK
The operation mode of a filter used in :meth:`~CAN.setfilter()` for CAN FD.

View File

@ -122,3 +122,15 @@ Methods
dac2 = DAC(2)
dac1.write_timed(buf1, pyb.Timer(6, freq=100), mode=DAC.CIRCULAR)
dac2.write_timed(buf2, pyb.Timer(7, freq=200), mode=DAC.CIRCULAR)
Constants
---------
.. data:: DAC.NORMAL
NORMAL mode does a single transmission of the waveform in the data buffer,
.. data:: DAC.CIRCULAR
CIRCULAR mode does a transmission of the waveform in the data buffer, and wraps around
to the start of the data buffer every time it reaches the end of the table.

View File

@ -98,7 +98,7 @@ Class methods
Methods
-------
.. method:: Pin.init(mode, pull=Pin.PULL_NONE, \*, value=None, alt=-1)
.. method:: Pin.init(mode, pull=Pin.PULL_NONE, *, value=None, alt=-1)
Initialise the pin:
@ -237,17 +237,17 @@ pin X3.
For the pyboard, x3_af would contain:
[Pin.AF1_TIM2, Pin.AF2_TIM5, Pin.AF3_TIM9, Pin.AF7_USART2]
Normally, each peripheral would configure the af automatically, but sometimes
the same function is available on multiple pins, and having more control
is desired.
Normally, each peripheral would configure the alternate function automatically,
but sometimes the same function is available on multiple pins, and having more
control is desired.
To configure X3 to expose TIM2_CH3, you could use::
pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF1_TIM2)
pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, alt=pyb.Pin.AF1_TIM2)
or::
pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=1)
pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, alt=1)
Methods
-------

View File

@ -51,7 +51,7 @@ Methods
Turn off the SPI bus.
.. method:: SPI.init(mode, baudrate=328125, *, prescaler, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
.. method:: SPI.init(mode, baudrate=328125, *, prescaler=-1, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
Initialise the SPI bus with the given parameters:

View File

@ -262,3 +262,12 @@ Methods
for which the pulse is active. The value can be an integer or
floating-point number for more accuracy. For example, a value of 25 gives
a duty cycle of 25%.
Constants
---------
.. data:: Timer.UP
Timer.DOWN
Timer.CENTER
Configures the timer to count Up, Down, or from 0 to ARR and then back down to 0.

View File

@ -298,6 +298,15 @@ Miscellaneous functions
The *high_speed* parameter, when set to ``True``, enables USB HS mode if
it is supported by the hardware.
Constants
---------
.. data:: pyb.hid_mouse
pyb.hid_keyboard
A tuple of (subclass, protocol, max packet length, polling interval, report
descriptor) to set appropriate values for a USB mouse or keyboard.
Classes
-------

View File

@ -10,7 +10,7 @@ The ``rp2`` module contains functions and classes specific to the RP2040, as
used in the Raspberry Pi Pico.
See the `RP2040 Python datasheet
<https://datasheets.raspberrypi.org/pico/raspberry-pi-pico-python-sdk.pdf>`_
<https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-python-sdk.pdf>`_
for more information, and `pico-micropython-examples
<https://github.com/raspberrypi/pico-micropython-examples/tree/master/pio>`_
for example code.

View File

@ -66,19 +66,6 @@ Tuple address format for ``socket`` module:
Functions
---------
.. function:: socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, /)
Create a new socket using the given address family, socket type and
protocol number. Note that specifying *proto* in most cases is not
required (and not recommended, as some MicroPython ports may omit
``IPPROTO_*`` constants). Instead, *type* argument will select needed
protocol automatically::
# Create STREAM TCP socket
socket(AF_INET, SOCK_STREAM)
# Create DGRAM UDP socket
socket(AF_INET, SOCK_DGRAM)
.. function:: getaddrinfo(host, port, af=0, type=0, proto=0, flags=0, /)
Translate the host/port argument into a sequence of 5-tuples that contain all the
@ -176,6 +163,19 @@ Constants specific to WiPy:
class socket
============
.. class:: socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, /)
Create a new socket using the given address family, socket type and
protocol number. Note that specifying *proto* in most cases is not
required (and not recommended, as some MicroPython ports may omit
``IPPROTO_*`` constants). Instead, *type* argument will select needed
protocol automatically::
# Create STREAM TCP socket
socket(AF_INET, SOCK_STREAM)
# Create DGRAM UDP socket
socket(AF_INET, SOCK_DGRAM)
Methods
-------

View File

@ -70,6 +70,8 @@ Constants
* *name* - string "micropython"
* *version* - tuple (major, minor, micro), e.g. (1, 7, 0)
* *_machine* - string describing the underlying machine
* *_mpy* - supported mpy file-format version (optional attribute)
This object is the recommended way to distinguish MicroPython from other
Python implementations (note that it still may not exist in the very
@ -132,6 +134,12 @@ Constants
If you need to check whether your program runs on MicroPython (vs other
Python implementation), use `sys.implementation` instead.
.. data:: ps1
ps2
Mutable attributes holding strings, which are used for the REPL prompt. The defaults
give the standard Python prompt of ``>>>`` and ``...``.
.. data:: stderr
Standard error `stream`.
@ -144,6 +152,14 @@ Constants
Standard output `stream`.
.. data:: tracebacklimit
A mutable attribute holding an integer value which is the maximum number of traceback
entries to store in an exception. Set to 0 to disable adding tracebacks. Defaults
to 1000.
Note: this is not available on all ports.
.. data:: version
Python language version that this implementation conforms to, as a string.

View File

@ -159,7 +159,7 @@ class ThreadSafeFlag
.. method:: ThreadSafeFlag.wait()
Wait for the flag to be set. If the flag is already set then it returns
immediately.
immediately. The flag is automatically reset upon return from ``wait``.
A flag may only be waited on by a single task at a time.

397
docs/library/wm8960.rst Normal file
View File

@ -0,0 +1,397 @@
.. _wm8960:
:mod:`WM8960` -- Driver for the WM8960 codec
============================================
This driver is used to control a WM8960 codec chip. It is a Python
translation of the C-Code provided by NXP/Freescale for their i.MX RT series of
MCUs. Very little has been added, and just a few API related names were changed
or added to cope with the naming style of MicroPython.
The primary purpose of the driver is initialization and setting operation modes
of the codec. It does not do the audio data processing for the codec. That is
the task of a separate driver.
The WM8960 supports an I2C interface, in addition to the audio interface. The
connection depends on the interface used and the number of devices in the
system. For the I2C interface, SCL and SDA have to be connected, and of course
GND and Vcc. The I2C default address is ``0x1A``.
Constructor
-----------
.. class:: WM8960(i2c, sample_rate, *, bits=16, swap=SWAP_NONE, route=ROUTE_PLAYBACK_RECORD, left_input=INPUT_MIC3, right_input=INPUT_MIC2, sysclk_source=SYSCLK_MCLK, mclk_freq=None, primary=False, adc_sync=SYNC_DAC, protocol=BUS_I2S, i2c_address=WM8960_I2C_ADDR)
Create a WM8960 driver object, initialize the device with default settings and return the
WM8960 object.
Only the first two arguments are mandatory. All others are optional. The arguments are:
- *i2c* is the I2C bus object.
- *sample_rate* is the audio sample rate. Acceptable values are 8000,
11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 96000, 192000
and 384000. Note that not every I2S hardware will support all values.
- *bits* is the number of bits per audio word. Acceptable value are 16,
20, 24, and 32.
- *swap* swaps the left & right channel, if set; see below for options.
- *route* Setting the audio path in the codec; see below for options.
- *left_input* sets the audio source for the left input channel;
see below for options.
- *right_input* sets the audio source for the right input channel;
see below for options.
- *play_source* sets the audio target for the output audio;
see below for options.
- *sysclk_source* controls whether the internal master clock called
"sysclk" is directly taken from the MCLK input or derived from it
using an internal PLL. It is usually not required to change this.
- *mclk_freq* sets the mclk frequency applied to the MCLK pin of the
codec. If not set, default values are used.
- *primary* lets the WM8960 act as primary or secondary device. The
default setting is ``False``. When set to ``False``,
*sample_rate* and *bits* are controlled by the MCU.
- *adc_sync* sets which input is used for the ADC sync signal.
The default is using the DACLRC pin.
- *protocol* sets the communication protocol. The default is I2S.
See below for all options.
- *i2c_address* sets the I2C address of the WM8960, with default ``0x1A``.
If *mclk_freq* is not set the following default values are used:
- sysclk_source == SYSCLK_PLL: 11.2896 MHz for sample rates of 44100,
22050 and 11015 Hz, and 12.288 Mhz for sample rates < 48000, otherwise
sample_rate * 256.
- sysclk_source == SYSCLK_MCLK: sample_rate * 256.
If the MCLK signal is applied using, for example,. a separate oscillator,
it must be specified for proper operation.
Tables of parameter constants
-----------------------------
.. table:: **Swap Parameter**
:widths: auto
:align: left
===== ====
Value Name
===== ====
0 SWAP_NONE
1 SWAP_INPUT
2 SWAP_OUTPUT
===== ====
.. table:: **Protocol Parameter**
:widths: auto
:align: left
===== ====
Value Name
===== ====
2 BUS_I2S
1 BUS_LEFT_JUSTIFIED
0 BUS_RIGHT_JUSTIFIED
3 BUS_PCMA
19 BUS_PCMB
===== ====
.. table:: **Input Source Parameter**
:widths: auto
:align: left
===== ============ ====
Value Name Type
===== ============ ====
0 INPUT_CLOSED
1 INPUT_MIC1 Single ended
2 INPUT_MIC2 Differential
3 INPUT_MIC3 Differential
4 INPUT_LINE2
5 INPUT_LINE3
===== ============ ====
.. table:: **Route Parameter**
:widths: auto
:align: left
===== ====
Value Name
===== ====
0 ROUTE_BYPASS
1 ROUTE_PLAYBACK
2 ROUTE_PLAYBACK_RECORD
5 ROUTE_RECORD
===== ====
.. table:: **Master Clock Source Parameter**
:widths: auto
:align: left
===== ====
Value Name
===== ====
0 SYSCLK_MCLK
1 SYSCLK_PLL
===== ====
.. table:: **Module Names**
:widths: auto
:align: left
===== ====
Value Name
===== ====
0 MODULE_ADC
1 MODULE_DAC
2 MODULE_VREF
3 MODULE_HEADPHONE
4 MODULE_MIC_BIAS
5 MODULE_MIC
6 MODULE_LINE_IN
7 MODULE_LINE_OUT
8 MODULE_SPEAKER
9 MODULE_OMIX
10 MODULE_MONO_OUT
===== ====
.. table:: **Play Channel Names**
:widths: auto
:align: left
===== ====
Value Name
===== ====
1 PLAY_HEADPHONE_LEFT
2 PLAY_HEADPHONE_RIGHT
4 PLAY_SPEAKER_LEFT
8 PLAY_SPEAKER_RIGHT
===== ====
.. table:: **adc_sync Parameters**
:widths: auto
:align: left
===== ====
Value Name
===== ====
0 SYNC_ADC
1 SYNC_DAC
===== ====
Methods
-------
In addition to initialization, the driver provides some useful methods for
controlling its operation:
.. method:: WM8960.set_left_input(input_source)
Specify the source for the left input. The input source names are listed above.
.. method:: WM8960.set_right_input(input_source)
Specify the source for the right input. The input source names are listed above.
.. method:: WM8960.volume(module, volume_l=None, volume_r=None)
Sets or gets the volume of a certain module.
If no volume values are supplied, the actual volume tuple is returned.
If one or two values are supplied, it sets the volume of a certain module.
If two values are provided, the first one is used for the left channel,
the second for the right channel. If only one value is supplied, it is used
for both channels. The value range is normalized to 0.0-100.0 with a
logarithmic scale.
For a list of suitable modules and db/step, see the table below.
.. table:: **Module Names and dB steps**
:widths: auto
:align: center
======= ====
dB/Step Name
======= ====
1.28 MODULE_ADC
1.28 MODULE_DAC
0.8 MODULE_HEADPHONE
0.475 MODULE_LINE_IN
0.8 MODULE_SPEAKER
======= ====
.. method:: WM8960.mute(module, mute, soft=True, ramp=wm8960.MUTE_FAST)
Mute or unmute the output. If *mute* is True, the output is muted, if ``False``
it is unmuted.
If *soft* is set as True, muting will happen as a soft transition. The time for
the transition is defined by *ramp*, which is either ``MUTE_FAST`` or ``MUTE_SLOW``.
.. method:: WM8960.set_data_route(route)
Set the audio data route. For the parameter value/names, see the table above.
.. method:: WM8960.set_module(module, active)
Enable or disable a module, with *active* being ``False`` or ``True``. For
the list of module names, see the table above.
Note that enabling ``MODULE_MONO_OUT`` is different from the `WM8960.mono`
method. The first enables output 3, while the `WM8960.mono` method sends a
mono mix to the left and right output.
.. method:: WM8960.enable_module(module)
Enable a module. For the list of module names, see the table above.
.. method:: WM8960.disable_module(module)
Disable a module. For the list of module names, see the table above.
.. method:: WM8960.expand_3d(level)
Enable Stereo 3D exansion. *level* is a number between 0 and 15.
A value of 0 disables the expansion.
.. method:: WM8960.mono(active)
If *active* is ``True``, a Mono mix is sent to the left and right output
channel. This is different from enabling the ``MODULE_MONO_MIX``, which
enables output 3.
.. method:: WM8960.alc_mode(channel, mode=ALC_MODE)
Enables or disables ALC mode. Parameters are:
- *channel* enables and sets the channel for ALC. The parameter values are:
- ALC_OFF: Switch ALC off
- ALS_RIGHT: Use the right input channel
- ALC_LEFT: Use the left input channel
- ALC_STEREO: Use both input channels.
- *mode* sets the ALC mode. Input values are:
- ALC_MODE: act as ALC
- ALC_LIMITER: act as limiter.
.. method:: WM8960.alc_gain(target=-12, max_gain=30, min_gain=-17.25, noise_gate=-78)
Set the target level, highest and lowest gain levels and the noise gate as dB level.
Permitted ranges are:
- *target*: -22.5 to -1.5 dB
- *max_gain*: -12 to 30 dB
- *min_gain*: -17 to 25 dB
- *noise_gate*: -78 to -30 dB
Excess values are limited to the permitted ranges. A value of -78 or less
for *noise_gate* disables the noise gate function.
.. method:: WM8960.alc_time(attack=24, decay=192, hold=0)
Set the dynamic characteristic of ALC. The times are given as millisecond
values. Permitted ranges are:
- *attack*: 6 to 6140
- *decay*: 24 to 24580
- *hold*: 0 to 43000
Excess values are limited within the permitted ranges.
.. method:: WM8960.deemphasis(active)
Enables or disables a deemphasis filter for playback, with *active* being
``False`` or ``True``. This filter is applied only for sample rates of
32000, 44100 and 48000. For other sample rates, the filter setting
is silently ignored.
.. method:: WM8960.deinit()
Disable all modules.
Examples
--------
Run WM8960 in secondary mode (default)::
# Micro_python WM8960 Codec driver
#
# Setting the driver to Slave mode using the default settings
#
from machine import Pin, I2C
import wm8960
i2c = I2C(0)
wm=wm8960.WM8960(i2c, 32000, left_input=wm8960.INPUT_MIC1)
wm.set_volume(wm8960.MODULE_HEADPHONE, 100)
Run WM8960 in primary mode::
# Micro_python WM8960 Codec driver
#
# Setting the driver to Master mode using specific audio format settings
#
from machine import Pin, I2C
import wm8960
i2c = I2C(0)
wm=wm8960.WM8960(i2c, 44100, primary=True, bits=16)
Run WM8960 on a MIMXRT10xx_DEV board in secondary mode (default)::
# Micro_python WM8960 Codec driver
#
# Setting the driver to Slave mode using the default settings
# swap the input channels such that a MIMXRT Dev board mic, which
# is connected to the right input, is assigned to the left audio channel.
#
from machine import Pin, I2C
import wm8960
i2c = I2C(0)
wm=wm8960.WM8960(i2c, sample_rate=16_000,
adc_sync=wm8960.SYNC_DAC,
swap=wm8960.SWAP_INPUT,
sysclk_source=wm8960.SYSCLK_MCLK)
Record with a Sparkfun WM8960 breakout board with Teensy in secondary mode (default)::
# Micro_python WM8960 Codec driver
#
# The breakout board uses a fixed 24MHz MCLK. Therefore the internal
# PLL must be used as sysclk, which is the master audio clock.
# The Sparkfun board has the WS pins for RX and TX connected on the
# board. Therefore adc_sync must be set to sync_adc, to configure
# it's ADCLRC pin as input.
#
from machine import Pin, I2C
import wm8960
i2c = I2C(0)
wm=wm8960.WM8960(i2c, sample_rate=16_000,
adc_sync=wm8960.SYNC_ADC,
sysclk_source=wm8960.SYSCLK_PLL,
mclk_freq=24_000_000,
left_input=wm8960.INPUT_MIC1,
right_input=wm8960.INPUT_CLOSED)
Play with a Sparkfun WM8960 breakout board with Teensy in secondary mode (default)::
# The breakout board uses a fixed 24MHz MCLK. Therefore the internal
# PLL must be used as sysclk, which is the master audio clock.
# The Sparkfun board has the WS pins for RX and TX connected on the
# board. Therefore adc_sync must be set to sync_adc, to configure
# it's ADCLRC pin as input.
from machine import I2C
i2c=I2C(0)
import wm8960
wm=wm8960.WM8960(i2c, sample_rate=44_100,
adc_sync=wm8960.SYNC_ADC,
sysclk_source=wm8960.SYSCLK_PLL,
mclk_freq=24_000_000)
wm.set_volume(wm8960.MODULE_HEADPHONE, 100)

94
docs/mimxrt/general.rst Normal file
View File

@ -0,0 +1,94 @@
.. _mimxrt_general:
General information about the MIMXRT port
=========================================
The i.MXRT MCU family is a high performance family of devices made by NXP.
Based on an ARM7 core, they provide many on-chip I/O units for building
small to medium sized devices.
Multitude of boards
-------------------
There is a multitude of modules and boards from different sources which carry
an i.MXRT chip. MicroPython aims to provide a generic port which runs on
as many boards/modules as possible, but there may be limitations. The
NXP IMXRT1020-EVK and the Teensy 4.0 and Teensy 4.1 development boards are taken
as reference for the port (for example, testing is performed on them).
For any board you are using please make sure you have a data sheet, schematics
and other reference materials so you can look up any board-specific functions.
The following boards are supported by the port:
- MIMXRT1010-EVK
- MIMXRT1020-EVK
- MIMXRT1050-EVK
- MIMXRT1060-EVK
- MIMXRT1064-EVK
- Teensy 4.0
- Teensy 4.1
Supported MCUs
--------------
+-------------+--------------------+-------------------------+
| Product | CPU | Memory |
+=============+====================+=========================+
| i.MX RT1064 | Cortex-M7 @600 MHz | 1 MB SRAM, 4 MB Flash |
+-------------+--------------------+-------------------------+
| i.MX RT1061 | Cortex-M7 @600 MHz | 1 MB SRAM |
+-------------+--------------------+-------------------------+
| i.MX RT1062 | Cortex-M7 @600 MHz | 1 MB SRAM |
+-------------+--------------------+-------------------------+
| i.MX RT1050 | Cortex-M7 @600 MHz | 512 kB SRAM |
+-------------+--------------------+-------------------------+
| i.MX RT1020 | Cortex-M7 @500 MHz | 256 kB SRAM |
+-------------+--------------------+-------------------------+
| i.MX RT1015 | Cortex-M7 @500 MHz | 128 kB SRAM |
+-------------+--------------------+-------------------------+
| i.MX RT1010 | Cortex-M7 @500 MHz | 128 kB SRAM |
+-------------+--------------------+-------------------------+
Note: Most of the controllers do not have internal flash memory. Therefore
their flash capacity is dependent on an external flash chip.
To make a generic MIMXRT port and support as many boards as possible the
following design and implementation decision were made:
* GPIO pin numbering is based on the board numbering as well as on the
MCU numbering. Please have the manual/pin diagram of your board at hand
to find correspondence between your board pins and actual i.MXRT pins.
* All MCU pins are supported by MicroPython but not all are usable on any given board.
Technical specifications and SoC datasheets
-------------------------------------------
The data sheets and other reference material for i.MXRT chip are available
from the vendor site: https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/i-mx-rt-crossover-mcus:IMX-RT-SERIES .
They are the primary reference for the chip technical specifications, capabilities,
operating modes, internal functioning, etc.
For your convenience, a few technical specifications are provided below:
* Architecture: ARM Cortex M7
* CPU frequency: up to 600MHz
* Total RAM available: up to 1 MByte (see table)
* BootROM: 96KB
* External FlashROM: code and data, via SPI Flash; usual size 2 - 16 MB
Some boards provide additional external RAM and SPI flash.
* GPIO: up to 124 (GPIOs are multiplexed with other functions, including
external FlashROM, UART, etc.)
* UART: 4 or 8 RX/TX UART. Hardware handshaking is supported by the MCU,
but the boards used for testing do not expose the signals.
* SPI: 2 or 4 low power SPI interfaces (software implementation available on every pin)
* I2C: 2 or 4 low power I2C interfaces (software implementation available on every pin)
* I2S: 1 to 3 I2S interfaces
* ADC: one or two 12-bit SAR ADC converters
* Ethernet controller (except i.MX RT1010/-1015)
* Programming: using BootROM bootloader from USB - due to external FlashROM
and always-available BootROM bootloader, the MIMXRT is not brickable
The lower numbers for UART, SPI and I2C apply to the i.MXRT 101x MCU.
For more information see the i.MXRT data sheets or reference manuals.
NXP provides software support through it's SDK packages.

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

380
docs/mimxrt/pinout.rst Normal file
View File

@ -0,0 +1,380 @@
.. _mimxrt_pinout:
Pinout for the i.MXRT machine modules
=====================================
.. _mimxrt_uart_pinout:
|
UART pin assignment
-------------------
The pin assignment of UARTs to pins is fixed.
The UARTs are numbered 0..8. The rx/tx pins are assigned according to the
tables below:
================ =========== =========== =========== ===========
Board / Pin UART0 UART1 UART2 UART3
================ =========== =========== =========== ===========
Teensy 4.0 - 0/1 7/8 14/15
Teensy 4.1 - 0/1 7/8 14/15
MIMXRT1010-EVK Debug USB D0/D1 D7/D6 -
MIMXRT1015-EVK Debug USB D0/D1 D7/A1 -
MIMXRT1020-EVK Debug USB D0/D1 D9/D6 D10/D13
MIMXRT1050-EVK Debug USB D0/D1 D7/D6 D8/D9
MIMXRT1050-EVKB Debug USB D0/D1 D7/D6 D8/D9
MIMXRT1060-EVK Debug USB D0/D1 D7/D6 D8/D9
MIMXRT1064-EVK Debug USB D0/D1 D7/D6 D8/D9
MIMXRT1170-EVK Debug USB D0/D1 D12/D11 D10/D13
Olimex RT1010Py - RxD/TxD D5/D6 -
Seeed ARCH MIX - J3_19/J3_20 J4_16/J4_17 J4_06/J4_07
================ =========== =========== =========== ===========
|
================ =========== =========== ======= ======= =====
Board / Pin UART4 UART5 UART6 UART7 UART8
================ =========== =========== ======= ======= =====
Teensy 4.0 16/17 21/20 25/24 28/29 -
Teensy 4.1 16/17 21/20 25/24 28/29 34/35
MIMXRT1010-EVK - - - - -
MIMXRT1015-EVK - - - - -
MIMXRT1020-EVK D15/D14 A1/A0 - - -
MIMXRT1050-EVK A1/A0 - - - -
MIMXRT1050-EVKB A1/A0 - - - -
MIMXRT1060-EVK A1/A0 - - - -
MIMXRT1064-EVK A1/A0 - - - -
MIMXRT1170-EVK D15/D14 D25/D26 D33/D34 D35/D36 -
Olimex RT1010Py - - - - -
Seeed ARCH MIX J4_10/J4_11 J5_08/J5_12 - - -
================ =========== =========== ======= ======= =====
.. _mimxrt_pwm_pinout:
|
|
PWM pin assignment
------------------
Pins are specified in the same way as for the Pin class. The following tables show
the assignment of the board Pins to PWM modules:
=========== ========== ========== ====== ============== ======
Pin/ MIMXRT 1010 1015 1020 1050/1060/1064 1170
=========== ========== ========== ====== ============== ======
D0 - Q1/1 F1/1/B - -
D1 - Q1/0 F1/1/A - -
D2 F1/3/B F1/3/A - F1/3/B -
D3 F1/3/A F1/0/A F2/3/B F4/0/A F1/2/A
D4 F1/3/A (*) Q1/2 Q2/1 F2/3/A Q4/2
D5 F1/0/B (*) F1/0/B F2/3/A F1/3/A F1/2/B
D6 - F1/2/B F2/0/A Q3/2 F1/0/A
D7 - - F1/0/A Q3/3 -
D8 F1/0/A F1/1/B F1/0/B F1/1/X Q4/3
D9 F1/1/B (*) F1/2/A F2/0/B F1/0/X F1/0/B
D10 F1/3/B - F2/2/B F1/0/B (*) F2/2/B
D11 F1/2/A - F2/1/A F1/1/A (*) -
D12 F1/2/B - F2/1/B F1/1/B (*) -
D13 F1/3/A - F2/2/A F1/0/A (*) F2/2/A
D14 F1/0/B - - F2/3/B -
D15 F1/0/A - - F2/3/A -
A0 - - F1/2/A - -
A1 F1/3/X F1/3/B F1/2/B - -
A2 F1/2/X F1/3/A F1/3/A - -
A3 - F1/2/A F1/3/B - -
A4 - - - Q3/1 -
A5 - - - Q3/0 -
D31 - - - - F1/2/B
D32 - - - - F1/2/A
D33 - - - - F1/1/B
D34 - - - - F1/1/A
D35 - - - - F1/0/B
D36 - - - - F1/0/A
=========== ========== ========== ====== ============== ======
Pins denoted with (*) are by default not wired at the board.
==== ========== ==== ==========
Pin Teensy 4.0 Pin Teensy 4.1
==== ========== ==== ==========
0 F1/1/X 0 F1/1/X
1 F1/0/X 1 F1/0/X
2 F4/2/A 2 F4/2/A
3 F4/2/B 3 F4/2/B
4 F2/0/A 4 F2/0/A
5 F2/1/A 5 F2/1/A
6 F2/2/A 6 F2/2/A
7 F1/3/B 7 F1/3/B
8 F1/3/A 8 F1/3/A
9 F2/2/B 9 F2/2/B
10 Q1/0 10 Q1/0
11 Q1/2 11 Q1/2
12 Q1/1 12 Q1/1
13 Q2/0 13 Q2/0
14 Q3/2 14 Q3/2
15 Q3/3 15 Q3/3
18 Q3/1 18 Q3/1
19 Q3/0 19 Q3/0
22 F4/0/A 22 F4/0/A
23 F4/1/A 23 F4/1/A
24 F1/2/X 24 F1/2/X
25 F1/3/X 25 F1/3/X
28 F3/1/B 28 F3/1/B
29 F3/1/A 29 F3/1/A
33 F2/0/B 33 F2/0/B
- - 36 F2/3/A
- - 37 F2/3/B
DAT1 F1/1/B 42 F1/1/B
DAT0 F1/1/A 43 F1/1/A
CLK F1/0/B 44 F1/0/B
CMD F1/0/A 45 F1/0/A
DAT2 F1/2/A 46 F1/2/A
DAT3 F1/2/B 47 F1/2/B
- - 48 F1/0/B
- - 49 F1/2/A
- - 50 F1/2/B
- - 51 F3/3/B
- - 52 F1/1/B
- - 53 F1/1/A
- - 54 F3/0/A
==== ========== ==== ==========
|
========= ==============
Pin Seeed ARCH MIX
========= ==============
J3_04 Q4/3
J3_10 Q1/3
J3_12 Q2/3
J3_13 Q3/3
J3_16 Q3/0
J3_17 Q3/1
J3_19 F1/3/X
J3_20 F1/2/X
J4_08 F4/0/A
J4_09 F4/1/A
J4_16 Q3/2
J4_17 Q3/3
J5_32 Q1/0
J5_28 Q1/1
J5_29 Q1/2
J5_30 Q2/0
J5_04 Q2/1
J5_05 Q2/3
J5_06 F2/0/A
J5_07 F2/0/B
J5_08 F2/1/A
J5_12 F2/1/B
J5_13 F2/2/A
J5_14 F2/2/B
J5_23 F1/3/A
J5_24 F1/3/B
J5_25 F2/3/A
J5_26 F2/3/B
J5_42 Q3/0
J5_43 Q3/1
J5_50 F1/0/X
LED_RED F2/3/A
LED_GREEN F1/3/A
LED_BLUE F1/3/B
========= ==============
|
========= ===============
Pin Olimex RT1010PY
========= ===============
D0 -
D1 F1/0/B
D2 F1/0/A
D3 F1/1/B
D4 F1/1/A
D5 F1/2/B
D6 F1/2/A
D7 F1/3/B
D8 F1/3/A
D9 -
D10 F1/0/B
D11 F1/0/A
D12 F1/1/B
D13 F1/1/A
D14 -
A0 -
A1 F1/2/B
A2 F1/2/A
A3 F1/3/B
A4 F1/3/A
SDI F1/3/X
SDO F1/2/X
CS0 F1/1/X
SCK F1/0/X
========= ===============
Legend:
* Qm/n: QTMR module m, channel n
* Fm/n/l: FLEXPWM module m, submodule n, channel l. The pulse at a X channel
is always aligned to the period start.
Pins without a PWM signal are not listed. A signal may be available at more
than one Pin. FlexPWM pins may also be pure CPU pin, not assigned to a board
signal. In that case the PWM output is disabled. The PWM channel of a submodule
0 may still be used as synchronization source for other channels of the same
module, unless used by another peripheral.
Submodule 0 pins for i.MX RT1011:
================== =======
Pin Channel
================== =======
Pin.cpu.GPIO_01 B
Pin.cpu.GPIO_02 A
Pin.cpu.GPIO_AD_12 X
Pin.cpu.GPIO_SD_01 B
Pin.cpu.GPIO_SD_02 A
================== =======
Submodule 0 pins for i.MX RT1021:
===================== ==================
Pin Module & Channel
===================== ==================
Pin.cpu.GPIO_AD_B1_06 FLEXPWM1 Channel A
Pin.cpu.GPIO_AD_B1_07 FLEXPWM1 Channel B
Pin.cpu.GPIO_EMC_26 FLEXPWM1 Channel A
Pin.cpu.GPIO_EMC_27 FLEXPWM1 Channel B
Pin.cpu.GPIO_AD_B0_14 FLEXPWM2 Channel A
Pin.cpu.GPIO_AD_B0_15 FLEXPWM2 Channel B
Pin.cpu.GPIO_EMC_10 FLEXPWM2 Channel X
Pin.cpu.GPIO_EMC_38 FLEXPWM2 Channel A
Pin.cpu.GPIO_EMC_39 FLEXPWM2 Channel B
===================== ==================
Submodule 0 pins for i.MX RT1052, i.MX RT1062 and i.MX RT1064:
===================== ==================
Pin Module & Channel
===================== ==================
Pin.cpu.GPIO_AD_B0_02 FLEXPWM1 Channel X
Pin.cpu.GPIO_EMC_23 FLEXPWM1 Channel A
Pin.cpu.GPIO_EMC_24 FLEXPWM1 Channel B
Pin.cpu.GPIO_SD_B0_00 FLEXPWM1 Channel A
Pin.cpu.GPIO_SD_B0_01 FLEXPWM1 Channel B
Pin.cpu.GPIO_B0_06 FLEXPWM2 Channel A
Pin.cpu.GPIO_B0_07 FLEXPWM2 Channel B
Pin.cpu.GPIO_EMC_06 FLEXPWM2 Channel A
Pin.cpu.GPIO_EMC_07 FLEXPWM2 Channel B
Pin.cpu.GPIO_EMC_29 FLEXPWM3 Channel A
Pin.cpu.GPIO_EMC_30 FLEXPWM3 Channel B
Pin.cpu.GPIO_AD_B1_08 FLEXPWM4 Channel A
Pin.cpu.GPIO_EMC_00 FLEXPWM4 Channel A
Pin.cpu.GPIO_EMC_01 FLEXPWM4 Channel B
===================== ==================
Submodule 0 pins for i.MX RT1176
====================== ======================
Pin Module & Channel
====================== ======================
Pin.cpu.GPIO_EMC_B1_00 FLEXPWM4 Channel A (*)
Pin.cpu.GPIO_EMC_B1_01 FLEXPWM4 Channel B (*)
Pin.cpu.GPIO_EMC_B1_06 FLEXPWM2 Channel A (*)
Pin.cpu.GPIO_EMC_B1_07 FLEXPWM2 Channel B (*)
Pin.cpu.GPIO_EMC_B1_23 FLEXPWM1 Channel A (*)
Pin.cpu.GPIO_EMC_B1_24 FLEXPWM1 Channel B (*)
Pin.cpu.GPIO_EMC_B1_29 FLEXPWM3 Channel A (*)
Pin.cpu.GPIO_EMC_B1_30 FLEXPWM3 Channel B (*)
Pin.cpu.GPIO_AD_00 FLEXPWM1 Channel A
Pin.cpu.GPIO_AD_01 FLEXPWM1 Channel B
Pin.cpu.GPIO_AD_24 FLEXPWM2 Channel A
Pin.cpu.GPIO_AD_25 FLEXPWM2 Channel B
====================== ======================
.. _mimxrt_spi_pinout:
|
|
Hardware SPI pin assignment
---------------------------
The SPI signals have fixed assignments to GPIO pins.
It depends on the board design, which SPI's signals are exposed to the user, as
detailed in the table below. The signal order in the table is: CS0, CS1, MOSI, MISO, CLK.
================= ========================= ======================= ===============
Board / Pin SPI0 SPI1 SPI2
================= ========================= ======================= ===============
Teensy 4.0 10/-/11/12/13 0/-/26/1/27 -
Teensy 4.1 10/37/11/12/13 0/-/26/1/27 -/29/50/54/49
MIXMXRT1010-EVK D10/D7/D11/D12/D13 - -
MIXMXRT1015-EVK D10/-/D11/D12/D13 - -
MIXMXRT1020-EVK D10/-/D11/D12/D13 A3/D0/A5/A4/A0 -
MIXMXRT1050-EVK D10/-/D11/D12/D13 (*) - -
MIXMXRT1050-EVKB D10/-/D11/D12/D13 (*) - -
MIXMXRT1060-EVK D10/-/D11/D12/D13 (*) - -
MIXMXRT1064-EVK D10/-/D11/D12/D13 (*) - -
MIXMXRT1170-EVK D10/-/D11/D12/D13 D28/-/D25/D24/D26 -/-/D14/D15/D24
Olimex RT1010Py - CS0/-/SDO/SDI/SCK SDCARD with CS1
Seeed ARCH MIX J4_12/-/J4_14/J4_13/J4_15 J3_09/J3_05/J3_08_J3_11
================= ========================= ======================= ===============
Pins denoted with (*) are by default not wired at the board.
.. _mimxrt_i2c_pinout:
|
|
Hardware I2C pin assignment
---------------------------
The I2C signals have fixed assignments to GPIO pins.
It depends on the board design, which I2C's signals are exposed to the user, as
detailed in the table below. The signal order in the table is: SDA, SCL.
================= =========== =========== =========== ======= =======
Board / Pin I2C 0 I2C 1 I2C 2 I2C 3 I2C 4
================= =========== =========== =========== ======= =======
Teensy 4.0 18/19 17/16 25/24 - -
Teensy 4.1 18/19 17/16 25/24 - -
MIXMXRT1010-EVK D14/D15 D0/D1 - - -
MIXMXRT1015-EVK D14/D15 - - - -
MIXMXRT1020-EVK D14/D15 A4/A5 D0/D1 - -
MIXMXRT1050-EVK A4/A5 D1/D0 - - -
MIXMXRT1050-EVKB A4/A5 D1/D0 - - -
MIXMXRT1060-EVK A4/A5 D1/D0 - - -
MIXMXRT1064-EVK A4/A5 D1/D0 - - -
MIXMXRT1170-EVK D14/D15 D1/D0 A4/A5 D26/D25 D19/D18
Olimex RT1010Py - SDA1/SCL1 SDA2/SCL2 - -
Seeed ARCH MIX J3_17/J3_16 J4_06/J4_07 J5_05/J5_04 - -
================= =========== =========== =========== ======= =======
.. _mimxrt_i2s_pinout:
|
|
Hardware I2S pin assignment
---------------------------
Pin assignments for a few MIMXRT boards:
=============== == ===== ======== ======= ======= ======== ======= =======
Board ID MCK SCK_TX WS_TX SD_TX SCK_RX WS_RX SD_RX
=============== == ===== ======== ======= ======= ======== ======= =======
Teensy 4.0 1 23 26 27 7 21 20 8
Teensy 4.0 2 33 4 3 2 - - 5
Teensy 4.1 1 23 26 27 7 21 20 8
Teensy 4.1 2 33 4 3 2 - - 5
Seeed Arch MIX 1 J4_09 J4_14 J4_15 J14_13 J4_11 J4_10 J4_10
Olimex RT1010Py 1 D8 D6 D7 D4 D1 D2 D3
Olimex RT1010Py 3 - D10 D9 D11 - - -
MIMXRT_DEV 1 "MCK" "SCK_TX" "WS_TX" "SD_TX" "SCK_RX" "WS_RX" "SD_RX"
=============== == ===== ======== ======= ======= ======== ======= =======
Symbolic pin names are provided for the MIMXRT_10xx_DEV boards.
These are provided for the other boards as well.

546
docs/mimxrt/quickref.rst Normal file
View File

@ -0,0 +1,546 @@
.. _mimxrt_quickref:
Quick reference for the i.MXRT family
=====================================
.. image:: img/teensy_4.1.jpg
:alt: Teensy 4.1 board
:width: 640px
The Teensy 4.1 board.
Below is a quick reference for i.MXRT-based boards. If it is your first time
working with this board it may be useful to get an overview of the microcontroller:
.. toctree::
:maxdepth: 1
general.rst
tutorial/intro.rst
pinout.rst
Installing MicroPython
----------------------
See the corresponding section of tutorial: :ref:`mimxrt_intro`. It also includes
a troubleshooting subsection.
General board control
---------------------
The MicroPython REPL is on the USB port, configured in VCP mode.
Tab-completion is useful to find out what methods an object has.
Paste mode (ctrl-E) is useful to paste a large slab of Python code into
the REPL.
The :mod:`machine` module::
import machine
machine.freq() # get the current frequency of the CPU
Delay and timing
----------------
Use the :mod:`time <time>` module::
import time
time.sleep(1) # sleep for 1 second
time.sleep_ms(500) # sleep for 500 milliseconds
time.sleep_us(10) # sleep for 10 microseconds
start = time.ticks_ms() # get millisecond counter
delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference
Timers
------
The i.MXRT port has three hardware timers. Use the :ref:`machine.Timer <machine.Timer>` class
with a timer ID from 0 to 2 (inclusive)::
from machine import Timer
tim0 = Timer(0)
tim0.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(0))
tim1 = Timer(1)
tim1.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(1))
The period is in milliseconds.
Virtual timers are not currently supported on this port.
.. _mimxrt_Pins_and_GPIO:
Pins and GPIO
-------------
Use the :ref:`machine.Pin <machine.Pin>` class::
from machine import Pin
p0 = Pin('D0', Pin.OUT) # create output pin on GPIO0
p0.on() # set pin to "on" (high) level
p0.off() # set pin to "off" (low) level
p0.value(1) # set pin to on/high
p2 = Pin('D2', Pin.IN) # create input pin on GPIO2
print(p2.value()) # get value, 0 or 1
p4 = Pin('D4', Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
p5 = Pin('D5', Pin.OUT, value=1) # set pin high on creation
p6 = Pin(pin.cpu.GPIO_B1_15, Pin.OUT) # Use the cpu pin name.
Available Pins follow the ranges and labelling of the respective board, like:
- 0-33 for Teensy 4.0,
- 0-21 for the MIMXRT10xx-EVK board, or 'D0-Dxx', or 'A0-Ann',
- 0-14 for the Olimex RT1010Py board, or 'D0'-'Dxx' and 'A0'-'Ann'
- 'J3_xx', 'J4_xx', 'J5_xx' for the Seeed ARCH MIX board,
or the pin names of the Pin.board or Pin.cpu classes.
Notes:
* The MIMXRT1xxx-EVK boards may have other on-board devices connected to these
pins, limiting it's use for input or output.
* At the MIMXRT1010_EVK, pins D4, D5 and D9 of the Arduino connector are by
default not connected to the MCU. For details refer to the schematics.
* At the MIMXRT1170_EVK board, the inner rows of the Arduino connectors are assigned as follows:
- D16 - D23: J9, odd pin numbers; D17 is by default not connected.
- D24 - D27: J26, odd pin numbers; J63-J66 have to be closed to enable these pins.
- D29 - D36: J25, odd pin numbers; D29 and D30 are by default not connected.
There's a higher-level abstraction :ref:`machine.Signal <machine.Signal>`
which can be used to invert a pin. Useful for illuminating active-low LEDs
using ``on()`` or ``value(1)``.
UART (serial bus)
-----------------
See :ref:`machine.UART <machine.UART>`. ::
from machine import UART
uart1 = UART(1, baudrate=115200)
uart1.write('hello') # write 5 bytes
uart1.read(5) # read up to 5 bytes
The i.MXRT has up to eight hardware UARTs, but not every board exposes all
TX and RX pins for users. For the assignment of Pins to UART signals,
refer to the :ref:`UART pinout <mimxrt_uart_pinout>`.
PWM (pulse width modulation)
----------------------------
The i.MXRT has up to four dedicated PWM modules with four FLEXPWM submodules each
and up to four QTMR modules with four channels, which can be used to generate
a PWM signal or signal pair.
The PWM functions are provided by the :ref:`machine.PWM <machine.PWM>` class.
It supports all basic methods listed for that class and a few additional methods for
handling signal groups. ::
# Samples for Teensy
#
from machine import Pin, PWM
pwm2 = PWM(Pin(2)) # create PWM object from a pin
pwm2.freq() # get current frequency
pwm2.freq(1000) # set frequency
pwm2.duty_u16() # get current duty cycle, range 0-65535
pwm2.duty_u16(200) # set duty cycle, range 0-65535
pwm2.deinit() # turn off PWM on the pin
# create a complementary signal pair on Pin 2 and 3
pwm2 = PWM((2, 3), freq=2000, duty_ns=20000)
# Create a group of four synchronized signals.
# Start with Pin(4) at submodule 0, which creates the sync pulse.
pwm4 = PWM(Pin(4), freq=1000, align=PWM.HEAD)
# Pins 5, 6, and 9 are pins at the same module
pwm5 = PWM(Pin(5), freq=1000, duty_u16=10000, align=PWM.HEAD, sync=True)
pwm6 = PWM(Pin(6), freq=1000, duty_u16=20000, align=PWM.HEAD, sync=True)
pwm9 = PWM(Pin(9), freq=1000, duty_u16=30000, align=PWM.HEAD, sync=True)
pwm3 # show the PWM objects properties
PWM Constructor
```````````````
.. class:: PWM(dest, freq, duty_u16, duty_ns, *, center, align, invert, sync, xor, deadtime)
:noindex:
Construct and return a new PWM object using the following parameters:
- *dest* is the entity on which the PWM is output, which is usually a
:ref:`machine.Pin <machine.Pin>` object, but a port may allow other values,
like integers or strings, which designate a Pin in the machine.PIN class.
*dest* is either a single object or a two element object tuple.
If the object tuple is specified, the two pins act in complementary
mode. These two pins must be the A/B channels of the same submodule.
PWM objects are either provided by a FLEXPWM module or a QTMR module.
The i.MXRT devices have either two or four FLEXPWM and QTMR modules.
Each FLEXPWM module has four submodules with three channels, each,
called A, B and X. Each QTMR module has four channels.
Each FLEXPWM submodule or QTMR channel may be set to different parameters.
Not every channel is routed to a board pin. Details are listed below.
Setting *freq* affects the three channels of the same FLEXPWM submodule.
Only one of *duty_u16* and *duty_ns* should be specified at a time.
Keyword arguments:
- *freq* should be an integer which sets the frequency in Hz for the
PWM cycle. The valid frequency range is 15 Hz resp. 18Hz resp. 24Hz up to > 1 MHz.
- *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65536``.
The duty cycle of a X channel can only be changed, if the A and B channel
of the respective submodule is not used. Otherwise the duty_16 value of the
X channel is 32768 (50%).
- *duty_ns* sets the pulse width in nanoseconds. The limitation for X channels
apply as well.
- *center*\=value. An integer sets the center of the pulse within the pulse period.
The range is 0-65535. The resulting pulse will last from center - duty_u16/2 to
center + duty_u16/2.
- *align*\=value. Shortcuts for the pulse center setting, causing the pulse either at
the center of the frame (value=0), the leading edge at the begin (value=1) or the
trailing edge at the end of a pulse period (value=2).
- *invert*\=True|False channel_mask. Setting a bit in the mask inverts the respective channel.
Bit 0 inverts the first specified channel, bit 2 the second. The default is 0.
- *sync*\=True|False. If a channel of a module's submodule 0 is already active, other
submodules of the same module can be forced to be synchronous to submodule 0. Their
pulse period start then at at same clock cycle. The default is False.
- *xor*\=0|1|2. If set to 1 or 2, the channel will output the XOR'd signal from channels
A or B. If set to 1 on channel A or B, both A and B will show the same signal. If set
to 2, A and B will show alternating signals. For details and an illustration, please
refer to the MCU's reference manual, chapter "Double Switching PWMs".
- *deadtime*\=time_ns. This setting affects complementary channels and defines a deadtime
between an edge of a first channel and the edge of the next channel, in which both
channels are set to low. That allows connected H-bridges to switch off one side
of a push-pull driver before switching on the other side.
PWM Methods
```````````
The methods are identical to the generic :ref:`machine.PWM <machine.PWM>` class,
with additional keyword arguments to the init() method, matchings those of the constructor.
Each FLEX submodule or QTMR module may run at different frequencies. The PWM signal
is created by dividing the pwm_clk signal by an integral factor, according to the formula::
f = pwm_clk / (2**n * m)
with n being in the range of 0..7, and m in the range of 2..65536. pmw_clk is 125Mhz
for MIMXRT1010/1015/1020, 150 MHz for MIMXRT1050/1060/1064 and 160MHz for MIMXRT1170.
The lowest frequency is pwm_clk/2**23 (15, 18, 20Hz). The highest frequency with
U16 resolution is pwm_clk/2**16 (1907, 2288, 2441 Hz), the highest frequency
with 1 percent resolution is pwm_clk/100 (1.25, 1.5, 1.6 MHz). The highest achievable
frequency is pwm_clk/3 for the A/B channels, and pwm_clk/2 for the X channels and QTMR
signal.
PWM Pin Assignment
``````````````````
Pins are specified in the same way as for the Pin class. For the assignment of Pins
to PWM signals, refer to the :ref:`PWM pinout <mimxrt_pwm_pinout>`.
ADC (analog to digital conversion)
----------------------------------
On the i.MXRT ADC functionality is available on Pins labeled 'Ann'.
Use the :ref:`machine.ADC <machine.ADC>` class::
from machine import ADC
adc = ADC(Pin(32)) # create ADC object on ADC pin
adc.read_u16() # read value, 0-65536 across voltage range 0.0v - 3.3v
The resolution of the ADC is 12 bit with 10 to 11 bit accuracy, irrespective of the
value returned by read_u16(). If you need a higher resolution or better accuracy, use
an external ADC.
Software SPI bus
----------------
Software SPI (using bit-banging) works on all pins, and is accessed via the
:ref:`machine.SoftSPI <machine.SoftSPI>` class. ::
from machine import Pin, SoftSPI
# construct a SoftSPI bus on the given pins
# polarity is the idle state of SCK
# phase=0 means sample on the first edge of SCK, phase=1 means the second
spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
spi.init(baudrate=200000) # set the baudrate
spi.read(10) # read 10 bytes on MISO
spi.read(10, 0xff) # read 10 bytes while outputting 0xff on MOSI
buf = bytearray(50) # create a buffer
spi.readinto(buf) # read into the given buffer (reads 50 bytes in this case)
spi.readinto(buf, 0xff) # read into the given buffer and output 0xff on MOSI
spi.write(b'12345') # write 5 bytes on MOSI
buf = bytearray(4) # create a buffer
spi.write_readinto(b'1234', buf) # write to MOSI and read from MISO into the buffer
spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf
The highest supported baud rate is 500000.
Hardware SPI bus
----------------
There are up to four hardware SPI channels that allow faster transmission
rates (up to 30Mhz). Hardware SPI is accessed via the
:ref:`machine.SPI <machine.SPI>` class and has the same methods as software SPI above::
from machine import SPI
spi = SPI(0, 10000000)
spi.write('Hello World')
For the assignment of Pins to SPI signals, refer to
:ref:`Hardware SPI pinout <mimxrt_spi_pinout>`.
Notes:
1. Even if the highest reliable baud rate at the moment is about 30 Mhz,
setting a baud rate will not always result in exactly that
frequency, especially at high baud rates.
2. Sending at higher baud rate is possible. In the tests receiving
worked up to 60 MHz, sending up to 90 MHz.
Software I2C bus
----------------
Software I2C (using bit-banging) works on all output-capable pins, and is
accessed via the :ref:`machine.SoftI2C <machine.SoftI2C>` class::
from machine import Pin, SoftI2C
i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=100000)
i2c.scan() # scan for devices
i2c.readfrom(0x3a, 4) # read 4 bytes from device with address 0x3a
i2c.writeto(0x3a, '12') # write '12' to device with address 0x3a
buf = bytearray(10) # create a buffer with 10 bytes
i2c.writeto(0x3a, buf) # write the given buffer to the slave
The highest supported freq is 400000.
Hardware I2C bus
----------------
There are up to four hardware I2C channels that allow faster transmission rates
and support the full I2C protocol. The I2C signals have fixed assignments to GPIO pins.
For the assignment of Pins to I2C signals, refer to :ref:`Hardware I2C pinout <mimxrt_i2c_pinout>`.
Hardware I2C is accessed via the :ref:`machine.I2C <machine.I2C>` class and
has the same methods as software SPI above::
from machine import I2C
i2c = I2C(0, 400_000)
i2c.writeto(0x76, b"Hello World")
I2S bus
-------
See :ref:`machine.I2S <machine.I2S>`. Example using a Teensy 4.1 board with a simple
external Codec like UDA1334.::
from machine import I2S, Pin
i2s = I2S(2, sck=Pin(26), ws=Pin(27), sd=Pin(7),
mode=I2S.TX, bts=16,format=I2S.STEREO,
rate=44100,ibuf=40000)
i2s.write(buf) # write buffer of audio samples to I2S device
Example for using I2S with a MIMXRT10xx_DEV board::
from machine import I2S, I2C, Pin
import wm8960
i2c=I2C(0)
wm=wm8960.WM8960(i2c, sample_rate=SAMPLE_RATE_IN_HZ,
adc_sync=wm8960.sync_dac,
swap=wm8960.swap_input)
i2s = I2S(1, sck=Pin("SCK_TX"), ws=Pin("WS_TX"), sd=Pin("SD_RX"),
mck=Pin("MCK),mode=I2S.RX, bts=16,format=I2S.MONO,
rate=32000,ibuf=10000)
i2s.readinto(buf) # fill buffer with audio samples from I2S device
In this example, the input channels are swapped in the WM8960 driver, since the
on-board microphone is connected to the right channel, but mono audio is taken
from the left channel. Note, that the sck and ws pins are connected to the TX
signals of the I2S bus. That is intentional, since at the MW8960 codec these
signals are shared for RX and TX.
Example using the Teensy audio shield::
from machine import I2C, I2S, Pin
from sgtl5000 import CODEC
i2s = I2S(1, sck=Pin(21), ws=Pin(20), sd=Pin(7), mck=Pin(23),
mode=I2S.TX, bits=16,rate=44100,format=I2S.STEREO,
ibuf=40000,
)
# configure the SGTL5000 codec
i2c = I2C(0, freq=400000)
codec = CODEC(0x0A, i2c)
codec.mute_dac(False)
codec.dac_volume(0.9, 0.9)
codec.headphone_select(0)
codec.mute_headphone(False)
codec.volume(0.7, 0.7)
i2s.write(buf) # write buffer of audio samples to I2S device
The SGTL5000 codec used by the Teensy Audio shield uses the RX signals for both
RX and TX. Note that the codec is initialized after the I2S device. That is
essential since MCK is needed for its I2C operation and is provided by the I2S
controller.
MIMXRT boards may have 1 or 2 I2S buses available at the board connectors.
On MIMXRT1010 devices the bus numbers are 1 and 3. The I2S signals have
fixed assignments to GPIO pins. For the assignment of Pins to I2S signals,
refer to :ref:`I2S pinout <mimxrt_i2s_pinout>`.
Real time clock (RTC)
---------------------
See :ref:`machine.RTC <machine.RTC>`::
from machine import RTC
rtc = RTC()
rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time
rtc.datetime() # get date and time
rtc.now() # return date and time in CPython format.
The i.MXRT MCU supports battery backup of the RTC. By connecting a battery of
1.5-3.6V, time and date are maintained in the absence of the main power. The
current drawn from the battery is ~20µA, which is rather high. A CR2032 coin
cell will last for about one year.
SD card
-------
See :ref:`machine.SDCard <machine.SDCard>`::
import machine, os
sd = machine.SDCard()
fs = os.VfsFat(sd)
os.mount(fs, "/sd") # mount
os.listdir('/sd') # list directory contents
os.umount('/sd') # eject
Note: The i.mx-rt 1011 and 1015 based boards do not support the ``machine.SDCard``
class. For these, the SPI based driver ``sdcard.py`` from the MicroPython drivers
can be used. When using it, you have to overdrive the CS pin of the SPI hardware
module. Example::
import os, sdcard, machine
cs_pin = "D10"
spi = machine.SPI(0) # SPI0 with cs at Pin "D10" used for SDCARD
cs = machine.Pin(cs_pin, machine.Pin.OUT, value=1)
sd = sdcard.SDCard(spi, cs)
vfs = os.VfsFat(sd)
os.mount(vfs, "/sdcard")
OneWire driver
--------------
The OneWire driver is implemented in software and works on all pins::
from machine import Pin
import onewire
ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12
ow.scan() # return a list of devices on the bus
ow.reset() # reset the bus
ow.readbyte() # read a byte
ow.writebyte(0x12) # write a byte on the bus
ow.write('123') # write bytes on the bus
ow.select_rom(b'12345678') # select a specific device by its ROM code
There is a specific driver for DS18S20 and DS18B20 devices::
import time, ds18x20
ds = ds18x20.DS18X20(ow)
roms = ds.scan()
ds.convert_temp()
time.sleep_ms(750)
for rom in roms:
print(ds.read_temp(rom))
Be sure to put a 4.7k pull-up resistor on the data line. Note that
the ``convert_temp()`` method must be called each time you want to
sample the temperature.
DHT driver
----------
The DHT driver is implemented in software and works on all pins::
import dht
import machine
d = dht.DHT11(machine.Pin(4))
d.measure()
d.temperature() # eg. 23 (°C)
d.humidity() # eg. 41 (% RH)
d = dht.DHT22(machine.Pin(4))
d.measure()
d.temperature() # eg. 23.6 (°C)
d.humidity() # eg. 41.3 (% RH)
Be sure to have a 4.7k pull-up resistor on the data line. Some
DHT modules may already have one.
Ethernet driver
---------------
All MIMXRT boards except the MIMXRT1011 based boards and Teensy 4.0 support
Ethernet. Example usage::
import network
lan = network.LAN(0)
lan.active(True)
If there is a DHCP server in the LAN, the IP address is supplied by that server.
Otherwise, the IP address can be set with lan.ifconfig(). The default address
is 192.168.0.1.
Teensy 4.1 does not have an Ethernet jack on the board, but PJRC offers an
adapter for self-assembly. The Seeed ARCH MIX board has no PHY hardware on the
board, however you can attach external PHY interfaces. By default, the firmware
for Seeed Arch Mix uses the driver for a LAN8720 PHY. The MIMXRT1170_EVK is
equipped with two Ethernet ports, which are addressed as LAN(0) for the 100M
port and LAN(1) for the 1G port.
For details of the network interface refer to the class :ref:`network.LAN <network.LAN>`.
Transferring files
------------------
Files can be transferred to the i.MXRT devices for instance with the ``mpremote``
tool or using an SD card. If Ethernet is available, you can also use ftp.
See the MicroPython forum for the FTP server or other community-supported
alternatives to transfer files to an i.MXRT board, like rshell or Thonny.

View File

@ -0,0 +1,125 @@
.. _mimxrt_intro:
Getting started with MicroPython on the i.MXRT
==============================================
Using MicroPython is a great way to get the most of your i.MXRT board. And
vice versa, the i.MXRT chip is a great platform for using MicroPython. This
tutorial will guide you through setting up MicroPython, getting a prompt, using
the hardware peripherals, and controlling some external components.
Let's get started!
Requirements
------------
The first thing you need is a board with an i.MXRT chip. The MicroPython
software supports the i.MXRT chip itself and any board should work. The main
characteristic of a board is how the GPIO pins are connected to the outside
world, and whether it includes a built-in USB-serial converter to make the
UART available to your PC.
Names of pins will be given in this tutorial using the chip names (eg GPIO2)
and it should be straightforward to find which pin this corresponds to on your
particular board.
Powering the board
------------------
If your board has a USB connector on it then most likely it is powered through
this when connected to your PC. Otherwise you will need to power it directly.
Please refer to the documentation for your board for further details.
Getting the firmware
--------------------
Firmware versions are provided at the
`MicroPython download page <https://micropython.org/download/?port=mimxrt>`_.
You can download the most recent MicroPython firmware .hex or .bin file to load
onto your i.MXRT device. From that download page you have two main choices:
* stable firmware builds
* daily firmware builds
If you are just starting with MicroPython, the best bet is to go for the stable
firmware builds. If you are an advanced, experienced MicroPython i.MXRT user
who would like to follow development closely and help with testing new
features, there are daily builds.
Deploying the firmware
----------------------
Once you have the MicroPython firmware you need to load it onto your
i.MXRT device. The exact procedure for these steps is highly dependent
on the particular board and you will need to refer to its documentation
for details.
Teensy 4.0 and 4.1
~~~~~~~~~~~~~~~~~~
For Teensy 4.0 and 4.1 you have to use the built-in loader together with the PC
loader provided by PJRC. The built-in loader will be activated by pushing the
button on the board. Then you can upload the firmware with the command::
teensy_loader_cli --mcu=imxrt1062 -v -w firmware.hex
IMXRT10xx-EVK boards
~~~~~~~~~~~~~~~~~~~~
The IMXRT10xx-EVK boards have a second USB port connected to a support MCU.
Connecting that USB port to your PC will register a disk drive with the name of
the board. Just copy the firmware.bin file to this drive, and that will start
the flashing procedure. You will know that the flash was complete, if that
drive disappears and reappears. If you decided to install the very useful
Segger open-SDA firmware on that sidekick MCU, then you have to use the debugger
software to upload the i.MXRT firmware.
Seed ARCH MIX board
~~~~~~~~~~~~~~~~~~~
Firmware upload to the Seed ARCH MIX board is less convenient. The vendor
suggests using J-Link as a method and tool. For that, follow the instructions
given by Seed in their Wiki at
https://wiki.seeedstudio.com/Arch_Mix/#flashing-arduino-bootloader-to-arch-mix.
You will need a J-Link debug probe and software. You may find Segger JLink edu
or Segger JLink edu mini convenient. As a matching loader you can use
JFlashLite. The target address for loading is 0x60000000.
The MIMXRT family also support a serial upload method. The software for serial
upload is provided by NXP. The steps to use it are:
- Connect J3, Pin 19 to 3.3V (GPIO_AD_B0_05).
- Change the DIP-Switch settings from off-off-on-off to off-off-off-on
- Push Reset
- Run the upload with: ./FLASH.sh <firmware_image_file name>
- Once the upload has finished, set the DIP-switch back to off-off-on-off.
- Remove the Jumper to J3, Pin19 and push reset
To avoid running the Flash loader as superuser, you can copy the provided udev-rules
script to /etc/udev/rules.d/. FLASH.sh calls two binaries, blhost and sdphost,
which are provided by NXP under the BSD-3-Clause License. A version of these
binaries and the script can be downloaded at
https://github.com/robert-hh/Shared-Stuff/blob/master/mimxrt_serial_downloader.zip.
Serial downloading can be used for the NXP MIMXRT boards as well. But the built-in loader
is much more convenient to use.
Serial prompt
-------------
Once you have the firmware on the device you can access the REPL (Python prompt)
over USB.
From there you can follow the i.MXRT tutorial.
Troubleshooting installation problems
-------------------------------------
If you experience problems during flashing or with running firmware immediately
after it, here are some troubleshooting recommendations:
* Be aware of and try to exclude hardware problems. There are two common
problems: bad power source quality, and worn-out/defective Flash ROM.
Speaking of power source, not just raw amperage is important, but also low
ripple and noise/EMI in general. The most reliable and convenient power
source is a USB port.

View File

@ -112,7 +112,8 @@ with an underscore as in ``_COLS``: this symbol is not visible outside the
module so will not occupy RAM.
The argument to ``const()`` may be anything which, at compile time, evaluates
to an integer e.g. ``0x100`` or ``1 << 8``. It can even include other const
to a constant e.g. ``0x100``, ``1 << 8`` or ``(True, "string", b"bytes")``
(see section below for details). It can even include other const
symbols that have already been defined, e.g. ``1 << BIT``.
**Constant data structures**
@ -126,8 +127,9 @@ that the objects remain in flash memory rather than being copied to RAM. The
Python built-in types.
When considering the implications of frozen bytecode, note that in Python
strings, floats, bytes, integers and complex numbers are immutable. Accordingly
these will be frozen into flash. Thus, in the line
strings, floats, bytes, integers, complex numbers and tuples are immutable.
Accordingly these will be frozen into flash (for tuples, only if all their
elements are immutable). Thus, in the line
.. code::
@ -146,16 +148,16 @@ As in the string example, at runtime a reference to the arbitrarily large
integer is assigned to the variable ``bar``. That reference occupies a
single machine word.
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
is ineffective (the code works, but RAM is not saved).
Tuples of constant objects are themselves constant. Such constant tuples are
optimised by the compiler so they do not need to be created at runtime each time
they are used. For example:
.. code::
foo = (1, 2, 3, 4, 5, 6, 100000)
foo = (1, 2, 3, 4, 5, 6, 100000, ("string", b"bytes", False, True))
At runtime the tuple will be located in RAM. This may be subject to future
improvement.
This entire tuple will exist as a single object (potentially in flash if the
code is frozen) and referenced each time it is needed.
**Needless object creation**
@ -214,7 +216,7 @@ buffer; this is both faster and more efficient in terms of memory fragmentation.
**Bytes are smaller than ints**
On most platforms an integer consumes four bytes. Consider the two calls to the
On most platforms an integer consumes four bytes. Consider the three calls to the
function ``foo()``:
.. code::
@ -222,12 +224,16 @@ function ``foo()``:
def foo(bar):
for x in bar:
print(x)
foo([1, 2, 0xff])
foo((1, 2, 0xff))
foo(b'\1\2\xff')
In the first call a tuple of integers is created in RAM. The second efficiently
In the first call a `list` of integers is created in RAM each time the code is
executed. The second call creates a constant `tuple` object (a `tuple` containing
only constant objects) as part of the compilation phase, so it is only created
once and is more efficient than the `list`. The third call efficiently
creates a `bytes` object consuming the minimum amount of RAM. If the module
were frozen as bytecode, the `bytes` object would reside in flash.
were frozen as bytecode, both the `tuple` and `bytes` object would reside in flash.
**Strings Versus Bytes**

View File

@ -219,6 +219,33 @@ Exceptions
If an ISR raises an exception it will not propagate to the main loop. The interrupt will be disabled unless the
exception is handled by the ISR code.
Interfacing to uasyncio
-----------------------
When an ISR runs it can preempt the `uasyncio` scheduler. If the ISR performs a `uasyncio`
operation the scheduler's operation can be disrupted. This applies whether the interrupt is hard
or soft and also applies if the ISR has passed execution to another function via
`micropython.schedule`. In particular creating or cancelling tasks is invalid in an ISR context.
The safe way to interact with `uasyncio` is to implement a coroutine with synchronisation performed by
`uasyncio.ThreadSafeFlag`. The following fragment illustrates the creation of a task in response
to an interrupt:
.. code:: python
tsf = uasyncio.ThreadSafeFlag()
def isr(_): # Interrupt handler
tsf.set()
async def foo():
while True:
await tsf.wait()
uasyncio.create_task(bar())
In this example there will be a variable amount of latency between the execution of the ISR and the execution
of ``foo()``. This is inherent to cooperative scheduling. The maximum latency is application
and platform dependent but may typically be measured in tens of ms.
General issues
--------------
@ -339,8 +366,8 @@ A critical section can comprise a single line of code and a single variable. Con
This example illustrates a subtle source of bugs. The line ``count += 1`` in the main loop carries a specific race
condition hazard known as a read-modify-write. This is a classic cause of bugs in real time systems. In the main loop
MicroPython reads the value of ``t.counter``, adds 1 to it, and writes it back. On rare occasions the interrupt occurs
after the read and before the write. The interrupt modifies ``t.counter`` but its change is overwritten by the main
MicroPython reads the value of ``count``, adds 1 to it, and writes it back. On rare occasions the interrupt occurs
after the read and before the write. The interrupt modifies ``count`` but its change is overwritten by the main
loop when the ISR returns. In a real system this could lead to rare, unpredictable failures.
As mentioned above, care should be taken if an instance of a Python built in type is modified in the main code and

View File

@ -57,7 +57,7 @@ Freezing source code
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``.
to ``.mpy``. These levels are described in :func:`micropython.opt_level`.
.. function:: freeze_as_str(path)

View File

@ -60,6 +60,25 @@ The full list of supported commands are:
$ mpremote disconnect
After a disconnect, auto soft-reset is enabled.
- resume a previous ``mpremote`` session:
.. code-block:: bash
$ mpremote resume
This disables auto soft-reset.
- perform a soft-reset of the device:
.. code-block:: bash
$ mpremote soft-reset
This will clear out the Python heap and restart the interpreter. It also
disables auto soft-reset.
- enter the REPL on the connected device:
.. code-block:: bash
@ -114,14 +133,49 @@ The full list of supported commands are:
.. code-block:: bash
$ mpremote mount <local-dir>
$ mpremote mount [options] <local-dir>
During usage, Ctrl-D will soft-reboot and normally reconnect the mount automatically.
If the unit has a main.py running at startup however the remount cannot occur.
In this case a raw mode soft reboot can be used: Ctrl-A Ctrl-D to reboot,
then Ctrl-B to get back to normal repl at which point the mount will be ready.
Options are:
- ``-l``, ``--unsafe-links``: By default an error will be raised if the device
accesses a file or directory which is outside (up one or more directory levels) the
local directory that is mounted. This option disables this check for symbolic
links, allowing the device to follow symbolic links outside of the local directory.
- unmount the local directory from the remote device:
.. code-block:: bash
$ mpremote umount
Multiple commands can be specified and they will be run sequentially.
Auto connection and soft-reset
------------------------------
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.
Once connected to a device, ``mpremote`` will automatically soft-reset the
device if needed. This clears the Python heap and restarts the interpreter,
making sure that subsequent Python code executes in a fresh environment. Auto
soft-reset is performed the first time one of the following commands are
executed: ``mount``, ``eval``, ``exec``, ``run``, ``fs``. After doing a
soft-reset for the first time, it will not be done again automatically, until a
``disconnect`` command is issued.
Auto soft-reset behaviour can be controlled by the ``resume`` command. And the
``soft-reset`` command can be used to perform an explicit soft reset.
Shortcuts
---------

View File

@ -27,24 +27,16 @@ Compatibility is based on the following:
* Version of the .mpy file: the version of the file must match the version
supported by the system loading it.
* Bytecode features used in the .mpy file: there are two bytecode features
which must match between the file and the system: unicode support and
inline caching of map lookups in the bytecode.
* Small integer bits: the .mpy file will require a minimum number of bits in
a small integer and the system loading it must support at least this many
bits.
* Qstr compression window size: the .mpy file will require a minimum window
size for qstr decompression and the system loading it must have a window
greater or equal to this size.
* Native architecture: if the .mpy file contains native machine code then
it will specify the architecture of that machine code and the system
loading it must support execution of that architecture's code.
If a MicroPython system supports importing .mpy files then the
``sys.implementation.mpy`` field will exist and return an integer which
``sys.implementation._mpy`` field will exist and return an integer which
encodes the version (lower 8 bits), features and native architecture.
Trying to import an .mpy file that fails one of the first four tests will
@ -58,7 +50,7 @@ If importing an .mpy file fails then try the following:
by executing::
import sys
sys_mpy = sys.implementation.mpy
sys_mpy = sys.implementation._mpy
arch = [None, 'x86', 'x64',
'armv6', 'armv6m', 'armv7m', 'armv7em', 'armv7emsp', 'armv7emdp',
'xtensa', 'xtensawin'][sys_mpy >> 10]
@ -66,8 +58,6 @@ If importing an .mpy file fails then try the following:
print('mpy flags:', end='')
if arch:
print(' -march=' + arch, end='')
if not sys_mpy & 0x200:
print(' -mno-unicode', end='')
print()
* Check the validity of the .mpy file by inspecting the first two bytes of
@ -90,7 +80,8 @@ and .mpy version.
=================== ============
MicroPython release .mpy version
=================== ============
v1.12 and up 5
v1.19 and up 6
v1.12 - v1.18 5
v1.11 4
v1.9.3 - v1.10 3
v1.9 - v1.9.2 2
@ -103,6 +94,7 @@ MicroPython repository at which the .mpy version was changed.
=================== ========================================
.mpy version change Git commit
=================== ========================================
5 to 6 f2040bfc7ee033e48acef9f289790f3b4e6b74e5
4 to 5 5716c5cf65e9b2cb46c2906f40302401bdd27517
3 to 4 9a5f92ea72754c01cc03e5efcdfe94021120531e
2 to 3 ff93fd4f50321c6190e1659b19e64fef3045a484
@ -114,21 +106,31 @@ initial version 0 d8c834c95d506db979ec871417de90b7951edc30
Binary encoding of .mpy files
-----------------------------
MicroPython .mpy files are a binary container format with code objects
stored internally in a nested hierarchy. To keep files small while still
MicroPython .mpy files are a binary container format with code objects (bytecode
and native machine code) stored internally in a nested hierarchy. The code for
the outer module is stored first, and then its children follow. Each child may
have further children, for example in the case of a class having methods, or a
function defining a lambda or comprehension. To keep files small while still
providing a large range of possible values it uses the concept of a
variably-encoded-unsigned-integer (vuint) in many places. Similar to utf-8
encoding, this encoding stores 7 bits per byte with the 8th bit (MSB) set
if one or more bytes follow. The bits of the unsigned integer are stored
in the vuint in LSB form.
The top-level of an .mpy file consists of two parts:
The top-level of an .mpy file consists of three parts:
* The header.
* The global qstr and constant tables.
* The raw-code for the outer scope of the module.
This outer scope is executed when the .mpy file is imported.
You can inspect the contents of a .mpy file by using ``mpy-tool.py``, for
example (run from the root of the main MicroPython repository)::
$ ./tools/mpy-tool.py -xd myfile.mpy
The header
~~~~~~~~~~
@ -141,7 +143,26 @@ byte value 0x4d (ASCII 'M')
byte .mpy version number
byte feature flags
byte number of bits in a small int
vuint size of qstr window
====== ================================
The global qstr and constant tables
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An .mpy file contains a single qstr table, and a single constant object table.
These are global to the .mpy file, they are referenced by all nested raw-code
objects. The qstr table maps internal qstr number (internal to the .mpy file)
to the resolved qstr number of the runtime that the .mpy file is imported into.
This links the .mpy file with the rest of the system that it executes within.
The constant object table is populated with references to all constant objects
that the .mpy file needs.
====== ================================
size field
====== ================================
vuint number of qstrs
vuint number of constant objects
... qstr data
... encoded constant objects
====== ================================
Raw code elements
@ -153,24 +174,21 @@ contents are:
====== ================================
size field
====== ================================
vuint type and size
vuint type, size and whether there are sub-raw-code elements
... code (bytecode or machine code)
vuint number of constant objects
vuint number of sub-raw-code elements
... constant objects
vuint number of sub-raw-code elements (only if non-zero)
... sub-raw-code elements
====== ================================
The first vuint in a raw-code element encodes the type of code stored in this
element (the two least-significant bits), and the decompressed length of the code
(the amount of RAM to allocate for it).
element (the two least-significant bits), whether this raw-code has any
children (the third least-significant bit), and the length of the code that
follows (the amount of RAM to allocate for it).
Following the vuint comes the code itself. In the case of bytecode it also contains
compressed qstr values.
Following the vuint comes the code itself. Unless the code type is viper code
with relocations, this code is constant data and does not need to be modified.
Following the code comes a vuint counting the number of constant objects, and
another vuint counting the number of sub-raw-code elements.
The constant objects are then stored next.
If this raw-code has any children (as indicated by a bit in the first vuint),
following the code comes a vuint counting the number of sub-raw-code elements.
Finally any sub-raw-code elements are stored, recursively.

View File

@ -0,0 +1,42 @@
.. _renesas-ra_general:
General information about Renesas RA port
=========================================
Overview
--------
The renesas-ra port supports boards powered by Renesas Electronics's
the flexible Renesas Advanced (RA) 32-bit microcontrollers (MCUs) family,
industry-leading 32-bit MCUs with the Arm® Cortex®-M33, -M23 and -M4
processor cores and PSA certification.
The ported hardware functionalities are Pin, SPI, I2C, UART and RTC at this present.
Other hardware functionalities such as Timer, PWM, USB, CAN and WDT are not implemented yet.
The following boards are officially supported.
* RA4M1-CLICKER
For the manual and other references for the board and RA Family MCU, please refer to the web page: `EK-RA4M1 CLICKER <https://www.mikroe.com/ra4m1-clicker>`_
* EK-RA6M2
For the manual and other references for the board and RA Family MCU, please refer to the web page: `EK-RA6M2 <https://www.renesas.com/products/microcontrollers-microprocessors/ra-cortex-m-mcus/ek-ra6m2-ra6m2-mcu-group-evaluation-board>`_
The following boards are unofficially supported.
* EK-RA4M1
For the manual and other references for the board and RA Family MCU, please refer to the web page: `EK-RA4M1 <https://www.renesas.com/products/microcontrollers-microprocessors/ra-cortex-m-mcus/ek-ra4m1-ra4m1-mcu-group-evaluation-board>`_
* EK-RA4W1
For the manual and other references for the board and RA Family MCU, please refer to the web page: `EK-RA4W1 <https://www.renesas.com/products/microcontrollers-microprocessors/ra-cortex-m-mcus/ek-ra4w1-ra4w1-mcu-group-evaluation-board>`_
* EK-RA6M1
For the manual and other references for the board and RA Family MCU, please refer to the web page: `EK-RA6M1 <https://www.renesas.com/products/microcontrollers-microprocessors/ra-cortex-m-mcus/ek-ra6m1-ra6m1-mcu-group-evaluation-board>`_
For more information, please visit the web page: `<https://github.com/renesas/micropython/wiki>`_

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

View File

@ -0,0 +1,415 @@
.. _renesas-ra_quickref:
Quick reference for the Renesas RA
==================================
.. image:: img/ek_ra6m2_board.jpg
:alt: Renesas Evaluation Kit for RA6M2 MCU Group
:width: 640px
The Renesas EK-RA6M2 board.
Below is a quick reference for the Renesas RA boards. If it is your first time
working with this board, it may be useful to get an overview of the microcontroller and the board:
.. toctree::
:maxdepth: 1
general.rst
tutorial/index.rst
Installing MicroPython
----------------------
See the corresponding section of tutorial: :ref:`renesas-ra_intro`. It also includes a troubleshooting subsection.
General board control
---------------------
The MicroPython REPL is accessed via the USB serial port. Tab-completion is useful to find out what methods an object has. Paste mode (ctrl-E) is useful to paste a large slab of Python code into the REPL. Some of features are not implemented for Renesas RA boards yet, please refer to the tutorial for more details.
The :mod:`machine` module::
import machine
machine.freq() # get the current frequency of the CPU
Following functions are supported::
machine.freq()
machine.reset()
machine.soft_reset()
machine.unique_id()
Following functions are not supported at the present::
machine.reset_cause()
machine.bootloader([value])
machine.disable_irq()
machine.enable_irq(state)
machine.freq([hz])
machine.idle()
machine.sleep()
machine.lightsleep()
machine.lightsleep([time_ms])
machine.deepsleep()
machine.deepsleep([time_ms])
machine.wake_reason()
machine.time_pulse_us(pin, pulse_level, timeout_us=1000000,/)
machine.bitstream(pin, encoding, timing, data, /)
machine.rng()
Delay and timing
----------------
Use the :mod:`time <time>` module::
import time
time.sleep(1) # sleep for 1 second
time.sleep_ms(500) # sleep for 500 milliseconds
time.sleep_us(10) # sleep for 10 microseconds
start = time.ticks_ms() # get value of millisecond counter
delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference
Timers
------
The RA MCU's system timer peripheral provides a global microsecond timebase and generates interrupts for it. The software timer is available currently and there are unlimited number of them (memory permitting). There is no need to specify the timer id (id=-1 is supported at the moment) as it will default to this.
Use the :mod:`machine.Timer` class::
from machine import Timer
tim = Timer(-1)
tim.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(1))
tim.init(period=2000, mode=Timer.PERIODIC, callback=lambda t: print(2))
Following functions are not supported at the present::
Timer(id) # hardware timer is not supported.
Pins and GPIO
-------------
Use the :ref:`machine.Pin <machine.Pin>` class::
from machine import Pin
p0 = Pin('P000', Pin.OUT) # create output pin on P000
p0.on() # set pin to "on" (high) level
p0.off() # set pin to "off" (low) level
p0.value(1) # set pin to on/high
p2 = Pin(Pin.cpu.P002, Pin.IN) # create input pin on P002
print(p2.value()) # get value, 0 or 1
p4 = Pin('P004', Pin.PULL_UP) # enable internal pull-up register
p5 = Pin('P005', Pin.OUT, value=1) # set pin high on creation
Pin id is available corresponding to the RA MCU's pin name which are Pin.cpu.P106 and 'P106'. The RA MCU has many feature's pins. However, there are some cases that pin feature is fixed or not connected by the board. Please confirm the board manual for the pin mapping.
UART (serial bus)
-----------------
The RA MCU has some hardware UARTs called SCI (Serial Communication Interface).
UART id is available corresponding to the RA MCU's SCI number which are UART(0) as SCI0 and UART(1) as SCI1.
See :ref:`machine.UART <machine.UART>`. ::
from machine import UART
uart1 = UART(1, 115200)
uart1.write('hello') # write 5 bytes
uart1.read(5) # read up to 5 bytes
Available UARTs and pins on the board are fixed and follows. One of these UARTs is used for REPL.
============= ============== ============== ==============
EK-RA4M1 UART0(REPL) UART1 UART2
============= ============== ============== ==============
tx P411 P401 P302
rx P410 P402 P301
============= ============== ============== ==============
============= ============== ============== ==============
EK-RA4W1 UART1 UART4(REPL) UART9
============= ============== ============== ==============
tx P213 P204 P109
rx P212 P206 P110
============= ============== ============== ==============
============= ============== ============== ==============
EK-RA6M1 UART0(REPL) UART2 UART8
============= ============== ============== ==============
tx P411 P302 P105
rx P410 P301 P104
============= ============== ============== ==============
============= ============== ============== ==============
EK-RA6M2 UART0(REPL) UART7 UART9
============= ============== ============== ==============
tx P411 P401 P602
rx P410 P402 P601
============= ============== ============== ==============
============= ============== ==============
RA4M1-CLICKER UART0 UART1(REPL)
============= ============== ==============
tx P411 P401
rx P410 P402
============= ============== ==============
Following functions are not supported at the present::
UART.init(baudrate) # now only 115200 is confirmed
UART.init(cts, rts) # Pins are fixed.
UART.init(invert)
UART.init(tx,rx) # Pins are fixed.
UART.init(txbuf)
UART.init(flow)
UART.irq(handler)
UART.irq(trigger=RX_ANY)
UART.irq(priority)
UART.irq(wake=machine.IDLE)
Real time clock (RTC)
---------------------
See :ref:`machine.RTC <machine.RTC>` ::
from machine import RTC
rtc = RTC()
rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time
# time, eg 2017/8/23 1:12:48
rtc.datetime() # get date and time
Following functions are not supported at the present::
RTC.init(datetime)
RTC.now()
RTC.deinit()
RTC.alarm()
RTC.alarm_left()
RTC.cancel()
RTC.irq()
ADC (analog to digital conversion)
----------------------------------
See :ref:`machine.ADC <machine.ADC>` ::
from machine import ADC
adc = ADC('P000') # create an ADC object acting on a pin
adc.read_u16() # read a raw analog value in the range 0-65535
Pin id is available corresponding to the RA MCU's pin name which are 'P000' as AN000 (analog channel 000). The RA MCU has many analog channels. However, there are some cases that pin feature is fixed or not available by the board. Please confirm the MCU and board manual for the pin mapping.
Following functions are not supported at the present::
ADC.init()
ADC(sample_ns)
ADC(atten)
ADC.read_uv()
ADC.block()
SPI bus
-------
The RA MCU has some hardware SPIs (Serial Peripheral Interface).
SPI id is available corresponding to the RA MCU's SPI number which are SPI(0) as SPI0 and SPI(1) as SPI1. If with no additional parameters, machine.SoftSPI() is called.
See :ref:`machine.SPI <machine.SPI>`. ::
from machine import SPI, Pin
spi = SPI(0, baudrate=500000)
cs = Pin.cpu.P103
cs(0)
spi.write(b"12345678")
cs(1)
Available SPIs and pins on the board are fixed and follows.
============= ====
EK-RA4M1 SPI0
============= ====
sck P102
mosi P101
miso P100
cs P206
============= ====
============= ====
EK-RA4W1 SPI0
============= ====
sck P102
mosi P101
miso P100
cs P103
============= ====
============= ====
EK-RA6M1 SPI0
============= ====
sck P102
mosi P101
miso P100
cs P103
============= ====
============= ==== ====
EK-RA6M2 SPI0 SPI1
============= ==== ====
sck P102 P702
mosi P101 P701
miso P100 P700
cs P103 P703
============= ==== ====
============= ====
RA4M1-CLICKER SPI0
============= ====
sck P102
mosi P101
miso P100
cs P103
============= ====
Following functions are not supported at the present::
SPI.init(firstbit) # now fixed with SPI.LSB
SPI.init(baudrate) # now confirmed only 500000
I2C bus
-------
The RA MCU has some hardware IIC (Inter-Integrated Circuit Bus).
I2C id is available corresponding to the RA MCU's I2C number which are I2C(0) as IIC0 and I2C(1) as IIC1. If with no additional parameters, machine.SoftI2C() is called.
See :ref:`machine.I2C <machine.I2C>` ::
from machine import I2C
i2c = I2C(0)
i2c.scan() # returns list of slave addresses
i2c.readfrom_mem(0x50, 0x10, 2, addrsize=16) # read 2 bytes from slave 0x50, slave memory 0x10
Available I2Cs and pins on the board are fixed and follows.
============= =============
EK-RA4M1 -
============= =============
scl not supported
sda not supported
============= =============
============= ====
EK-RA4W1 I2C0
============= ====
scl P204
sda P407
============= ====
============= ====
EK-RA6M1 I2C0
============= ====
scl P400
sda P401
============= ====
============= ====
EK-RA6M2 I2C2
============= ====
scl P512
sda P511
============= ====
============= ====
RA4M1-CLICKER I2C1
============= ====
scl P205
sda P206
============= ====
Following functions are not supported at the present::
I2C.init(freq) # now confirmed only 400000
I2C.deinit()
I2C.start()
I2C.stop()
PWM (pulse width modulation)
----------------------------
PWM is not supported.
WDT (Watchdog timer)
--------------------
WDT is not supported.
SDCard
------
The frozen sdcard driver (drivers/sdcard/sdcard.py) is available by connecting microSD card device to hardware SPI0 pins.::
from machine import Pin, SPI
import os, sdcard
spi = SPI(0, baudrate=500000)
cs = Pin.cpu.P103
sd = sdcard.SDCard(spi, cs)
os.mount(sd, '/sd')
os.listdir('/')
os.chdir('/sd')
os.umount('/sd')
OneWire driver
--------------
The OneWire driver is implemented in software and works on all pins::
from machine import Pin
import onewire
ow = onewire.OneWire(Pin(P012)) # create a OneWire bus on P012
ow.scan() # return a list of devices on the bus
ow.reset() # reset the bus
ow.readbyte() # read a byte
ow.writebyte(0x12) # write a byte on the bus
ow.write('123') # write bytes on the bus
ow.select_rom(b'12345678') # select a specific device by its ROM code
There is a specific driver for DS18S20 and DS18B20 devices::
import time, ds18x20
ds = ds18x20.DS18X20(ow)
roms = ds.scan()
ds.convert_temp()
time.sleep_ms(750)
for rom in roms:
print(ds.read_temp(rom))
Be sure to put a 4.7k pull-up resistor on the data line. Note that
the ``convert_temp()`` method must be called each time you want to
sample the temperature.
NeoPixel and APA106 driver
--------------------------
NeoPixel is not supported currently.

View File

@ -0,0 +1,16 @@
.. _renesas-ra_tutorial:
MicroPython tutorial for Renesas RA port
========================================
This tutorial is intended to get you started using MicroPython on the Renesas RA port.
.. toctree::
:maxdepth: 1
:numbered:
intro.rst
using_peripheral.rst
program_in_flash.rst
reset.rst
troubleshooting.rst

View File

@ -0,0 +1,67 @@
.. _renesas-ra_intro:
Getting started with MicroPython on the Renesas RA
==================================================
This tutorial will guide you through setting up MicroPython,
getting a prompt, using the hardware peripherals, using internal
flash file system, reset and boot modes, and Factory reset the
internal file system.
Requirements
------------
You need a board. For the information of available boards,
please refer to the general information about Renesas RA port: :ref:`renesas-ra_general`.
You need a USB-Serial conversion cable to connect the board and your PC.
Please get a type with separate signal pins so that you can connect to
the UART TX and RX pins on the board.
Flashing the MicroPython image with J-Link OB
---------------------------------------------
The board has a builtin programmer interface called J-Link OB.
Using the J-Link Software, you can flash the binary image "firmware.hex"
of MicroPython on the board via J-Link OB.
You can download the J-Link Software and Documentation pack from https://www.segger.com/downloads/jlink/.
After installing J-Link Software, start J-Flash-Lite program. Then specify following device in Device select menu in J-Flash-Lite.
=============== ================
Board Device
--------------- ----------------
EK-RA4M1 R7FA4M1AB
EK-RA4W1 R7FA4W1AD2CNG
EK-RA6M1 R7FA6M1AD
EK-RA6M2 R7FA6M2AF
RA4M1 CLICKER R7FA4M1AB
=============== ================
Select a firmware hex file in Data File of J-Link-Lite, and push Program Device button to flash the firmware.
Getting a prompt of MicroPython
-------------------------------
Cross connect USB-Serial conversion cable RX/TX/GND pins to TX/RX/GND pins on the board.
=============== =============== ===============
Board USB Serial RX USB Serial TX
--------------- --------------- ---------------
EK-RA4M1 P411 P410
EK-RA4W1 P205 P206
EK-RA6M1 P411 P410
EK-RA6M2 P411 P410
RA4M1 CLICKER P401 P402
=============== =============== ===============
Access the MicroPython REPL (the Python prompt) via USB serial or UART with 115200 baud rate, 1 stop bit and no parity bit using your favorite terminal software, picocom on Linux or Tera Term on Windows. You can try on Linux::
$ picocom /dev/ttyACM0
You can see the MicroPython REPL prompt like below::
MicroPython v1.18-293-g339aa09b8-dirty on 2022-03-26; RA6M2_EK with RA6M2
Type "help()" for more information.
>>>

View File

@ -0,0 +1,62 @@
.. _renesas-ra_program_in_flash:
Write a program in internal file system
=======================================
Internal file system
--------------------
The FAT file system is created and initialized in the RA MCU's internal
flash when the MicroPython starts at the first time on the board.
The file system is mounted as "/flash", so you can access this flash system
and create a program file into the /flash directory.
As the factory setting, following size is allocated for the file system:
=============== ===================
Board File System Size
--------------- -------------------
EK-RA4M1 36KB ( 36864B)
EK-RA4W1 64KB ( 65536B)
EK-RA6M1 128KB (131072B)
EK-RA6M2 256KB (262144B)
RA4M1 CLICKER 36KB ( 36864B)
=============== ===================
As the factory setting, following 2 files are created in the file system:
* boot.py : executed first when the system starts
* main.py : executed after boot.py completes
Write a program in the internal file system
-------------------------------------------
You can write a program in main.py which is executed automatically
when the MicroPython starts. For example, you can write LED blinking
program like below::
import os
os.getcwd()
f = open('main.py', 'rw+')
print(f.read())
f.write('import time\n')
f.write('from machine import Pin\n')
f.write('led1 = Pin(Pin.cpu.P106)\n')
f.write('while True:\n')
f.write(' led1.on()\n')
f.write(' time.sleep(1)\n')
f.write(' led1.off()\n')
f.write(' time.sleep(1)\n')
f.close()
f = open('main.py', 'r')
print(f.read())
f.close()
Entering CTRL-D for software reset, the MicroPython reboots, displays
following messages::
MPY: sync filesystems
MPY: soft reboot
and main.py is executed and LED1 blinks per 1 second.
If you want to stop the program, please enter CTRL-C.

View File

@ -0,0 +1,61 @@
.. _renesas-ra_reset:
Reset and boot mode
===================
Resetting the board
-------------------
If something goes wrong, you can reset the board in two ways. The first is
to press CTRL-D at the MicroPython prompt, which performs a soft reset.
You will see a message something like ::
MPY: sync filesystems
MPY: soft reboot
MicroPython v1.18-293-g339aa09b8-dirty on 2022-03-26; RA6M2_EK with RA6M2
Type "help()" for more information.
>>>
If that isn't working you can perform a hard reset (turn-it-off-and-on-again)
by pressing the RESET button. This will end your session, disconnecting
whatever program (PuTTY, screen, etc) that you used to connect to the board.
boot mode
---------
There are 3 boot modes:
* normal boot mode
* safe boot mode
* factory filesystem boot mode
boot.py and main.py are executed on "normal boot mode".
boot.py and main.py are *NOT* executed on "safe boot mode".
The file system of internal flash is initialized and *all files are erased* on "factory filesystem boot mode".
For changing boot mode, please push the RESET button with pressing USER SW1
on the board:
* For normal boot mode, release the USER SW1 after LED1 flashes 4 times or more
* For safe boot mode, release the USER SW1 after LED1 flashes 2 times
* For factory file system boot mode, release the USER SW1 after LED1 flashes 3 times.
You have created the main.py which executes LED1 blinking in the previous part.
If you change the boot mode to safe boot mode, the MicroPython starts without
the execution of main.py. Then you can remove the main.py by following
command or change the boot mode to factory file system boot mode.::
import os
os.remove('main.py')
or change the boot mode to factory file system boot mode.
You can confirm that the initialized file system that there are only boot.py and main.py files.::
import os
os.listdir()

View File

@ -0,0 +1,18 @@
.. _renesas-ra_troubleshooting:
Trouble Shooting
===================
Flash file system
-------------------
* MicroPython REPL prompt is not displayed.
- Re-program the MicroPython image file.
- Confirm serial port connection.
The connection must be crossed that the board TXD pin is connected with
USB-serial conversion's RXD signal pin.
- If the prompt is not displayed suddenly, try to do factory file
system boot mode as the final method. Please note that all files are removed forever.

View File

@ -0,0 +1,68 @@
.. _renesas-ra_using_peripheral:
Using peripherals
=================
For quick help information, please enter::
help()
You can access RA MCU's peripherals using MicroPython modules.
To list supported modules, please enter::
help('modules')
Especially `machine` module and class :ref:`machine.Pin <machine.Pin>` are very important for using
peripherals. Note that prefix 'u' is added to the module for MicroPython,
so you can see "umachine" in the list but you can use it like "import machine".
Using "from machine import Pin", Pin name is available corresponding to
the RA MCU's pin name which are Pin.cpu.P000 and 'P000'.
In addition, you can use 'LED1', 'LED2', 'SW1', and 'SW2' name if the board
has these LEDs and switches.
LED blinking
------------
As simple example, you can enter following program to blink LED1.
Please enter key 4 times after the input of last time.sleep(1). ::
import time
from machine import Pin
led1 = Pin('LED1')
print(led1)
while True:
led1.on()
time.sleep(1)
led1.off()
time.sleep(1)
You can see the LED1 blinking per 1 second.
If you want to stop the program, please enter CTRL-C. ::
Traceback (most recent call last):
File "<stdin>", line 5, in <module>
KeyboardInterrupt:
This message is displayed, and the program stops.
The message means the program was interrupted at line 5 "while" statement.
Using print(led1), you can confirm that LED1 is assigned to Pin.cpu.P106
on the board.::
Pin(Pin.cpu.P106, mode=Pin.OUT, pull=Pin.PULL_NONE, drive=Pin.LOW_POWER)
So you can get the same result if Pin(Pin.cpu.P106) is specified
instead of Pin('LED1'). ::
import time
from machine import Pin
led1 = Pin(Pin.cpu.P106)
print(led1)
while True:
led1.on()
time.sleep(1)
led1.off()
time.sleep(1)

View File

@ -11,7 +11,7 @@ Technical specifications and SoC datasheets
-------------------------------------------
For detailed technical specifications, please refer to the `datasheets
<https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf>`_
<https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf>`_
The RP2040 microcontroller is manufactured on a 40 nm silicon process in a 7x7mm
QFN-56 SMD package. The key features include:

View File

@ -62,6 +62,10 @@
<a class="biglink" href="{{ pathto("rp2/quickref") }}">Quick reference for the Raspberry Pi RP2xxx</a><br/>
<span class="linkdescr">pinout for rp2xxx-based boards, snippets of useful code, and a tutorial</span>
</p>
<p class="biglink">
<a class="biglink" href="{{ pathto("mimxrt/quickref") }}">Quick reference for the NXP i.MXRT 10xx</a><br/>
<span class="linkdescr">general introduction, snippets of useful code, and a tutorial</span>
</p>
<p class="biglink">
<a class="biglink" href="{{ pathto("wipy/quickref") }}">Quick reference for the WiPy/CC3200</a><br/>
<span class="linkdescr">pinout for the WiPy/CC3200, snippets of useful code, and a tutorial</span>
@ -74,6 +78,10 @@
<a class="biglink" href="{{ pathto("zephyr/quickref") }}">Quick reference for the Zephyr port</a><br/>
<span class="linkdescr">snippets of useful code and a tutorial</span>
</p>
<p class="biglink">
<a class="biglink" href="{{ pathto("renesas-ra/quickref") }}">Quick reference for the Renesas RA</a><br/>
<span class="linkdescr">general information for Renesas RA based boards, snippets of useful code, and a tutorial</span>
</p>
</td>
</tr></table>

View File

@ -73,6 +73,8 @@ General options:
- ``-X heapsize=<n>[w][K|M]`` sets the heap size for the garbage collector.
The suffix ``w`` means words instead of bytes. ``K`` means x1024 and ``M``
means x1024x1024.
- ``-X realtime`` sets thread priority to realtime. This can be used to
improve timer precision. Only available on macOS.

View File

@ -345,7 +345,7 @@ Example::
Create a server instance, see ``init`` for parameters of initialization.
.. method:: server.init(\*, login=('micro', 'python'), timeout=300)
.. method:: server.init(*, login=('micro', 'python'), timeout=300)
Init (and effectively start the server). Optionally a new ``user``, ``password``
and ``timeout`` (in seconds) can be passed.
@ -368,7 +368,7 @@ Adhoc VFS-like support
WiPy doesn't implement full MicroPython VFS support, instead following
functions are defined in ``os`` module:
.. function:: mount(block_device, mount_point, \*, readonly=False)
.. function:: mount(block_device, mount_point, *, readonly=False)
Mounts a block device (like an ``SD`` object) in the specified mount
point. Example::

View File

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

View File

@ -28,7 +28,9 @@
#include "py/mphal.h"
#define MP_SPI_ADDR_IS_32B(addr) (addr & 0xff000000)
#ifndef MICROPY_HW_SPI_ADDR_IS_32BIT
#define MICROPY_HW_SPI_ADDR_IS_32BIT(addr) (addr & 0xff000000)
#endif
enum {
MP_QSPI_IOCTL_INIT,
@ -57,7 +59,7 @@ typedef struct _mp_soft_qspi_obj_t {
extern const mp_qspi_proto_t mp_soft_qspi_proto;
static inline uint8_t mp_spi_set_addr_buff(uint8_t *buf, uint32_t addr) {
if (MP_SPI_ADDR_IS_32B(addr)) {
if (MICROPY_HW_SPI_ADDR_IS_32BIT(addr)) {
buf[0] = addr >> 24;
buf[1] = addr >> 16;
buf[2] = addr >> 8;

753
drivers/codec/wm8960.py Normal file
View File

@ -0,0 +1,753 @@
#
# Driver class for the WM8960 Codec to be used e.g. with MIMXRT_1xxx Boards.
# Derived from the NXP SDK drivers.
#
# Copyright (c) 2015, Freescale Semiconductor, Inc., (C-Code)
# Copyright 2016-2021 NXP, (C-Code)
# All rights reserved.
#
# Translated to MicroPython by Robert Hammelrath, 2022
#
# SPDX-License-Identifier: BSD-3-Clause
#
import array
from micropython import const
# Define the register addresses of WM8960.
_LINVOL = const(0x0)
_RINVOL = const(0x1)
_LOUT1 = const(0x2)
_ROUT1 = const(0x3)
_CLOCK1 = const(0x4)
_DACCTL1 = const(0x5)
_DACCTL2 = const(0x6)
_IFACE1 = const(0x7)
_CLOCK2 = const(0x8)
_IFACE2 = const(0x9)
_LDAC = const(0xA)
_RDAC = const(0xB)
_RESET = const(0xF)
_3D = const(0x10)
_ALC1 = const(0x11)
_ALC2 = const(0x12)
_ALC3 = const(0x13)
_NOISEG = const(0x14)
_LADC = const(0x15)
_RADC = const(0x16)
_ADDCTL1 = const(0x17)
# Register _ADDCTL2 = const(0x18)
_POWER1 = const(0x19)
_POWER2 = const(0x1A)
_ADDCTL3 = const(0x1B)
# Register _APOP1 = const(0x1C)
# Register _APOP2 = const(0x1D)
_LINPATH = const(0x20)
_RINPATH = const(0x21)
_LOUTMIX = const(0x22)
_ROUTMIX = const(0x25)
_MONOMIX1 = const(0x26)
_MONOMIX2 = const(0x27)
_LOUT2 = const(0x28)
_ROUT2 = const(0x29)
_MONO = const(0x2A)
_INBMIX1 = const(0x2B)
_INBMIX2 = const(0x2C)
_BYPASS1 = const(0x2D)
_BYPASS2 = const(0x2E)
_POWER3 = const(0x2F)
_ADDCTL4 = const(0x30)
_CLASSD1 = const(0x31)
# Register _CLASSD3 = const(0x33)
_PLL1 = const(0x34)
_PLL2 = const(0x35)
_PLL3 = const(0x36)
_PLL4 = const(0x37)
# WM8960 PLLN range */
_PLL_N_MIN_VALUE = const(6)
_PLL_N_MAX_VALUE = const(12)
# WM8960 CLOCK2 bits
_CLOCK2_BCLK_DIV_MASK = const(0x0F)
_CLOCK2_DCLK_DIV_MASK = const(0x1C0)
_CLOCK2_DCLK_DIV_SHIFT = const(0x06)
# Register _IFACE1
_IFACE1_FORMAT_MASK = const(0x03)
_IFACE1_WL_MASK = const(0x0C)
_IFACE1_WL_SHIFT = const(0x02)
_IFACE1_LRP_MASK = const(0x10)
_IFACE1_MS_MASK = const(0x40)
_IFACE1_DLRSWAP_MASK = const(0x20)
_IFACE1_ALRSWAP_MASK = const(0x100)
# Register _POWER1
_POWER1_VREF_MASK = const(0x40)
_POWER1_VREF_SHIFT = const(0x06)
_POWER1_AINL_MASK = const(0x20)
_POWER1_AINR_MASK = const(0x10)
_POWER1_ADCL_MASK = const(0x08)
_POWER1_ADCR_MASK = const(0x0)
_POWER1_MICB_MASK = const(0x02)
_POWER1_MICB_SHIFT = const(0x01)
# Register _POWER2
_POWER2_DACL_MASK = const(0x100)
_POWER2_DACR_MASK = const(0x80)
_POWER2_LOUT1_MASK = const(0x40)
_POWER2_ROUT1_MASK = const(0x20)
_POWER2_SPKL_MASK = const(0x10)
_POWER2_SPKR_MASK = const(0x08)
_POWER3_LMIC_MASK = const(0x20)
_POWER3_RMIC_MASK = const(0x10)
_POWER3_LOMIX_MASK = const(0x08)
_POWER3_ROMIX_MASK = const(0x04)
# Register _DACCTL1 .. 3
_DACCTL1_MONOMIX_MASK = const(0x10)
_DACCTL1_MONOMIX_SHIFT = const(0x4)
_DACCTL1_DACMU_MASK = const(0x08)
_DACCTL1_DEEM_MASK = const(0x06)
_DACCTL1_DEEM_SHIFT = const(0x01)
_DACCTL2_DACSMM_MASK = const(0x08)
_DACCTL2_DACMR_MASK = const(0x04)
_DACCTL3_ALCSR_MASK = const(0x07)
# _WM8060_ALC1 .. 3
_ALC_CHANNEL_MASK = const(0x180)
_ALC_CHANNEL_SHIFT = const(0x7)
_ALC_MODE_MASK = const(0x100)
_ALC_MODE_SHIFT = const(0x8)
_ALC_GAIN_MASK = const(0x70)
_ALC_GAIN_SHIFT = const(0x4)
_ALC_TARGET_MASK = const(0x0F)
_ALC_ATTACK_MASK = const(0x0F)
_ALC_DECAY_MASK = const(0xF0)
_ALC_DECAY_SHIFT = const(4)
_ALC_HOLD_MASK = const(0xF)
# Register _NOISEG
_NOISEG_LEVEL_SHIFT = const(3)
_I2C_ADDR = const(0x1A)
# WM8960 maximum volume values
_MAX_VOLUME_ADC = const(0xFF)
_MAX_VOLUME_DAC = const(0xFF)
_MAX_VOLUME_HEADPHONE = const(0x7F)
_MAX_VOLUME_LINEIN = const(0x3F)
_MAX_VOLUME_SPEAKER = const(0x7F)
# Config symbol names
# Modules
MODULE_ADC = const(0) # ADC module in WM8960
MODULE_DAC = const(1) # DAC module in WM8960
MODULE_VREF = const(2) # VREF module
MODULE_HEADPHONE = const(3) # Headphone
MODULE_MIC_BIAS = const(4) # Mic bias
MODULE_MIC = const(5) # Input Mic
MODULE_LINE_IN = const(6) # Analog in PGA
MODULE_LINE_OUT = const(7) # Line out module
MODULE_SPEAKER = const(8) # Speaker module
MODULE_OMIX = const(9) # Output mixer
MODULE_MONO_OUT = const(10) # Mono mix
# Route
ROUTE_BYPASS = const(0) # LINEIN->Headphone.
ROUTE_PLAYBACK = const(1) # I2SIN->DAC->Headphone.
ROUTE_PLAYBACK_RECORD = const(2) # I2SIN->DAC->Headphone, LINEIN->ADC->I2SOUT.
ROUTE_RECORD = const(5) # LINEIN->ADC->I2SOUT.
# Input
INPUT_CLOSED = const(0) # Input device is closed
INPUT_MIC1 = const(1) # Input as single ended mic, only use L/RINPUT1
INPUT_MIC2 = const(2) # Input as diff. mic, use L/RINPUT1 and L/RINPUT2
INPUT_MIC3 = const(3) # Input as diff. mic, use L/RINPUT1 and L/RINPUT3
INPUT_LINE2 = const(4) # Input as line input, only use L/RINPUT2
INPUT_LINE3 = const(5) # Input as line input, only use L/RINPUT3
# ADC sync input
SYNC_ADC = const(0) # Use ADCLRC pin for ADC sync
SYNC_DAC = const(1) # used DACLRC pin for ADC sync
# Protocol type
BUS_I2S = const(2) # I2S type
BUS_LEFT_JUSTIFIED = const(1) # Left justified mode
BUS_RIGHT_JUSTIFIED = const(0) # Right justified mode
BUS_PCMA = const(3) # PCM A mode
BUS_PCMB = const(3 | (1 << 4)) # PCM B mode
# Channel swap
SWAP_NONE = const(0)
SWAP_INPUT = const(1)
SWAP_OUTPUT = const(2)
# Mute settings
MUTE_FAST = const(0)
MUTE_SLOW = const(1)
# ALC settings
ALC_OFF = const(0)
ALC_RIGHT = const(1)
ALC_LEFT = const(2)
ALC_STEREO = const(3)
ALC_MODE = const(0) # ALC mode
ALC_LIMITER = const(1) # Limiter mode
# Clock Source
SYSCLK_MCLK = const(0) # sysclk source from external MCLK
SYSCLK_PLL = const(1) # sysclk source from internal PLL
class Regs:
# register cache of 56 register. Since registers cannot be read back, they are
# kept in the table for modification
# fmt: off
cache = array.array("H", (
0x0097, 0x0097, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000,
0x000a, 0x01c0, 0x0000, 0x00ff, 0x00ff, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x007b, 0x0100, 0x0032, 0x0000,
0x00c3, 0x00c3, 0x01c0, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0100, 0x0050,
0x0050, 0x0050, 0x0050, 0x0000, 0x0000, 0x0000, 0x0000,
0x0040, 0x0000, 0x0000, 0x0050, 0x0050, 0x0000, 0x0002,
0x0037, 0x004d, 0x0080, 0x0008, 0x0031, 0x0026, 0x00e9
))
# fmt: on
def __init__(self, i2c, i2c_address=_I2C_ADDR):
self.value_buffer = bytearray(2)
self.i2c = i2c
self.i2c_address = i2c_address
def __getitem__(self, reg):
return self.cache[reg]
def __setitem__(self, reg, value):
if type(reg) is tuple:
if type(value) is tuple:
self[reg[0]] = value[0]
self[reg[1]] = value[1]
else:
self[reg[0]] = value
self[reg[1]] = value
else:
if type(value) is tuple:
val = (self.cache[reg] & (~value[0] & 0xFFFF)) | value[1]
else:
val = value
self.cache[reg] = val
self.value_buffer[0] = (reg << 1) | ((val >> 8) & 0x01)
self.value_buffer[1] = val & 0xFF
self.i2c.writeto(self.i2c_address, self.value_buffer)
class WM8960:
_bit_clock_divider_table = {
2: 0,
3: 1,
4: 2,
6: 3,
8: 4,
11: 5,
12: 6,
16: 7,
22: 8,
24: 9,
32: 10,
44: 11,
48: 12,
}
_dac_divider_table = {
1.0 * 256: 0b000,
1.5 * 256: 0b001,
2 * 256: 0b010,
3 * 256: 0b011,
4 * 256: 0b100,
5.5 * 256: 0b101,
6 * 256: 0b110,
}
_audio_word_length_table = {
16: 0b00,
20: 0b01,
24: 0b10,
32: 0b11,
}
_alc_sample_rate_table = {
48000: 0,
44100: 0,
32000: 1,
24000: 2,
22050: 2,
16000: 3,
12000: 4,
11025: 4,
8000: 5,
}
_volume_config_table = {
MODULE_ADC: (_MAX_VOLUME_ADC, _LADC, 0x100),
MODULE_DAC: (_MAX_VOLUME_DAC, _LDAC, 0x100),
MODULE_HEADPHONE: (_MAX_VOLUME_HEADPHONE, _LOUT1, 0x180),
MODULE_LINE_IN: (_MAX_VOLUME_LINEIN, _LINVOL, 0x140),
MODULE_SPEAKER: (_MAX_VOLUME_SPEAKER, _LOUT2, 0x180),
}
_input_config_table = {
INPUT_CLOSED: None,
INPUT_MIC1: (0x138, 0x117),
INPUT_MIC2: (0x178, 0x117),
INPUT_MIC3: (0x1B8, 0x117),
INPUT_LINE2: (0, 0xE),
INPUT_LINE3: (0, 0x70),
}
def __init__(
self,
i2c,
sample_rate=16000,
bits=16,
swap=SWAP_NONE,
route=ROUTE_PLAYBACK_RECORD,
left_input=INPUT_MIC3,
right_input=INPUT_MIC2,
sysclk_source=SYSCLK_MCLK,
mclk_freq=None,
primary=False,
adc_sync=SYNC_DAC,
protocol=BUS_I2S,
i2c_address=_I2C_ADDR,
):
self.regs = regs = Regs(i2c, i2c_address)
self.sample_rate = sample_rate
# check parameter consistency and set the sysclk value
if sysclk_source == SYSCLK_PLL:
if sample_rate in (11025, 22050, 44100):
sysclk = 11289600
else:
sysclk = 12288000
if sysclk < sample_rate * 256:
sysclk = sample_rate * 256
if mclk_freq is None:
mclk_freq = sysclk
else: # sysclk_source == SYSCLK_MCLK
if mclk_freq is None:
mclk_freq = sample_rate * 256
sysclk = mclk_freq
regs[_RESET] = 0x00
# VMID=50K, Enable VREF, AINL, AINR, ADCL and ADCR
# I2S_IN (bit 0), I2S_OUT (bit 1), DAP (bit 4), DAC (bit 5), ADC (bit 6) are powered on
regs[_POWER1] = 0xFE
# Enable DACL, DACR, LOUT1, ROUT1, PLL down, SPKL, SPKR
regs[_POWER2] = 0x1F8
# Enable left and right channel input PGA, left and right output mixer
regs[_POWER3] = 0x3C
if adc_sync == SYNC_ADC:
# ADC and DAC use different Frame Clock Pins
regs[_IFACE2] = 0x00 # ADCLRC 0x00:Input 0x40:output.
else:
# ADC and DAC use the same Frame Clock Pin
regs[_IFACE2] = 0x40 # ADCLRC 0x00:Input 0x40:output.
self.set_data_route(route)
self.set_protocol(protocol)
if sysclk_source == SYSCLK_PLL:
self.set_internal_pll_config(mclk_freq, sysclk)
if primary:
self.set_master_clock(sysclk, sample_rate, bits)
# set master bit.
self.regs[_IFACE1] = (0, _IFACE1_MS_MASK)
self.set_speaker_clock(sysclk)
# swap channels
if swap & SWAP_INPUT:
regs[_IFACE1] = (0, _IFACE1_ALRSWAP_MASK)
if swap & SWAP_OUTPUT:
regs[_IFACE1] = (0, _IFACE1_DLRSWAP_MASK)
self.set_left_input(left_input)
self.set_right_input(right_input)
regs[_ADDCTL1] = 0x0C0
regs[_ADDCTL4] = 0x60 # Set GPIO1 to 0.
regs[_BYPASS1] = regs[_BYPASS2] = 0x0
# ADC volume, 0dB
regs[_LADC, _RADC] = 0x1C3
# Digital DAC volume, 0dB
regs[_LDAC, _RDAC] = 0x1FF
# Headphone volume, LOUT1 and ROUT1, 0dB
regs[_LOUT1, _ROUT1] = 0x16F
# speaker volume 6dB
regs[_LOUT2, _ROUT2] = 0x1FF
# enable class D output
regs[_CLASSD1] = 0xF7
# Unmute DAC.
regs[_DACCTL1] = 0x0000
# Input PGA volume 0 dB
regs[_LINVOL, _RINVOL] = 0x117
self.config_data_format(sysclk, sample_rate, bits)
def deinit(self):
self.set_module(MODULE_ADC, False)
self.set_module(MODULE_DAC, False)
self.set_module(MODULE_VREF, False)
self.set_module(MODULE_LINE_IN, False)
self.set_module(MODULE_LINE_OUT, False)
self.set_module(MODULE_SPEAKER, False)
def set_internal_pll_config(self, input_mclk, output_clk):
regs = self.regs
pllF2 = output_clk * 4
pll_prescale = 0
sysclk_div = 1
frac_mode = 0
# disable PLL power
regs[_POWER2] = (1, 0)
regs[_CLOCK1] = (7, 0)
pllN = pllF2 // input_mclk
if pllN < _PLL_N_MIN_VALUE:
input_mclk //= 2
pll_prescale = 1
pllN = pllF2 // input_mclk
if pllN < _PLL_N_MIN_VALUE:
sysclk_div = 2
pllF2 *= 2
pllN = pllF2 // input_mclk
if (pllN < _PLL_N_MIN_VALUE) or (pllN > _PLL_N_MAX_VALUE):
raise ValueError("Invalid MCLK vs. sysclk ratio")
pllK = ((pllF2 % input_mclk) * (1 << 24)) // input_mclk
if pllK != 0:
frac_mode = 1
regs[_PLL1] = (frac_mode << 5) | (pll_prescale << 4) | (pllN & 0x0F)
regs[_PLL2] = (pllK >> 16) & 0xFF
regs[_PLL3] = (pllK >> 8) & 0xFF
regs[_PLL4] = pllK & 0xFF
# enable PLL power
regs[_POWER2] = (1, 1)
regs[_CLOCK1] = (7, ((0 if sysclk_div == 1 else sysclk_div) << 1) | 1)
def set_master_clock(self, sysclk, sample_rate, bit_width):
bit_clock_divider = (sysclk * 2) // (sample_rate * bit_width * 2)
try:
reg_divider = self._bit_clock_divider_table[bit_clock_divider]
except:
raise ValueError("Invalid ratio of sysclk sample rate and bits")
# configure the master bit clock divider
self.regs[_CLOCK2] = (_CLOCK2_BCLK_DIV_MASK, reg_divider)
def set_speaker_clock(self, sysclk):
speaker_divider_table = (1.5, 2, 3, 4, 6, 8, 12, 16)
for val in range(8):
divider = speaker_divider_table[val]
f = sysclk / divider
if 500_000 < f < 1_000_000:
break
else:
val = 7
self.regs[_CLOCK2] = (
_CLOCK2_DCLK_DIV_MASK,
val << _CLOCK2_DCLK_DIV_SHIFT,
)
def set_module(self, module, is_enabled):
is_enabled = 1 if is_enabled else 0
regs = self.regs
if module == MODULE_ADC:
regs[_POWER1] = (
_POWER1_ADCL_MASK | _POWER1_ADCR_MASK,
(_POWER1_ADCL_MASK | _POWER1_ADCR_MASK) * is_enabled,
)
elif module == MODULE_DAC:
regs[_POWER2] = (
_POWER2_DACL_MASK | _POWER2_DACR_MASK,
(_POWER2_DACL_MASK | _POWER2_DACR_MASK) * is_enabled,
)
elif module == MODULE_VREF:
regs[_POWER1] = (
_POWER1_VREF_MASK,
(is_enabled << _POWER1_VREF_SHIFT),
)
elif module == MODULE_LINE_IN:
regs[_POWER1] = (
_POWER1_AINL_MASK | _POWER1_AINR_MASK,
(_POWER1_AINL_MASK | _POWER1_AINR_MASK) * is_enabled,
)
regs[_POWER3] = (
_POWER3_LMIC_MASK | _POWER3_RMIC_MASK,
(_POWER3_LMIC_MASK | _POWER3_RMIC_MASK) * is_enabled,
)
elif module == MODULE_LINE_OUT:
regs[_POWER2] = (
_POWER2_LOUT1_MASK | _POWER2_ROUT1_MASK,
(_POWER2_LOUT1_MASK | _POWER2_ROUT1_MASK) * is_enabled,
)
elif module == MODULE_MIC_BIAS:
regs[_POWER1] = (
_POWER1_MICB_MASK,
(is_enabled << _POWER1_MICB_SHIFT),
)
elif module == MODULE_SPEAKER:
regs[_POWER2] = (
_POWER2_SPKL_MASK | _POWER2_SPKR_MASK,
(_POWER2_SPKL_MASK | _POWER2_SPKR_MASK) * is_enabled,
)
regs[_CLASSD1] = 0xF7
elif module == MODULE_OMIX:
regs[_POWER3] = (
_POWER3_LOMIX_MASK | _POWER3_ROMIX_MASK,
(_POWER3_LOMIX_MASK | _POWER3_ROMIX_MASK) * is_enabled,
)
elif module == MODULE_MONO_OUT:
regs[_MONOMIX1] = regs[_MONOMIX2] = is_enabled << 7
regs[_MONO] = is_enabled << 6
else:
raise ValueError("Invalid module")
def enable_module(self, module):
self.set_module(module, True)
def disable_module(self, module):
self.set_module(module, False)
def set_data_route(self, route):
regs = self.regs
if route == ROUTE_BYPASS:
# Bypass means from line-in to HP
# Left LINPUT3 to left output mixer, LINPUT3 left output mixer volume = 0dB
# Right RINPUT3 to right output mixer, RINPUT3 right output mixer volume = 0dB
regs[_LOUTMIX, _ROUTMIX] = 0x80
elif route == ROUTE_PLAYBACK:
# Data route I2S_IN-> DAC-> HP
#
# Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB
# Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB
regs[_LOUTMIX, _ROUTMIX] = 0x100
regs[_POWER3] = 0x0C
# Set power for DAC
self.set_module(MODULE_DAC, True)
self.set_module(MODULE_OMIX, True)
self.set_module(MODULE_LINE_OUT, True)
elif route == ROUTE_PLAYBACK_RECORD:
#
# Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB
# Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB
regs[_LOUTMIX, _ROUTMIX] = 0x100
regs[_POWER3] = 0x3C
self.set_module(MODULE_DAC, True)
self.set_module(MODULE_ADC, True)
self.set_module(MODULE_LINE_IN, True)
self.set_module(MODULE_OMIX, True)
self.set_module(MODULE_LINE_OUT, True)
elif route == ROUTE_RECORD:
# LINE_IN->ADC->I2S_OUT
# Left and right input boost, LIN3BOOST and RIN3BOOST = 0dB
regs[_POWER3] = 0x30
# Power up ADC and AIN
self.set_module(MODULE_LINE_IN, True)
self.set_module(MODULE_ADC, True)
else:
raise ValueError("Invalid route")
def set_left_input(self, input):
if not input in self._input_config_table.keys():
raise ValueError("Invalid input")
input = self._input_config_table[input]
regs = self.regs
if input is None:
regs[_POWER1] = (_POWER1_AINL_MASK | _POWER1_ADCL_MASK, 0)
elif input[0] == 0:
regs[_POWER1] = (0, _POWER1_AINL_MASK | _POWER1_ADCL_MASK)
regs[_INBMIX1] = input
else:
regs[_POWER1] = (0, _POWER1_AINL_MASK | _POWER1_ADCL_MASK | _POWER1_MICB_MASK)
regs[_LINPATH] = input[0]
regs[_LINVOL] = input[1]
def set_right_input(self, input):
if not input in self._input_config_table.keys():
raise ValueError("Invalid input name")
input = self._input_config_table[input]
regs = self.regs
if input is None:
regs[_POWER1] = (_POWER1_AINR_MASK | _POWER1_ADCR_MASK, 0)
elif input[0] == 0:
regs[_POWER1] = (0, _POWER1_AINL_MASK | _POWER1_ADCR_MASK)
regs[_INBMIX2] = input
else:
regs[_POWER1] = (0, _POWER1_AINR_MASK | _POWER1_ADCR_MASK | _POWER1_MICB_MASK)
regs[_RINPATH] = input[0]
regs[_RINVOL] = input[1]
def set_protocol(self, protocol):
self.regs[_IFACE1] = (
_IFACE1_FORMAT_MASK | _IFACE1_LRP_MASK,
protocol,
)
def config_data_format(self, sysclk, sample_rate, bits):
# Compute sample rate divider, dac and adc are the same sample rate
try:
divider = self._dac_divider_table[sysclk // sample_rate]
wl = self._audio_word_length_table[bits]
except:
raise ValueError("Invalid ratio sysclk/sample_rate or invalid bit length")
self.regs[_CLOCK1] = (0x1F8, divider << 6 | divider << 3)
self.regs[_IFACE1] = (_IFACE1_WL_MASK, wl << _IFACE1_WL_SHIFT)
def volume(self, module, volume_l=None, volume_r=None):
if not module in self._volume_config_table.keys():
raise ValueError("Invalid module")
if volume_l is None: # get volume
vol_max, regnum, _ = self._volume_config_table[module]
return (
int((self.regs[regnum] & vol_max) * 100 / vol_max + 0.5),
int((self.regs[regnum + 1] & vol_max) * 100 / vol_max + 0.5),
)
else: # set volume
if volume_r is None:
volume_r = volume_l
if not ((0 <= volume_l <= 100) and (0 <= volume_r <= 100)):
raise ValueError("Invalid value for volume")
elif not module in self._volume_config_table.keys():
raise ValueError("Invalid module")
vol_max, regnum, flags = self._volume_config_table[module]
self.regs[regnum] = int(volume_l * vol_max / 100 + 0.5) | flags
self.regs[regnum + 1] = int(volume_r * vol_max / 100 + 0.5) | flags
def mute(self, enable, soft=True, ramp=MUTE_FAST):
enable = _DACCTL1_DACMU_MASK if enable else 0
soft = _DACCTL2_DACSMM_MASK if soft else 0
ramp = _DACCTL2_DACMR_MASK if ramp == MUTE_SLOW else 0
self.regs[_DACCTL1] = (_DACCTL1_DACMU_MASK, enable)
self.regs[_DACCTL2] = (
_DACCTL2_DACSMM_MASK | _DACCTL2_DACMR_MASK,
soft | ramp,
)
def expand_3d(self, depth=0):
depth &= 0x0F
cutoff = 0 if self.sample_rate >= 32000 else 0b1100000
self.regs[_3D] = cutoff | depth << 1 | (1 if depth > 0 else 0)
def mono(self, enable):
enable = 1 if enable else 0
self.regs[_DACCTL1] = (
_DACCTL1_MONOMIX_MASK,
enable << _DACCTL1_MONOMIX_SHIFT,
)
def alc_mode(self, channel, mode=ALC_MODE):
if mode != ALC_MODE:
mode = ALC_LIMITER
channel &= 3
self.regs[_ALC1] = (
_ALC_CHANNEL_MASK,
channel << _ALC_CHANNEL_SHIFT,
)
self.regs[_ALC3] = (_ALC_MODE_MASK, mode << _ALC_MODE_SHIFT)
try:
rate = _alc_sample_rate_table[self.sample_rate]
except:
rate = 0
self.regs[_ADDCTL3] = (_DACCTL3_ALCSR_MASK, rate)
def alc_gain(self, target=-12, max_gain=30, min_gain=-17.25, noise_gate=-78):
def limit(value, minval, maxval):
value = int(value)
if value < minval:
value = minval
if value > maxval:
value = maxval
return value
target = limit((16 + (target * 2) // 3), 0, 15)
max_gain = limit((max_gain + 12) // 6, 0, 7)
min_gain = limit((min_gain * 4 + 69) // 24, 0, 7)
noise_gate = limit((noise_gate * 2 + 153) // 3, -1, 31)
self.regs[_ALC1] = (
_ALC_GAIN_MASK | _ALC_TARGET_MASK,
(max_gain << _ALC_GAIN_SHIFT) | target,
)
self.regs[_ALC2] = (_ALC_GAIN_MASK, (min_gain << _ALC_GAIN_SHIFT))
if noise_gate >= 0:
self.regs[_NOISEG] = noise_gate << _NOISEG_LEVEL_SHIFT | 1
else:
self.regs[_NOISEG] = 0
def alc_time(self, attack=24, decay=192, hold=0):
def logb(value, limit):
value = int(value)
lb = 0
while value > 1:
value >>= 1
lb += 1
if lb > limit:
lb = limit
return lb
attack = logb(attack / 6, 7)
decay = logb(decay / 24, 7)
hold = logb((hold * 3) / 8, 15)
self.regs[_ALC2] = (_ALC_HOLD_MASK, hold)
self.regs[_ALC3] = (
_ALC_DECAY_MASK | _ALC_ATTACK_MASK,
(decay << _ALC_DECAY_SHIFT) | attack,
)
def deemphasis(self, enable):
deem_table = (32000, 44100, 48000)
enable = not not enable
if enable and self.sample_rate in deem_table:
val = deem_table.index(self.sample_rate) + 1
else:
val = 0
self.regs[_DACCTL1] = (_DACCTL1_DEEM_MASK, val << _DACCTL1_DEEM_SHIFT)

View File

@ -9,8 +9,10 @@ elif sys.platform == "mimxrt":
from mimxrt import dht_readinto
elif sys.platform == "rp2":
from rp2 import dht_readinto
else:
elif sys.platform == "pyboard":
from pyb import dht_readinto
else:
from machine import dht_readinto
class DHTBase:

View File

@ -5,7 +5,7 @@ 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>
Copyright (c) 2021-2022 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
@ -30,15 +30,20 @@ Basic example usage:
import time
from lsm6dsox import LSM6DSOX
from machine import Pin, I2C
from machine import Pin, SPI, I2C
# Init in I2C mode.
lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12)))
# Or init in SPI mode.
#lsm = LSM6DSOX(SPI(5), cs_pin=Pin(10))
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
@ -73,7 +78,8 @@ class LSM6DSOX:
def __init__(
self,
i2c,
bus,
cs_pin=None,
address=_DEFAULT_ADDR,
gyro_odr=104,
accel_odr=104,
@ -88,8 +94,13 @@ class LSM6DSOX:
accel_scale: (+/-2g, +/-4g, +/-8g, +-16g)
ucf: MLC program to load.
"""
self.i2c = i2c
self.bus = bus
self.cs_pin = cs_pin
self.address = address
self._use_i2c = hasattr(self.bus, "readfrom_mem")
if not self._use_i2c and cs_pin is None:
raise ValueError("A CS pin must be provided in SPI mode")
# check the id of the Accelerometer/Gyro
if self.__read_reg(_WHO_AM_I_REG) != 108:
@ -149,13 +160,39 @@ class LSM6DSOX:
self.accel_scale = 32768 / accel_scale
def __read_reg(self, reg, size=1):
buf = self.i2c.readfrom_mem(self.address, reg, size)
if self._use_i2c:
buf = self.bus.readfrom_mem(self.address, reg, size)
else:
try:
self.cs_pin(0)
self.bus.write(bytes([reg | 0x80]))
buf = self.bus.read(size)
finally:
self.cs_pin(1)
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]))
if self._use_i2c:
self.bus.writeto_mem(self.address, reg, bytes([val]))
else:
try:
self.cs_pin(0)
self.bus.write(bytes([reg, val]))
finally:
self.cs_pin(1)
def __read_reg_into(self, reg, buf):
if self._use_i2c:
self.bus.readfrom_mem_into(self.address, reg, buf)
else:
try:
self.cs_pin(0)
self.bus.write(bytes([reg | 0x80]))
self.bus.readinto(buf)
finally:
self.cs_pin(1)
def reset(self):
self.__write_reg(_CTRL3_C, self.__read_reg(_CTRL3_C) | 0x1)
@ -223,12 +260,12 @@ class LSM6DSOX:
"""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)
self.__read_reg_into(_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)
self.__read_reg_into(_OUTX_L_XL, mv)
return (mv[0] / f, mv[1] / f, mv[2] / f)

View File

@ -5,6 +5,8 @@ from lsm6dsox import LSM6DSOX
from machine import Pin, I2C
lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12)))
# Or init in SPI mode.
# lsm = LSM6DSOX(SPI(5), cs_pin=Pin(10))
while True:
print("Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}".format(*lsm.read_accel()))

View File

@ -123,9 +123,9 @@ STATIC void mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len
const mp_spiflash_config_t *c = self->config;
uint8_t cmd;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
cmd = MP_SPI_ADDR_IS_32B(addr) ? CMD_READ_32 : CMD_READ;
cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? CMD_READ_32 : CMD_READ;
} else {
cmd = MP_SPI_ADDR_IS_32B(addr) ? CMD_C4READ_32 : CMD_C4READ;
cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? CMD_C4READ_32 : CMD_C4READ;
}
mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, NULL, dest);
}
@ -218,7 +218,7 @@ STATIC int mp_spiflash_erase_block_internal(mp_spiflash_t *self, uint32_t addr)
}
// erase the sector
uint8_t cmd = MP_SPI_ADDR_IS_32B(addr) ? CMD_SEC_ERASE_32 : CMD_SEC_ERASE;
uint8_t cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? CMD_SEC_ERASE_32 : CMD_SEC_ERASE;
mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, 0, NULL, NULL);
// wait WIP=0
@ -236,7 +236,7 @@ STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, size_t len
}
// write the page
uint8_t cmd = MP_SPI_ADDR_IS_32B(addr) ? CMD_WRITE_32 : CMD_WRITE;
uint8_t cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? CMD_WRITE_32 : CMD_WRITE;
mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, src, NULL);
// wait WIP=0

View File

@ -31,6 +31,8 @@
int nina_bsp_init(void);
int nina_bsp_deinit(void);
int nina_bsp_atomic_enter(void);
int nina_bsp_atomic_exit(void);
int nina_bsp_read_irq(void);
int nina_bsp_spi_slave_select(uint32_t timeout);
int nina_bsp_spi_slave_deselect(void);

View File

@ -90,6 +90,20 @@ int nina_bsp_deinit(void) {
return 0;
}
int nina_bsp_atomic_enter(void) {
#if MICROPY_ENABLE_SCHEDULER
mp_sched_lock();
#endif
return 0;
}
int nina_bsp_atomic_exit(void) {
#if MICROPY_ENABLE_SCHEDULER
mp_sched_unlock();
#endif
return 0;
}
int nina_bsp_read_irq(void) {
return mp_hal_pin_read(MICROPY_HW_NINA_GPIO0);
}
@ -97,7 +111,7 @@ int nina_bsp_read_irq(void) {
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) {
if (timeout && ((mp_hal_ticks_ms() - start) >= timeout)) {
return -1;
}
}

View File

@ -28,6 +28,7 @@
*/
#include "py/mphal.h"
#include "py/mperrno.h"
#if MICROPY_PY_NETWORK_NINAW10
@ -59,8 +60,7 @@
#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_SSELECT_TIMEOUT (1000)
#define NINA_CONNECT_TIMEOUT (10000)
#if NINA_DEBUG
@ -129,18 +129,24 @@ typedef enum {
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,
NINA_CMD_SOCKET_SOCKET = 0x70,
NINA_CMD_SOCKET_CLOSE = 0x71,
NINA_CMD_SOCKET_ERRNO = 0x72,
NINA_CMD_SOCKET_BIND = 0x73,
NINA_CMD_SOCKET_LISTEN = 0x74,
NINA_CMD_SOCKET_ACCEPT = 0x75,
NINA_CMD_SOCKET_CONNECT = 0x76,
NINA_CMD_SOCKET_SEND = 0x77,
NINA_CMD_SOCKET_RECV = 0x78,
NINA_CMD_SOCKET_SENDTO = 0x79,
NINA_CMD_SOCKET_RECVFROM = 0x7A,
NINA_CMD_SOCKET_IOCTL = 0x7B,
NINA_CMD_SOCKET_POLL = 0x7C,
NINA_CMD_SOCKET_SETSOCKOPT = 0x7D,
NINA_CMD_SOCKET_GETSOCKOPT = 0x7E,
NINA_CMD_SOCKET_GETPEERNAME = 0x7F,
// UDP commands.
NINA_CMD_UDP_SEND = 0x46,
@ -200,28 +206,15 @@ static uint8_t nina_bsp_spi_read_byte(void) {
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);
nina_bsp_spi_slave_deselect();
if (nina_bsp_spi_slave_select(NINA_SSELECT_TIMEOUT) != 0) {
return -1;
goto error_out;
}
// Send command header.
@ -264,29 +257,31 @@ error_out:
static int nina_read_response(uint32_t cmd, uint32_t nvals, uint32_t width, nina_vals_t *vals) {
int ret = -1;
uint32_t length = 3; // 3 bytes response header
uint8_t header[3] = {0, 0, 0};
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) {
nina_bsp_spi_slave_deselect();
if (nina_bsp_spi_slave_select(0) != 0) {
goto error_out;
}
// Should return CMD + REPLY flag.
if (nina_bsp_spi_read_byte() != (cmd | CMD_REPLY)) {
if (nina_bsp_spi_transfer(NULL, header, sizeof(header)) != 0
|| header[1] != (cmd | CMD_REPLY)) {
// Read padding.
uint8_t header_padding = nina_bsp_spi_read_byte();
(void)header_padding;
debug_printf("nina_read_response() hdr 0x%x 0x%x 0x%x 0x%x\n",
header[0], header[1], header[2], header_padding);
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;
if (nvals > header[2]) {
nvals = header[2];
}
// Read return value(s).
@ -309,9 +304,12 @@ static int nina_read_response(uint32_t cmd, uint32_t nvals, uint32_t width, nina
// Set the size.
*(vals[i].size) = bytes;
length += bytes + width;
}
if (nina_bsp_spi_read_byte() != CMD_END) {
// Read CMD_END and padding.
uint8_t rspbuf_end[4];
if (nina_bsp_spi_transfer(NULL, rspbuf_end, ((length + 1) % 4) + 1) != 0 || rspbuf_end[0] != CMD_END) {
goto error_out;
}
@ -327,21 +325,25 @@ error_out:
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;
nina_bsp_atomic_enter();
if (nina_send_command(cmd, nargs, width, args) != 0 ||
nina_read_response(cmd, 1, ARG_8BITS, NINA_VALS({&size, &rval})) != 0) {
return -1;
rval = -1;
}
nina_bsp_atomic_exit();
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) {
int ret = 0;
nina_bsp_atomic_enter();
if (nina_send_command(cmd, nargs, argsw, args) != 0 ||
nina_read_response(cmd, nvals, valsw, vals) != 0) {
return -1;
ret = -1;
}
return 0;
nina_bsp_atomic_exit();
return ret;
}
static void nina_fix_mac_addr(uint8_t *mac) {
@ -366,16 +368,6 @@ 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;
@ -468,21 +460,13 @@ int nina_disconnect(void) {
}
int nina_isconnected(void) {
int status = nina_connection_status();
if (status == -1) {
return -1;
}
return status == NINA_STATUS_CONNECTED;
return nina_connection_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;
@ -597,7 +581,7 @@ int nina_scan(nina_scan_callback_t scan_callback, void *arg, uint32_t timeout) {
if (timeout && (mp_hal_ticks_ms() - start) >= timeout) {
// Timeout, no networks.
return NINA_ERROR_TIMEOUT;
return -MP_ETIMEDOUT;
}
mp_hal_delay_ms(100);
@ -700,232 +684,240 @@ int nina_gethostbyname(const char *name, uint8_t *out_ip) {
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) {
int nina_ioctl(uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface) {
switch (cmd) {
case NINA_CMD_SET_PIN_MODE:
if (len != 2 || nina_send_command_read_ack(NINA_CMD_SET_PIN_MODE,
2, ARG_8BITS, NINA_ARGS(ARG_BYTE(buf[0]), ARG_BYTE(buf[1]))) != SPI_ACK) {
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;
case NINA_CMD_SET_DIGITAL_WRITE:
if (len != 2 || nina_send_command_read_ack(NINA_CMD_SET_DIGITAL_WRITE,
2, ARG_8BITS, NINA_ARGS(ARG_BYTE(buf[0]), ARG_BYTE(buf[1]))) != SPI_ACK) {
return -1;
}
if ((mp_hal_ticks_ms() - start) >= 5000) {
return NINA_ERROR_TIMEOUT;
}
break;
case NINA_CMD_GET_DIGITAL_READ:
if (len != 1 || nina_send_command_read_vals(NINA_CMD_GET_DIGITAL_READ,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(buf[0])),
1, ARG_8BITS, NINA_VALS({(uint16_t *)&len, buf})) != 0) {
return -1;
}
break;
default:
return 0;
}
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) {
int nina_socket_socket(uint8_t type, uint8_t proto) {
uint16_t size = 1;
uint8_t sock = 0;
if (nina_send_command_read_vals(NINA_CMD_SOCKET_SOCKET,
2, ARG_8BITS, NINA_ARGS(ARG_BYTE(type), ARG_BYTE(proto)),
1, ARG_8BITS, NINA_VALS({&size, &sock})) != 0) {
return -1;
}
return (sock == NO_SOCKET_AVAIL) ? -1 : sock;
}
// Only TCP sockets' states should be checked.
if (type == NINA_SOCKET_TYPE_TCP &&
nina_server_socket_status(fd) != SOCKET_STATE_LISTEN) {
int nina_socket_close(int fd) {
if (nina_send_command_read_ack(NINA_CMD_SOCKET_CLOSE,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd))) != SPI_ACK) {
return -1;
}
return 0;
}
int nina_socket_errno(int *_errno) {
uint16_t size = 1;
*_errno = 0;
if (nina_send_command_read_vals(NINA_CMD_SOCKET_ERRNO,
0, ARG_8BITS, NULL,
1, ARG_8BITS, NINA_VALS({&size, _errno})) != 0) {
return -1;
}
return 0;
}
int nina_socket_bind(int fd, uint8_t *ip, uint16_t port) {
if (nina_send_command_read_ack(NINA_CMD_SOCKET_BIND,
2, ARG_8BITS,
NINA_ARGS(
ARG_BYTE(fd),
ARG_SHORT(__REVSH(port)))) != SPI_ACK) {
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) {
if (nina_send_command_read_ack(NINA_CMD_SOCKET_LISTEN,
2, ARG_8BITS,
NINA_ARGS(
ARG_BYTE(fd),
ARG_BYTE(backlog))) != SPI_ACK) {
return -1;
}
return 0;
}
for (mp_uint_t start = mp_hal_ticks_ms(); sock == 0 || sock == NO_SOCKET_AVAIL; mp_hal_delay_ms(10)) {
int nina_socket_accept(int fd, uint8_t *ip, uint16_t *port, int *fd_out) {
uint16_t fd_len = 1;
uint16_t port_len = 2;
uint16_t ip_len = NINA_IPV4_ADDR_LEN;
*fd_out = 0;
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) {
3, ARG_8BITS, NINA_VALS({&fd_len, fd_out}, {&ip_len, ip}, {&port_len, port})) != 0) {
return -1;
}
if (timeout && (mp_hal_ticks_ms() - start) >= timeout) {
return NINA_ERROR_TIMEOUT;
}
return (*fd_out == NO_SOCKET_AVAIL) ? -1 : 0;
}
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) {
int nina_socket_connect(int fd, uint8_t *ip, uint16_t port) {
if (nina_send_command_read_ack(NINA_CMD_SOCKET_CONNECT,
4, ARG_8BITS,
3, ARG_8BITS,
NINA_ARGS(
ARG_WORD((*(uint32_t *)ip)),
ARG_SHORT(__REVSH(port)),
ARG_BYTE(fd),
ARG_BYTE(NINA_SOCKET_TYPE_TCP))) != SPI_ACK) {
ARG_WORD((*(uint32_t *)ip)),
ARG_SHORT(__REVSH(port)))) != 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) {
int nina_socket_send(int fd, const uint8_t *buf, uint32_t len) {
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,
if (nina_send_command_read_vals(NINA_CMD_SOCKET_SEND,
2, ARG_16BITS, NINA_ARGS(ARG_BYTE(fd), {len, buf}),
1, ARG_8BITS, NINA_VALS({&size, &bytes})) != 0 || bytes <= 0) {
1, ARG_8BITS, NINA_VALS({&size, &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)));
// Only args sizes (not args themselves) are reversed in read_response().
bytes = __REVSH(bytes);
if (resp == -1) {
if (bytes == 0) {
int _errno = 0;
if (nina_socket_errno(&_errno) != 0 || _errno != 0) {
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;
int nina_socket_recv(int fd, uint8_t *buf, uint32_t len) {
uint16_t bytes = len;
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)),
if (nina_send_command_read_vals(NINA_CMD_SOCKET_RECV,
2, ARG_8BITS, 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 (bytes == 0) {
int _errno = 0;
if (nina_socket_errno(&_errno) != 0 || _errno != 0) {
return -1;
}
}
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) {
int nina_socket_sendto(int fd, const uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t port) {
uint16_t size = 2;
uint16_t bytes = 0;
if (nina_send_command_read_vals(NINA_CMD_SOCKET_SENDTO,
4, ARG_16BITS, NINA_ARGS(ARG_BYTE(fd), ARG_WORD((*(uint32_t *)ip)), ARG_SHORT(__REVSH(port)), {len, buf}),
1, ARG_8BITS, NINA_VALS({&size, &bytes})) != 0) {
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) {
// Only args sizes (not args themselves) are reversed in read_response().
bytes = __REVSH(bytes);
if (bytes == 0) {
int _errno = 0;
if (nina_socket_errno(&_errno) != 0 || _errno != 0) {
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;
return bytes;
}
// 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;
int nina_socket_recvfrom(int fd, uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t *port) {
uint16_t bytes = len;
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) {
if (nina_send_command_read_vals(NINA_CMD_SOCKET_RECVFROM,
2, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd), ARG_SHORT(bytes)),
3, ARG_16BITS, NINA_VALS({&ip_len, ip}, {&port_len, port}, {&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) {
if (bytes == 0) {
int _errno = 0;
if (nina_socket_errno(&_errno) != 0 || _errno != 0) {
return -1;
}
}
return bytes;
}
int nina_socket_setsockopt(int fd, uint32_t level, uint32_t opt, const void *optval, uint32_t optlen) {
int nina_socket_ioctl(int fd, uint32_t cmd, void *argval, uint32_t arglen) {
uint16_t len = arglen;
if (nina_send_command_read_vals(NINA_CMD_SOCKET_IOCTL,
3, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd), ARG_WORD(cmd), {len, argval}),
1, ARG_8BITS, NINA_VALS({&len, argval})) != 0 || arglen == 0) {
return -1;
}
return 0;
}
int nina_socket_poll(int fd, uint8_t *flags) {
uint16_t flags_len = 1;
if (nina_send_command_read_vals(NINA_CMD_SOCKET_POLL,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)),
1, ARG_8BITS, NINA_VALS({&flags_len, flags})) != 0) {
return -1;
}
if (*flags & 0x80) {
// lwip_select() failed.
return -1;
}
return 0;
}
int nina_socket_setsockopt(int fd, uint32_t level, uint32_t optname, const void *optval, uint16_t optlen) {
if (nina_send_command_read_ack(
NINA_CMD_SOCKET_SETSOCKOPT,
3, ARG_8BITS,
NINA_ARGS(ARG_BYTE(fd), ARG_WORD(optname), {optlen, optval})) != SPI_ACK) {
return -1;
}
return 0;
}
int nina_socket_getsockopt(int fd, uint32_t level, uint32_t optname, void *optval, uint16_t optlen) {
if (nina_send_command_read_vals(
NINA_CMD_SOCKET_GETSOCKOPT,
3, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd), ARG_WORD(optname), ARG_BYTE(optlen)),
1, ARG_8BITS, NINA_VALS({&optlen, optval})) != 0 || optlen == 0) {
return -1;
}
return 0;
}
#endif // MICROPY_PY_NINAW10

View File

@ -38,9 +38,9 @@
#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_MIN_MAJOR (1)
#define NINA_FW_VER_MIN_MINOR (5)
#define NINA_FW_VER_MIN_PATCH (0)
#define NINA_FW_VER_MAJOR_OFFS (0)
#define NINA_FW_VER_MINOR_OFFS (2)
@ -54,18 +54,11 @@ typedef enum {
} 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_TCP = 1,
NINA_SOCKET_TYPE_UDP = 2,
NINA_SOCKET_TYPE_RAW = 3,
} 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];
@ -97,7 +90,6 @@ int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t
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);
@ -105,16 +97,21 @@ 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_ioctl(uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface);
int nina_socket_socket(uint8_t type, uint8_t proto);
int nina_socket_close(int fd);
int nina_socket_bind(int fd, uint8_t *ip, uint16_t port, int type);
int nina_socket_errno(int *_errno);
int nina_socket_bind(int fd, uint8_t *ip, uint16_t port);
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);
int nina_socket_accept(int fd, uint8_t *ip, uint16_t *port, int *fd_out);
int nina_socket_connect(int fd, uint8_t *ip, uint16_t port);
int nina_socket_send(int fd, const uint8_t *buf, uint32_t len);
int nina_socket_recv(int fd, uint8_t *buf, uint32_t len);
int nina_socket_sendto(int fd, const uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t port);
int nina_socket_recvfrom(int fd, uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t *port);
int nina_socket_ioctl(int fd, uint32_t cmd, void *argval, uint32_t arglen);
int nina_socket_poll(int fd, uint8_t *flags);
int nina_socket_setsockopt(int fd, uint32_t level, uint32_t opt, const void *optval, uint16_t optlen);
int nina_socket_getsockopt(int fd, uint32_t level, uint32_t opt, void *optval, uint16_t optlen);
int nina_socket_getpeername(int fd, uint8_t *ip, uint16_t *port);
#endif // MICROPY_INCLUDED_DRIVERS_NINAW10_NINA_WIFI_DRV_H

View File

@ -39,7 +39,7 @@ _TOKEN_DATA = const(0xFE)
class SDCard:
def __init__(self, spi, cs):
def __init__(self, spi, cs, baudrate=1320000):
self.spi = spi
self.cs = cs
@ -51,7 +51,7 @@ class SDCard:
self.dummybuf_memoryview = memoryview(self.dummybuf)
# initialise the card
self.init_card()
self.init_card(baudrate)
def init_spi(self, baudrate):
try:
@ -63,7 +63,8 @@ class SDCard:
# on pyboard
self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
def init_card(self):
def init_card(self, baudrate):
# init CS pin
self.cs.init(self.cs.OUT, value=1)
@ -99,9 +100,11 @@ class SDCard:
if csd[0] & 0xC0 == 0x40: # CSD version 2.0
self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024
elif csd[0] & 0xC0 == 0x00: # CSD version 1.0 (old, <=2GB)
c_size = csd[6] & 0b11 | csd[7] << 2 | (csd[8] & 0b11000000) << 4
c_size_mult = ((csd[9] & 0b11) << 1) | csd[10] >> 7
self.sectors = (c_size + 1) * (2 ** (c_size_mult + 2))
c_size = (csd[6] & 0b11) << 10 | csd[7] << 2 | csd[8] >> 6
c_size_mult = (csd[9] & 0b11) << 1 | csd[10] >> 7
read_bl_len = csd[5] & 0b1111
capacity = (c_size + 1) * (2 ** (c_size_mult + 2)) * (2**read_bl_len)
self.sectors = capacity // 512
else:
raise OSError("SD card CSD format not supported")
# print('sectors', self.sectors)
@ -111,12 +114,13 @@ class SDCard:
raise OSError("can't set 512 block size")
# set to high data rate now that it's initialised
self.init_spi(1320000)
self.init_spi(baudrate)
def init_card_v1(self):
for i in range(_CMD_TIMEOUT):
self.cmd(55, 0, 0)
if self.cmd(41, 0, 0) == 0:
# SDSC card, uses byte addressing in read/write/erase commands
self.cdv = 512
# print("[SDCard] v1 card")
return
@ -128,7 +132,13 @@ class SDCard:
self.cmd(58, 0, 0, 4)
self.cmd(55, 0, 0)
if self.cmd(41, 0x40000000, 0) == 0:
self.cmd(58, 0, 0, 4)
self.cmd(58, 0, 0, -4) # 4-byte response, negative means keep the first byte
ocr = self.tokenbuf[0] # get first byte of response, which is OCR
if not ocr & 0x40:
# SDSC card, uses byte addressing in read/write/erase commands
self.cdv = 512
else:
# SDHC/SDXC card, uses block addressing in read/write/erase commands
self.cdv = 1
# print("[SDCard] v2 card")
return
@ -156,6 +166,10 @@ class SDCard:
response = self.tokenbuf[0]
if not (response & 0x80):
# this could be a big-endian integer that we are getting here
# if final<0 then store the first byte to tokenbuf and discard the rest
if final < 0:
self.spi.readinto(self.tokenbuf, 0xFF)
final = -1 - final
for j in range(final):
self.spi.write(b"\xff")
if release:
@ -280,3 +294,5 @@ class SDCard:
def ioctl(self, op, arg):
if op == 4: # get number of blocks
return self.sectors
if op == 5: # get block size in bytes
return 512

View File

@ -137,7 +137,6 @@ SRC_C = $(addprefix ports/unix/,\
unix_mphal.c \
input.c \
modmachine.c \
modos.c \
moduselect.c \
alloc.c \
coverage.c \

View File

@ -28,6 +28,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "py/builtin.h"
#include "py/compile.h"
#include "py/runtime.h"
#include "py/gc.h"

View File

@ -75,21 +75,18 @@
#define MICROPY_PY_SYS_EXIT (0)
#define MICROPY_PY_SYS_PLATFORM "linux"
#define MICROPY_PY_SYS_MAXSIZE (0)
#define MICROPY_PY_SYS_PATH_DEFAULT ".frozen"
#define MICROPY_PY_SYS_STDFILES (0)
#define MICROPY_PY_CMATH (0)
#define MICROPY_PY_UCTYPES (0)
#define MICROPY_PY_UZLIB (0)
#define MICROPY_PY_UJSON (0)
#define MICROPY_PY_UOS (1)
#define MICROPY_PY_URE (0)
#define MICROPY_PY_UHEAPQ (0)
#define MICROPY_PY_UHASHLIB (0)
#define MICROPY_PY_UBINASCII (0)
extern const struct _mp_obj_module_t mp_module_os;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, \
#define MICROPY_PORT_ROOT_POINTERS \
//////////////////////////////////////////

View File

@ -0,0 +1,14 @@
# Location of top-level MicroPython directory
MPY_DIR = ../../..
# Name of module
MOD = features3
# Source files (.c or .py)
SRC = features3.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
ARCH = x64
# Include to get the rules for compiling and linking the module
include $(MPY_DIR)/py/dynruntime.mk

View File

@ -0,0 +1,60 @@
/* This example demonstrates the following features in a native module:
- using types
- using constant objects
- creating dictionaries
*/
// Include the header file to get access to the MicroPython API.
#include "py/dynruntime.h"
// A function that returns a tuple of object types.
STATIC mp_obj_t get_types(void) {
return mp_obj_new_tuple(9, ((mp_obj_t []) {
MP_OBJ_FROM_PTR(&mp_type_type),
MP_OBJ_FROM_PTR(&mp_type_NoneType),
MP_OBJ_FROM_PTR(&mp_type_bool),
MP_OBJ_FROM_PTR(&mp_type_int),
MP_OBJ_FROM_PTR(&mp_type_str),
MP_OBJ_FROM_PTR(&mp_type_bytes),
MP_OBJ_FROM_PTR(&mp_type_tuple),
MP_OBJ_FROM_PTR(&mp_type_list),
MP_OBJ_FROM_PTR(&mp_type_dict),
}));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(get_types_obj, get_types);
// A function that returns a tuple of constant objects.
STATIC mp_obj_t get_const_objects(void) {
return mp_obj_new_tuple(5, ((mp_obj_t []) {
mp_const_none,
mp_const_false,
mp_const_true,
mp_const_empty_bytes,
mp_const_empty_tuple,
}));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(get_const_objects_obj, get_const_objects);
// A function that creates a dictionary from the given arguments.
STATIC mp_obj_t make_dict(size_t n_args, const mp_obj_t *args) {
mp_obj_t dict = mp_obj_new_dict(n_args / 2);
for (; n_args >= 2; n_args -= 2, args += 2) {
mp_obj_dict_store(dict, args[0], args[1]);
}
return dict;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(make_dict_obj, 0, MP_OBJ_FUN_ARGS_MAX, make_dict);
// This is the entry point and is called when the module is imported.
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
// This must be first, it sets up the globals dict and other things.
MP_DYNRUNTIME_INIT_ENTRY
// Make the functions available in the module's namespace.
mp_store_global(MP_QSTR_make_dict, MP_OBJ_FROM_PTR(&make_dict_obj));
mp_store_global(MP_QSTR_get_types, MP_OBJ_FROM_PTR(&get_types_obj));
mp_store_global(MP_QSTR_get_const_objects, MP_OBJ_FROM_PTR(&get_const_objects_obj));
// This must be last, it restores the globals dict.
MP_DYNRUNTIME_INIT_EXIT
}

View File

@ -31,7 +31,4 @@ const mp_obj_module_t example_user_cmodule = {
};
// Register the module to make it available in Python.
// Note: the "1" in the third argument means this module is always enabled.
// This "1" can be optionally replaced with a macro like MODULE_CEXAMPLE_ENABLED
// which can then be used to conditionally enable this module.
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, 1);
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule);

View File

@ -22,7 +22,4 @@ const mp_obj_module_t cppexample_user_cmodule = {
};
// Register the module to make it available in Python.
// Note: the "1" in the third argument means this module is always enabled.
// This "1" can be optionally replaced with a macro like MODULE_CPPEXAMPLE_ENABLED
// which can then be used to conditionally enable this module.
MP_REGISTER_MODULE(MP_QSTR_cppexample, cppexample_user_cmodule, 1);
MP_REGISTER_MODULE(MP_QSTR_cppexample, cppexample_user_cmodule);

View File

@ -6,7 +6,7 @@ SRC_USERMOD_CXX += $(CPPEXAMPLE_MOD_DIR)/example.cpp
# Add our module directory to the include path.
CFLAGS_USERMOD += -I$(CPPEXAMPLE_MOD_DIR)
CXXFLAGS_USERMOD += -I$(CPPEXAMPLE_MOD_DIR)
CXXFLAGS_USERMOD += -I$(CPPEXAMPLE_MOD_DIR) -std=c++11
# We use C++ features so have to link against the standard library.
LDFLAGS_USERMOD += -lstdc++

View File

@ -25,6 +25,7 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_EXTMOD_DIR}/moduhashlib.c
${MICROPY_EXTMOD_DIR}/moduheapq.c
${MICROPY_EXTMOD_DIR}/modujson.c
${MICROPY_EXTMOD_DIR}/moduos.c
${MICROPY_EXTMOD_DIR}/moduplatform.c
${MICROPY_EXTMOD_DIR}/modurandom.c
${MICROPY_EXTMOD_DIR}/modure.c
@ -53,9 +54,9 @@ set(MICROPY_SOURCE_EXTMOD
# Library for btree module and associated code
if(MICROPY_PY_BTREE)
set(MICROPY_LIB_BERKELEY_DIR "${MICROPY_DIR}/lib/berkeley-db-1.xx")
if(EXISTS "${MICROPY_LIB_BERKELEY_DIR}/btree/bt_close.c")
add_library(micropy_extmod_btree OBJECT
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_close.c
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_conv.c
@ -96,3 +97,153 @@ if(EXISTS "${MICROPY_LIB_BERKELEY_DIR}/btree/bt_close.c")
"virt_fd_t=void*"
)
endif()
# Library for mbedtls
if(MICROPY_SSL_MBEDTLS)
add_library(micropy_lib_mbedtls INTERFACE)
set(MICROPY_LIB_MBEDTLS_DIR "${MICROPY_DIR}/lib/mbedtls")
target_include_directories(micropy_lib_mbedtls INTERFACE
${MICROPY_LIB_MBEDTLS_DIR}/include
)
target_sources(micropy_lib_mbedtls INTERFACE
${MICROPY_LIB_MBEDTLS_DIR}/library/aes.c
${MICROPY_LIB_MBEDTLS_DIR}/library/aesni.c
${MICROPY_LIB_MBEDTLS_DIR}/library/arc4.c
${MICROPY_LIB_MBEDTLS_DIR}/library/asn1parse.c
${MICROPY_LIB_MBEDTLS_DIR}/library/asn1write.c
${MICROPY_LIB_MBEDTLS_DIR}/library/base64.c
${MICROPY_LIB_MBEDTLS_DIR}/library/bignum.c
${MICROPY_LIB_MBEDTLS_DIR}/library/blowfish.c
${MICROPY_LIB_MBEDTLS_DIR}/library/camellia.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ccm.c
${MICROPY_LIB_MBEDTLS_DIR}/library/certs.c
${MICROPY_LIB_MBEDTLS_DIR}/library/chacha20.c
${MICROPY_LIB_MBEDTLS_DIR}/library/chachapoly.c
${MICROPY_LIB_MBEDTLS_DIR}/library/cipher.c
${MICROPY_LIB_MBEDTLS_DIR}/library/cipher_wrap.c
${MICROPY_LIB_MBEDTLS_DIR}/library/cmac.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ctr_drbg.c
${MICROPY_LIB_MBEDTLS_DIR}/library/debug.c
${MICROPY_LIB_MBEDTLS_DIR}/library/des.c
${MICROPY_LIB_MBEDTLS_DIR}/library/dhm.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ecdh.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ecdsa.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ecjpake.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ecp.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ecp_curves.c
${MICROPY_LIB_MBEDTLS_DIR}/library/entropy.c
${MICROPY_LIB_MBEDTLS_DIR}/library/entropy_poll.c
${MICROPY_LIB_MBEDTLS_DIR}/library/error.c
${MICROPY_LIB_MBEDTLS_DIR}/library/gcm.c
${MICROPY_LIB_MBEDTLS_DIR}/library/havege.c
${MICROPY_LIB_MBEDTLS_DIR}/library/hmac_drbg.c
${MICROPY_LIB_MBEDTLS_DIR}/library/md2.c
${MICROPY_LIB_MBEDTLS_DIR}/library/md4.c
${MICROPY_LIB_MBEDTLS_DIR}/library/md5.c
${MICROPY_LIB_MBEDTLS_DIR}/library/md.c
${MICROPY_LIB_MBEDTLS_DIR}/library/md_wrap.c
${MICROPY_LIB_MBEDTLS_DIR}/library/oid.c
${MICROPY_LIB_MBEDTLS_DIR}/library/padlock.c
${MICROPY_LIB_MBEDTLS_DIR}/library/pem.c
${MICROPY_LIB_MBEDTLS_DIR}/library/pk.c
${MICROPY_LIB_MBEDTLS_DIR}/library/pkcs11.c
${MICROPY_LIB_MBEDTLS_DIR}/library/pkcs12.c
${MICROPY_LIB_MBEDTLS_DIR}/library/pkcs5.c
${MICROPY_LIB_MBEDTLS_DIR}/library/pkparse.c
${MICROPY_LIB_MBEDTLS_DIR}/library/pk_wrap.c
${MICROPY_LIB_MBEDTLS_DIR}/library/pkwrite.c
${MICROPY_LIB_MBEDTLS_DIR}/library/platform.c
${MICROPY_LIB_MBEDTLS_DIR}/library/platform_util.c
${MICROPY_LIB_MBEDTLS_DIR}/library/poly1305.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ripemd160.c
${MICROPY_LIB_MBEDTLS_DIR}/library/rsa.c
${MICROPY_LIB_MBEDTLS_DIR}/library/rsa_internal.c
${MICROPY_LIB_MBEDTLS_DIR}/library/sha1.c
${MICROPY_LIB_MBEDTLS_DIR}/library/sha256.c
${MICROPY_LIB_MBEDTLS_DIR}/library/sha512.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ssl_cache.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ssl_ciphersuites.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ssl_cli.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ssl_cookie.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ssl_srv.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ssl_ticket.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ssl_tls.c
${MICROPY_LIB_MBEDTLS_DIR}/library/timing.c
${MICROPY_LIB_MBEDTLS_DIR}/library/x509.c
${MICROPY_LIB_MBEDTLS_DIR}/library/x509_create.c
${MICROPY_LIB_MBEDTLS_DIR}/library/x509_crl.c
${MICROPY_LIB_MBEDTLS_DIR}/library/x509_crt.c
${MICROPY_LIB_MBEDTLS_DIR}/library/x509_csr.c
${MICROPY_LIB_MBEDTLS_DIR}/library/x509write_crt.c
${MICROPY_LIB_MBEDTLS_DIR}/library/x509write_csr.c
${MICROPY_LIB_MBEDTLS_DIR}/library/xtea.c
)
target_compile_definitions(micropy_lib_mbedtls INTERFACE
MBEDTLS_CONFIG_FILE="${MICROPY_PORT_DIR}/mbedtls/mbedtls_config.h"
)
list(APPEND MICROPY_INC_CORE
"${MICROPY_LIB_MBEDTLS_DIR}/include"
)
endif()
# Library for lwIP network stack
if(MICROPY_PY_LWIP)
add_library(micropy_lib_lwip INTERFACE)
set(MICROPY_LIB_LWIP_DIR "${MICROPY_DIR}/lib/lwip/src")
target_include_directories(micropy_lib_lwip INTERFACE
${MICROPY_LIB_LWIP_DIR}/include
)
target_sources(micropy_lib_lwip INTERFACE
${MICROPY_DIR}/shared/netutils/netutils.c
${MICROPY_LIB_LWIP_DIR}/apps/mdns/mdns.c
${MICROPY_LIB_LWIP_DIR}/core/def.c
${MICROPY_LIB_LWIP_DIR}/core/dns.c
${MICROPY_LIB_LWIP_DIR}/core/inet_chksum.c
${MICROPY_LIB_LWIP_DIR}/core/init.c
${MICROPY_LIB_LWIP_DIR}/core/ip.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/autoip.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/dhcp.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/etharp.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/icmp.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/igmp.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/ip4.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/ip4_addr.c
${MICROPY_LIB_LWIP_DIR}/core/ipv4/ip4_frag.c
${MICROPY_LIB_LWIP_DIR}/core/ipv6/dhcp6.c
${MICROPY_LIB_LWIP_DIR}/core/ipv6/ethip6.c
${MICROPY_LIB_LWIP_DIR}/core/ipv6/icmp6.c
${MICROPY_LIB_LWIP_DIR}/core/ipv6/inet6.c
${MICROPY_LIB_LWIP_DIR}/core/ipv6/ip6.c
${MICROPY_LIB_LWIP_DIR}/core/ipv6/ip6_addr.c
${MICROPY_LIB_LWIP_DIR}/core/ipv6/ip6_frag.c
${MICROPY_LIB_LWIP_DIR}/core/ipv6/mld6.c
${MICROPY_LIB_LWIP_DIR}/core/ipv6/nd6.c
${MICROPY_LIB_LWIP_DIR}/core/mem.c
${MICROPY_LIB_LWIP_DIR}/core/memp.c
${MICROPY_LIB_LWIP_DIR}/core/netif.c
${MICROPY_LIB_LWIP_DIR}/core/pbuf.c
${MICROPY_LIB_LWIP_DIR}/core/raw.c
${MICROPY_LIB_LWIP_DIR}/core/stats.c
${MICROPY_LIB_LWIP_DIR}/core/sys.c
${MICROPY_LIB_LWIP_DIR}/core/tcp.c
${MICROPY_LIB_LWIP_DIR}/core/tcp_in.c
${MICROPY_LIB_LWIP_DIR}/core/tcp_out.c
${MICROPY_LIB_LWIP_DIR}/core/timeouts.c
${MICROPY_LIB_LWIP_DIR}/core/udp.c
${MICROPY_LIB_LWIP_DIR}/netif/ethernet.c
)
list(APPEND MICROPY_INC_CORE
${MICROPY_LIB_LWIP_DIR}/include
)
endif()

128
extmod/font_petme128_8x8.h Normal file
View File

@ -0,0 +1,128 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* 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_STM32_FONT_PETME128_8X8_H
#define MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H
static const uint8_t font_petme128_8x8[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 32=
0x00, 0x00, 0x00, 0x4f, 0x4f, 0x00, 0x00, 0x00, // 33=!
0x00, 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, // 34="
0x14, 0x7f, 0x7f, 0x14, 0x14, 0x7f, 0x7f, 0x14, // 35=#
0x00, 0x24, 0x2e, 0x6b, 0x6b, 0x3a, 0x12, 0x00, // 36=$
0x00, 0x63, 0x33, 0x18, 0x0c, 0x66, 0x63, 0x00, // 37=%
0x00, 0x32, 0x7f, 0x4d, 0x4d, 0x77, 0x72, 0x50, // 38=&
0x00, 0x00, 0x00, 0x04, 0x06, 0x03, 0x01, 0x00, // 39='
0x00, 0x00, 0x1c, 0x3e, 0x63, 0x41, 0x00, 0x00, // 40=(
0x00, 0x00, 0x41, 0x63, 0x3e, 0x1c, 0x00, 0x00, // 41=)
0x08, 0x2a, 0x3e, 0x1c, 0x1c, 0x3e, 0x2a, 0x08, // 42=*
0x00, 0x08, 0x08, 0x3e, 0x3e, 0x08, 0x08, 0x00, // 43=+
0x00, 0x00, 0x80, 0xe0, 0x60, 0x00, 0x00, 0x00, // 44=,
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, // 45=-
0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, // 46=.
0x00, 0x40, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, // 47=/
0x00, 0x3e, 0x7f, 0x49, 0x45, 0x7f, 0x3e, 0x00, // 48=0
0x00, 0x40, 0x44, 0x7f, 0x7f, 0x40, 0x40, 0x00, // 49=1
0x00, 0x62, 0x73, 0x51, 0x49, 0x4f, 0x46, 0x00, // 50=2
0x00, 0x22, 0x63, 0x49, 0x49, 0x7f, 0x36, 0x00, // 51=3
0x00, 0x18, 0x18, 0x14, 0x16, 0x7f, 0x7f, 0x10, // 52=4
0x00, 0x27, 0x67, 0x45, 0x45, 0x7d, 0x39, 0x00, // 53=5
0x00, 0x3e, 0x7f, 0x49, 0x49, 0x7b, 0x32, 0x00, // 54=6
0x00, 0x03, 0x03, 0x79, 0x7d, 0x07, 0x03, 0x00, // 55=7
0x00, 0x36, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00, // 56=8
0x00, 0x26, 0x6f, 0x49, 0x49, 0x7f, 0x3e, 0x00, // 57=9
0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x00, // 58=:
0x00, 0x00, 0x80, 0xe4, 0x64, 0x00, 0x00, 0x00, // 59=;
0x00, 0x08, 0x1c, 0x36, 0x63, 0x41, 0x41, 0x00, // 60=<
0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, // 61==
0x00, 0x41, 0x41, 0x63, 0x36, 0x1c, 0x08, 0x00, // 62=>
0x00, 0x02, 0x03, 0x51, 0x59, 0x0f, 0x06, 0x00, // 63=?
0x00, 0x3e, 0x7f, 0x41, 0x4d, 0x4f, 0x2e, 0x00, // 64=@
0x00, 0x7c, 0x7e, 0x0b, 0x0b, 0x7e, 0x7c, 0x00, // 65=A
0x00, 0x7f, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00, // 66=B
0x00, 0x3e, 0x7f, 0x41, 0x41, 0x63, 0x22, 0x00, // 67=C
0x00, 0x7f, 0x7f, 0x41, 0x63, 0x3e, 0x1c, 0x00, // 68=D
0x00, 0x7f, 0x7f, 0x49, 0x49, 0x41, 0x41, 0x00, // 69=E
0x00, 0x7f, 0x7f, 0x09, 0x09, 0x01, 0x01, 0x00, // 70=F
0x00, 0x3e, 0x7f, 0x41, 0x49, 0x7b, 0x3a, 0x00, // 71=G
0x00, 0x7f, 0x7f, 0x08, 0x08, 0x7f, 0x7f, 0x00, // 72=H
0x00, 0x00, 0x41, 0x7f, 0x7f, 0x41, 0x00, 0x00, // 73=I
0x00, 0x20, 0x60, 0x41, 0x7f, 0x3f, 0x01, 0x00, // 74=J
0x00, 0x7f, 0x7f, 0x1c, 0x36, 0x63, 0x41, 0x00, // 75=K
0x00, 0x7f, 0x7f, 0x40, 0x40, 0x40, 0x40, 0x00, // 76=L
0x00, 0x7f, 0x7f, 0x06, 0x0c, 0x06, 0x7f, 0x7f, // 77=M
0x00, 0x7f, 0x7f, 0x0e, 0x1c, 0x7f, 0x7f, 0x00, // 78=N
0x00, 0x3e, 0x7f, 0x41, 0x41, 0x7f, 0x3e, 0x00, // 79=O
0x00, 0x7f, 0x7f, 0x09, 0x09, 0x0f, 0x06, 0x00, // 80=P
0x00, 0x1e, 0x3f, 0x21, 0x61, 0x7f, 0x5e, 0x00, // 81=Q
0x00, 0x7f, 0x7f, 0x19, 0x39, 0x6f, 0x46, 0x00, // 82=R
0x00, 0x26, 0x6f, 0x49, 0x49, 0x7b, 0x32, 0x00, // 83=S
0x00, 0x01, 0x01, 0x7f, 0x7f, 0x01, 0x01, 0x00, // 84=T
0x00, 0x3f, 0x7f, 0x40, 0x40, 0x7f, 0x3f, 0x00, // 85=U
0x00, 0x1f, 0x3f, 0x60, 0x60, 0x3f, 0x1f, 0x00, // 86=V
0x00, 0x7f, 0x7f, 0x30, 0x18, 0x30, 0x7f, 0x7f, // 87=W
0x00, 0x63, 0x77, 0x1c, 0x1c, 0x77, 0x63, 0x00, // 88=X
0x00, 0x07, 0x0f, 0x78, 0x78, 0x0f, 0x07, 0x00, // 89=Y
0x00, 0x61, 0x71, 0x59, 0x4d, 0x47, 0x43, 0x00, // 90=Z
0x00, 0x00, 0x7f, 0x7f, 0x41, 0x41, 0x00, 0x00, // 91=[
0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x40, // 92='\'
0x00, 0x00, 0x41, 0x41, 0x7f, 0x7f, 0x00, 0x00, // 93=]
0x00, 0x08, 0x0c, 0x06, 0x06, 0x0c, 0x08, 0x00, // 94=^
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, // 95=_
0x00, 0x00, 0x01, 0x03, 0x06, 0x04, 0x00, 0x00, // 96=`
0x00, 0x20, 0x74, 0x54, 0x54, 0x7c, 0x78, 0x00, // 97=a
0x00, 0x7f, 0x7f, 0x44, 0x44, 0x7c, 0x38, 0x00, // 98=b
0x00, 0x38, 0x7c, 0x44, 0x44, 0x6c, 0x28, 0x00, // 99=c
0x00, 0x38, 0x7c, 0x44, 0x44, 0x7f, 0x7f, 0x00, // 100=d
0x00, 0x38, 0x7c, 0x54, 0x54, 0x5c, 0x58, 0x00, // 101=e
0x00, 0x08, 0x7e, 0x7f, 0x09, 0x03, 0x02, 0x00, // 102=f
0x00, 0x98, 0xbc, 0xa4, 0xa4, 0xfc, 0x7c, 0x00, // 103=g
0x00, 0x7f, 0x7f, 0x04, 0x04, 0x7c, 0x78, 0x00, // 104=h
0x00, 0x00, 0x00, 0x7d, 0x7d, 0x00, 0x00, 0x00, // 105=i
0x00, 0x40, 0xc0, 0x80, 0x80, 0xfd, 0x7d, 0x00, // 106=j
0x00, 0x7f, 0x7f, 0x30, 0x38, 0x6c, 0x44, 0x00, // 107=k
0x00, 0x00, 0x41, 0x7f, 0x7f, 0x40, 0x00, 0x00, // 108=l
0x00, 0x7c, 0x7c, 0x18, 0x30, 0x18, 0x7c, 0x7c, // 109=m
0x00, 0x7c, 0x7c, 0x04, 0x04, 0x7c, 0x78, 0x00, // 110=n
0x00, 0x38, 0x7c, 0x44, 0x44, 0x7c, 0x38, 0x00, // 111=o
0x00, 0xfc, 0xfc, 0x24, 0x24, 0x3c, 0x18, 0x00, // 112=p
0x00, 0x18, 0x3c, 0x24, 0x24, 0xfc, 0xfc, 0x00, // 113=q
0x00, 0x7c, 0x7c, 0x04, 0x04, 0x0c, 0x08, 0x00, // 114=r
0x00, 0x48, 0x5c, 0x54, 0x54, 0x74, 0x20, 0x00, // 115=s
0x04, 0x04, 0x3f, 0x7f, 0x44, 0x64, 0x20, 0x00, // 116=t
0x00, 0x3c, 0x7c, 0x40, 0x40, 0x7c, 0x3c, 0x00, // 117=u
0x00, 0x1c, 0x3c, 0x60, 0x60, 0x3c, 0x1c, 0x00, // 118=v
0x00, 0x1c, 0x7c, 0x30, 0x18, 0x30, 0x7c, 0x1c, // 119=w
0x00, 0x44, 0x6c, 0x38, 0x38, 0x6c, 0x44, 0x00, // 120=x
0x00, 0x9c, 0xbc, 0xa0, 0xa0, 0xfc, 0x7c, 0x00, // 121=y
0x00, 0x44, 0x64, 0x74, 0x5c, 0x4c, 0x44, 0x00, // 122=z
0x00, 0x08, 0x08, 0x3e, 0x77, 0x41, 0x41, 0x00, // 123={
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, // 124=|
0x00, 0x41, 0x41, 0x77, 0x3e, 0x08, 0x08, 0x00, // 125=}
0x00, 0x02, 0x03, 0x01, 0x03, 0x02, 0x03, 0x01, // 126=~
0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, // 127
};
#endif // MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H

View File

@ -33,6 +33,8 @@
#include "py/runtime.h"
#include "extmod/machine_i2c.h"
#define SOFT_I2C_DEFAULT_TIMEOUT_US (50000) // 50ms
#if MICROPY_PY_MACHINE_SOFTI2C
typedef mp_machine_soft_i2c_obj_t machine_i2c_obj_t;
@ -512,6 +514,22 @@ STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t a
uint8_t memaddr_buf[4];
size_t memaddr_len = fill_memaddr_buf(&memaddr_buf[0], memaddr, addrsize);
#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1
// The I2C transfer function may support the MP_MACHINE_I2C_FLAG_WRITE1 option
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
if (i2c_p->transfer_supports_write1) {
// Create partial write and read buffers
mp_machine_i2c_buf_t bufs[2] = {
{.len = memaddr_len, .buf = memaddr_buf},
{.len = len, .buf = buf},
};
// Do write+read I2C transfer
return i2c_p->transfer(self, addr, 2, bufs,
MP_MACHINE_I2C_FLAG_WRITE1 | MP_MACHINE_I2C_FLAG_READ | MP_MACHINE_I2C_FLAG_STOP);
}
#endif
int ret = mp_machine_i2c_writeto(self, addr, memaddr_buf, memaddr_len, false);
if (ret != memaddr_len) {
// must generate STOP
@ -651,7 +669,7 @@ STATIC void mp_machine_soft_i2c_init(mp_obj_base_t *self_in, size_t n_args, cons
{ MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 255} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SOFT_I2C_DEFAULT_TIMEOUT_US} },
};
mp_machine_soft_i2c_obj_t *self = (mp_machine_soft_i2c_obj_t *)self_in;
@ -666,8 +684,7 @@ STATIC void mp_machine_soft_i2c_init(mp_obj_base_t *self_in, size_t n_args, cons
STATIC mp_obj_t mp_machine_soft_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// create new soft I2C object
machine_i2c_obj_t *self = m_new_obj(machine_i2c_obj_t);
self->base.type = &mp_machine_soft_i2c_type;
machine_i2c_obj_t *self = mp_obj_malloc(machine_i2c_obj_t, &mp_machine_soft_i2c_type);
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
mp_machine_soft_i2c_init(&self->base, n_args, args, &kw_args);

View File

@ -45,6 +45,11 @@
#define MP_MACHINE_I2C_FLAG_READ (0x01) // if not set then it's a write
#define MP_MACHINE_I2C_FLAG_STOP (0x02)
#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1
// If set, the first mp_machine_i2c_buf_t in a transfer is a write.
#define MP_MACHINE_I2C_FLAG_WRITE1 (0x04)
#endif
typedef struct _mp_machine_i2c_buf_t {
size_t len;
uint8_t *buf;
@ -56,6 +61,9 @@ typedef struct _mp_machine_i2c_buf_t {
// - transfer must be non-NULL
// - transfer_single only needs to be set if transfer=mp_machine_i2c_transfer_adaptor
typedef struct _mp_machine_i2c_p_t {
#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1
bool transfer_supports_write1;
#endif
void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
int (*start)(mp_obj_base_t *obj);
int (*stop)(mp_obj_base_t *obj);

View File

@ -108,8 +108,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t
}
}
machine_signal_t *o = m_new_obj(machine_signal_t);
o->base.type = type;
machine_signal_t *o = mp_obj_malloc(machine_signal_t, type);
o->pin = pin;
o->invert = invert;
return MP_OBJ_FROM_PTR(o);

View File

@ -175,8 +175,7 @@ STATIC mp_obj_t mp_machine_soft_spi_make_new(const mp_obj_type_t *type, size_t n
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// create new object
mp_machine_soft_spi_obj_t *self = m_new_obj(mp_machine_soft_spi_obj_t);
self->base.type = &mp_machine_soft_spi_type;
mp_machine_soft_spi_obj_t *self = mp_obj_malloc(mp_machine_soft_spi_obj_t, &mp_machine_soft_spi_type);
// set parameters
self->spi.delay_half = baudrate_to_delay_half(args[ARG_baudrate].u_int);

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