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:
commit
38c5106a9d
@ -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
25
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal 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
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal 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
16
.github/ISSUE_TEMPLATE/documentation.md
vendored
Normal 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/
|
||||
24
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
24
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal 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
16
.github/ISSUE_TEMPLATE/security.md
vendored
Normal 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?
|
||||
18
.github/workflows/ports.yml
vendored
18
.github/workflows/ports.yml
vendored
@ -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
230
.github/workflows/ports_unix.yml
vendored
Normal 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
10
.gitmodules
vendored
@ -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
|
||||
|
||||
@ -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:
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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:
|
||||
|
||||
|
||||
@ -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>`_ |
|
||||
|
||||
@ -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>`_ |
|
||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
-------------
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)``.
|
||||
|
||||
@ -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
|
||||
-----------------------
|
||||
|
||||
@ -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.
|
||||
|
||||
58
docs/library/machine.ADCBlock.rst
Normal file
58
docs/library/machine.ADCBlock.rst
Normal 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.
|
||||
@ -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:
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
93
docs/library/network.LAN.rst
Normal file
93
docs/library/network.LAN.rst
Normal 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``.
|
||||
@ -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::
|
||||
|
||||
@ -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)
|
||||
============= ===========
|
||||
|
||||
@ -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
|
||||
=================
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
-------
|
||||
|
||||
@ -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:
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
-------
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
-------
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
397
docs/library/wm8960.rst
Normal 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
94
docs/mimxrt/general.rst
Normal 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.
|
||||
BIN
docs/mimxrt/img/teensy_4.1.jpg
Normal file
BIN
docs/mimxrt/img/teensy_4.1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 125 KiB |
380
docs/mimxrt/pinout.rst
Normal file
380
docs/mimxrt/pinout.rst
Normal 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
546
docs/mimxrt/quickref.rst
Normal 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.
|
||||
125
docs/mimxrt/tutorial/intro.rst
Normal file
125
docs/mimxrt/tutorial/intro.rst
Normal 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.
|
||||
@ -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**
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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
|
||||
---------
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
42
docs/renesas-ra/general.rst
Normal file
42
docs/renesas-ra/general.rst
Normal 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>`_
|
||||
|
||||
BIN
docs/renesas-ra/img/ek_ra6m2_board.jpg
Normal file
BIN
docs/renesas-ra/img/ek_ra6m2_board.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 177 KiB |
415
docs/renesas-ra/quickref.rst
Normal file
415
docs/renesas-ra/quickref.rst
Normal 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.
|
||||
16
docs/renesas-ra/tutorial/index.rst
Normal file
16
docs/renesas-ra/tutorial/index.rst
Normal 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
|
||||
67
docs/renesas-ra/tutorial/intro.rst
Normal file
67
docs/renesas-ra/tutorial/intro.rst
Normal 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.
|
||||
>>>
|
||||
62
docs/renesas-ra/tutorial/program_in_flash.rst
Normal file
62
docs/renesas-ra/tutorial/program_in_flash.rst
Normal 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.
|
||||
61
docs/renesas-ra/tutorial/reset.rst
Normal file
61
docs/renesas-ra/tutorial/reset.rst
Normal 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()
|
||||
|
||||
18
docs/renesas-ra/tutorial/troubleshooting.rst
Normal file
18
docs/renesas-ra/tutorial/troubleshooting.rst
Normal 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.
|
||||
68
docs/renesas-ra/tutorial/using_peripheral.rst
Normal file
68
docs/renesas-ra/tutorial/using_peripheral.rst
Normal 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)
|
||||
|
||||
@ -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:
|
||||
|
||||
8
docs/templates/topindex.html
vendored
8
docs/templates/topindex.html
vendored
@ -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>
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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::
|
||||
|
||||
@ -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.
|
||||
>>>
|
||||
|
||||
|
||||
@ -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
753
drivers/codec/wm8960.py
Normal 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)
|
||||
@ -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:
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()))
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -137,7 +137,6 @@ SRC_C = $(addprefix ports/unix/,\
|
||||
unix_mphal.c \
|
||||
input.c \
|
||||
modmachine.c \
|
||||
modos.c \
|
||||
moduselect.c \
|
||||
alloc.c \
|
||||
coverage.c \
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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 \
|
||||
|
||||
//////////////////////////////////////////
|
||||
|
||||
14
examples/natmod/features3/Makefile
Normal file
14
examples/natmod/features3/Makefile
Normal 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
|
||||
60
examples/natmod/features3/features3.c
Normal file
60
examples/natmod/features3/features3.c
Normal 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
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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++
|
||||
|
||||
@ -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
128
extmod/font_petme128_8x8.h
Normal 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
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user