Ken
4 years ago
commit
22abc7086e
12301 changed files with 5964279 additions and 0 deletions
@ -0,0 +1,26 @@ |
|||
# Per default everything gets normalized and gets LF line endings on checkout. |
|||
* text eol=lf |
|||
|
|||
# These will always have CRLF line endings on checkout. |
|||
*.vcxproj text eol=crlf |
|||
*.props text eol=crlf |
|||
*.bat text eol=crlf |
|||
|
|||
# These are binary so should never be modified by git. |
|||
*.a binary |
|||
*.png binary |
|||
*.jpg binary |
|||
*.dxf binary |
|||
*.mpy binary |
|||
|
|||
# These should also not be modified by git. |
|||
tests/basics/string_cr_conversion.py -text |
|||
tests/basics/string_crlf_conversion.py -text |
|||
ports/stm32/pybcdc.inf_template -text |
|||
ports/stm32/usbhost/** -text |
|||
ports/cc3200/hal/aes.c -text |
|||
ports/cc3200/hal/aes.h -text |
|||
ports/cc3200/hal/des.c -text |
|||
ports/cc3200/hal/i2s.c -text |
|||
ports/cc3200/hal/i2s.h -text |
|||
ports/cc3200/version.h -text |
@ -0,0 +1,57 @@ |
|||
# Compiled Sources |
|||
################### |
|||
*.o |
|||
*.a |
|||
*.elf |
|||
*.bin |
|||
*.map |
|||
*.hex |
|||
*.dis |
|||
*.exe |
|||
|
|||
# Packages |
|||
############ |
|||
|
|||
# Logs and Databases |
|||
###################### |
|||
*.log |
|||
|
|||
# VIM Swap Files |
|||
###################### |
|||
*.swp |
|||
|
|||
# Build directories |
|||
###################### |
|||
build/ |
|||
build-*/ |
|||
|
|||
# Test failure outputs |
|||
###################### |
|||
tests/*.exp |
|||
tests/*.out |
|||
|
|||
# Python cache files |
|||
###################### |
|||
__pycache__/ |
|||
*.pyc |
|||
|
|||
# Customized Makefile/project overrides |
|||
###################### |
|||
GNUmakefile |
|||
user.props |
|||
|
|||
# Generated rst files |
|||
###################### |
|||
genrst/ |
|||
|
|||
ports/stm32/boards/Passport/finalbootloader/bootloader.bin.tmp |
|||
|
|||
ports/stm32/boards/Passport/finalbootloader/bootloader.lss |
|||
|
|||
ports/stm32/boards/Passport/finalbootloader/bootloader.sym |
|||
|
|||
*.d |
|||
|
|||
ports/stm32/boards/Passport/tools/signit/x86/release/ |
|||
|
|||
ports/stm32/boards/Passport/tools/cosign/x86/release/ |
@ -0,0 +1,32 @@ |
|||
[submodule "lib/axtls"] |
|||
path = lib/axtls |
|||
url = https://github.com/pfalcon/axtls |
|||
branch = micropython |
|||
[submodule "lib/libffi"] |
|||
path = lib/libffi |
|||
url = https://github.com/atgreen/libffi |
|||
[submodule "lib/lwip"] |
|||
path = lib/lwip |
|||
url = https://git.savannah.gnu.org/r/lwip.git |
|||
[submodule "lib/berkeley-db-1.xx"] |
|||
path = lib/berkeley-db-1.xx |
|||
url = https://github.com/pfalcon/berkeley-db-1.xx |
|||
[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 |
|||
[submodule "lib/nrfx"] |
|||
path = lib/nrfx |
|||
url = https://github.com/NordicSemiconductor/nrfx.git |
|||
[submodule "lib/mbedtls"] |
|||
path = lib/mbedtls |
|||
url = https://github.com/ARMmbed/mbedtls.git |
|||
[submodule "lib/asf4"] |
|||
path = lib/asf4 |
|||
url = https://github.com/adafruit/asf4 |
|||
[submodule "lib/tinyusb"] |
|||
path = lib/tinyusb |
|||
url = https://github.com/hathach/tinyusb |
|||
[submodule "lib/mynewt-nimble"] |
|||
path = lib/mynewt-nimble |
|||
url = https://github.com/apache/mynewt-nimble.git |
@ -0,0 +1,19 @@ |
|||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ |
|||
Upstream-Name: Passport |
|||
Upstream-Contact: hello@foundationdevices.com |
|||
Source: https://git.example.com/FoundationDevices/passport |
|||
|
|||
Files: ACKNOWLEDGEMENTS *.md docs/* drivers/* examples/* extmod/* lib/* py/* tests/* tools/* .gitattributes .gitignore .gitmodules .travis.yml logo/* mpy-cross/* |
|||
Copyright: Copyright (c) 2016-2020 Damien P. George (http://micropython.org/) |
|||
License: MIT |
|||
|
|||
Files: ports/bare-arm/* ports/cc3200/* ports/esp32/* ports/esp8266/* ports/javascript/* ports/minimal/* ports/nrf/* ports/pic16bit/* ports/powerpc/* ports/qemu/* ports/qemu-arm/* ports/samd/* ports/teensy/* ports/unix/* ports/windows/* ports/zephyr/* |
|||
Copyright: Copyright (c) 2016-2020 Damien P. George (http://micropython.org/) |
|||
License: MIT |
|||
|
|||
Files: ports/stm32/* |
|||
Copyright: Copyright (c) 2016-2020 Damien P. George (http://micropython.org/) |
|||
License: MIT |
|||
Copyright: 020 Foundation Devices, Inc. <hello@foundationdevices.com> |
|||
License: GPL-3.0-or-later |
|||
|
@ -0,0 +1,265 @@ |
|||
# global options |
|||
dist: xenial |
|||
language: |
|||
- c |
|||
compiler: |
|||
- gcc |
|||
cache: |
|||
directories: |
|||
- "${HOME}/persist" |
|||
env: |
|||
global: |
|||
- MAKEOPTS="-j4" |
|||
git: |
|||
submodules: false |
|||
|
|||
# define the successive stages |
|||
stages: |
|||
- name: test |
|||
|
|||
# define the jobs for the stages |
|||
# order of the jobs has longest running first to optimise total time |
|||
jobs: |
|||
include: |
|||
# stm32 port |
|||
- stage: test |
|||
env: NAME="stm32 port build" |
|||
install: |
|||
# need newer gcc version for Cortex-M7 support |
|||
- sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa |
|||
- sudo apt-get update -qq || true |
|||
- sudo apt-get install gcc-arm-embedded |
|||
- sudo apt-get install libnewlib-arm-none-eabi |
|||
- arm-none-eabi-gcc --version |
|||
script: |
|||
- make ${MAKEOPTS} -C mpy-cross |
|||
- make ${MAKEOPTS} -C ports/stm32 submodules |
|||
- make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_F091RC |
|||
- make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_WIZNET5K=5200 MICROPY_PY_CC3K=1 |
|||
- make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 |
|||
- make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_H743ZI CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1' |
|||
- make ${MAKEOPTS} -C ports/stm32 BOARD=B_L072Z_LRWAN1 |
|||
- make ${MAKEOPTS} -C ports/stm32 BOARD=STM32L476DISC |
|||
- make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_WB55 |
|||
- make ${MAKEOPTS} -C ports/stm32/mboot BOARD=PYBD_SF6 |
|||
|
|||
# qemu-arm port |
|||
- stage: test |
|||
env: NAME="qemu-arm port build and tests" |
|||
install: |
|||
- sudo apt-get install gcc-arm-none-eabi |
|||
- sudo apt-get install libnewlib-arm-none-eabi |
|||
- sudo apt-get install qemu-system |
|||
- arm-none-eabi-gcc --version |
|||
- qemu-system-arm --version |
|||
script: |
|||
- make ${MAKEOPTS} -C mpy-cross |
|||
- make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test test |
|||
after_failure: |
|||
- grep "FAIL" ports/qemu-arm/build/console.out |
|||
|
|||
# unix coverage |
|||
- stage: test |
|||
env: NAME="unix coverage build and tests" |
|||
install: |
|||
- sudo apt-get install python3-pip |
|||
- sudo pip install cpp-coveralls |
|||
- sudo pip3 install setuptools |
|||
- sudo pip3 install pyelftools |
|||
- gcc --version |
|||
- python3 --version |
|||
script: |
|||
- make ${MAKEOPTS} -C mpy-cross |
|||
- make ${MAKEOPTS} -C ports/unix submodules |
|||
- make ${MAKEOPTS} -C ports/unix deplibs |
|||
- make ${MAKEOPTS} -C ports/unix coverage |
|||
# run the main test suite |
|||
- (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests) |
|||
- (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -d thread) |
|||
- (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --emit native) |
|||
- (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy -d basics float micropython) |
|||
- (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy --emit native -d basics float micropython) |
|||
# test when input script comes from stdin |
|||
- cat tests/basics/0prelim.py | ports/unix/micropython_coverage | grep -q 'abc' |
|||
# test building native mpy modules |
|||
- make -C examples/natmod/features1 ARCH=x64 |
|||
- make -C examples/natmod/features2 ARCH=x64 |
|||
- make -C examples/natmod/btree ARCH=x64 |
|||
- make -C examples/natmod/framebuf ARCH=x64 |
|||
- make -C examples/natmod/uheapq ARCH=x64 |
|||
- make -C examples/natmod/urandom ARCH=x64 |
|||
- make -C examples/natmod/ure ARCH=x64 |
|||
- make -C examples/natmod/uzlib ARCH=x64 |
|||
# test importing .mpy generated by mpy_ld.py |
|||
- MICROPYPATH=examples/natmod/features2 ./ports/unix/micropython_coverage -m features2 |
|||
- (cd tests && ./run-natmodtests.py extmod/{btree*,framebuf*,uheapq*,ure*,uzlib*}.py) |
|||
# run coveralls coverage analysis (try to, even if some builds/tests failed) |
|||
- (cd ports/unix && coveralls --root ../.. --build-root . --gcov $(which gcov) --gcov-options '\-o build-coverage/' --include py --include extmod) |
|||
after_failure: |
|||
- (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done) |
|||
|
|||
# standard unix port |
|||
- stage: test |
|||
env: NAME="unix port build and tests" |
|||
script: |
|||
- make ${MAKEOPTS} -C mpy-cross |
|||
- make ${MAKEOPTS} -C ports/unix submodules |
|||
- make ${MAKEOPTS} -C ports/unix deplibs |
|||
- make ${MAKEOPTS} -C ports/unix |
|||
- make ${MAKEOPTS} -C ports/unix test |
|||
- (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython ./run-perfbench.py 1000 1000) |
|||
|
|||
# unix nanbox (and using Python 2 to check it can run the build scripts) |
|||
- stage: test |
|||
env: NAME="unix nanbox port build and tests" |
|||
install: |
|||
- sudo apt-get install gcc-multilib libffi-dev:i386 |
|||
script: |
|||
- make ${MAKEOPTS} -C mpy-cross PYTHON=python2 |
|||
- make ${MAKEOPTS} -C ports/unix submodules |
|||
- make ${MAKEOPTS} -C ports/unix PYTHON=python2 deplibs |
|||
- make ${MAKEOPTS} -C ports/unix PYTHON=python2 nanbox |
|||
- (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_nanbox ./run-tests) |
|||
|
|||
# unix stackless |
|||
- stage: test |
|||
env: NAME="unix stackless port build and tests with clang" |
|||
install: |
|||
- sudo apt-get install clang |
|||
script: |
|||
- make ${MAKEOPTS} -C mpy-cross CC=clang |
|||
- make ${MAKEOPTS} -C ports/unix submodules |
|||
- make ${MAKEOPTS} -C ports/unix CC=clang CFLAGS_EXTRA="-DMICROPY_STACKLESS=1 -DMICROPY_STACKLESS_STRICT=1" |
|||
- make ${MAKEOPTS} -C ports/unix CC=clang test |
|||
|
|||
# unix with sys.settrace |
|||
- stage: test |
|||
env: NAME="unix port with sys.settrace build and tests" |
|||
script: |
|||
- make ${MAKEOPTS} -C mpy-cross |
|||
- make ${MAKEOPTS} -C ports/unix MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 MICROPY_PY_USSL=0 CFLAGS_EXTRA="-DMICROPY_PY_SYS_SETTRACE=1" test |
|||
- make ${MAKEOPTS} -C ports/unix clean |
|||
- make ${MAKEOPTS} -C ports/unix MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 MICROPY_PY_USSL=0 CFLAGS_EXTRA="-DMICROPY_STACKLESS=1 -DMICROPY_STACKLESS_STRICT=1 -DMICROPY_PY_SYS_SETTRACE=1" test |
|||
after_failure: |
|||
- (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done) |
|||
|
|||
# minimal unix port with tests |
|||
- stage: test |
|||
env: NAME="minimal unix port build and tests" |
|||
script: |
|||
- make ${MAKEOPTS} -C ports/unix minimal |
|||
- (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_minimal ./run-tests -e exception_chain -e self_type_check -e subclass_native_init -d basics) |
|||
|
|||
# windows port via mingw |
|||
- stage: test |
|||
env: NAME="windows port build via mingw" |
|||
install: |
|||
- sudo apt-get install gcc-mingw-w64 |
|||
script: |
|||
- make ${MAKEOPTS} -C mpy-cross |
|||
- make ${MAKEOPTS} -C ports/windows CROSS_COMPILE=i686-w64-mingw32- |
|||
|
|||
# esp32 port |
|||
- stage: test |
|||
env: NAME="esp32 port build" |
|||
install: |
|||
- sudo apt-get install python3-pip |
|||
- sudo pip3 install 'pyparsing<2.4' |
|||
- wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz |
|||
- zcat xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz | tar x |
|||
- export PATH=$(pwd)/xtensa-esp32-elf/bin:$PATH |
|||
- git clone https://github.com/espressif/esp-idf.git |
|||
- export IDF_PATH=$(pwd)/esp-idf |
|||
script: |
|||
- make ${MAKEOPTS} -C mpy-cross |
|||
# IDF v3 build |
|||
- git -C esp-idf checkout $(grep "ESPIDF_SUPHASH_V3 :=" ports/esp32/Makefile | cut -d " " -f 3) |
|||
- git -C esp-idf submodule update --init components/json/cJSON components/esp32/lib components/esptool_py/esptool components/expat/expat components/lwip/lwip components/mbedtls/mbedtls components/micro-ecc/micro-ecc components/nghttp/nghttp2 |
|||
- make ${MAKEOPTS} -C ports/esp32 submodules |
|||
- make ${MAKEOPTS} -C ports/esp32 |
|||
# clean |
|||
- git -C esp-idf clean -f -f -d components/json/cJSON components/esp32/lib components/expat/expat components/micro-ecc/micro-ecc components/nghttp/nghttp2 |
|||
- make ${MAKEOPTS} -C ports/esp32 clean |
|||
# IDF v4 build |
|||
- git -C esp-idf checkout $(grep "ESPIDF_SUPHASH_V4 :=" ports/esp32/Makefile | cut -d " " -f 3) |
|||
- git -C esp-idf submodule update --init components/bt/controller/lib components/bt/host/nimble/nimble components/esp_wifi/lib_esp32 components/esptool_py/esptool components/lwip/lwip components/mbedtls/mbedtls |
|||
- make ${MAKEOPTS} -C ports/esp32 submodules |
|||
- make ${MAKEOPTS} -C ports/esp32 |
|||
|
|||
# esp8266 port |
|||
- stage: test |
|||
env: NAME="esp8266 port build" |
|||
install: |
|||
- wget https://github.com/jepler/esp-open-sdk/releases/download/2018-06-10/xtensa-lx106-elf-standalone.tar.gz |
|||
- zcat xtensa-lx106-elf-standalone.tar.gz | tar x |
|||
- export PATH=$(pwd)/xtensa-lx106-elf/bin:$PATH |
|||
script: |
|||
- make ${MAKEOPTS} -C mpy-cross |
|||
- make ${MAKEOPTS} -C ports/esp8266 submodules |
|||
- make ${MAKEOPTS} -C ports/esp8266 |
|||
- make ${MAKEOPTS} -C ports/esp8266 BOARD=GENERIC_512K |
|||
|
|||
# nrf port |
|||
- stage: test |
|||
env: NAME="nrf port build" |
|||
install: |
|||
- sudo apt-get install gcc-arm-none-eabi |
|||
- sudo apt-get install libnewlib-arm-none-eabi |
|||
- arm-none-eabi-gcc --version |
|||
script: |
|||
- make ${MAKEOPTS} -C ports/nrf submodules |
|||
- make ${MAKEOPTS} -C ports/nrf |
|||
|
|||
# bare-arm and minimal ports |
|||
- stage: test |
|||
env: NAME="bare-arm and minimal ports build" |
|||
install: |
|||
- sudo apt-get install gcc-arm-none-eabi |
|||
- sudo apt-get install libnewlib-arm-none-eabi |
|||
- arm-none-eabi-gcc --version |
|||
script: |
|||
- make ${MAKEOPTS} -C ports/bare-arm |
|||
- make ${MAKEOPTS} -C ports/minimal CROSS=1 build/firmware.bin |
|||
- ls -l ports/minimal/build/firmware.bin |
|||
- tools/check_code_size.sh |
|||
- mkdir -p ${HOME}/persist |
|||
# Save new firmware for reference, but only if building a main branch, not a pull request |
|||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then cp ports/minimal/build/firmware.bin ${HOME}/persist/; fi' |
|||
|
|||
# cc3200 port |
|||
- stage: test |
|||
env: NAME="cc3200 port build" |
|||
install: |
|||
- sudo apt-get install gcc-arm-none-eabi |
|||
- sudo apt-get install libnewlib-arm-none-eabi |
|||
script: |
|||
- make ${MAKEOPTS} -C ports/cc3200 BTARGET=application BTYPE=release |
|||
- make ${MAKEOPTS} -C ports/cc3200 BTARGET=bootloader BTYPE=release |
|||
|
|||
# samd port |
|||
- stage: test |
|||
env: NAME="samd port build" |
|||
install: |
|||
- sudo apt-get install gcc-arm-none-eabi |
|||
- sudo apt-get install libnewlib-arm-none-eabi |
|||
script: |
|||
- make ${MAKEOPTS} -C ports/samd submodules |
|||
- make ${MAKEOPTS} -C ports/samd |
|||
|
|||
# teensy port |
|||
- stage: test |
|||
env: NAME="teensy port build" |
|||
install: |
|||
- sudo apt-get install gcc-arm-none-eabi |
|||
- sudo apt-get install libnewlib-arm-none-eabi |
|||
script: |
|||
- make ${MAKEOPTS} -C ports/teensy |
|||
|
|||
# powerpc port |
|||
- stage: test |
|||
env: NAME="powerpc port build" |
|||
install: |
|||
- sudo apt-get install gcc-powerpc64le-linux-gnu |
|||
- sudo apt-get install libc6-dev-ppc64el-cross |
|||
script: |
|||
- make ${MAKEOPTS} -C ports/powerpc CROSS_COMPILE=powerpc64le-linux-gnu- |
File diff suppressed because it is too large
@ -0,0 +1,210 @@ |
|||
Git commit conventions |
|||
====================== |
|||
|
|||
Each commit message should start with a directory or full file path |
|||
prefix, so it was clear which part of codebase a commit affects. If |
|||
a change affects one file, it's better to use path to a file. If it |
|||
affects few files in a subdirectory, using subdirectory as a prefix |
|||
is ok. For longish paths, it's acceptable to drop intermediate |
|||
components, which still should provide good context of a change. |
|||
It's also ok to drop file extensions. |
|||
|
|||
Besides prefix, first line of a commit message should describe a |
|||
change clearly and to the point, and be a grammatical sentence with |
|||
final full stop. First line should fit within 78 characters. Examples |
|||
of good first line of commit messages: |
|||
|
|||
py/objstr: Add splitlines() method. |
|||
py: Rename FOO to BAR. |
|||
docs/machine: Fix typo in reset() description. |
|||
ports: Switch to use lib/foo instead of duplicated code. |
|||
|
|||
After the first line, add an empty line and in following lines describe |
|||
a change in a detail, if needed. Any change beyond 5 lines would likely |
|||
require such detailed description. |
|||
|
|||
To get good practical examples of good commits and their messages, browse |
|||
the `git log` of the project. |
|||
|
|||
MicroPython doesn't require explicit sign-off for patches ("Signed-off-by" |
|||
lines and similar). Instead, the commit message, and your name and email |
|||
address on it construes your sign-off of the following: |
|||
|
|||
* That you wrote the change yourself, or took it from a project with |
|||
a compatible license (in the latter case the commit message, and possibly |
|||
source code should provide reference where the implementation was taken |
|||
from and give credit to the original author, as required by the license). |
|||
* That you are allowed to release these changes to an open-source project |
|||
(for example, changes done during paid work for a third party may require |
|||
explicit approval from that third party). |
|||
* That you (or your employer) agree to release the changes under |
|||
MicroPython's license, which is the MIT license. Note that you retain |
|||
copyright for your changes (for smaller changes, the commit message |
|||
conveys your copyright; if you make significant changes to a particular |
|||
source module, you're welcome to add your name to the file header). |
|||
* Your signature for all of the above, which is the 'Author' line in |
|||
the commit message, and which should include your full real name and |
|||
a valid and active email address by which you can be contacted in the |
|||
foreseeable future. |
|||
|
|||
Python code conventions |
|||
======================= |
|||
|
|||
Python code follows [PEP 8](http://legacy.python.org/dev/peps/pep-0008/). |
|||
|
|||
Naming conventions: |
|||
- Module names are short and all lowercase; eg pyb, stm. |
|||
- Class names are CamelCase, with abreviations all uppercase; eg I2C, not |
|||
I2c. |
|||
- Function and method names are all lowercase with words separated by |
|||
a single underscore as necessary to improve readability; eg mem_read. |
|||
- Constants are all uppercase with words separated by a single underscore; |
|||
eg GPIO_IDR. |
|||
|
|||
C code conventions |
|||
================== |
|||
|
|||
When writing new C code, please adhere to the following conventions. |
|||
|
|||
White space: |
|||
- Expand tabs to 4 spaces. |
|||
- Don't leave trailing whitespace at the end of a line. |
|||
- For control blocks (if, for, while), put 1 space between the |
|||
keyword and the opening parenthesis. |
|||
- Put 1 space after a comma, and 1 space around operators. |
|||
|
|||
Braces: |
|||
- Use braces for all blocks, even no-line and single-line pieces of |
|||
code. |
|||
- Put opening braces on the end of the line it belongs to, not on |
|||
a new line. |
|||
- For else-statements, put the else on the same line as the previous |
|||
closing brace. |
|||
|
|||
Header files: |
|||
- Header files should be protected from multiple inclusion with #if |
|||
directives. See an existing header for naming convention. |
|||
|
|||
Names: |
|||
- Use underscore_case, not camelCase for all names. |
|||
- Use CAPS_WITH_UNDERSCORE for enums and macros. |
|||
- When defining a type use underscore_case and put '_t' after it. |
|||
|
|||
Integer types: MicroPython runs on 16, 32, and 64 bit machines, so it's |
|||
important to use the correctly-sized (and signed) integer types. The |
|||
general guidelines are: |
|||
- For most cases use mp_int_t for signed and mp_uint_t for unsigned |
|||
integer values. These are guaranteed to be machine-word sized and |
|||
therefore big enough to hold the value from a MicroPython small-int |
|||
object. |
|||
- Use size_t for things that count bytes / sizes of objects. |
|||
- You can use int/uint, but remember that they may be 16-bits wide. |
|||
- If in doubt, use mp_int_t/mp_uint_t. |
|||
|
|||
Comments: |
|||
- Be concise and only write comments for things that are not obvious. |
|||
- Use `// ` prefix, NOT `/* ... */`. No extra fluff. |
|||
|
|||
Memory allocation: |
|||
- Use m_new, m_renew, m_del (and friends) to allocate and free heap memory. |
|||
These macros are defined in py/misc.h. |
|||
|
|||
Examples |
|||
-------- |
|||
|
|||
Braces, spaces, names and comments: |
|||
|
|||
#define TO_ADD (123) |
|||
|
|||
// This function will always recurse indefinitely and is only used to show |
|||
// coding style |
|||
int foo_function(int x, int some_value) { |
|||
if (x < some_value) { |
|||
foo(some_value, x); |
|||
} else { |
|||
foo(x + TO_ADD, some_value - 1); |
|||
} |
|||
|
|||
for (int my_counter = 0; my_counter < x; my_counter++) { |
|||
} |
|||
} |
|||
|
|||
Type declarations: |
|||
|
|||
typedef struct _my_struct_t { |
|||
int member; |
|||
void *data; |
|||
} my_struct_t; |
|||
|
|||
Documentation conventions |
|||
========================= |
|||
|
|||
MicroPython generally follows CPython in documentation process and |
|||
conventions. reStructuredText syntax is used for the documention. |
|||
|
|||
Specific conventions/suggestions: |
|||
|
|||
* Use `*` markup to refer to arguments of a function, e.g.: |
|||
|
|||
``` |
|||
.. method:: poll.unregister(obj) |
|||
|
|||
Unregister *obj* from polling. |
|||
``` |
|||
|
|||
* Use following syntax for cross-references/cross-links: |
|||
|
|||
``` |
|||
:func:`foo` - function foo in current module |
|||
:func:`module1.foo` - function foo in module "module1" |
|||
(similarly for other referent types) |
|||
:class:`Foo` - class Foo |
|||
:meth:`Class.method1` - method1 in Class |
|||
:meth:`~Class.method1` - method1 in Class, but rendered just as "method1()", |
|||
not "Class.method1()" |
|||
:meth:`title <method1>` - reference method1, but render as "title" (use only |
|||
if really needed) |
|||
:mod:`module1` - module module1 |
|||
|
|||
`symbol` - generic xref syntax which can replace any of the above in case |
|||
the xref is unambiguous. If there's ambiguity, there will be a warning |
|||
during docs generation, which need to be fixed using one of the syntaxes |
|||
above |
|||
``` |
|||
|
|||
* Cross-referencing arbitrary locations |
|||
~~~ |
|||
.. _xref_target: |
|||
|
|||
Normal non-indented text. |
|||
|
|||
This is :ref:`reference <xref_target>`. |
|||
|
|||
(If xref target is followed by section title, can be just |
|||
:ref:`xref_target`). |
|||
~~~ |
|||
|
|||
* Linking to external URL: |
|||
``` |
|||
`link text <http://foo.com/...>`_ |
|||
``` |
|||
|
|||
* Referencing builtin singleton objects: |
|||
``` |
|||
``None``, ``True``, ``False`` |
|||
``` |
|||
|
|||
* Use following syntax to create common description for more than one element: |
|||
~~~ |
|||
.. function:: foo(x) |
|||
bar(y) |
|||
|
|||
Description common to foo() and bar(). |
|||
~~~ |
|||
|
|||
|
|||
More detailed guides and quickrefs: |
|||
|
|||
* http://www.sphinx-doc.org/en/stable/rest.html |
|||
* http://www.sphinx-doc.org/en/stable/markup/inline.html |
|||
* http://docutils.sourceforge.net/docs/user/rst/quickref.html |
@ -0,0 +1,53 @@ |
|||
MicroPython Code of Conduct |
|||
=========================== |
|||
|
|||
The MicroPython community is made up of members from around the globe with a |
|||
diverse set of skills, personalities, and experiences. It is through these |
|||
differences that our community experiences great successes and continued growth. |
|||
When you're working with members of the community, this Code of Conduct will |
|||
help steer your interactions and keep MicroPython a positive, successful, and |
|||
growing community. |
|||
|
|||
Members of the MicroPython community are open, considerate, and respectful. |
|||
Behaviours that reinforce these values contribute to a positive environment, and |
|||
include: acknowledging time and effort, being respectful of differing viewpoints |
|||
and experiences, gracefully accepting constructive criticism, and using |
|||
welcoming and inclusive language. |
|||
|
|||
Every member of our community has the right to have their identity respected. |
|||
The MicroPython community is dedicated to providing a positive experience for |
|||
everyone, regardless of age, gender identity and expression, sexual orientation, |
|||
disability, physical appearance, body size, ethnicity, nationality, race, or |
|||
religion (or lack thereof), education, or socio-economic status. |
|||
|
|||
Unacceptable behaviour includes: harassment, trolling, deliberate intimidation, |
|||
violent threats or language directed against another person; insults, put downs, |
|||
or jokes that are based upon stereotypes, that are exclusionary, or that hold |
|||
others up for ridicule; unwelcome sexual attention or advances; sustained |
|||
disruption of community discussions; publishing others' private information |
|||
without explicit permission; and other conduct that is inappropriate for a |
|||
professional audience including people of many different backgrounds. |
|||
|
|||
This code of conduct covers all online and offline presence related to the |
|||
MicroPython project, including GitHub and the forum. If a participant engages |
|||
in behaviour that violates this code of conduct, the MicroPython team may take |
|||
action as they deem appropriate, including warning the offender or expulsion |
|||
from the community. Community members asked to stop any inappropriate behaviour |
|||
are expected to comply immediately. |
|||
|
|||
Thank you for helping make this a welcoming, friendly community for everyone. |
|||
|
|||
If you believe that someone is violating the code of conduct, or have any other |
|||
concerns, please contact a member of the MicroPython team by emailing |
|||
contact@micropython.org. |
|||
|
|||
License |
|||
------- |
|||
|
|||
This Code of Conduct is licensed under the Creative Commons |
|||
Attribution-ShareAlike 3.0 Unported License. |
|||
|
|||
Attributions |
|||
------------ |
|||
|
|||
Based on the Python code of conduct found at https://www.python.org/psf/conduct/ |
@ -0,0 +1,8 @@ |
|||
When reporting an issue and especially submitting a pull request, please |
|||
make sure that you are acquainted with Contributor Guidelines: |
|||
|
|||
https://github.com/micropython/micropython/wiki/ContributorGuidelines |
|||
|
|||
and Code Conventions: |
|||
|
|||
https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md |
@ -0,0 +1,163 @@ |
|||
# Development |
|||
|
|||
This document describes how to develop for Passport. |
|||
|
|||
## Installation |
|||
|
|||
### Get the Source Code |
|||
The instructions below assume you are installing into your home folder at `~/`. You can choose |
|||
to install to a different folder, and just update the `cd` commands appropriately. |
|||
|
|||
cd ~/ |
|||
git clone git@github.com:Foundation-Devices/passport-ng.git |
|||
|
|||
### Install Dependencies |
|||
Several tools are required for building and debugging Passport. |
|||
|
|||
#### Cross-Compiler Toolchain |
|||
sudo apt install gcc-arm-none-eabi |
|||
cd ~/passport-ng |
|||
make -C mpy-cross |
|||
|
|||
#### Autotools and USB |
|||
|
|||
sudo apt install autotools-dev |
|||
sudo apt install automake |
|||
sudo apt install libusb-1.0-0-dev |
|||
sudo apt install libtool |
|||
|
|||
#### OpenOCD - On-Chip Debugger |
|||
cd ~/ |
|||
git clone https://github.com/ntfreak/openocd.git |
|||
cd ~/openocd/ |
|||
./bootstrap |
|||
./configure --enable-stlink |
|||
make |
|||
sudo make install |
|||
|
|||
#### RShell - Micropython Shell and REPL |
|||
cd ~/ |
|||
git clone https://github.com/dhylands/rshell |
|||
sudo apt install python3-pip |
|||
sudo pip3 install rshell (this should install rshell in /usr/local/ area) |
|||
|
|||
## Building |
|||
### Open Shell Windows/Tabs |
|||
You will need several shell windows or tabs open to interact with the various tools. |
|||
|
|||
### Build Window |
|||
|
|||
#### Building the Main Firmare |
|||
In one shell, make sure that you `cd` to the root `stm32` source folder, e.g., `cd ~/passport-ng/ports/stm32`: |
|||
|
|||
make BOARD=Passport |
|||
|
|||
To include debug symbols for use in `ddd`, run the following: |
|||
|
|||
make BOARD=Passport DEBUG=1 |
|||
|
|||
You should see it building various `.c` files and freezing `.py` files. Once complete, the final output should look similar to the following: |
|||
|
|||
LINK build-Passport/firmware.elf |
|||
text data bss dec hex filename |
|||
475304 792 57600 533696 824c0 build-Passport/firmware.elf |
|||
GEN build-Passport/firmware.dfu |
|||
GEN build-Passport/firmware.hex |
|||
|
|||
#### Code Signing |
|||
In order to load the files onto the device, they need to first be signed by two separate keys. |
|||
The `cosign` program performs this task, and it needs to be called twice with two separate |
|||
private keys. |
|||
|
|||
First, you need to build the `cosign` tool and copy it somewhere in your `PATH`: |
|||
|
|||
cd ports/stm32/boards/Passport/tools/cosign |
|||
make |
|||
cp x86/release/cosign ~/.local/bin # You can run `echo $PATH` to see the list of possible places you can put this file |
|||
|
|||
|
|||
Next you want to sign the firmware twice. The `cosign` tool appends `-signed` to the end of the main filename each time it signs. |
|||
Assuming you are still in the `ports/stm32` folder run the following: |
|||
|
|||
# TODO: Update once actual signing is implemented |
|||
cosign -f build-Passport/firmware.bin -k 1 -v 0.9 |
|||
cosign -f build-Passport/firmware-signed.bin -k 2 |
|||
|
|||
You can also dump the contents of the firmware header with the following command: |
|||
|
|||
cosign -f build-Passport/firmware-signed-signed.bin -x |
|||
|
|||
#### Building the Bootloader |
|||
To build the bootloader do the following: |
|||
|
|||
cd ports/stm32/boards/Passport/finalbootloader folder |
|||
make |
|||
|
|||
### OpenOCD Server Window |
|||
OpenOCD server provides a socket on `localhost:4444` that you can connect to and issue commands. This server acts as an intermediary between that socket and the board connected over JTAG. |
|||
|
|||
Once the OpenOCD server is running, you can pretty much ignore this window. You will interact with the OpenOCD client window (see below). Open a second shell and run the following: |
|||
|
|||
/usr/local/bin/openocd -f stlink.cfg -c "adapter speed 1000; transport select hla_swd" -f stm32h7x.cfg |
|||
|
|||
You should see output similar to the following: |
|||
|
|||
Open On-Chip Debugger 0.10.0+dev-01383-gd46f28c2e-dirty (2020-08-24-08:31) |
|||
Licensed under GNU GPL v2 |
|||
For bug reports, read |
|||
http://openocd.org/doc/doxygen/bugs.html |
|||
hla_swd |
|||
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD |
|||
Info : Listening on port 6666 for tcl connections |
|||
Info : Listening on port 4444 for telnet connections |
|||
Info : clock speed 1800 kHz |
|||
Info : STLINK V2J29S7 (API v2) VID:PID 0483:3748 |
|||
Info : Target voltage: 2.975559 |
|||
Info : stm32h7x.cpu0: hardware has 8 breakpoints, 4 watchpoints |
|||
Info : starting gdb server for stm32h7x.cpu0 on 3333 |
|||
Info : Listening on port 3333 for gdb connections |
|||
|
|||
### OpenOCD Client Window (aka `telnet` Window) |
|||
We use `telnet` to connect to the OpenOCD Server. Open a third shell and run the following: |
|||
|
|||
telnet localhost 4444 |
|||
|
|||
From here can connect over JTAG and run a range of commands (see the help for OpenOCD for details): |
|||
|
|||
Whenever you change any code in the `finalbootlaoder` folder or in the `common` folder, you will need to rebuild the bootloader (see above), and then flash it to the device with the following sequence in OpenOCD: |
|||
|
|||
reset halt |
|||
flash write_image erase boards/Passport/finalbootloader/bootloader.bin 0x8000000 |
|||
reset |
|||
|
|||
The following command sequence is one you will run repeatedly (i.e., after each build): |
|||
|
|||
reset halt |
|||
flash write_image erase build-Passport/firmware-signed-signed.bin 0x8020000 |
|||
reset |
|||
|
|||
These commands do the following: |
|||
|
|||
- Stop execution of code on the MCU |
|||
- Write part 0 of the firmware to flash at address 0x8000000 |
|||
- Write part 1 of the firmware to flash at address 0x8040000 |
|||
- Reset the MCU and start executing code at address 0x8000000 |
|||
|
|||
### RShell Window |
|||
We use `rshell` to connect to the MicroPython device over USB serial. Open another shell and run: |
|||
|
|||
sudo rshell -p /dev/ttyUSB0 |
|||
|
|||
This gives us an interactive shell where we can do things like inspect the flash file system, or run a REPL: |
|||
|
|||
- `ls -la /flash` - Get a listing of the files in `/flash` on the device |
|||
- `cp local_folder/my_math.py /flash` - Copy a local file into `/flash` |
|||
- `repl` - Open a MicroPython REPL. If there are any files in `/flash`, you can import them. For example: |
|||
|
|||
``` |
|||
import my_math |
|||
my_math.add(1, 2) |
|||
``` |
|||
|
|||
|
|||
|
@ -0,0 +1,208 @@ |
|||
Apache License |
|||
|
|||
Version 2.0, January 2004 |
|||
|
|||
http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, |
|||
AND DISTRIBUTION |
|||
|
|||
1. Definitions. |
|||
|
|||
|
|||
|
|||
"License" shall mean the terms and conditions for use, reproduction, and distribution |
|||
as defined by Sections 1 through 9 of this document. |
|||
|
|||
|
|||
|
|||
"Licensor" shall mean the copyright owner or entity authorized by the copyright |
|||
owner that is granting the License. |
|||
|
|||
|
|||
|
|||
"Legal Entity" shall mean the union of the acting entity and all other entities |
|||
that control, are controlled by, or are under common control with that entity. |
|||
For the purposes of this definition, "control" means (i) the power, direct |
|||
or indirect, to cause the direction or management of such entity, whether |
|||
by contract or otherwise, or (ii) ownership of fifty percent (50%) or more |
|||
of the outstanding shares, or (iii) beneficial ownership of such entity. |
|||
|
|||
|
|||
|
|||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions |
|||
granted by this License. |
|||
|
|||
|
|||
|
|||
"Source" form shall mean the preferred form for making modifications, including |
|||
but not limited to software source code, documentation source, and configuration |
|||
files. |
|||
|
|||
|
|||
|
|||
"Object" form shall mean any form resulting from mechanical transformation |
|||
or translation of a Source form, including but not limited to compiled object |
|||
code, generated documentation, and conversions to other media types. |
|||
|
|||
|
|||
|
|||
"Work" shall mean the work of authorship, whether in Source or Object form, |
|||
made available under the License, as indicated by a copyright notice that |
|||
is included in or attached to the work (an example is provided in the Appendix |
|||
below). |
|||
|
|||
|
|||
|
|||
"Derivative Works" shall mean any work, whether in Source or Object form, |
|||
that is based on (or derived from) the Work and for which the editorial revisions, |
|||
annotations, elaborations, or other modifications represent, as a whole, an |
|||
original work of authorship. For the purposes of this License, Derivative |
|||
Works shall not include works that remain separable from, or merely link (or |
|||
bind by name) to the interfaces of, the Work and Derivative Works thereof. |
|||
|
|||
|
|||
|
|||
"Contribution" shall mean any work of authorship, including the original version |
|||
of the Work and any modifications or additions to that Work or Derivative |
|||
Works thereof, that is intentionally submitted to Licensor for inclusion in |
|||
the Work by the copyright owner or by an individual or Legal Entity authorized |
|||
to submit on behalf of the copyright owner. For the purposes of this definition, |
|||
"submitted" means any form of electronic, verbal, or written communication |
|||
sent to the Licensor or its representatives, including but not limited to |
|||
communication on electronic mailing lists, source code control systems, and |
|||
issue tracking systems that are managed by, or on behalf of, the Licensor |
|||
for the purpose of discussing and improving the Work, but excluding communication |
|||
that is conspicuously marked or otherwise designated in writing by the copyright |
|||
owner as "Not a Contribution." |
|||
|
|||
|
|||
|
|||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf |
|||
of whom a Contribution has been received by Licensor and subsequently incorporated |
|||
within the Work. |
|||
|
|||
2. Grant of Copyright License. Subject to the terms and conditions of this |
|||
License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, |
|||
no-charge, royalty-free, irrevocable copyright license to reproduce, prepare |
|||
Derivative Works of, publicly display, publicly perform, sublicense, and distribute |
|||
the Work and such Derivative Works in Source or Object form. |
|||
|
|||
3. Grant of Patent License. Subject to the terms and conditions of this License, |
|||
each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, |
|||
no-charge, royalty-free, irrevocable (except as stated in this section) patent |
|||
license to make, have made, use, offer to sell, sell, import, and otherwise |
|||
transfer the Work, where such license applies only to those patent claims |
|||
licensable by such Contributor that are necessarily infringed by their Contribution(s) |
|||
alone or by combination of their Contribution(s) with the Work to which such |
|||
Contribution(s) was submitted. If You institute patent litigation against |
|||
any entity (including a cross-claim or counterclaim in a lawsuit) alleging |
|||
that the Work or a Contribution incorporated within the Work constitutes direct |
|||
or contributory patent infringement, then any patent licenses granted to You |
|||
under this License for that Work shall terminate as of the date such litigation |
|||
is filed. |
|||
|
|||
4. Redistribution. You may reproduce and distribute copies of the Work or |
|||
Derivative Works thereof in any medium, with or without modifications, and |
|||
in Source or Object form, provided that You meet the following conditions: |
|||
|
|||
(a) You must give any other recipients of the Work or Derivative Works a copy |
|||
of this License; and |
|||
|
|||
(b) You must cause any modified files to carry prominent notices stating that |
|||
You changed the files; and |
|||
|
|||
(c) You must retain, in the Source form of any Derivative Works that You distribute, |
|||
all copyright, patent, trademark, and attribution notices from the Source |
|||
form of the Work, excluding those notices that do not pertain to any part |
|||
of the Derivative Works; and |
|||
|
|||
(d) If the Work includes a "NOTICE" text file as part of its distribution, |
|||
then any Derivative Works that You distribute must include a readable copy |
|||
of the attribution notices contained within such NOTICE file, excluding those |
|||
notices that do not pertain to any part of the Derivative Works, in at least |
|||
one of the following places: within a NOTICE text file distributed as part |
|||
of the Derivative Works; within the Source form or documentation, if provided |
|||
along with the Derivative Works; or, within a display generated by the Derivative |
|||
Works, if and wherever such third-party notices normally appear. The contents |
|||
of the NOTICE file are for informational purposes only and do not modify the |
|||
License. You may add Your own attribution notices within Derivative Works |
|||
that You distribute, alongside or as an addendum to the NOTICE text from the |
|||
Work, provided that such additional attribution notices cannot be construed |
|||
as modifying the License. |
|||
|
|||
You may add Your own copyright statement to Your modifications and may provide |
|||
additional or different license terms and conditions for use, reproduction, |
|||
or distribution of Your modifications, or for any such Derivative Works as |
|||
a whole, provided Your use, reproduction, and distribution of the Work otherwise |
|||
complies with the conditions stated in this License. |
|||
|
|||
5. Submission of Contributions. Unless You explicitly state otherwise, any |
|||
Contribution intentionally submitted for inclusion in the Work by You to the |
|||
Licensor shall be under the terms and conditions of this License, without |
|||
any additional terms or conditions. Notwithstanding the above, nothing herein |
|||
shall supersede or modify the terms of any separate license agreement you |
|||
may have executed with Licensor regarding such Contributions. |
|||
|
|||
6. Trademarks. This License does not grant permission to use the trade names, |
|||
trademarks, service marks, or product names of the Licensor, except as required |
|||
for reasonable and customary use in describing the origin of the Work and |
|||
reproducing the content of the NOTICE file. |
|||
|
|||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to |
|||
in writing, Licensor provides the Work (and each Contributor provides its |
|||
Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
|||
KIND, either express or implied, including, without limitation, any warranties |
|||
or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR |
|||
A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness |
|||
of using or redistributing the Work and assume any risks associated with Your |
|||
exercise of permissions under this License. |
|||
|
|||
8. Limitation of Liability. In no event and under no legal theory, whether |
|||
in tort (including negligence), contract, or otherwise, unless required by |
|||
applicable law (such as deliberate and grossly negligent acts) or agreed to |
|||
in writing, shall any Contributor be liable to You for damages, including |
|||
any direct, indirect, special, incidental, or consequential damages of any |
|||
character arising as a result of this License or out of the use or inability |
|||
to use the Work (including but not limited to damages for loss of goodwill, |
|||
work stoppage, computer failure or malfunction, or any and all other commercial |
|||
damages or losses), even if such Contributor has been advised of the possibility |
|||
of such damages. |
|||
|
|||
9. Accepting Warranty or Additional Liability. While redistributing the Work |
|||
or Derivative Works thereof, You may choose to offer, and charge a fee for, |
|||
acceptance of support, warranty, indemnity, or other liability obligations |
|||
and/or rights consistent with this License. However, in accepting such obligations, |
|||
You may act only on Your own behalf and on Your sole responsibility, not on |
|||
behalf of any other Contributor, and only if You agree to indemnify, defend, |
|||
and hold each Contributor harmless for any liability incurred by, or claims |
|||
asserted against, such Contributor by reason of your accepting any such warranty |
|||
or additional liability. END OF TERMS AND CONDITIONS |
|||
|
|||
APPENDIX: How to apply the Apache License to your work. |
|||
|
|||
To apply the Apache License to your work, attach the following boilerplate |
|||
notice, with the fields enclosed by brackets "[]" replaced with your own identifying |
|||
information. (Don't include the brackets!) The text should be enclosed in |
|||
the appropriate comment syntax for the file format. We also recommend that |
|||
a file or class name and description of purpose be included on the same "printed |
|||
page" as the copyright notice for easier identification within third-party |
|||
archives. |
|||
|
|||
Copyright [yyyy] [name of copyright owner] |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
|
|||
you may not use this file except in compliance with the License. |
|||
|
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
|
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
|
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
|
|||
See the License for the specific language governing permissions and |
|||
|
|||
limitations under the License. |
@ -0,0 +1,47 @@ |
|||
Copyright (c) 2020 Foundation Devices, Inc. |
|||
|
|||
Redistribution and use in source and binary forms, with or without modification, |
|||
are permitted provided that the following conditions are met: |
|||
|
|||
1. Redistributions of source code must retain the above copyright notice, |
|||
this list of conditions and the following disclaimer. |
|||
|
|||
2. Redistributions in binary form must reproduce the above copyright notice, |
|||
this list of conditions and the following disclaimer in the documentation |
|||
and/or other materials provided with the distribution. |
|||
|
|||
Subject to the terms and conditions of this license, each copyright holder |
|||
and contributor hereby grants to those receiving rights under this license |
|||
a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
|||
(except for failure to satisfy the conditions of this license) patent license |
|||
to make, have made, use, offer to sell, sell, import, and otherwise transfer |
|||
this software, where such license applies only to those patent claims, already |
|||
acquired or hereafter acquired, licensable by such copyright holder or contributor |
|||
that are necessarily infringed by: |
|||
|
|||
(a) their Contribution(s) (the licensed copyrights of copyright holders and |
|||
non-copyrightable additions of contributors, in source or binary form) alone; |
|||
or |
|||
|
|||
(b) combination of their Contribution(s) with the work of authorship to which |
|||
such Contribution(s) was added by such copyright holder or contributor, if, |
|||
at the time the Contribution is added, such addition causes such combination |
|||
to be necessarily infringed. The patent license shall not apply to any other |
|||
combinations which include the Contribution. |
|||
|
|||
Except as expressly stated above, no rights or licenses from any copyright |
|||
holder or contributor is granted under this license, whether expressly, by |
|||
implication, estoppel or otherwise. |
|||
|
|||
DISCLAIMER |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE |
|||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
|||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
|||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
@ -0,0 +1,22 @@ |
|||
Copyright (c) <year> <owner> All rights reserved. |
|||
|
|||
Redistribution and use in source and binary forms, with or without modification, |
|||
are permitted provided that the following conditions are met: |
|||
|
|||
1. Redistributions of source code must retain the above copyright notice, |
|||
this list of conditions and the following disclaimer. |
|||
|
|||
2. Redistributions in binary form must reproduce the above copyright notice, |
|||
this list of conditions and the following disclaimer in the documentation |
|||
and/or other materials provided with the distribution. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
|||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
|||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
@ -0,0 +1,26 @@ |
|||
Copyright (c) <year> <owner>. All rights reserved. |
|||
|
|||
Redistribution and use in source and binary forms, with or without modification, |
|||
are permitted provided that the following conditions are met: |
|||
|
|||
1. Redistributions of source code must retain the above copyright notice, |
|||
this list of conditions and the following disclaimer. |
|||
|
|||
2. Redistributions in binary form must reproduce the above copyright notice, |
|||
this list of conditions and the following disclaimer in the documentation |
|||
and/or other materials provided with the distribution. |
|||
|
|||
3. Neither the name of the copyright holder nor the names of its contributors |
|||
may be used to endorse or promote products derived from this software without |
|||
specific prior written permission. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
|||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
|||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
@ -0,0 +1,625 @@ |
|||
GNU GENERAL PUBLIC LICENSE |
|||
|
|||
Version 3, 29 June 2007 |
|||
|
|||
Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/> |
|||
|
|||
Everyone is permitted to copy and distribute verbatim copies of this license |
|||
document, but changing it is not allowed. |
|||
|
|||
Preamble |
|||
|
|||
The GNU General Public License is a free, copyleft license for software and |
|||
other kinds of works. |
|||
|
|||
The licenses for most software and other practical works are designed to take |
|||
away your freedom to share and change the works. By contrast, the GNU General |
|||
Public License is intended to guarantee your freedom to share and change all |
|||
versions of a program--to make sure it remains free software for all its users. |
|||
We, the Free Software Foundation, use the GNU General Public License for most |
|||
of our software; it applies also to any other work released this way by its |
|||
authors. You can apply it to your programs, too. |
|||
|
|||
When we speak of free software, we are referring to freedom, not price. Our |
|||
General Public Licenses are designed to make sure that you have the freedom |
|||
to distribute copies of free software (and charge for them if you wish), that |
|||
you receive source code or can get it if you want it, that you can change |
|||
the software or use pieces of it in new free programs, and that you know you |
|||
can do these things. |
|||
|
|||
To protect your rights, we need to prevent others from denying you these rights |
|||
or asking you to surrender the rights. Therefore, you have certain responsibilities |
|||
if you distribute copies of the software, or if you modify it: responsibilities |
|||
to respect the freedom of others. |
|||
|
|||
For example, if you distribute copies of such a program, whether gratis or |
|||
for a fee, you must pass on to the recipients the same freedoms that you received. |
|||
You must make sure that they, too, receive or can get the source code. And |
|||
you must show them these terms so they know their rights. |
|||
|
|||
Developers that use the GNU GPL protect your rights with two steps: (1) assert |
|||
copyright on the software, and (2) offer you this License giving you legal |
|||
permission to copy, distribute and/or modify it. |
|||
|
|||
For the developers' and authors' protection, the GPL clearly explains that |
|||
there is no warranty for this free software. For both users' and authors' |
|||
sake, the GPL requires that modified versions be marked as changed, so that |
|||
their problems will not be attributed erroneously to authors of previous versions. |
|||
|
|||
Some devices are designed to deny users access to install or run modified |
|||
versions of the software inside them, although the manufacturer can do so. |
|||
This is fundamentally incompatible with the aim of protecting users' freedom |
|||
to change the software. The systematic pattern of such abuse occurs in the |
|||
area of products for individuals to use, which is precisely where it is most |
|||
unacceptable. Therefore, we have designed this version of the GPL to prohibit |
|||
the practice for those products. If such problems arise substantially in other |
|||
domains, we stand ready to extend this provision to those domains in future |
|||
versions of the GPL, as needed to protect the freedom of users. |
|||
|
|||
Finally, every program is threatened constantly by software patents. States |
|||
should not allow patents to restrict development and use of software on general-purpose |
|||
computers, but in those that do, we wish to avoid the special danger that |
|||
patents applied to a free program could make it effectively proprietary. To |
|||
prevent this, the GPL assures that patents cannot be used to render the program |
|||
non-free. |
|||
|
|||
The precise terms and conditions for copying, distribution and modification |
|||
follow. |
|||
|
|||
TERMS AND CONDITIONS |
|||
|
|||
0. Definitions. |
|||
|
|||
"This License" refers to version 3 of the GNU General Public License. |
|||
|
|||
"Copyright" also means copyright-like laws that apply to other kinds of works, |
|||
such as semiconductor masks. |
|||
|
|||
"The Program" refers to any copyrightable work licensed under this License. |
|||
Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals |
|||
or organizations. |
|||
|
|||
To "modify" a work means to copy from or adapt all or part of the work in |
|||
a fashion requiring copyright permission, other than the making of an exact |
|||
copy. The resulting work is called a "modified version" of the earlier work |
|||
or a work "based on" the earlier work. |
|||
|
|||
A "covered work" means either the unmodified Program or a work based on the |
|||
Program. |
|||
|
|||
To "propagate" a work means to do anything with it that, without permission, |
|||
would make you directly or secondarily liable for infringement under applicable |
|||
copyright law, except executing it on a computer or modifying a private copy. |
|||
Propagation includes copying, distribution (with or without modification), |
|||
making available to the public, and in some countries other activities as |
|||
well. |
|||
|
|||
To "convey" a work means any kind of propagation that enables other parties |
|||
to make or receive copies. Mere interaction with a user through a computer |
|||
network, with no transfer of a copy, is not conveying. |
|||
|
|||
An interactive user interface displays "Appropriate Legal Notices" to the |
|||
extent that it includes a convenient and prominently visible feature that |
|||
(1) displays an appropriate copyright notice, and (2) tells the user that |
|||
there is no warranty for the work (except to the extent that warranties are |
|||
provided), that licensees may convey the work under this License, and how |
|||
to view a copy of this License. If the interface presents a list of user commands |
|||
or options, such as a menu, a prominent item in the list meets this criterion. |
|||
|
|||
1. Source Code. |
|||
|
|||
The "source code" for a work means the preferred form of the work for making |
|||
modifications to it. "Object code" means any non-source form of a work. |
|||
|
|||
A "Standard Interface" means an interface that either is an official standard |
|||
defined by a recognized standards body, or, in the case of interfaces specified |
|||
for a particular programming language, one that is widely used among developers |
|||
working in that language. |
|||
|
|||
The "System Libraries" of an executable work include anything, other than |
|||
the work as a whole, that (a) is included in the normal form of packaging |
|||
a Major Component, but which is not part of that Major Component, and (b) |
|||
serves only to enable use of the work with that Major Component, or to implement |
|||
a Standard Interface for which an implementation is available to the public |
|||
in source code form. A "Major Component", in this context, means a major essential |
|||
component (kernel, window system, and so on) of the specific operating system |
|||
(if any) on which the executable work runs, or a compiler used to produce |
|||
the work, or an object code interpreter used to run it. |
|||
|
|||
The "Corresponding Source" for a work in object code form means all the source |
|||
code needed to generate, install, and (for an executable work) run the object |
|||
code and to modify the work, including scripts to control those activities. |
|||
However, it does not include the work's System Libraries, or general-purpose |
|||
tools or generally available free programs which are used unmodified in performing |
|||
those activities but which are not part of the work. For example, Corresponding |
|||
Source includes interface definition files associated with source files for |
|||
the work, and the source code for shared libraries and dynamically linked |
|||
subprograms that the work is specifically designed to require, such as by |
|||
intimate data communication or control flow between those subprograms and |
|||
other parts of the work. |
|||
|
|||
The Corresponding Source need not include anything that users can regenerate |
|||
automatically from other parts of the Corresponding Source. |
|||
|
|||
The Corresponding Source for a work in source code form is that same work. |
|||
|
|||
2. Basic Permissions. |
|||
|
|||
All rights granted under this License are granted for the term of copyright |
|||
on the Program, and are irrevocable provided the stated conditions are met. |
|||
This License explicitly affirms your unlimited permission to run the unmodified |
|||
Program. The output from running a covered work is covered by this License |
|||
only if the output, given its content, constitutes a covered work. This License |
|||
acknowledges your rights of fair use or other equivalent, as provided by copyright |
|||
law. |
|||
|
|||
You may make, run and propagate covered works that you do not convey, without |
|||
conditions so long as your license otherwise remains in force. You may convey |
|||
covered works to others for the sole purpose of having them make modifications |
|||
exclusively for you, or provide you with facilities for running those works, |
|||
provided that you comply with the terms of this License in conveying all material |
|||
for which you do not control copyright. Those thus making or running the covered |
|||
works for you must do so exclusively on your behalf, under your direction |
|||
and control, on terms that prohibit them from making any copies of your copyrighted |
|||
material outside their relationship with you. |
|||
|
|||
Conveying under any other circumstances is permitted solely under the conditions |
|||
stated below. Sublicensing is not allowed; section 10 makes it unnecessary. |
|||
|
|||
3. Protecting Users' Legal Rights From Anti-Circumvention Law. |
|||
|
|||
No covered work shall be deemed part of an effective technological measure |
|||
under any applicable law fulfilling obligations under article 11 of the WIPO |
|||
copyright treaty adopted on 20 December 1996, or similar laws prohibiting |
|||
or restricting circumvention of such measures. |
|||
|
|||
When you convey a covered work, you waive any legal power to forbid circumvention |
|||
of technological measures to the extent such circumvention is effected by |
|||
exercising rights under this License with respect to the covered work, and |
|||
you disclaim any intention to limit operation or modification of the work |
|||
as a means of enforcing, against the work's users, your or third parties' |
|||
legal rights to forbid circumvention of technological measures. |
|||
|
|||
4. Conveying Verbatim Copies. |
|||
|
|||
You may convey verbatim copies of the Program's source code as you receive |
|||
it, in any medium, provided that you conspicuously and appropriately publish |
|||
on each copy an appropriate copyright notice; keep intact all notices stating |
|||
that this License and any non-permissive terms added in accord with section |
|||
7 apply to the code; keep intact all notices of the absence of any warranty; |
|||
and give all recipients a copy of this License along with the Program. |
|||
|
|||
You may charge any price or no price for each copy that you convey, and you |
|||
may offer support or warranty protection for a fee. |
|||
|
|||
5. Conveying Modified Source Versions. |
|||
|
|||
You may convey a work based on the Program, or the modifications to produce |
|||
it from the Program, in the form of source code under the terms of section |
|||
4, provided that you also meet all of these conditions: |
|||
|
|||
a) The work must carry prominent notices stating that you modified it, and |
|||
giving a relevant date. |
|||
|
|||
b) The work must carry prominent notices stating that it is released under |
|||
this License and any conditions added under section 7. This requirement modifies |
|||
the requirement in section 4 to "keep intact all notices". |
|||
|
|||
c) You must license the entire work, as a whole, under this License to anyone |
|||
who comes into possession of a copy. This License will therefore apply, along |
|||
with any applicable section 7 additional terms, to the whole of the work, |
|||
and all its parts, regardless of how they are packaged. This License gives |
|||
no permission to license the work in any other way, but it does not invalidate |
|||
such permission if you have separately received it. |
|||
|
|||
d) If the work has interactive user interfaces, each must display Appropriate |
|||
Legal Notices; however, if the Program has interactive interfaces that do |
|||
not display Appropriate Legal Notices, your work need not make them do so. |
|||
|
|||
A compilation of a covered work with other separate and independent works, |
|||
which are not by their nature extensions of the covered work, and which are |
|||
not combined with it such as to form a larger program, in or on a volume of |
|||
a storage or distribution medium, is called an "aggregate" if the compilation |
|||
and its resulting copyright are not used to limit the access or legal rights |
|||
of the compilation's users beyond what the individual works permit. Inclusion |
|||
of a covered work in an aggregate does not cause this License to apply to |
|||
the other parts of the aggregate. |
|||
|
|||
6. Conveying Non-Source Forms. |
|||
|
|||
You may convey a covered work in object code form under the terms of sections |
|||
4 and 5, provided that you also convey the machine-readable Corresponding |
|||
Source under the terms of this License, in one of these ways: |
|||
|
|||
a) Convey the object code in, or embodied in, a physical product (including |
|||
a physical distribution medium), accompanied by the Corresponding Source fixed |
|||
on a durable physical medium customarily used for software interchange. |
|||
|
|||
b) Convey the object code in, or embodied in, a physical product (including |
|||
a physical distribution medium), accompanied by a written offer, valid for |
|||
at least three years and valid for as long as you offer spare parts or customer |
|||
support for that product model, to give anyone who possesses the object code |
|||
either (1) a copy of the Corresponding Source for all the software in the |
|||
product that is covered by this License, on a durable physical medium customarily |
|||
used for software interchange, for a price no more than your reasonable cost |
|||
of physically performing this conveying of source, or (2) access to copy the |
|||
Corresponding Source from a network server at no charge. |
|||
|
|||
c) Convey individual copies of the object code with a copy of the written |
|||
offer to provide the Corresponding Source. This alternative is allowed only |
|||
occasionally and noncommercially, and only if you received the object code |
|||
with such an offer, in accord with subsection 6b. |
|||
|
|||
d) Convey the object code by offering access from a designated place (gratis |
|||
or for a charge), and offer equivalent access to the Corresponding Source |
|||
in the same way through the same place at no further charge. You need not |
|||
require recipients to copy the Corresponding Source along with the object |
|||
code. If the place to copy the object code is a network server, the Corresponding |
|||
Source may be on a different server (operated by you or a third party) that |
|||
supports equivalent copying facilities, provided you maintain clear directions |
|||
next to the object code saying where to find the Corresponding Source. Regardless |
|||
of what server hosts the Corresponding Source, you remain obligated to ensure |
|||
that it is available for as long as needed to satisfy these requirements. |
|||
|
|||
e) Convey the object code using peer-to-peer transmission, provided you inform |
|||
other peers where the object code and Corresponding Source of the work are |
|||
being offered to the general public at no charge under subsection 6d. |
|||
|
|||
A separable portion of the object code, whose source code is excluded from |
|||
the Corresponding Source as a System Library, need not be included in conveying |
|||
the object code work. |
|||
|
|||
A "User Product" is either (1) a "consumer product", which means any tangible |
|||
personal property which is normally used for personal, family, or household |
|||
purposes, or (2) anything designed or sold for incorporation into a dwelling. |
|||
In determining whether a product is a consumer product, doubtful cases shall |
|||
be resolved in favor of coverage. For a particular product received by a particular |
|||
user, "normally used" refers to a typical or common use of that class of product, |
|||
regardless of the status of the particular user or of the way in which the |
|||
particular user actually uses, or expects or is expected to use, the product. |
|||
A product is a consumer product regardless of whether the product has substantial |
|||
commercial, industrial or non-consumer uses, unless such uses represent the |
|||
only significant mode of use of the product. |
|||
|
|||
"Installation Information" for a User Product means any methods, procedures, |
|||
authorization keys, or other information required to install and execute modified |
|||
versions of a covered work in that User Product from a modified version of |
|||
its Corresponding Source. The information must suffice to ensure that the |
|||
continued functioning of the modified object code is in no case prevented |
|||
or interfered with solely because modification has been made. |
|||
|
|||
If you convey an object code work under this section in, or with, or specifically |
|||
for use in, a User Product, and the conveying occurs as part of a transaction |
|||
in which the right of possession and use of the User Product is transferred |
|||
to the recipient in perpetuity or for a fixed term (regardless of how the |
|||
transaction is characterized), the Corresponding Source conveyed under this |
|||
section must be accompanied by the Installation Information. But this requirement |
|||
does not apply if neither you nor any third party retains the ability to install |
|||
modified object code on the User Product (for example, the work has been installed |
|||
in ROM). |
|||
|
|||
The requirement to provide Installation Information does not include a requirement |
|||
to continue to provide support service, warranty, or updates for a work that |
|||
has been modified or installed by the recipient, or for the User Product in |
|||
which it has been modified or installed. Access to a network may be denied |
|||
when the modification itself materially and adversely affects the operation |
|||
of the network or violates the rules and protocols for communication across |
|||
the network. |
|||
|
|||
Corresponding Source conveyed, and Installation Information provided, in accord |
|||
with this section must be in a format that is publicly documented (and with |
|||
an implementation available to the public in source code form), and must require |
|||
no special password or key for unpacking, reading or copying. |
|||
|
|||
7. Additional Terms. |
|||
|
|||
"Additional permissions" are terms that supplement the terms of this License |
|||
by making exceptions from one or more of its conditions. Additional permissions |
|||
that are applicable to the entire Program shall be treated as though they |
|||
were included in this License, to the extent that they are valid under applicable |
|||
law. If additional permissions apply only to part of the Program, that part |
|||
may be used separately under those permissions, but the entire Program remains |
|||
governed by this License without regard to the additional permissions. |
|||
|
|||
When you convey a copy of a covered work, you may at your option remove any |
|||
additional permissions from that copy, or from any part of it. (Additional |
|||
permissions may be written to require their own removal in certain cases when |
|||
you modify the work.) You may place additional permissions on material, added |
|||
by you to a covered work, for which you have or can give appropriate copyright |
|||
permission. |
|||
|
|||
Notwithstanding any other provision of this License, for material you add |
|||
to a covered work, you may (if authorized by the copyright holders of that |
|||
material) supplement the terms of this License with terms: |
|||
|
|||
a) Disclaiming warranty or limiting liability differently from the terms of |
|||
sections 15 and 16 of this License; or |
|||
|
|||
b) Requiring preservation of specified reasonable legal notices or author |
|||
attributions in that material or in the Appropriate Legal Notices displayed |
|||
by works containing it; or |
|||
|
|||
c) Prohibiting misrepresentation of the origin of that material, or requiring |
|||
that modified versions of such material be marked in reasonable ways as different |
|||
from the original version; or |
|||
|
|||
d) Limiting the use for publicity purposes of names of licensors or authors |
|||
of the material; or |
|||
|
|||
e) Declining to grant rights under trademark law for use of some trade names, |
|||
trademarks, or service marks; or |
|||
|
|||
f) Requiring indemnification of licensors and authors of that material by |
|||
anyone who conveys the material (or modified versions of it) with contractual |
|||
assumptions of liability to the recipient, for any liability that these contractual |
|||
assumptions directly impose on those licensors and authors. |
|||
|
|||
All other non-permissive additional terms are considered "further restrictions" |
|||
within the meaning of section 10. If the Program as you received it, or any |
|||
part of it, contains a notice stating that it is governed by this License |
|||
along with a term that is a further restriction, you may remove that term. |
|||
If a license document contains a further restriction but permits relicensing |
|||
or conveying under this License, you may add to a covered work material governed |
|||
by the terms of that license document, provided that the further restriction |
|||
does not survive such relicensing or conveying. |
|||
|
|||
If you add terms to a covered work in accord with this section, you must place, |
|||
in the relevant source files, a statement of the additional terms that apply |
|||
to those files, or a notice indicating where to find the applicable terms. |
|||
|
|||
Additional terms, permissive or non-permissive, may be stated in the form |
|||
of a separately written license, or stated as exceptions; the above requirements |
|||
apply either way. |
|||
|
|||
8. Termination. |
|||
|
|||
You may not propagate or modify a covered work except as expressly provided |
|||
under this License. Any attempt otherwise to propagate or modify it is void, |
|||
and will automatically terminate your rights under this License (including |
|||
any patent licenses granted under the third paragraph of section 11). |
|||
|
|||
However, if you cease all violation of this License, then your license from |
|||
a particular copyright holder is reinstated (a) provisionally, unless and |
|||
until the copyright holder explicitly and finally terminates your license, |
|||
and (b) permanently, if the copyright holder fails to notify you of the violation |
|||
by some reasonable means prior to 60 days after the cessation. |
|||
|
|||
Moreover, your license from a particular copyright holder is reinstated permanently |
|||
if the copyright holder notifies you of the violation by some reasonable means, |
|||
this is the first time you have received notice of violation of this License |
|||
(for any work) from that copyright holder, and you cure the violation prior |
|||
to 30 days after your receipt of the notice. |
|||
|
|||
Termination of your rights under this section does not terminate the licenses |
|||
of parties who have received copies or rights from you under this License. |
|||
If your rights have been terminated and not permanently reinstated, you do |
|||
not qualify to receive new licenses for the same material under section 10. |
|||
|
|||
9. Acceptance Not Required for Having Copies. |
|||
|
|||
You are not required to accept this License in order to receive or run a copy |
|||
of the Program. Ancillary propagation of a covered work occurring solely as |
|||
a consequence of using peer-to-peer transmission to receive a copy likewise |
|||
does not require acceptance. However, nothing other than this License grants |
|||
you permission to propagate or modify any covered work. These actions infringe |
|||
copyright if you do not accept this License. Therefore, by modifying or propagating |
|||
a covered work, you indicate your acceptance of this License to do so. |
|||
|
|||
10. Automatic Licensing of Downstream Recipients. |
|||
|
|||
Each time you convey a covered work, the recipient automatically receives |
|||
a license from the original licensors, to run, modify and propagate that work, |
|||
subject to this License. You are not responsible for enforcing compliance |
|||
by third parties with this License. |
|||
|
|||
An "entity transaction" is a transaction transferring control of an organization, |
|||
or substantially all assets of one, or subdividing an organization, or merging |
|||
organizations. If propagation of a covered work results from an entity transaction, |
|||
each party to that transaction who receives a copy of the work also receives |
|||
whatever licenses to the work the party's predecessor in interest had or could |
|||
give under the previous paragraph, plus a right to possession of the Corresponding |
|||
Source of the work from the predecessor in interest, if the predecessor has |
|||
it or can get it with reasonable efforts. |
|||
|
|||
You may not impose any further restrictions on the exercise of the rights |
|||
granted or affirmed under this License. For example, you may not impose a |
|||
license fee, royalty, or other charge for exercise of rights granted under |
|||
this License, and you may not initiate litigation (including a cross-claim |
|||
or counterclaim in a lawsuit) alleging that any patent claim is infringed |
|||
by making, using, selling, offering for sale, or importing the Program or |
|||
any portion of it. |
|||
|
|||
11. Patents. |
|||
|
|||
A "contributor" is a copyright holder who authorizes use under this License |
|||
of the Program or a work on which the Program is based. The work thus licensed |
|||
is called the contributor's "contributor version". |
|||
|
|||
A contributor's "essential patent claims" are all patent claims owned or controlled |
|||
by the contributor, whether already acquired or hereafter acquired, that would |
|||
be infringed by some manner, permitted by this License, of making, using, |
|||
or selling its contributor version, but do not include claims that would be |
|||
infringed only as a consequence of further modification of the contributor |
|||
version. For purposes of this definition, "control" includes the right to |
|||
grant patent sublicenses in a manner consistent with the requirements of this |
|||
License. |
|||
|
|||
Each contributor grants you a non-exclusive, worldwide, royalty-free patent |
|||
license under the contributor's essential patent claims, to make, use, sell, |
|||
offer for sale, import and otherwise run, modify and propagate the contents |
|||
of its contributor version. |
|||
|
|||
In the following three paragraphs, a "patent license" is any express agreement |
|||
or commitment, however denominated, not to enforce a patent (such as an express |
|||
permission to practice a patent or covenant not to sue for patent infringement). |
|||
To "grant" such a patent license to a party means to make such an agreement |
|||
or commitment not to enforce a patent against the party. |
|||
|
|||
If you convey a covered work, knowingly relying on a patent license, and the |
|||
Corresponding Source of the work is not available for anyone to copy, free |
|||
of charge and under the terms of this License, through a publicly available |
|||
network server or other readily accessible means, then you must either (1) |
|||
cause the Corresponding Source to be so available, or (2) arrange to deprive |
|||
yourself of the benefit of the patent license for this particular work, or |
|||
(3) arrange, in a manner consistent with the requirements of this License, |
|||
to extend the patent license to downstream recipients. "Knowingly relying" |
|||
means you have actual knowledge that, but for the patent license, your conveying |
|||
the covered work in a country, or your recipient's use of the covered work |
|||
in a country, would infringe one or more identifiable patents in that country |
|||
that you have reason to believe are valid. |
|||
|
|||
If, pursuant to or in connection with a single transaction or arrangement, |
|||
you convey, or propagate by procuring conveyance of, a covered work, and grant |
|||
a patent license to some of the parties receiving the covered work authorizing |
|||
them to use, propagate, modify or convey a specific copy of the covered work, |
|||
then the patent license you grant is automatically extended to all recipients |
|||
of the covered work and works based on it. |
|||
|
|||
A patent license is "discriminatory" if it does not include within the scope |
|||
of its coverage, prohibits the exercise of, or is conditioned on the non-exercise |
|||
of one or more of the rights that are specifically granted under this License. |
|||
You may not convey a covered work if you are a party to an arrangement with |
|||
a third party that is in the business of distributing software, under which |
|||
you make payment to the third party based on the extent of your activity of |
|||
conveying the work, and under which the third party grants, to any of the |
|||
parties who would receive the covered work from you, a discriminatory patent |
|||
license (a) in connection with copies of the covered work conveyed by you |
|||
(or copies made from those copies), or (b) primarily for and in connection |
|||
with specific products or compilations that contain the covered work, unless |
|||
you entered into that arrangement, or that patent license was granted, prior |
|||
to 28 March 2007. |
|||
|
|||
Nothing in this License shall be construed as excluding or limiting any implied |
|||
license or other defenses to infringement that may otherwise be available |
|||
to you under applicable patent law. |
|||
|
|||
12. No Surrender of Others' Freedom. |
|||
|
|||
If conditions are imposed on you (whether by court order, agreement or otherwise) |
|||
that contradict the conditions of this License, they do not excuse you from |
|||
the conditions of this License. If you cannot convey a covered work so as |
|||
to satisfy simultaneously your obligations under this License and any other |
|||
pertinent obligations, then as a consequence you may not convey it at all. |
|||
For example, if you agree to terms that obligate you to collect a royalty |
|||
for further conveying from those to whom you convey the Program, the only |
|||
way you could satisfy both those terms and this License would be to refrain |
|||
entirely from conveying the Program. |
|||
|
|||
13. Use with the GNU Affero General Public License. |
|||
|
|||
Notwithstanding any other provision of this License, you have permission to |
|||
link or combine any covered work with a work licensed under version 3 of the |
|||
GNU Affero General Public License into a single combined work, and to convey |
|||
the resulting work. The terms of this License will continue to apply to the |
|||
part which is the covered work, but the special requirements of the GNU Affero |
|||
General Public License, section 13, concerning interaction through a network |
|||
will apply to the combination as such. |
|||
|
|||
14. Revised Versions of this License. |
|||
|
|||
The Free Software Foundation may publish revised and/or new versions of the |
|||
GNU General Public License from time to time. Such new versions will be similar |
|||
in spirit to the present version, but may differ in detail to address new |
|||
problems or concerns. |
|||
|
|||
Each version is given a distinguishing version number. If the Program specifies |
|||
that a certain numbered version of the GNU General Public License "or any |
|||
later version" applies to it, you have the option of following the terms and |
|||
conditions either of that numbered version or of any later version published |
|||
by the Free Software Foundation. If the Program does not specify a version |
|||
number of the GNU General Public License, you may choose any version ever |
|||
published by the Free Software Foundation. |
|||
|
|||
If the Program specifies that a proxy can decide which future versions of |
|||
the GNU General Public License can be used, that proxy's public statement |
|||
of acceptance of a version permanently authorizes you to choose that version |
|||
for the Program. |
|||
|
|||
Later license versions may give you additional or different permissions. However, |
|||
no additional obligations are imposed on any author or copyright holder as |
|||
a result of your choosing to follow a later version. |
|||
|
|||
15. Disclaimer of Warranty. |
|||
|
|||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE |
|||
LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR |
|||
OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER |
|||
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
|||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS |
|||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM |
|||
PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR |
|||
CORRECTION. |
|||
|
|||
16. Limitation of Liability. |
|||
|
|||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL |
|||
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM |
|||
AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, |
|||
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO |
|||
USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED |
|||
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE |
|||
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER |
|||
PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. |
|||
|
|||
17. Interpretation of Sections 15 and 16. |
|||
|
|||
If the disclaimer of warranty and limitation of liability provided above cannot |
|||
be given local legal effect according to their terms, reviewing courts shall |
|||
apply local law that most closely approximates an absolute waiver of all civil |
|||
liability in connection with the Program, unless a warranty or assumption |
|||
of liability accompanies a copy of the Program in return for a fee. END OF |
|||
TERMS AND CONDITIONS |
|||
|
|||
How to Apply These Terms to Your New Programs |
|||
|
|||
If you develop a new program, and you want it to be of the greatest possible |
|||
use to the public, the best way to achieve this is to make it free software |
|||
which everyone can redistribute and change under these terms. |
|||
|
|||
To do so, attach the following notices to the program. It is safest to attach |
|||
them to the start of each source file to most effectively state the exclusion |
|||
of warranty; and each file should have at least the "copyright" line and a |
|||
pointer to where the full notice is found. |
|||
|
|||
<one line to give the program's name and a brief idea of what it does.> |
|||
|
|||
Copyright (C) <year> <name of author> |
|||
|
|||
This program is free software: you can redistribute it and/or modify it under |
|||
the terms of the GNU General Public License as published by the Free Software |
|||
Foundation, either version 3 of the License, or (at your option) any later |
|||
version. |
|||
|
|||
This program is distributed in the hope that it will be useful, but WITHOUT |
|||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License along with |
|||
this program. If not, see <https://www.gnu.org/licenses/>. |
|||
|
|||
Also add information on how to contact you by electronic and paper mail. |
|||
|
|||
If the program does terminal interaction, make it output a short notice like |
|||
this when it starts in an interactive mode: |
|||
|
|||
<program> Copyright (C) <year> <name of author> |
|||
|
|||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
|||
|
|||
This is free software, and you are welcome to redistribute it under certain |
|||
conditions; type `show c' for details. |
|||
|
|||
The hypothetical commands `show w' and `show c' should show the appropriate |
|||
parts of the General Public License. Of course, your program's commands might |
|||
be different; for a GUI interface, you would use an "about box". |
|||
|
|||
You should also get your employer (if you work as a programmer) or school, |
|||
if any, to sign a "copyright disclaimer" for the program, if necessary. For |
|||
more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>. |
|||
|
|||
The GNU General Public License does not permit incorporating your program |
|||
into proprietary programs. If your program is a subroutine library, you may |
|||
consider it more useful to permit linking proprietary applications with the |
|||
library. If this is what you want to do, use the GNU Lesser General Public |
|||
License instead of this License. But first, please read <https://www.gnu.org/ |
|||
licenses /why-not-lgpl.html>. |
@ -0,0 +1,625 @@ |
|||
GNU GENERAL PUBLIC LICENSE |
|||
|
|||
Version 3, 29 June 2007 |
|||
|
|||
Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/> |
|||
|
|||
Everyone is permitted to copy and distribute verbatim copies of this license |
|||
document, but changing it is not allowed. |
|||
|
|||
Preamble |
|||
|
|||
The GNU General Public License is a free, copyleft license for software and |
|||
other kinds of works. |
|||
|
|||
The licenses for most software and other practical works are designed to take |
|||
away your freedom to share and change the works. By contrast, the GNU General |
|||
Public License is intended to guarantee your freedom to share and change all |
|||
versions of a program--to make sure it remains free software for all its users. |
|||
We, the Free Software Foundation, use the GNU General Public License for most |
|||
of our software; it applies also to any other work released this way by its |
|||
authors. You can apply it to your programs, too. |
|||
|
|||
When we speak of free software, we are referring to freedom, not price. Our |
|||
General Public Licenses are designed to make sure that you have the freedom |
|||
to distribute copies of free software (and charge for them if you wish), that |
|||
you receive source code or can get it if you want it, that you can change |
|||
the software or use pieces of it in new free programs, and that you know you |
|||
can do these things. |
|||
|
|||
To protect your rights, we need to prevent others from denying you these rights |
|||
or asking you to surrender the rights. Therefore, you have certain responsibilities |
|||
if you distribute copies of the software, or if you modify it: responsibilities |
|||
to respect the freedom of others. |
|||
|
|||
For example, if you distribute copies of such a program, whether gratis or |
|||
for a fee, you must pass on to the recipients the same freedoms that you received. |
|||
You must make sure that they, too, receive or can get the source code. And |
|||
you must show them these terms so they know their rights. |
|||
|
|||
Developers that use the GNU GPL protect your rights with two steps: (1) assert |
|||
copyright on the software, and (2) offer you this License giving you legal |
|||
permission to copy, distribute and/or modify it. |
|||
|
|||
For the developers' and authors' protection, the GPL clearly explains that |
|||
there is no warranty for this free software. For both users' and authors' |
|||
sake, the GPL requires that modified versions be marked as changed, so that |
|||
their problems will not be attributed erroneously to authors of previous versions. |
|||
|
|||
Some devices are designed to deny users access to install or run modified |
|||
versions of the software inside them, although the manufacturer can do so. |
|||
This is fundamentally incompatible with the aim of protecting users' freedom |
|||
to change the software. The systematic pattern of such abuse occurs in the |
|||
area of products for individuals to use, which is precisely where it is most |
|||
unacceptable. Therefore, we have designed this version of the GPL to prohibit |
|||
the practice for those products. If such problems arise substantially in other |
|||
domains, we stand ready to extend this provision to those domains in future |
|||
versions of the GPL, as needed to protect the freedom of users. |
|||
|
|||
Finally, every program is threatened constantly by software patents. States |
|||
should not allow patents to restrict development and use of software on general-purpose |
|||
computers, but in those that do, we wish to avoid the special danger that |
|||
patents applied to a free program could make it effectively proprietary. To |
|||
prevent this, the GPL assures that patents cannot be used to render the program |
|||
non-free. |
|||
|
|||
The precise terms and conditions for copying, distribution and modification |
|||
follow. |
|||
|
|||
TERMS AND CONDITIONS |
|||
|
|||
0. Definitions. |
|||
|
|||
"This License" refers to version 3 of the GNU General Public License. |
|||
|
|||
"Copyright" also means copyright-like laws that apply to other kinds of works, |
|||
such as semiconductor masks. |
|||
|
|||
"The Program" refers to any copyrightable work licensed under this License. |
|||
Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals |
|||
or organizations. |
|||
|
|||
To "modify" a work means to copy from or adapt all or part of the work in |
|||
a fashion requiring copyright permission, other than the making of an exact |
|||
copy. The resulting work is called a "modified version" of the earlier work |
|||
or a work "based on" the earlier work. |
|||
|
|||
A "covered work" means either the unmodified Program or a work based on the |
|||
Program. |
|||
|
|||
To "propagate" a work means to do anything with it that, without permission, |
|||
would make you directly or secondarily liable for infringement under applicable |
|||
copyright law, except executing it on a computer or modifying a private copy. |
|||
Propagation includes copying, distribution (with or without modification), |
|||
making available to the public, and in some countries other activities as |
|||
well. |
|||
|
|||
To "convey" a work means any kind of propagation that enables other parties |
|||
to make or receive copies. Mere interaction with a user through a computer |
|||
network, with no transfer of a copy, is not conveying. |
|||
|
|||
An interactive user interface displays "Appropriate Legal Notices" to the |
|||
extent that it includes a convenient and prominently visible feature that |
|||
(1) displays an appropriate copyright notice, and (2) tells the user that |
|||
there is no warranty for the work (except to the extent that warranties are |
|||
provided), that licensees may convey the work under this License, and how |
|||
to view a copy of this License. If the interface presents a list of user commands |
|||
or options, such as a menu, a prominent item in the list meets this criterion. |
|||
|
|||
1. Source Code. |
|||
|
|||
The "source code" for a work means the preferred form of the work for making |
|||
modifications to it. "Object code" means any non-source form of a work. |
|||
|
|||
A "Standard Interface" means an interface that either is an official standard |
|||
defined by a recognized standards body, or, in the case of interfaces specified |
|||
for a particular programming language, one that is widely used among developers |
|||
working in that language. |
|||
|
|||
The "System Libraries" of an executable work include anything, other than |
|||
the work as a whole, that (a) is included in the normal form of packaging |
|||
a Major Component, but which is not part of that Major Component, and (b) |
|||
serves only to enable use of the work with that Major Component, or to implement |
|||
a Standard Interface for which an implementation is available to the public |
|||
in source code form. A "Major Component", in this context, means a major essential |
|||
component (kernel, window system, and so on) of the specific operating system |
|||
(if any) on which the executable work runs, or a compiler used to produce |
|||
the work, or an object code interpreter used to run it. |
|||
|
|||
The "Corresponding Source" for a work in object code form means all the source |
|||
code needed to generate, install, and (for an executable work) run the object |
|||
code and to modify the work, including scripts to control those activities. |
|||
However, it does not include the work's System Libraries, or general-purpose |
|||
tools or generally available free programs which are used unmodified in performing |
|||
those activities but which are not part of the work. For example, Corresponding |
|||
Source includes interface definition files associated with source files for |
|||
the work, and the source code for shared libraries and dynamically linked |
|||
subprograms that the work is specifically designed to require, such as by |
|||
intimate data communication or control flow between those subprograms and |
|||
other parts of the work. |
|||
|
|||
The Corresponding Source need not include anything that users can regenerate |
|||
automatically from other parts of the Corresponding Source. |
|||
|
|||
The Corresponding Source for a work in source code form is that same work. |
|||
|
|||
2. Basic Permissions. |
|||
|
|||
All rights granted under this License are granted for the term of copyright |
|||
on the Program, and are irrevocable provided the stated conditions are met. |
|||
This License explicitly affirms your unlimited permission to run the unmodified |
|||
Program. The output from running a covered work is covered by this License |
|||
only if the output, given its content, constitutes a covered work. This License |
|||
acknowledges your rights of fair use or other equivalent, as provided by copyright |
|||
law. |
|||
|
|||
You may make, run and propagate covered works that you do not convey, without |
|||
conditions so long as your license otherwise remains in force. You may convey |
|||
covered works to others for the sole purpose of having them make modifications |
|||
exclusively for you, or provide you with facilities for running those works, |
|||
provided that you comply with the terms of this License in conveying all material |
|||
for which you do not control copyright. Those thus making or running the covered |
|||
works for you must do so exclusively on your behalf, under your direction |
|||
and control, on terms that prohibit them from making any copies of your copyrighted |
|||
material outside their relationship with you. |
|||
|
|||
Conveying under any other circumstances is permitted solely under the conditions |
|||
stated below. Sublicensing is not allowed; section 10 makes it unnecessary. |
|||
|
|||
3. Protecting Users' Legal Rights From Anti-Circumvention Law. |
|||
|
|||
No covered work shall be deemed part of an effective technological measure |
|||
under any applicable law fulfilling obligations under article 11 of the WIPO |
|||
copyright treaty adopted on 20 December 1996, or similar laws prohibiting |
|||
or restricting circumvention of such measures. |
|||
|
|||
When you convey a covered work, you waive any legal power to forbid circumvention |
|||
of technological measures to the extent such circumvention is effected by |
|||
exercising rights under this License with respect to the covered work, and |
|||
you disclaim any intention to limit operation or modification of the work |
|||
as a means of enforcing, against the work's users, your or third parties' |
|||
legal rights to forbid circumvention of technological measures. |
|||
|
|||
4. Conveying Verbatim Copies. |
|||
|
|||
You may convey verbatim copies of the Program's source code as you receive |
|||
it, in any medium, provided that you conspicuously and appropriately publish |
|||
on each copy an appropriate copyright notice; keep intact all notices stating |
|||
that this License and any non-permissive terms added in accord with section |
|||
7 apply to the code; keep intact all notices of the absence of any warranty; |
|||
and give all recipients a copy of this License along with the Program. |
|||
|
|||
You may charge any price or no price for each copy that you convey, and you |
|||
may offer support or warranty protection for a fee. |
|||
|
|||
5. Conveying Modified Source Versions. |
|||
|
|||
You may convey a work based on the Program, or the modifications to produce |
|||
it from the Program, in the form of source code under the terms of section |
|||
4, provided that you also meet all of these conditions: |
|||
|
|||
a) The work must carry prominent notices stating that you modified it, and |
|||
giving a relevant date. |
|||
|
|||
b) The work must carry prominent notices stating that it is released under |
|||
this License and any conditions added under section 7. This requirement modifies |
|||
the requirement in section 4 to "keep intact all notices". |
|||
|
|||
c) You must license the entire work, as a whole, under this License to anyone |
|||
who comes into possession of a copy. This License will therefore apply, along |
|||
with any applicable section 7 additional terms, to the whole of the work, |
|||
and all its parts, regardless of how they are packaged. This License gives |
|||
no permission to license the work in any other way, but it does not invalidate |
|||
such permission if you have separately received it. |
|||
|
|||
d) If the work has interactive user interfaces, each must display Appropriate |
|||
Legal Notices; however, if the Program has interactive interfaces that do |
|||
not display Appropriate Legal Notices, your work need not make them do so. |
|||
|
|||
A compilation of a covered work with other separate and independent works, |
|||
which are not by their nature extensions of the covered work, and which are |
|||
not combined with it such as to form a larger program, in or on a volume of |
|||
a storage or distribution medium, is called an "aggregate" if the compilation |
|||
and its resulting copyright are not used to limit the access or legal rights |
|||
of the compilation's users beyond what the individual works permit. Inclusion |
|||
of a covered work in an aggregate does not cause this License to apply to |
|||
the other parts of the aggregate. |
|||
|
|||
6. Conveying Non-Source Forms. |
|||
|
|||
You may convey a covered work in object code form under the terms of sections |
|||
4 and 5, provided that you also convey the machine-readable Corresponding |
|||
Source under the terms of this License, in one of these ways: |
|||
|
|||
a) Convey the object code in, or embodied in, a physical product (including |
|||
a physical distribution medium), accompanied by the Corresponding Source fixed |
|||
on a durable physical medium customarily used for software interchange. |
|||
|
|||
b) Convey the object code in, or embodied in, a physical product (including |
|||
a physical distribution medium), accompanied by a written offer, valid for |
|||
at least three years and valid for as long as you offer spare parts or customer |
|||
support for that product model, to give anyone who possesses the object code |
|||
either (1) a copy of the Corresponding Source for all the software in the |
|||
product that is covered by this License, on a durable physical medium customarily |
|||
used for software interchange, for a price no more than your reasonable cost |
|||
of physically performing this conveying of source, or (2) access to copy the |
|||
Corresponding Source from a network server at no charge. |
|||
|
|||
c) Convey individual copies of the object code with a copy of the written |
|||
offer to provide the Corresponding Source. This alternative is allowed only |
|||
occasionally and noncommercially, and only if you received the object code |
|||
with such an offer, in accord with subsection 6b. |
|||
|
|||
d) Convey the object code by offering access from a designated place (gratis |
|||
or for a charge), and offer equivalent access to the Corresponding Source |
|||
in the same way through the same place at no further charge. You need not |
|||
require recipients to copy the Corresponding Source along with the object |
|||
code. If the place to copy the object code is a network server, the Corresponding |
|||
Source may be on a different server (operated by you or a third party) that |
|||
supports equivalent copying facilities, provided you maintain clear directions |
|||
next to the object code saying where to find the Corresponding Source. Regardless |
|||
of what server hosts the Corresponding Source, you remain obligated to ensure |
|||
that it is available for as long as needed to satisfy these requirements. |
|||
|
|||
e) Convey the object code using peer-to-peer transmission, provided you inform |
|||
other peers where the object code and Corresponding Source of the work are |
|||
being offered to the general public at no charge under subsection 6d. |
|||
|
|||
A separable portion of the object code, whose source code is excluded from |
|||
the Corresponding Source as a System Library, need not be included in conveying |
|||
the object code work. |
|||
|
|||
A "User Product" is either (1) a "consumer product", which means any tangible |
|||
personal property which is normally used for personal, family, or household |
|||
purposes, or (2) anything designed or sold for incorporation into a dwelling. |
|||
In determining whether a product is a consumer product, doubtful cases shall |
|||
be resolved in favor of coverage. For a particular product received by a particular |
|||
user, "normally used" refers to a typical or common use of that class of product, |
|||
regardless of the status of the particular user or of the way in which the |
|||
particular user actually uses, or expects or is expected to use, the product. |
|||
A product is a consumer product regardless of whether the product has substantial |
|||
commercial, industrial or non-consumer uses, unless such uses represent the |
|||
only significant mode of use of the product. |
|||
|
|||
"Installation Information" for a User Product means any methods, procedures, |
|||
authorization keys, or other information required to install and execute modified |
|||
versions of a covered work in that User Product from a modified version of |
|||
its Corresponding Source. The information must suffice to ensure that the |
|||
continued functioning of the modified object code is in no case prevented |
|||
or interfered with solely because modification has been made. |
|||
|
|||
If you convey an object code work under this section in, or with, or specifically |
|||
for use in, a User Product, and the conveying occurs as part of a transaction |
|||
in which the right of possession and use of the User Product is transferred |
|||
to the recipient in perpetuity or for a fixed term (regardless of how the |
|||
transaction is characterized), the Corresponding Source conveyed under this |
|||
section must be accompanied by the Installation Information. But this requirement |
|||
does not apply if neither you nor any third party retains the ability to install |
|||
modified object code on the User Product (for example, the work has been installed |
|||
in ROM). |
|||
|
|||
The requirement to provide Installation Information does not include a requirement |
|||
to continue to provide support service, warranty, or updates for a work that |
|||
has been modified or installed by the recipient, or for the User Product in |
|||
which it has been modified or installed. Access to a network may be denied |
|||
when the modification itself materially and adversely affects the operation |
|||
of the network or violates the rules and protocols for communication across |
|||
the network. |
|||
|
|||
Corresponding Source conveyed, and Installation Information provided, in accord |
|||
with this section must be in a format that is publicly documented (and with |
|||
an implementation available to the public in source code form), and must require |
|||
no special password or key for unpacking, reading or copying. |
|||
|
|||
7. Additional Terms. |
|||
|
|||
"Additional permissions" are terms that supplement the terms of this License |
|||
by making exceptions from one or more of its conditions. Additional permissions |
|||
that are applicable to the entire Program shall be treated as though they |
|||
were included in this License, to the extent that they are valid under applicable |
|||
law. If additional permissions apply only to part of the Program, that part |
|||
may be used separately under those permissions, but the entire Program remains |
|||
governed by this License without regard to the additional permissions. |
|||
|
|||
When you convey a copy of a covered work, you may at your option remove any |
|||
additional permissions from that copy, or from any part of it. (Additional |
|||
permissions may be written to require their own removal in certain cases when |
|||
you modify the work.) You may place additional permissions on material, added |
|||
by you to a covered work, for which you have or can give appropriate copyright |
|||
permission. |
|||
|
|||
Notwithstanding any other provision of this License, for material you add |
|||
to a covered work, you may (if authorized by the copyright holders of that |
|||
material) supplement the terms of this License with terms: |
|||
|
|||
a) Disclaiming warranty or limiting liability differently from the terms of |
|||
sections 15 and 16 of this License; or |
|||
|
|||
b) Requiring preservation of specified reasonable legal notices or author |
|||
attributions in that material or in the Appropriate Legal Notices displayed |
|||
by works containing it; or |
|||
|
|||
c) Prohibiting misrepresentation of the origin of that material, or requiring |
|||
that modified versions of such material be marked in reasonable ways as different |
|||
from the original version; or |
|||
|
|||
d) Limiting the use for publicity purposes of names of licensors or authors |
|||
of the material; or |
|||
|
|||
e) Declining to grant rights under trademark law for use of some trade names, |
|||
trademarks, or service marks; or |
|||
|
|||
f) Requiring indemnification of licensors and authors of that material by |
|||
anyone who conveys the material (or modified versions of it) with contractual |
|||
assumptions of liability to the recipient, for any liability that these contractual |
|||
assumptions directly impose on those licensors and authors. |
|||
|
|||
All other non-permissive additional terms are considered "further restrictions" |
|||
within the meaning of section 10. If the Program as you received it, or any |
|||
part of it, contains a notice stating that it is governed by this License |
|||
along with a term that is a further restriction, you may remove that term. |
|||
If a license document contains a further restriction but permits relicensing |
|||
or conveying under this License, you may add to a covered work material governed |
|||
by the terms of that license document, provided that the further restriction |
|||
does not survive such relicensing or conveying. |
|||
|
|||
If you add terms to a covered work in accord with this section, you must place, |
|||
in the relevant source files, a statement of the additional terms that apply |
|||
to those files, or a notice indicating where to find the applicable terms. |
|||
|
|||
Additional terms, permissive or non-permissive, may be stated in the form |
|||
of a separately written license, or stated as exceptions; the above requirements |
|||
apply either way. |
|||
|
|||
8. Termination. |
|||
|
|||
You may not propagate or modify a covered work except as expressly provided |
|||
under this License. Any attempt otherwise to propagate or modify it is void, |
|||
and will automatically terminate your rights under this License (including |
|||
any patent licenses granted under the third paragraph of section 11). |
|||
|
|||
However, if you cease all violation of this License, then your license from |
|||
a particular copyright holder is reinstated (a) provisionally, unless and |
|||
until the copyright holder explicitly and finally terminates your license, |
|||
and (b) permanently, if the copyright holder fails to notify you of the violation |
|||
by some reasonable means prior to 60 days after the cessation. |
|||
|
|||
Moreover, your license from a particular copyright holder is reinstated permanently |
|||
if the copyright holder notifies you of the violation by some reasonable means, |
|||
this is the first time you have received notice of violation of this License |
|||
(for any work) from that copyright holder, and you cure the violation prior |
|||
to 30 days after your receipt of the notice. |
|||
|
|||
Termination of your rights under this section does not terminate the licenses |
|||
of parties who have received copies or rights from you under this License. |
|||
If your rights have been terminated and not permanently reinstated, you do |
|||
not qualify to receive new licenses for the same material under section 10. |
|||
|
|||
9. Acceptance Not Required for Having Copies. |
|||
|
|||
You are not required to accept this License in order to receive or run a copy |
|||
of the Program. Ancillary propagation of a covered work occurring solely as |
|||
a consequence of using peer-to-peer transmission to receive a copy likewise |
|||
does not require acceptance. However, nothing other than this License grants |
|||
you permission to propagate or modify any covered work. These actions infringe |
|||
copyright if you do not accept this License. Therefore, by modifying or propagating |
|||
a covered work, you indicate your acceptance of this License to do so. |
|||
|
|||
10. Automatic Licensing of Downstream Recipients. |
|||
|
|||
Each time you convey a covered work, the recipient automatically receives |
|||
a license from the original licensors, to run, modify and propagate that work, |
|||
subject to this License. You are not responsible for enforcing compliance |
|||
by third parties with this License. |
|||
|
|||
An "entity transaction" is a transaction transferring control of an organization, |
|||
or substantially all assets of one, or subdividing an organization, or merging |
|||
organizations. If propagation of a covered work results from an entity transaction, |
|||
each party to that transaction who receives a copy of the work also receives |
|||
whatever licenses to the work the party's predecessor in interest had or could |
|||
give under the previous paragraph, plus a right to possession of the Corresponding |
|||
Source of the work from the predecessor in interest, if the predecessor has |
|||
it or can get it with reasonable efforts. |
|||
|
|||
You may not impose any further restrictions on the exercise of the rights |
|||
granted or affirmed under this License. For example, you may not impose a |
|||
license fee, royalty, or other charge for exercise of rights granted under |
|||
this License, and you may not initiate litigation (including a cross-claim |
|||
or counterclaim in a lawsuit) alleging that any patent claim is infringed |
|||
by making, using, selling, offering for sale, or importing the Program or |
|||
any portion of it. |
|||
|
|||
11. Patents. |
|||
|
|||
A "contributor" is a copyright holder who authorizes use under this License |
|||
of the Program or a work on which the Program is based. The work thus licensed |
|||
is called the contributor's "contributor version". |
|||
|
|||
A contributor's "essential patent claims" are all patent claims owned or controlled |
|||
by the contributor, whether already acquired or hereafter acquired, that would |
|||
be infringed by some manner, permitted by this License, of making, using, |
|||
or selling its contributor version, but do not include claims that would be |
|||
infringed only as a consequence of further modification of the contributor |
|||
version. For purposes of this definition, "control" includes the right to |
|||
grant patent sublicenses in a manner consistent with the requirements of this |
|||
License. |
|||
|
|||
Each contributor grants you a non-exclusive, worldwide, royalty-free patent |
|||
license under the contributor's essential patent claims, to make, use, sell, |
|||
offer for sale, import and otherwise run, modify and propagate the contents |
|||
of its contributor version. |
|||
|
|||
In the following three paragraphs, a "patent license" is any express agreement |
|||
or commitment, however denominated, not to enforce a patent (such as an express |
|||
permission to practice a patent or covenant not to sue for patent infringement). |
|||
To "grant" such a patent license to a party means to make such an agreement |
|||
or commitment not to enforce a patent against the party. |
|||
|
|||
If you convey a covered work, knowingly relying on a patent license, and the |
|||
Corresponding Source of the work is not available for anyone to copy, free |
|||
of charge and under the terms of this License, through a publicly available |
|||
network server or other readily accessible means, then you must either (1) |
|||
cause the Corresponding Source to be so available, or (2) arrange to deprive |
|||
yourself of the benefit of the patent license for this particular work, or |
|||
(3) arrange, in a manner consistent with the requirements of this License, |
|||
to extend the patent license to downstream recipients. "Knowingly relying" |
|||
means you have actual knowledge that, but for the patent license, your conveying |
|||
the covered work in a country, or your recipient's use of the covered work |
|||
in a country, would infringe one or more identifiable patents in that country |
|||
that you have reason to believe are valid. |
|||
|
|||
If, pursuant to or in connection with a single transaction or arrangement, |
|||
you convey, or propagate by procuring conveyance of, a covered work, and grant |
|||
a patent license to some of the parties receiving the covered work authorizing |
|||
them to use, propagate, modify or convey a specific copy of the covered work, |
|||
then the patent license you grant is automatically extended to all recipients |
|||
of the covered work and works based on it. |
|||
|
|||
A patent license is "discriminatory" if it does not include within the scope |
|||
of its coverage, prohibits the exercise of, or is conditioned on the non-exercise |
|||
of one or more of the rights that are specifically granted under this License. |
|||
You may not convey a covered work if you are a party to an arrangement with |
|||
a third party that is in the business of distributing software, under which |
|||
you make payment to the third party based on the extent of your activity of |
|||
conveying the work, and under which the third party grants, to any of the |
|||
parties who would receive the covered work from you, a discriminatory patent |
|||
license (a) in connection with copies of the covered work conveyed by you |
|||
(or copies made from those copies), or (b) primarily for and in connection |
|||
with specific products or compilations that contain the covered work, unless |
|||
you entered into that arrangement, or that patent license was granted, prior |
|||
to 28 March 2007. |
|||
|
|||
Nothing in this License shall be construed as excluding or limiting any implied |
|||
license or other defenses to infringement that may otherwise be available |
|||
to you under applicable patent law. |
|||
|
|||
12. No Surrender of Others' Freedom. |
|||
|
|||
If conditions are imposed on you (whether by court order, agreement or otherwise) |
|||
that contradict the conditions of this License, they do not excuse you from |
|||
the conditions of this License. If you cannot convey a covered work so as |
|||
to satisfy simultaneously your obligations under this License and any other |
|||
pertinent obligations, then as a consequence you may not convey it at all. |
|||
For example, if you agree to terms that obligate you to collect a royalty |
|||
for further conveying from those to whom you convey the Program, the only |
|||
way you could satisfy both those terms and this License would be to refrain |
|||
entirely from conveying the Program. |
|||
|
|||
13. Use with the GNU Affero General Public License. |
|||
|
|||
Notwithstanding any other provision of this License, you have permission to |
|||
link or combine any covered work with a work licensed under version 3 of the |
|||
GNU Affero General Public License into a single combined work, and to convey |
|||
the resulting work. The terms of this License will continue to apply to the |
|||
part which is the covered work, but the special requirements of the GNU Affero |
|||
General Public License, section 13, concerning interaction through a network |
|||
will apply to the combination as such. |
|||
|
|||
14. Revised Versions of this License. |
|||
|
|||
The Free Software Foundation may publish revised and/or new versions of the |
|||
GNU General Public License from time to time. Such new versions will be similar |
|||
in spirit to the present version, but may differ in detail to address new |
|||
problems or concerns. |
|||
|
|||
Each version is given a distinguishing version number. If the Program specifies |
|||
that a certain numbered version of the GNU General Public License "or any |
|||
later version" applies to it, you have the option of following the terms and |
|||
conditions either of that numbered version or of any later version published |
|||
by the Free Software Foundation. If the Program does not specify a version |
|||
number of the GNU General Public License, you may choose any version ever |
|||
published by the Free Software Foundation. |
|||
|
|||
If the Program specifies that a proxy can decide which future versions of |
|||
the GNU General Public License can be used, that proxy's public statement |
|||
of acceptance of a version permanently authorizes you to choose that version |
|||
for the Program. |
|||
|
|||
Later license versions may give you additional or different permissions. However, |
|||
no additional obligations are imposed on any author or copyright holder as |
|||
a result of your choosing to follow a later version. |
|||
|
|||
15. Disclaimer of Warranty. |
|||
|
|||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE |
|||
LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR |
|||
OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER |
|||
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
|||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS |
|||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM |
|||
PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR |
|||
CORRECTION. |
|||
|
|||
16. Limitation of Liability. |
|||
|
|||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL |
|||
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM |
|||
AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, |
|||
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO |
|||
USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED |
|||
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE |
|||
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER |
|||
PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. |
|||
|
|||
17. Interpretation of Sections 15 and 16. |
|||
|
|||
If the disclaimer of warranty and limitation of liability provided above cannot |
|||
be given local legal effect according to their terms, reviewing courts shall |
|||
apply local law that most closely approximates an absolute waiver of all civil |
|||
liability in connection with the Program, unless a warranty or assumption |
|||
of liability accompanies a copy of the Program in return for a fee. END OF |
|||
TERMS AND CONDITIONS |
|||
|
|||
How to Apply These Terms to Your New Programs |
|||
|
|||
If you develop a new program, and you want it to be of the greatest possible |
|||
use to the public, the best way to achieve this is to make it free software |
|||
which everyone can redistribute and change under these terms. |
|||
|
|||
To do so, attach the following notices to the program. It is safest to attach |
|||
them to the start of each source file to most effectively state the exclusion |
|||
of warranty; and each file should have at least the "copyright" line and a |
|||
pointer to where the full notice is found. |
|||
|
|||
<one line to give the program's name and a brief idea of what it does.> |
|||
|
|||
Copyright (C) <year> <name of author> |
|||
|
|||
This program is free software: you can redistribute it and/or modify it under |
|||
the terms of the GNU General Public License as published by the Free Software |
|||
Foundation, either version 3 of the License, or (at your option) any later |
|||
version. |
|||
|
|||
This program is distributed in the hope that it will be useful, but WITHOUT |
|||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License along with |
|||
this program. If not, see <https://www.gnu.org/licenses/>. |
|||
|
|||
Also add information on how to contact you by electronic and paper mail. |
|||
|
|||
If the program does terminal interaction, make it output a short notice like |
|||
this when it starts in an interactive mode: |
|||
|
|||
<program> Copyright (C) <year> <name of author> |
|||
|
|||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
|||
|
|||
This is free software, and you are welcome to redistribute it under certain |
|||
conditions; type `show c' for details. |
|||
|
|||
The hypothetical commands `show w' and `show c' should show the appropriate |
|||
parts of the General Public License. Of course, your program's commands might |
|||
be different; for a GUI interface, you would use an "about box". |
|||
|
|||
You should also get your employer (if you work as a programmer) or school, |
|||
if any, to sign a "copyright disclaimer" for the program, if necessary. For |
|||
more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>. |
|||
|
|||
The GNU General Public License does not permit incorporating your program |
|||
into proprietary programs. If your program is a subroutine library, you may |
|||
consider it more useful to permit linking proprietary applications with the |
|||
library. If this is what you want to do, use the GNU Lesser General Public |
|||
License instead of this License. But first, please read <https://www.gnu.org/ |
|||
licenses /why-not-lgpl.html>. |
@ -0,0 +1,15 @@ |
|||
ISC License: |
|||
|
|||
Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC") |
|||
Copyright (c) 1995-2003 by Internet Software Consortium |
|||
|
|||
Permission to use, copy, modify, and/or distribute this software for any purpose |
|||
with or without fee is hereby granted, provided that the above copyright notice |
|||
and this permission notice appear in all copies. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD |
|||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. |
|||
IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
|||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
|||
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING |
|||
OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
@ -0,0 +1,21 @@ |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2013-2019 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. |
@ -0,0 +1,22 @@ |
|||
This is free and unencumbered software released into the public domain. |
|||
|
|||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute |
|||
this software, either in source code form or as a compiled binary, for any |
|||
purpose, commercial or non-commercial, and by any means. |
|||
|
|||
In jurisdictions that recognize copyright laws, the author or authors of this |
|||
software dedicate any and all copyright interest in the software to the public |
|||
domain. We make this dedication for the benefit of the public at large and |
|||
to the detriment of our heirs and |
|||
successors. We intend this dedication to be an overt act of relinquishment |
|||
in perpetuity of all present and future rights to this software under copyright |
|||
law. |
|||
|
|||
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 |
|||
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. |
|||
|
|||
For more information, please refer to <http://unlicense.org/> |
@ -0,0 +1,188 @@ |
|||
[![Build Status](https://travis-ci.org/micropython/micropython.png?branch=master)](https://travis-ci.org/micropython/micropython) [![Coverage Status](https://coveralls.io/repos/micropython/micropython/badge.png?branch=master)](https://coveralls.io/r/micropython/micropython?branch=master) |
|||
|
|||
The MicroPython project |
|||
======================= |
|||
<p align="center"> |
|||
<img src="https://raw.githubusercontent.com/micropython/micropython/master/logo/upython-with-micro.jpg" alt="MicroPython Logo"/> |
|||
</p> |
|||
|
|||
This is the MicroPython project, which aims to put an implementation |
|||
of Python 3.x on microcontrollers and small embedded systems. |
|||
You can find the official website at [micropython.org](http://www.micropython.org). |
|||
|
|||
WARNING: this project is in beta stage and is subject to changes of the |
|||
code-base, including project-wide name changes and API changes. |
|||
|
|||
MicroPython implements the entire Python 3.4 syntax (including exceptions, |
|||
`with`, `yield from`, etc., and additionally `async`/`await` keywords from |
|||
Python 3.5). The following core datatypes are provided: `str` (including |
|||
basic Unicode support), `bytes`, `bytearray`, `tuple`, `list`, `dict`, `set`, |
|||
`frozenset`, `array.array`, `collections.namedtuple`, classes and instances. |
|||
Builtin modules include `sys`, `time`, and `struct`, etc. Select ports have |
|||
support for `_thread` module (multithreading). Note that only a subset of |
|||
Python 3 functionality is implemented for the data types and modules. |
|||
|
|||
MicroPython can execute scripts in textual source form or from precompiled |
|||
bytecode, in both cases either from an on-device filesystem or "frozen" into |
|||
the MicroPython executable. |
|||
|
|||
See the repository http://github.com/micropython/pyboard for the MicroPython |
|||
board (PyBoard), the officially supported reference electronic circuit board. |
|||
|
|||
Major components in this repository: |
|||
- py/ -- the core Python implementation, including compiler, runtime, and |
|||
core library. |
|||
- mpy-cross/ -- the MicroPython cross-compiler which is used to turn scripts |
|||
into precompiled bytecode. |
|||
- ports/unix/ -- a version of MicroPython that runs on Unix. |
|||
- ports/stm32/ -- a version of MicroPython that runs on the PyBoard and similar |
|||
STM32 boards (using ST's Cube HAL drivers). |
|||
- ports/minimal/ -- a minimal MicroPython port. Start with this if you want |
|||
to port MicroPython to another microcontroller. |
|||
- tests/ -- test framework and test scripts. |
|||
- docs/ -- user documentation in Sphinx reStructuredText format. Rendered |
|||
HTML documentation is available at http://docs.micropython.org. |
|||
|
|||
Additional components: |
|||
- ports/bare-arm/ -- a bare minimum version of MicroPython for ARM MCUs. Used |
|||
mostly to control code size. |
|||
- ports/teensy/ -- a version of MicroPython that runs on the Teensy 3.1 |
|||
(preliminary but functional). |
|||
- ports/pic16bit/ -- a version of MicroPython for 16-bit PIC microcontrollers. |
|||
- ports/cc3200/ -- a version of MicroPython that runs on the CC3200 from TI. |
|||
- ports/esp8266/ -- a version of MicroPython that runs on Espressif's ESP8266 SoC. |
|||
- ports/esp32/ -- a version of MicroPython that runs on Espressif's ESP32 SoC. |
|||
- ports/nrf/ -- a version of MicroPython that runs on Nordic's nRF51 and nRF52 MCUs. |
|||
- extmod/ -- additional (non-core) modules implemented in C. |
|||
- tools/ -- various tools, including the pyboard.py module. |
|||
- examples/ -- a few example Python scripts. |
|||
|
|||
The subdirectories above may include READMEs with additional info. |
|||
|
|||
"make" is used to build the components, or "gmake" on BSD-based systems. |
|||
You will also need bash, gcc, and Python 3.3+ available as the command `python3` |
|||
(if your system only has Python 2.7 then invoke make with the additional option |
|||
`PYTHON=python2`). |
|||
|
|||
The MicroPython cross-compiler, mpy-cross |
|||
----------------------------------------- |
|||
|
|||
Most ports require the MicroPython cross-compiler to be built first. This |
|||
program, called mpy-cross, is used to pre-compile Python scripts to .mpy |
|||
files which can then be included (frozen) into the firmware/executable for |
|||
a port. To build mpy-cross use: |
|||
|
|||
$ cd mpy-cross |
|||
$ make |
|||
|
|||
The Unix version |
|||
---------------- |
|||
|
|||
The "unix" port requires a standard Unix environment with gcc and GNU make. |
|||
x86 and x64 architectures are supported (i.e. x86 32- and 64-bit), as well |
|||
as ARM and MIPS. Making full-featured port to another architecture requires |
|||
writing some assembly code for the exception handling and garbage collection. |
|||
Alternatively, fallback implementation based on setjmp/longjmp can be used. |
|||
|
|||
To build (see section below for required dependencies): |
|||
|
|||
$ cd ports/unix |
|||
$ make submodules |
|||
$ make |
|||
|
|||
Then to give it a try: |
|||
|
|||
$ ./micropython |
|||
>>> list(5 * x + y for x in range(10) for y in [4, 2, 1]) |
|||
|
|||
Use `CTRL-D` (i.e. EOF) to exit the shell. |
|||
Learn about command-line options (in particular, how to increase heap size |
|||
which may be needed for larger applications): |
|||
|
|||
$ ./micropython --help |
|||
|
|||
Run complete testsuite: |
|||
|
|||
$ make test |
|||
|
|||
Unix version comes with a builtin package manager called upip, e.g.: |
|||
|
|||
$ ./micropython -m upip install micropython-pystone |
|||
$ ./micropython -m pystone |
|||
|
|||
Browse available modules on |
|||
[PyPI](https://pypi.python.org/pypi?%3Aaction=search&term=micropython). |
|||
Standard library modules come from |
|||
[micropython-lib](https://github.com/micropython/micropython-lib) project. |
|||
|
|||
External dependencies |
|||
--------------------- |
|||
|
|||
Building MicroPython ports may require some dependencies installed. |
|||
|
|||
For Unix port, `libffi` library and `pkg-config` tool are required. On |
|||
Debian/Ubuntu/Mint derivative Linux distros, install `build-essential` |
|||
(includes toolchain and make), `libffi-dev`, and `pkg-config` packages. |
|||
|
|||
Other dependencies can be built together with MicroPython. This may |
|||
be required to enable extra features or capabilities, and in recent |
|||
versions of MicroPython, these may be enabled by default. To build |
|||
these additional dependencies, in the port directory you're |
|||
interested in (e.g. `ports/unix/`) first execute: |
|||
|
|||
$ make submodules |
|||
|
|||
This will fetch all the relevant git submodules (sub repositories) that |
|||
the port needs. Use the same command to get the latest versions of |
|||
submodules as they are updated from time to time. After that execute: |
|||
|
|||
$ make deplibs |
|||
|
|||
This will build all available dependencies (regardless whether they |
|||
are used or not). If you intend to build MicroPython with additional |
|||
options (like cross-compiling), the same set of options should be passed |
|||
to `make deplibs`. To actually enable/disable use of dependencies, edit |
|||
`ports/unix/mpconfigport.mk` file, which has inline descriptions of the options. |
|||
For example, to build SSL module (required for `upip` tool described above, |
|||
and so enabled by dfeault), `MICROPY_PY_USSL` should be set to 1. |
|||
|
|||
For some ports, building required dependences is transparent, and happens |
|||
automatically. But they still need to be fetched with the `make submodules` |
|||
command. |
|||
|
|||
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 |
|||
|
|||
To build: |
|||
|
|||
$ cd ports/stm32 |
|||
$ make submodules |
|||
$ make |
|||
|
|||
You then need to get your board into DFU mode. On the pyboard, connect the |
|||
3V3 pin to the P1/DFU pin with a wire (on PYBv1.0 they are next to each other |
|||
on the bottom left of the board, second row from the bottom). |
|||
|
|||
Then to flash the code via USB DFU to your device: |
|||
|
|||
$ make deploy |
|||
|
|||
This will use the included `tools/pydfu.py` script. If flashing the firmware |
|||
does not work it may be because you don't have the correct permissions, and |
|||
need to use `sudo make deploy`. |
|||
See the README.md file in the ports/stm32/ directory for further details. |
|||
|
|||
Contributing |
|||
------------ |
|||
|
|||
MicroPython is an open-source project and welcomes contributions. To be |
|||
productive, please be sure to follow the |
|||
[Contributors' Guidelines](https://github.com/micropython/micropython/wiki/ContributorGuidelines) |
|||
and the [Code Conventions](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md). |
|||
Note that MicroPython is licenced under the MIT license, and all contributions |
|||
should follow this license. |
@ -0,0 +1,13 @@ |
|||
# Passport Wallet |
|||
|
|||
Passport is an Ultra-secure, Open Source Hardware Wallet for Bitcoin that offers |
|||
excellent usability and a great design. |
|||
|
|||
Get yours at [FoundationDevices.com](https://foundationdevices.com) |
|||
|
|||
[Follow @FOUNDATIONdvcs on Twitter](https://twitter.com/FOUNDATIONdvcs) to keep up |
|||
with the latest updates and security alerts. |
|||
|
|||
![foundation logo](https://user-images.githubusercontent.com/62639971/100529265-99345380-319a-11eb-8ecc-195dd435edab.png) |
|||
|
|||
![passport picture](https://user-images.githubusercontent.com/62639971/100529305-07791600-319b-11eb-8a02-6b14f6060bd3.png) |
@ -0,0 +1,191 @@ |
|||
# Makefile for Sphinx documentation
|
|||
#
|
|||
|
|||
# You can set these variables from the command line.
|
|||
PYTHON = python3 |
|||
SPHINXOPTS = |
|||
SPHINXBUILD = sphinx-build |
|||
PAPER = |
|||
BUILDDIR = build/$(MICROPY_PORT) |
|||
CPYDIFFDIR = ../tools |
|||
CPYDIFF = gen-cpydiff.py |
|||
GENRSTDIR = genrst |
|||
# Run "make FORCE= ..." to avoid rebuilding from scratch (and risk
|
|||
# producing incorrect docs).
|
|||
FORCE = -E |
|||
|
|||
# User-friendly check for sphinx-build
|
|||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) |
|||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) |
|||
endif |
|||
|
|||
# Internal variables.
|
|||
PAPEROPT_a4 = -D latex_paper_size=a4 |
|||
PAPEROPT_letter = -D latex_paper_size=letter |
|||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . |
|||
# the i18n builder cannot share the environment and doctrees with the others
|
|||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . |
|||
|
|||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext |
|||
|
|||
help: |
|||
@echo "Please use \`make <target>' where <target> is one of" |
|||
@echo " html to make standalone HTML files" |
|||
@echo " dirhtml to make HTML files named index.html in directories" |
|||
@echo " singlehtml to make a single large HTML file" |
|||
@echo " pickle to make pickle files" |
|||
@echo " json to make JSON files" |
|||
@echo " htmlhelp to make HTML files and a HTML help project" |
|||
@echo " qthelp to make HTML files and a qthelp project" |
|||
@echo " devhelp to make HTML files and a Devhelp project" |
|||
@echo " epub to make an epub" |
|||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" |
|||
@echo " latexpdf to make LaTeX files and run them through pdflatex" |
|||
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" |
|||
@echo " text to make text files" |
|||
@echo " man to make manual pages" |
|||
@echo " texinfo to make Texinfo files" |
|||
@echo " info to make Texinfo files and run them through makeinfo" |
|||
@echo " gettext to make PO message catalogs" |
|||
@echo " changes to make an overview of all changed/added/deprecated items" |
|||
@echo " xml to make Docutils-native XML files" |
|||
@echo " pseudoxml to make pseudoxml-XML files for display purposes" |
|||
@echo " linkcheck to check all external links for integrity" |
|||
@echo " doctest to run all doctests embedded in the documentation (if enabled)" |
|||
@echo " cpydiff to generate the MicroPython differences from CPython" |
|||
|
|||
clean: |
|||
rm -rf $(BUILDDIR)/* |
|||
rm -f $(GENRSTDIR)/* |
|||
|
|||
cpydiff: |
|||
@echo "Generating MicroPython Differences." |
|||
rm -f $(GENRSTDIR)/* |
|||
cd $(CPYDIFFDIR) && $(PYTHON) $(CPYDIFF) |
|||
|
|||
html: cpydiff |
|||
$(SPHINXBUILD) $(FORCE) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html |
|||
@echo |
|||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html." |
|||
|
|||
dirhtml: |
|||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml |
|||
@echo |
|||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." |
|||
|
|||
singlehtml: |
|||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml |
|||
@echo |
|||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." |
|||
|
|||
pickle: |
|||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle |
|||
@echo |
|||
@echo "Build finished; now you can process the pickle files." |
|||
|
|||
json: |
|||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json |
|||
@echo |
|||
@echo "Build finished; now you can process the JSON files." |
|||
|
|||
htmlhelp: |
|||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp |
|||
@echo |
|||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
|||
".hhp project file in $(BUILDDIR)/htmlhelp." |
|||
|
|||
qthelp: |
|||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp |
|||
@echo |
|||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
|||
".qhcp project file in $(BUILDDIR)/qthelp, like this:" |
|||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/MicroPython.qhcp" |
|||
@echo "To view the help file:" |
|||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/MicroPython.qhc" |
|||
|
|||
devhelp: |
|||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp |
|||
@echo |
|||
@echo "Build finished." |
|||
@echo "To view the help file:" |
|||
@echo "# mkdir -p $$HOME/.local/share/devhelp/MicroPython" |
|||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/MicroPython" |
|||
@echo "# devhelp" |
|||
|
|||
epub: |
|||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub |
|||
@echo |
|||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub." |
|||
|
|||
latex: cpydiff |
|||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex |
|||
@echo |
|||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." |
|||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
|||
"(use \`make latexpdf' here to do that automatically)." |
|||
|
|||
latexpdf: cpydiff |
|||
$(SPHINXBUILD) $(FORCE) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex |
|||
@echo "Running LaTeX files through pdflatex..." |
|||
$(MAKE) -C $(BUILDDIR)/latex all-pdf |
|||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." |
|||
|
|||
latexpdfja: cpydiff |
|||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex |
|||
@echo "Running LaTeX files through platex and dvipdfmx..." |
|||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja |
|||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." |
|||
|
|||
text: |
|||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text |
|||
@echo |
|||
@echo "Build finished. The text files are in $(BUILDDIR)/text." |
|||
|
|||
man: |
|||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man |
|||
@echo |
|||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man." |
|||
|
|||
texinfo: |
|||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo |
|||
@echo |
|||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." |
|||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
|||
"(use \`make info' here to do that automatically)." |
|||
|
|||
info: |
|||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo |
|||
@echo "Running Texinfo files through makeinfo..." |
|||
make -C $(BUILDDIR)/texinfo info |
|||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." |
|||
|
|||
gettext: |
|||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale |
|||
@echo |
|||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." |
|||
|
|||
changes: |
|||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes |
|||
@echo |
|||
@echo "The overview file is in $(BUILDDIR)/changes." |
|||
|
|||
linkcheck: |
|||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck |
|||
@echo |
|||
@echo "Link check complete; look for any errors in the above output " \
|
|||
"or in $(BUILDDIR)/linkcheck/output.txt." |
|||
|
|||
doctest: |
|||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest |
|||
@echo "Testing of doctests in the sources finished, look at the " \
|
|||
"results in $(BUILDDIR)/doctest/output.txt." |
|||
|
|||
xml: |
|||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml |
|||
@echo |
|||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml." |
|||
|
|||
pseudoxml: |
|||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml |
|||
@echo |
|||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." |
@ -0,0 +1,38 @@ |
|||
MicroPython Documentation |
|||
========================= |
|||
|
|||
The MicroPython documentation can be found at: |
|||
http://docs.micropython.org/en/latest/ |
|||
|
|||
The documentation you see there is generated from the files in the docs tree: |
|||
https://github.com/micropython/micropython/tree/master/docs |
|||
|
|||
Building the documentation locally |
|||
---------------------------------- |
|||
|
|||
If you're making changes to the documentation, you may want to build the |
|||
documentation locally so that you can preview your changes. |
|||
|
|||
Install Sphinx, and optionally (for the RTD-styling), sphinx_rtd_theme, |
|||
preferably in a virtualenv: |
|||
|
|||
pip install sphinx |
|||
pip install sphinx_rtd_theme |
|||
|
|||
In `micropython/docs`, build the docs: |
|||
|
|||
make html |
|||
|
|||
You'll find the index page at `micropython/docs/build/html/index.html`. |
|||
|
|||
PDF manual generation |
|||
--------------------- |
|||
|
|||
This can be achieved with: |
|||
|
|||
make latexpdf |
|||
|
|||
but require rather complete install of LaTeX with various extensions. On |
|||
Debian/Ubuntu, try (500MB+ download): |
|||
|
|||
apt-get install texlive-latex-recommended texlive-latex-extra |
@ -0,0 +1,301 @@ |
|||
#!/usr/bin/env python3 |
|||
# -*- coding: utf-8 -*- |
|||
# |
|||
# MicroPython documentation build configuration file, created by |
|||
# sphinx-quickstart on Sun Sep 21 11:42:03 2014. |
|||
# |
|||
# This file is execfile()d with the current directory set to its |
|||
# containing dir. |
|||
# |
|||
# Note that not all possible configuration values are present in this |
|||
# autogenerated file. |
|||
# |
|||
# All configuration values have a default; values that are commented out |
|||
# serve to show the default. |
|||
|
|||
import sys |
|||
import os |
|||
|
|||
# If extensions (or modules to document with autodoc) are in another directory, |
|||
# add these directories to sys.path here. If the directory is relative to the |
|||
# documentation root, use os.path.abspath to make it absolute, like shown here. |
|||
sys.path.insert(0, os.path.abspath('.')) |
|||
|
|||
# The members of the html_context dict are available inside topindex.html |
|||
micropy_version = os.getenv('MICROPY_VERSION') or 'latest' |
|||
micropy_all_versions = (os.getenv('MICROPY_ALL_VERSIONS') or 'latest').split(',') |
|||
url_pattern = '%s/en/%%s' % (os.getenv('MICROPY_URL_PREFIX') or '/',) |
|||
html_context = { |
|||
'cur_version':micropy_version, |
|||
'all_versions':[ |
|||
(ver, url_pattern % ver) for ver in micropy_all_versions |
|||
], |
|||
'downloads':[ |
|||
('PDF', url_pattern % micropy_version + '/micropython-docs.pdf'), |
|||
], |
|||
} |
|||
|
|||
|
|||
# -- General configuration ------------------------------------------------ |
|||
|
|||
# If your documentation needs a minimal Sphinx version, state it here. |
|||
#needs_sphinx = '1.0' |
|||
|
|||
# Add any Sphinx extension module names here, as strings. They can be |
|||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom |
|||
# ones. |
|||
extensions = [ |
|||
'sphinx.ext.autodoc', |
|||
'sphinx.ext.doctest', |
|||
'sphinx.ext.intersphinx', |
|||
'sphinx.ext.todo', |
|||
'sphinx.ext.coverage', |
|||
] |
|||
|
|||
# Add any paths that contain templates here, relative to this directory. |
|||
templates_path = ['templates'] |
|||
|
|||
# The suffix of source filenames. |
|||
source_suffix = '.rst' |
|||
|
|||
# The encoding of source files. |
|||
#source_encoding = 'utf-8-sig' |
|||
|
|||
# The master toctree document. |
|||
master_doc = 'index' |
|||
|
|||
# General information about the project. |
|||
project = 'MicroPython' |
|||
copyright = '2014-2019, Damien P. George, Paul Sokolovsky, and contributors' |
|||
|
|||
# The version info for the project you're documenting, acts as replacement for |
|||
# |version| and |release|, also used in various other places throughout the |
|||
# built documents. |
|||
# |
|||
# 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.12' |
|||
|
|||
# The language for content autogenerated by Sphinx. Refer to documentation |
|||
# for a list of supported languages. |
|||
#language = None |
|||
|
|||
# There are two options for replacing |today|: either, you set today to some |
|||
# non-false value, then it is used: |
|||
#today = '' |
|||
# Else, today_fmt is used as the format for a strftime call. |
|||
#today_fmt = '%B %d, %Y' |
|||
|
|||
# List of patterns, relative to source directory, that match files and |
|||
# directories to ignore when looking for source files. |
|||
exclude_patterns = ['build', '.venv'] |
|||
|
|||
# The reST default role (used for this markup: `text`) to use for all |
|||
# documents. |
|||
default_role = 'any' |
|||
|
|||
# If true, '()' will be appended to :func: etc. cross-reference text. |
|||
#add_function_parentheses = True |
|||
|
|||
# If true, the current module name will be prepended to all description |
|||
# unit titles (such as .. function::). |
|||
#add_module_names = True |
|||
|
|||
# If true, sectionauthor and moduleauthor directives will be shown in the |
|||
# output. They are ignored by default. |
|||
#show_authors = False |
|||
|
|||
# The name of the Pygments (syntax highlighting) style to use. |
|||
pygments_style = 'sphinx' |
|||
|
|||
# A list of ignored prefixes for module index sorting. |
|||
#modindex_common_prefix = [] |
|||
|
|||
# If true, keep warnings as "system message" paragraphs in the built documents. |
|||
#keep_warnings = False |
|||
|
|||
# Global include files. Sphinx docs suggest using rst_epilog in preference |
|||
# of rst_prolog, so we follow. Absolute paths below mean "from the base |
|||
# of the doctree". |
|||
rst_epilog = """ |
|||
.. include:: /templates/replace.inc |
|||
""" |
|||
|
|||
# -- Options for HTML output ---------------------------------------------- |
|||
|
|||
# on_rtd is whether we are on readthedocs.org |
|||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True' |
|||
|
|||
if not on_rtd: # only import and set the theme if we're building docs locally |
|||
try: |
|||
import sphinx_rtd_theme |
|||
html_theme = 'sphinx_rtd_theme' |
|||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.'] |
|||
except: |
|||
html_theme = 'default' |
|||
html_theme_path = ['.'] |
|||
else: |
|||
html_theme_path = ['.'] |
|||
|
|||
# Theme options are theme-specific and customize the look and feel of a theme |
|||
# further. For a list of options available for each theme, see the |
|||
# documentation. |
|||
#html_theme_options = {} |
|||
|
|||
# Add any paths that contain custom themes here, relative to this directory. |
|||
# html_theme_path = ['.'] |
|||
|
|||
# The name for this set of Sphinx documents. If None, it defaults to |
|||
# "<project> v<release> documentation". |
|||
#html_title = None |
|||
|
|||
# A shorter title for the navigation bar. Default is the same as html_title. |
|||
#html_short_title = None |
|||
|
|||
# The name of an image file (relative to this directory) to place at the top |
|||
# of the sidebar. |
|||
#html_logo = '../../logo/trans-logo.png' |
|||
|
|||
# The name of an image file (within the static path) to use as favicon of the |
|||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 |
|||
# pixels large. |
|||
html_favicon = 'static/favicon.ico' |
|||
|
|||
# Add any paths that contain custom static files (such as style sheets) here, |
|||
# relative to this directory. They are copied after the builtin static files, |
|||
# so a file named "default.css" will overwrite the builtin "default.css". |
|||
html_static_path = ['static'] |
|||
|
|||
# Add any extra paths that contain custom files (such as robots.txt or |
|||
# .htaccess) here, relative to this directory. These files are copied |
|||
# directly to the root of the documentation. |
|||
#html_extra_path = [] |
|||
|
|||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, |
|||
# using the given strftime format. |
|||
html_last_updated_fmt = '%d %b %Y' |
|||
|
|||
# If true, SmartyPants will be used to convert quotes and dashes to |
|||
# typographically correct entities. |
|||
#html_use_smartypants = True |
|||
|
|||
# Custom sidebar templates, maps document names to template names. |
|||
#html_sidebars = {} |
|||
|
|||
# Additional templates that should be rendered to pages, maps page names to |
|||
# template names. |
|||
html_additional_pages = {"index": "topindex.html"} |
|||
|
|||
# If false, no module index is generated. |
|||
#html_domain_indices = True |
|||
|
|||
# If false, no index is generated. |
|||
#html_use_index = True |
|||
|
|||
# If true, the index is split into individual pages for each letter. |
|||
#html_split_index = False |
|||
|
|||
# If true, links to the reST sources are added to the pages. |
|||
#html_show_sourcelink = True |
|||
|
|||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. |
|||
#html_show_sphinx = True |
|||
|
|||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. |
|||
#html_show_copyright = True |
|||
|
|||
# If true, an OpenSearch description file will be output, and all pages will |
|||
# contain a <link> tag referring to it. The value of this option must be the |
|||
# base URL from which the finished HTML is served. |
|||
#html_use_opensearch = '' |
|||
|
|||
# This is the file name suffix for HTML files (e.g. ".xhtml"). |
|||
#html_file_suffix = None |
|||
|
|||
# Output file base name for HTML help builder. |
|||
htmlhelp_basename = 'MicroPythondoc' |
|||
|
|||
|
|||
# -- Options for LaTeX output --------------------------------------------- |
|||
|
|||
latex_elements = { |
|||
# The paper size ('letterpaper' or 'a4paper'). |
|||
#'papersize': 'letterpaper', |
|||
|
|||
# The font size ('10pt', '11pt' or '12pt'). |
|||
#'pointsize': '10pt', |
|||
|
|||
# Additional stuff for the LaTeX preamble. |
|||
#'preamble': '', |
|||
# Include 3 levels of headers in PDF ToC |
|||
'preamble': '\setcounter{tocdepth}{2}', |
|||
} |
|||
|
|||
# Grouping the document tree into LaTeX files. List of tuples |
|||
# (source start file, target name, title, |
|||
# author, documentclass [howto, manual, or own class]). |
|||
latex_documents = [ |
|||
(master_doc, 'MicroPython.tex', 'MicroPython Documentation', |
|||
'Damien P. George, Paul Sokolovsky, and contributors', 'manual'), |
|||
] |
|||
|
|||
# The name of an image file (relative to this directory) to place at the top of |
|||
# the title page. |
|||
#latex_logo = None |
|||
|
|||
# For "manual" documents, if this is true, then toplevel headings are parts, |
|||
# not chapters. |
|||
#latex_use_parts = False |
|||
|
|||
# If true, show page references after internal links. |
|||
#latex_show_pagerefs = False |
|||
|
|||
# If true, show URL addresses after external links. |
|||
#latex_show_urls = False |
|||
|
|||
# Documents to append as an appendix to all manuals. |
|||
#latex_appendices = [] |
|||
|
|||
# If false, no module index is generated. |
|||
#latex_domain_indices = True |
|||
|
|||
|
|||
# -- Options for manual page output --------------------------------------- |
|||
|
|||
# One entry per manual page. List of tuples |
|||
# (source start file, name, description, authors, manual section). |
|||
man_pages = [ |
|||
('index', 'micropython', 'MicroPython Documentation', |
|||
['Damien P. George, Paul Sokolovsky, and contributors'], 1), |
|||
] |
|||
|
|||
# If true, show URL addresses after external links. |
|||
#man_show_urls = False |
|||
|
|||
|
|||
# -- Options for Texinfo output ------------------------------------------- |
|||
|
|||
# Grouping the document tree into Texinfo files. List of tuples |
|||
# (source start file, target name, title, author, |
|||
# dir menu entry, description, category) |
|||
texinfo_documents = [ |
|||
(master_doc, 'MicroPython', 'MicroPython Documentation', |
|||
'Damien P. George, Paul Sokolovsky, and contributors', 'MicroPython', 'One line description of project.', |
|||
'Miscellaneous'), |
|||
] |
|||
|
|||
# Documents to append as an appendix to all manuals. |
|||
#texinfo_appendices = [] |
|||
|
|||
# If false, no module index is generated. |
|||
#texinfo_domain_indices = True |
|||
|
|||
# How to display URL addresses: 'footnote', 'no', or 'inline'. |
|||
#texinfo_show_urls = 'footnote' |
|||
|
|||
# If true, do not generate a @detailmenu in the "Top" node's menu. |
|||
#texinfo_no_detailmenu = False |
|||
|
|||
|
|||
# Example configuration for intersphinx: refer to the Python standard library. |
|||
intersphinx_mapping = {'python': ('https://docs.python.org/3.5', None)} |
@ -0,0 +1,180 @@ |
|||
.. _cmodules: |
|||
|
|||
MicroPython external C modules |
|||
============================== |
|||
|
|||
When developing modules for use with MicroPython you may find you run into |
|||
limitations with the Python environment, often due to an inability to access |
|||
certain hardware resources or Python speed limitations. |
|||
|
|||
If your limitations can't be resolved with suggestions in :ref:`speed_python`, |
|||
writing some or all of your module in C is a viable option. |
|||
|
|||
If your module is designed to access or work with commonly available |
|||
hardware or libraries please consider implementing it inside the MicroPython |
|||
source tree alongside similar modules and submitting it as a pull request. |
|||
If however you're targeting obscure or proprietary systems it may make |
|||
more sense to keep this external to the main MicroPython repository. |
|||
|
|||
This chapter describes how to compile such external modules into the |
|||
MicroPython executable or firmware image. |
|||
|
|||
An alternative approach is to use :ref:`natmod` which allows writing custom C |
|||
code that is placed in a .mpy file, which can be imported dynamically in to |
|||
a running MicroPython system without the need to recompile the main firmware. |
|||
|
|||
|
|||
Structure of an external C module |
|||
--------------------------------- |
|||
|
|||
A MicroPython user C module is a directory with the following files: |
|||
|
|||
* ``*.c`` and/or ``*.h`` source code files for your module. |
|||
|
|||
These will typically include the low level functionality being implemented and |
|||
the MicroPython binding functions to expose the functions and module(s). |
|||
|
|||
Currently the best reference for writing these functions/modules is |
|||
to find similar modules within the MicroPython tree and use them as examples. |
|||
|
|||
* ``micropython.mk`` contains the Makefile fragment for this module. |
|||
|
|||
``$(USERMOD_DIR)`` is available in ``micropython.mk`` as the path to your |
|||
module directory. As it's redefined for each c module, is should be expanded |
|||
in your ``micropython.mk`` to a local make variable, |
|||
eg ``EXAMPLE_MOD_DIR := $(USERMOD_DIR)`` |
|||
|
|||
Your ``micropython.mk`` must add your modules C files relative to your |
|||
expanded copy of ``$(USERMOD_DIR)`` to ``SRC_USERMOD``, eg |
|||
``SRC_USERMOD += $(EXAMPLE_MOD_DIR)/example.c`` |
|||
|
|||
If you have custom ``CFLAGS`` settings or include folders to define, these |
|||
should be added to ``CFLAGS_USERMOD``. |
|||
|
|||
See below for full usage example. |
|||
|
|||
|
|||
Basic Example |
|||
------------- |
|||
|
|||
This simple module named ``example`` provides a single function |
|||
``example.add_ints(a, b)`` which adds the two integer args together and returns |
|||
the result. |
|||
|
|||
Directory:: |
|||
|
|||
example/ |
|||
├── example.c |
|||
└── micropython.mk |
|||
|
|||
|
|||
``example.c`` |
|||
|
|||
.. code-block:: c |
|||
|
|||
// Include required definitions first. |
|||
#include "py/obj.h" |
|||
#include "py/runtime.h" |
|||
#include "py/builtin.h" |
|||
|
|||
// This is the function which will be called from Python as example.add_ints(a, b). |
|||
STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) { |
|||
// Extract the ints from the micropython input objects |
|||
int a = mp_obj_get_int(a_obj); |
|||
int b = mp_obj_get_int(b_obj); |
|||
|
|||
// Calculate the addition and convert to MicroPython object. |
|||
return mp_obj_new_int(a + b); |
|||
} |
|||
// Define a Python reference to the function above |
|||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints); |
|||
|
|||
// Define all properties of the example module. |
|||
// Table entries are key/value pairs of the attribute name (a string) |
|||
// and the MicroPython object reference. |
|||
// All identifiers and strings are written as MP_QSTR_xxx and will be |
|||
// optimized to word-sized integers by the build system (interned strings). |
|||
STATIC const mp_rom_map_elem_t example_module_globals_table[] = { |
|||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example) }, |
|||
{ MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) }, |
|||
}; |
|||
STATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table); |
|||
|
|||
// Define module object. |
|||
const mp_obj_module_t example_user_cmodule = { |
|||
.base = { &mp_type_module }, |
|||
.globals = (mp_obj_dict_t*)&example_module_globals, |
|||
}; |
|||
|
|||
// Register the module to make it available in Python |
|||
MP_REGISTER_MODULE(MP_QSTR_example, example_user_cmodule, MODULE_EXAMPLE_ENABLED); |
|||
|
|||
|
|||
``micropython.mk`` |
|||
|
|||
.. code-block:: make |
|||
|
|||
EXAMPLE_MOD_DIR := $(USERMOD_DIR) |
|||
|
|||
# Add all C files to SRC_USERMOD. |
|||
SRC_USERMOD += $(EXAMPLE_MOD_DIR)/example.c |
|||
|
|||
# We can add our module folder to include paths if needed |
|||
# This is not actually needed in this example. |
|||
CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR) |
|||
|
|||
Finally you will need to define ``MODULE_EXAMPLE_ENABLED`` to 1. This |
|||
can be done by adding ``CFLAGS_EXTRA=-DMODULE_EXAMPLE_ENABLED=1`` to |
|||
the ``make`` command, or editing ``mpconfigport.h`` or |
|||
``mpconfigboard.h`` to add |
|||
|
|||
.. code-block:: c |
|||
|
|||
#define MODULE_EXAMPLE_ENABLED (1) |
|||
|
|||
Note that the exact method depends on the port as they have different |
|||
structures. If not done correctly it will compile but importing will |
|||
fail to find the module. |
|||
|
|||
|
|||
Compiling the cmodule into MicroPython |
|||
-------------------------------------- |
|||
|
|||
To build such a module, compile MicroPython (see `getting started |
|||
<https://github.com/micropython/micropython/wiki/Getting-Started>`_) with an |
|||
extra ``make`` flag named ``USER_C_MODULES`` set to the directory containing |
|||
all modules you want included (not to the module itself). For example: |
|||
|
|||
|
|||
Directory:: |
|||
|
|||
my_project/ |
|||
├── modules/ |
|||
│ └──example/ |
|||
│ ├──example.c |
|||
│ └──micropython.mk |
|||
└── micropython/ |
|||
├──ports/ |
|||
... ├──stm32/ |
|||
... |
|||
|
|||
Building for stm32 port: |
|||
|
|||
.. code-block:: bash |
|||
|
|||
cd my_project/micropython/ports/stm32 |
|||
make USER_C_MODULES=../../../modules CFLAGS_EXTRA=-DMODULE_EXAMPLE_ENABLED=1 all |
|||
|
|||
|
|||
Module usage in MicroPython |
|||
--------------------------- |
|||
|
|||
Once built into your copy of MicroPython, the module implemented |
|||
in ``example.c`` above can now be accessed in Python just |
|||
like any other builtin module, eg |
|||
|
|||
.. code-block:: python |
|||
|
|||
import example |
|||
print(example.add_ints(1, 3)) |
|||
# should display 4 |
@ -0,0 +1,14 @@ |
|||
Developing and building MicroPython |
|||
=================================== |
|||
|
|||
This chapter describes some options for extending MicroPython in C. Note |
|||
that it doesn't aim to be a complete guide for developing with MicroPython. |
|||
See the `getting started guide |
|||
<https://github.com/micropython/micropython/wiki/Getting-Started>`_ for further information. |
|||
|
|||
.. toctree:: |
|||
:maxdepth: 1 |
|||
|
|||
cmodules.rst |
|||
qstr.rst |
|||
natmod.rst |
@ -0,0 +1,202 @@ |
|||
.. _natmod: |
|||
|
|||
Native machine code in .mpy files |
|||
================================= |
|||
|
|||
This section describes how to build and work with .mpy files that contain native |
|||
machine code from a language other than Python. This allows you to |
|||
write code in a language like C, compile and link it into a .mpy file, and then |
|||
import this file like a normal Python module. This can be used for implementing |
|||
functionality which is performance critical, or for including an existing |
|||
library written in another language. |
|||
|
|||
One of the main advantages of using native .mpy files is that native machine code |
|||
can be imported by a script dynamically, without the need to rebuild the main |
|||
MicroPython firmware. This is in contrast to :ref:`cmodules` which also allows |
|||
defining custom modules in C but they must be compiled into the main firmware image. |
|||
|
|||
The focus here is on using C to build native modules, but in principle any |
|||
language which can be compiled to stand-alone machine code can be put into a |
|||
.mpy file. |
|||
|
|||
A native .mpy module is built using the ``mpy_ld.py`` tool, which is found in the |
|||
``tools/`` directory of the project. This tool takes a set of object files |
|||
(.o files) and links them together to create a native .mpy files. |
|||
|
|||
Supported features and limitations |
|||
---------------------------------- |
|||
|
|||
A .mpy file can contain MicroPython bytecode and/or native machine code. If it |
|||
contains native machine code then the .mpy file has a specific architecture |
|||
associated with it. Current supported architectures are (these are the valid |
|||
options for the ``ARCH`` variable, see below): |
|||
|
|||
* ``x86`` (32 bit) |
|||
* ``x64`` (64 bit x86) |
|||
* ``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) |
|||
* ``xtensa`` (non-windowed, eg ESP8266) |
|||
* ``xtensawin`` (windowed with window size 8, eg ESP32) |
|||
|
|||
When compiling and linking the native .mpy file the architecture must be chosen |
|||
and the corresponding file can only be imported on that architecture. For more |
|||
details about .mpy files see :ref:`mpy_files`. |
|||
|
|||
Native code must be compiled as position independent code (PIC) and use a global |
|||
offset table (GOT), although the details of this varies from architecture to |
|||
architecture. When importing .mpy files with native code the import machinery |
|||
is able to do some basic relocation of the native code. This includes |
|||
relocating text, rodata and BSS sections. |
|||
|
|||
Supported features of the linker and dynamic loader are: |
|||
|
|||
* executable code (text) |
|||
* read-only data (rodata), including strings and constant data (arrays, structs, etc) |
|||
* zeroed data (BSS) |
|||
* pointers in text to text, rodata and BSS |
|||
* pointers in rodata to text, rodata and BSS |
|||
|
|||
The known limitations are: |
|||
|
|||
* data sections are not supported; workaround: use BSS data and initialise the |
|||
data values explicitly |
|||
|
|||
* static BSS variables are not supported; workaround: use global BSS variables |
|||
|
|||
So, if your C code has writable data, make sure the data is defined globally, |
|||
without an initialiser, and only written to within functions. |
|||
|
|||
Defining a native module |
|||
------------------------ |
|||
|
|||
A native .mpy module is defined by a set of files that are used to build the .mpy. |
|||
The filesystem layout consists of two main parts, the source files and the Makefile: |
|||
|
|||
* In the simplest case only a single C source file is required, which contains all |
|||
the code that will be compiled into the .mpy module. This C source code must |
|||
include the ``py/dynruntime.h`` file to access the MicroPython dynamic API, and |
|||
must at least define a function called ``mpy_init``. This function will be the |
|||
entry point of the module, called when the module is imported. |
|||
|
|||
The module can be split into multiple C source files if desired. Parts of the |
|||
module can also be implemented in Python. All source files should be listed in |
|||
the Makefile, by adding them to the ``SRC`` variable (see below). This includes |
|||
both C source files as well as any Python files which will be included in the |
|||
resulting .mpy file. |
|||
|
|||
* The ``Makefile`` contains the build configuration for the module and list the |
|||
source files used to build the .mpy module. It should define ``MPY_DIR`` as the |
|||
location of the MicroPython repository (to find header files, the relevant Makefile |
|||
fragment, and the ``mpy_ld.py`` tool), ``MOD`` as the name of the module, ``SRC`` |
|||
as the list of source files, optionally specify the machine architecture via ``ARCH``, |
|||
and then include ``py/dynruntime.mk``. |
|||
|
|||
Minimal example |
|||
--------------- |
|||
|
|||
This section provides a fully working example of a simple module named ``factorial``. |
|||
This module provides a single function ``factorial.factorial(x)`` which computes the |
|||
factorial of the input and returns the result. |
|||
|
|||
Directory layout:: |
|||
|
|||
factorial/ |
|||
├── factorial.c |
|||
└── Makefile |
|||
|
|||
The file ``factorial.c`` contains: |
|||
|
|||
.. code-block:: c |
|||
|
|||
// Include the header file to get access to the MicroPython API |
|||
#include "py/dynruntime.h" |
|||
|
|||
// Helper function to compute factorial |
|||
STATIC mp_int_t factorial_helper(mp_int_t x) { |
|||
if (x == 0) { |
|||
return 1; |
|||
} |
|||
return x * factorial_helper(x - 1); |
|||
} |
|||
|
|||
// This is the function which will be called from Python, as factorial(x) |
|||
STATIC mp_obj_t factorial(mp_obj_t x_obj) { |
|||
// Extract the integer from the MicroPython input object |
|||
mp_int_t x = mp_obj_get_int(x_obj); |
|||
// Calculate the factorial |
|||
mp_int_t result = factorial_helper(x); |
|||
// Convert the result to a MicroPython integer object and return it |
|||
return mp_obj_new_int(result); |
|||
} |
|||
// Define a Python reference to the function above |
|||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial); |
|||
|
|||
// 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 function available in the module's namespace |
|||
mp_store_global(MP_QSTR_factorial, MP_OBJ_FROM_PTR(&factorial_obj)); |
|||
|
|||
// This must be last, it restores the globals dict |
|||
MP_DYNRUNTIME_INIT_EXIT |
|||
} |
|||
|
|||
The file ``Makefile`` contains: |
|||
|
|||
.. code-block:: make |
|||
|
|||
# Location of top-level MicroPython directory |
|||
MPY_DIR = ../../.. |
|||
|
|||
# Name of module |
|||
MOD = features0 |
|||
|
|||
# Source files (.c or .py) |
|||
SRC = features0.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 |
|||
|
|||
Compiling the module |
|||
-------------------- |
|||
|
|||
Be sure to select the correct ``ARCH`` for the target you are going to run on. |
|||
Then build with:: |
|||
|
|||
$ make |
|||
|
|||
Without modifying the Makefile you can specify the target architecture via:: |
|||
|
|||
$ make ARCH=armv7m |
|||
|
|||
Module usage in MicroPython |
|||
--------------------------- |
|||
|
|||
Once the module is built there should be a file called ``factorial.mpy``. Copy |
|||
this so it is accessible on the filesystem of your MicroPython system and can be |
|||
found in the import path. The module con now be accessed in Python just like any |
|||
other module, for example:: |
|||
|
|||
import factorial |
|||
print(factorial.factorial(10)) |
|||
# should display 3628800 |
|||
|
|||
Further examples |
|||
---------------- |
|||
|
|||
See ``examples/natmod/`` for further examples which show many of the available |
|||
features of native .mpy modules. Such features include: |
|||
|
|||
* using multiple C source files |
|||
* including Python code alongside C code |
|||
* rodata and BSS data |
|||
* memory allocation |
|||
* use of floating point |
|||
* exception handling |
|||
* including external C libraries |
@ -0,0 +1,112 @@ |
|||
MicroPython string interning |
|||
============================ |
|||
|
|||
MicroPython uses `string interning`_ to save both RAM and ROM. This avoids |
|||
having to store duplicate copies of the same string. Primarily, this applies to |
|||
identifiers in your code, as something like a function or variable name is very |
|||
likely to appear in multiple places in the code. In MicroPython an interned |
|||
string is called a QSTR (uniQue STRing). |
|||
|
|||
A QSTR value (with type ``qstr``) is a index into a linked list of QSTR pools. |
|||
QSTRs store their length and a hash of their contents for fast comparison during |
|||
the de-duplication process. All bytecode operations that work with strings use |
|||
a QSTR argument. |
|||
|
|||
Compile-time QSTR generation |
|||
---------------------------- |
|||
|
|||
In the MicroPython C code, any strings that should be interned in the final |
|||
firmware are written as ``MP_QSTR_Foo``. At compile time this will evaluate to |
|||
a ``qstr`` value that points to the index of ``"Foo"`` in the QSTR pool. |
|||
|
|||
A multi-step process in the ``Makefile`` makes this work. In summary this |
|||
process has three parts: |
|||
|
|||
1. Find all ``MP_QSTR_Foo`` tokens in the code. |
|||
|
|||
2. Generate a static QSTR pool containing all the string data (including lengths |
|||
and hashes). |
|||
|
|||
3. Replace all ``MP_QSTR_Foo`` (via the preprocessor) with their corresponding |
|||
index. |
|||
|
|||
``MP_QSTR_Foo`` tokens are searched for in two sources: |
|||
|
|||
1. All files referenced in ``$(SRC_QSTR)``. This is all C code (i.e. ``py``, |
|||
``extmod``, ``ports/stm32``) but not including third-party code such as |
|||
``lib``. |
|||
|
|||
2. Additional ``$(QSTR_GLOBAL_DEPENDENCIES)`` (which includes ``mpconfig*.h``). |
|||
|
|||
*Note:* ``frozen_mpy.c`` (generated by mpy-tool.py) has its own QSTR generation |
|||
and pool. |
|||
|
|||
Some additional strings that can't be expressed using the ``MP_QSTR_Foo`` syntax |
|||
(e.g. they contain non-alphanumeric characters) are explicitly provided in |
|||
``qstrdefs.h`` and ``qstrdefsport.h`` via the ``$(QSTR_DEFS)`` variable. |
|||
|
|||
Processing happens in the following stages: |
|||
|
|||
1. ``qstr.i.last`` is the concatenation of putting every single input file |
|||
through the C pre-processor. This means that any conditionally disabled code |
|||
will be removed, and macros expanded. This means we don't add strings to the |
|||
pool that won't be used in the final firmware. Because at this stage (thanks |
|||
to the ``NO_QSTR`` macro added by ``QSTR_GEN_EXTRA_CFLAGS``) there is no |
|||
definition for ``MP_QSTR_Foo`` it passes through this stage unaffected. This |
|||
file also includes comments from the preprocessor that include line number |
|||
information. Note that this step only uses files that have changed, which |
|||
means that ``qstr.i.last`` will only contain data from files that have |
|||
changed since the last compile. |
|||
2. ``qstr.split`` is an empty file created after running ``makeqstrdefs.py split`` |
|||
on qstr.i.last. It's just used as a dependency to indicate that the step ran. |
|||
This script outputs one file per input C file, ``genhdr/qstr/...file.c.qstr``, |
|||
which contains only the matched QSTRs. Each QSTR is printed as ``Q(Foo)``. |
|||
This step is necessary to combine the existing files with the new data |
|||
generated from the incremental update in ``qstr.i.last``. |
|||
|
|||
3. ``qstrdefs.collected.h`` is the output of concatenating ``genhdr/qstr/*`` |
|||
using ``makeqstrdefs.py cat``. This is now the full set of ``MP_QSTR_Foo``'s |
|||
found in the code, now formatted as ``Q(Foo)``, one-per-line, with duplicates. |
|||
This file is only updated if the set of qstrs has changed. A hash of the QSTR |
|||
data is written to another file (``qstrdefs.collected.h.hash``) which allows |
|||
it to track changes across builds. |
|||
|
|||
4. ``qstrdefs.preprocessed.h`` adds in the QSTRs from qstrdefs*. It |
|||
concatenates ``qstrdefs.collected.h`` with ``qstrdefs*.h``, then it transforms |
|||
each line from ``Q(Foo)`` to ``"Q(Foo)"`` so they pass through the preprocessor |
|||
unchanged. Then the preprocessor is used to deal with any conditional |
|||
compilation in ``qstrdefs*.h``. Then the transformation is undone back to |
|||
``Q(Foo)``, and saved as ``qstrdefs.preprocessed.h``. |
|||
|
|||
5. ``qstrdefs.generated.h`` is the output of ``makeqstrdata.py``. For each |
|||
``Q(Foo)`` in qstrdefs.preprocessed.h (plus some extra hard-coded ones), it outputs |
|||
``QDEF(MP_QSTR_Foo, (const byte*)"hash" "Foo")``. |
|||
|
|||
Then in the main compile, two things happen with ``qstrdefs.generated.h``: |
|||
|
|||
1. In qstr.h, each QDEF becomes an entry in an enum, which makes ``MP_QSTR_Foo`` |
|||
available to code and equal to the index of that string in the QSTR table. |
|||
|
|||
2. In qstr.c, the actual QSTR data table is generated as elements of the |
|||
``mp_qstr_const_pool->qstrs``. |
|||
|
|||
.. _`string interning`: https://en.wikipedia.org/wiki/String_interning |
|||
|
|||
Run-time QSTR generation |
|||
------------------------ |
|||
|
|||
Additional QSTR pools can be created at runtime so that strings can be added to |
|||
them. For example, the code:: |
|||
|
|||
foo[x] = 3 |
|||
|
|||
Will need to create a QSTR for the value of ``x`` so it can be used by the |
|||
"load attr" bytecode. |
|||
|
|||
Also, when compiling Python code, identifiers and literals need to have QSTRs |
|||
created. Note: only literals shorter than 10 characters become QSTRs. This is |
|||
because a regular string on the heap always takes up a minimum of 16 bytes (one |
|||
GC block), whereas QSTRs allow them to be packed more efficiently into the pool. |
|||
|
|||
QSTR pools (and the underlying "chunks" that store the string data) are allocated |
|||
on-demand on the heap with a minimum size. |
@ -0,0 +1,11 @@ |
|||
.. _cpython_diffs: |
|||
|
|||
MicroPython differences from CPython |
|||
==================================== |
|||
|
|||
The operations listed in this section produce conflicting results in MicroPython when compared to standard Python. |
|||
MicroPython implements Python 3.4 and some select features of Python 3.5. |
|||
|
|||
.. toctree:: |
|||
:maxdepth: 2 |
|||
|
@ -0,0 +1,64 @@ |
|||
.. _esp32_general: |
|||
|
|||
General information about the ESP32 port |
|||
======================================== |
|||
|
|||
The ESP32 is a popular WiFi and Bluetooth enabled System-on-Chip (SoC) by |
|||
Espressif Systems. |
|||
|
|||
Multitude of boards |
|||
------------------- |
|||
|
|||
There is a multitude of modules and boards from different sources which carry |
|||
the ESP32 chip. MicroPython tries to provide a generic port which would run on |
|||
as many boards/modules as possible, but there may be limitations. Espressif |
|||
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 |
|||
datasheet, schematics and other reference materials so you can look up any |
|||
board-specific functions. |
|||
|
|||
To make a generic ESP32 port and support as many boards as possible the |
|||
following design and implementation decision were made: |
|||
|
|||
* GPIO pin numbering is based on ESP32 chip numbering. Please have the manual/pin |
|||
diagram of your board at hand to find correspondence between your board pins and |
|||
actual ESP32 pins. |
|||
* All pins are supported by MicroPython but not all are usable on any given board. |
|||
For example pins that are connected to external SPI flash should not be used, |
|||
and a board may only expose a certain selection of pins. |
|||
|
|||
|
|||
Technical specifications and SoC datasheets |
|||
------------------------------------------- |
|||
|
|||
The datasheets and other reference material for ESP32 chip are available |
|||
from the vendor site: https://www.espressif.com/en/support/download/documents?keys=esp32 . |
|||
They are the primary reference for the chip technical specifications, capabilities, |
|||
operating modes, internal functioning, etc. |
|||
|
|||
For your convenience, some of technical specifications are provided below: |
|||
|
|||
* Architecture: Xtensa Dual-Core 32-bit LX6 |
|||
* CPU frequency: up to 240MHz |
|||
* Total RAM available: 528KB (part of it reserved for system) |
|||
* BootROM: 448KB |
|||
* Internal FlashROM: none |
|||
* External FlashROM: code and data, via SPI Flash; usual size 4MB |
|||
* GPIO: 34 (GPIOs are multiplexed with other functions, including |
|||
external FlashROM, UART, etc.) |
|||
* UART: 3 RX/TX UART (no hardware handshaking), one TX-only UART |
|||
* SPI: 4 SPI interfaces (one used for FlashROM) |
|||
* I2C: 2 I2C (bitbang implementation available on any pins) |
|||
* I2S: 2 |
|||
* ADC: 12-bit SAR ADC up to 18 channels |
|||
* DAC: 2 8-bit DACs |
|||
* RMT: 8 channels allowing accurate pulse transmit/receive |
|||
* Programming: using BootROM bootloader from UART - due to external FlashROM |
|||
and always-available BootROM bootloader, the ESP32 is not brickable |
|||
|
|||
For more information see the ESP32 datasheet: https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf |
|||
|
|||
MicroPython is implemented on top of the ESP-IDF, Espressif's development |
|||
framework for the ESP32. This is a FreeRTOS based system. See the |
|||
`ESP-IDF Programming Guide <https://docs.espressif.com/projects/esp-idf/en/latest/index.html>`_ |
|||
for details. |
After Width: | Height: | Size: 84 KiB |
@ -0,0 +1,519 @@ |
|||
.. _esp32_quickref: |
|||
|
|||
Quick reference for the ESP32 |
|||
============================= |
|||
|
|||
.. image:: img/esp32.jpg |
|||
:alt: ESP32 board |
|||
:width: 640px |
|||
|
|||
The Espressif ESP32 Development Board (image attribution: Adafruit). |
|||
|
|||
Below is a quick reference for ESP32-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 |
|||
|
|||
Installing MicroPython |
|||
---------------------- |
|||
|
|||
See the corresponding section of tutorial: :ref:`esp32_intro`. It also includes |
|||
a troubleshooting subsection. |
|||
|
|||
General board control |
|||
--------------------- |
|||
|
|||
The MicroPython REPL is on UART0 (GPIO1=TX, GPIO3=RX) at baudrate 115200. |
|||
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 |
|||
machine.freq(240000000) # set the CPU frequency to 240 MHz |
|||
|
|||
The :mod:`esp` module:: |
|||
|
|||
import esp |
|||
|
|||
esp.osdebug(None) # turn off vendor O/S debugging messages |
|||
esp.osdebug(0) # redirect vendor O/S debugging messages to UART(0) |
|||
|
|||
# low level methods to interact with flash storage |
|||
esp.flash_size() |
|||
esp.flash_user_start() |
|||
esp.flash_erase(sector_no) |
|||
esp.flash_write(byte_offset, buffer) |
|||
esp.flash_read(byte_offset, buffer) |
|||
|
|||
The :mod:`esp32` module:: |
|||
|
|||
import esp32 |
|||
|
|||
esp32.hall_sensor() # read the internal hall sensor |
|||
esp32.raw_temperature() # read the internal temperature of the MCU, in Farenheit |
|||
esp32.ULP() # access to the Ultra-Low-Power Co-processor |
|||
|
|||
Note that the temperature sensor in the ESP32 will typically read higher than |
|||
ambient due to the IC getting warm while it runs. This effect can be minimised |
|||
by reading the temperature sensor immediately after waking up from sleep. |
|||
|
|||
Networking |
|||
---------- |
|||
|
|||
The :mod:`network` module:: |
|||
|
|||
import network |
|||
|
|||
wlan = network.WLAN(network.STA_IF) # create station interface |
|||
wlan.active(True) # activate the interface |
|||
wlan.scan() # scan for access points |
|||
wlan.isconnected() # check if the station is connected to an AP |
|||
wlan.connect('essid', 'password') # connect to an AP |
|||
wlan.config('mac') # get the interface's MAC address |
|||
wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses |
|||
|
|||
ap = network.WLAN(network.AP_IF) # create access-point interface |
|||
ap.config(essid='ESP-AP') # set the ESSID of the access point |
|||
ap.active(True) # activate the interface |
|||
|
|||
A useful function for connecting to your local WiFi network is:: |
|||
|
|||
def do_connect(): |
|||
import network |
|||
wlan = network.WLAN(network.STA_IF) |
|||
wlan.active(True) |
|||
if not wlan.isconnected(): |
|||
print('connecting to network...') |
|||
wlan.connect('essid', 'password') |
|||
while not wlan.isconnected(): |
|||
pass |
|||
print('network config:', wlan.ifconfig()) |
|||
|
|||
Once the network is established the :mod:`socket <usocket>` module can be used |
|||
to create and use TCP/UDP sockets as usual, and the ``urequests`` module for |
|||
convenient HTTP requests. |
|||
|
|||
Delay and timing |
|||
---------------- |
|||
|
|||
Use the :mod:`time <utime>` 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 |
|||
------ |
|||
|
|||
Virtual (RTOS-based) timers are supported. Use the :ref:`machine.Timer <machine.Timer>` class |
|||
with timer ID of -1:: |
|||
|
|||
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)) |
|||
|
|||
The period is in milliseconds. |
|||
|
|||
.. _Pins_and_GPIO: |
|||
|
|||
Pins and GPIO |
|||
------------- |
|||
|
|||
Use the :ref:`machine.Pin <machine.Pin>` class:: |
|||
|
|||
from machine import Pin |
|||
|
|||
p0 = Pin(0, 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(2, Pin.IN) # create input pin on GPIO2 |
|||
print(p2.value()) # get value, 0 or 1 |
|||
|
|||
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 |
|||
|
|||
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 |
|||
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. |
|||
|
|||
Notes: |
|||
|
|||
* Pins 1 and 3 are REPL UART TX and RX respectively |
|||
|
|||
* Pins 6, 7, 8, 11, 16, and 17 are used for connecting the embedded flash, |
|||
and are not recommended for other uses |
|||
|
|||
* 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. |
|||
|
|||
PWM (pulse width modulation) |
|||
---------------------------- |
|||
|
|||
PWM can be enabled on all output-enabled pins. The base frequency can |
|||
range from 1Hz to 40MHz but there is a tradeoff; as the base frequency |
|||
*increases* the duty resolution *decreases*. See |
|||
`LED Control <https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/ledc.html>`_ |
|||
for more details. |
|||
|
|||
Use the ``machine.PWM`` class:: |
|||
|
|||
from machine import Pin, PWM |
|||
|
|||
pwm0 = PWM(Pin(0)) # create PWM object from a pin |
|||
pwm0.freq() # get current frequency |
|||
pwm0.freq(1000) # set frequency |
|||
pwm0.duty() # get current duty cycle |
|||
pwm0.duty(200) # set duty cycle |
|||
pwm0.deinit() # turn off PWM on the pin |
|||
|
|||
pwm2 = PWM(Pin(2), freq=20000, duty=512) # create and configure in one go |
|||
|
|||
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. |
|||
|
|||
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.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 |
|||
|
|||
ESP32 specific ADC class method reference: |
|||
|
|||
.. method:: ADC.atten(attenuation) |
|||
|
|||
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: |
|||
|
|||
- ``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 |
|||
|
|||
.. 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! |
|||
|
|||
.. method:: ADC.width(width) |
|||
|
|||
This method allows for the setting of the number of bits to be utilised |
|||
and returned during ADC reads. Possible width options are: |
|||
|
|||
- ``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 |
|||
---------------- |
|||
|
|||
There are two SPI drivers. One is implemented in software (bit-banging) |
|||
and works on all pins, and is accessed via the :ref:`machine.SPI <machine.SPI>` |
|||
class:: |
|||
|
|||
from machine import Pin, SPI |
|||
|
|||
# construct an SPI 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 = SPI(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 |
|||
|
|||
.. Warning:: |
|||
Currently *all* of ``sck``, ``mosi`` and ``miso`` *must* be specified when |
|||
initialising Software SPI. |
|||
|
|||
Hardware SPI bus |
|||
---------------- |
|||
|
|||
There are two hardware SPI channels that allow faster transmission |
|||
rates (up to 80Mhz). These may be used on any IO pins that support the |
|||
required direction and are otherwise unused (see :ref:`Pins_and_GPIO`) |
|||
but if they are not configured to their default pins then they need to |
|||
pass through an extra layer of GPIO multiplexing, which can impact |
|||
their reliability at high speeds. Hardware SPI channels are limited |
|||
to 40MHz when used on pins other than the default ones listed below. |
|||
|
|||
===== =========== ============ |
|||
\ HSPI (id=1) VSPI (id=2) |
|||
===== =========== ============ |
|||
sck 14 18 |
|||
mosi 13 23 |
|||
miso 12 19 |
|||
===== =========== ============ |
|||
|
|||
Hardware SPI has the same methods as Software SPI above:: |
|||
|
|||
from machine import Pin, SPI |
|||
|
|||
hspi = SPI(1, 10000000, sck=Pin(14), mosi=Pin(13), miso=Pin(12)) |
|||
vspi = SPI(2, baudrate=80000000, polarity=0, phase=0, bits=8, firstbit=0, sck=Pin(18), mosi=Pin(23), miso=Pin(19)) |
|||
|
|||
|
|||
I2C bus |
|||
------- |
|||
|
|||
The I2C driver has both software and hardware implementations, and the two |
|||
hardware peripherals have identifiers 0 and 1. Any available output-capable |
|||
pins can be used for SCL and SDA. The driver is accessed via the |
|||
:ref:`machine.I2C <machine.I2C>` class:: |
|||
|
|||
from machine import Pin, I2C |
|||
|
|||
# construct a software I2C bus |
|||
i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000) |
|||
|
|||
# construct a hardware I2C bus |
|||
i2c = I2C(0) |
|||
i2c = I2C(1, scl=Pin(5), sda=Pin(4), freq=400000) |
|||
|
|||
i2c.scan() # scan for slave devices |
|||
|
|||
i2c.readfrom(0x3a, 4) # read 4 bytes from slave device with address 0x3a |
|||
i2c.writeto(0x3a, '12') # write '12' to slave device with address 0x3a |
|||
|
|||
buf = bytearray(10) # create a buffer with 10 bytes |
|||
i2c.writeto(0x3a, buf) # write the given buffer to the slave |
|||
|
|||
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 |
|||
|
|||
Deep-sleep mode |
|||
--------------- |
|||
|
|||
The following code can be used to sleep, wake and check the reset cause:: |
|||
|
|||
import machine |
|||
|
|||
# check if the device woke from a deep sleep |
|||
if machine.reset_cause() == machine.DEEPSLEEP_RESET: |
|||
print('woke from a deep sleep') |
|||
|
|||
# put the device to sleep for 10 seconds |
|||
machine.deepsleep(10000) |
|||
|
|||
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) |
|||
|
|||
After leaving deepsleep it may be necessary to un-hold the pin explicitly (e.g. if |
|||
it is an output pin) via:: |
|||
|
|||
p1 = Pin(4, Pin.OUT, None) |
|||
|
|||
RMT |
|||
--- |
|||
|
|||
The RMT is ESP32-specific and allows generation of accurate digital pulses with |
|||
12.5ns resolution. See :ref:`esp32.RMT <esp32.RMT>` for details. Usage is:: |
|||
|
|||
import esp32 |
|||
from machine import Pin |
|||
|
|||
r = esp32.RMT(0, pin=Pin(18), clock_div=8) |
|||
r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8) |
|||
# The channel resolution is 100ns (1/(source_freq/clock_div)). |
|||
r.write_pulses((1, 20, 2, 40), start=0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns |
|||
|
|||
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. |
|||
|
|||
NeoPixel driver |
|||
--------------- |
|||
|
|||
Use the ``neopixel`` module:: |
|||
|
|||
from machine import Pin |
|||
from neopixel import NeoPixel |
|||
|
|||
pin = Pin(0, Pin.OUT) # set GPIO0 to output to drive NeoPixels |
|||
np = NeoPixel(pin, 8) # create NeoPixel driver on GPIO0 for 8 pixels |
|||
np[0] = (255, 255, 255) # set the first pixel to white |
|||
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. |
|||
|
|||
|
|||
Capacitive Touch |
|||
---------------- |
|||
|
|||
Use the ``TouchPad`` class in the ``machine`` module:: |
|||
|
|||
from machine import TouchPad, Pin |
|||
|
|||
t = TouchPad(Pin(14)) |
|||
t.read() # Returns a smaller number when touched |
|||
|
|||
``TouchPad.read`` returns a value relative to the capacitive variation. Small numbers (typically in |
|||
the *tens*) are common when a pin is touched, larger numbers (above *one thousand*) when |
|||
no touch is present. However the values are *relative* and can vary depending on the board |
|||
and surrounding composition so some calibration may be required. |
|||
|
|||
There are ten capacitive touch-enabled pins that can be used on the ESP32: 0, 2, 4, 12, 13 |
|||
14, 15, 27, 32, 33. Trying to assign to any other pins will result in a ``ValueError``. |
|||
|
|||
Note that TouchPads can be used to wake an ESP32 from sleep:: |
|||
|
|||
import machine |
|||
from machine import TouchPad, Pin |
|||
import esp32 |
|||
|
|||
t = TouchPad(Pin(14)) |
|||
t.config(500) # configure the threshold at which the pin is considered touched |
|||
esp32.wake_on_touch(True) |
|||
machine.lightsleep() # put the MCU to sleep until a touchpad is touched |
|||
|
|||
For more details on touchpads refer to `Espressif Touch Sensor |
|||
<https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/touch_pad.html>`_. |
|||
|
|||
|
|||
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) |
|||
|
|||
WebREPL (web browser interactive prompt) |
|||
---------------------------------------- |
|||
|
|||
WebREPL (REPL over WebSockets, accessible via a web browser) is an |
|||
experimental feature available in ESP32 port. Download web client |
|||
from https://github.com/micropython/webrepl (hosted version available |
|||
at http://micropython.org/webrepl), and configure it by executing:: |
|||
|
|||
import webrepl_setup |
|||
|
|||
and following on-screen instructions. After reboot, it will be available |
|||
for connection. If you disabled automatic start-up on boot, you may |
|||
run configured daemon on demand using:: |
|||
|
|||
import webrepl |
|||
webrepl.start() |
|||
|
|||
# or, start with a specific password |
|||
webrepl.start(password='mypass') |
|||
|
|||
The WebREPL daemon listens on all active interfaces, which can be STA or |
|||
AP. This allows you to connect to the ESP32 via a router (the STA |
|||
interface) or directly when connected to its access point. |
|||
|
|||
In addition to terminal/command prompt access, WebREPL also has provision |
|||
for file transfer (both upload and download). The web client has buttons for |
|||
the corresponding functions, or you can use the command-line client |
|||
``webrepl_cli.py`` from the repository above. |
|||
|
|||
See the MicroPython forum for other community-supported alternatives |
|||
to transfer files to an ESP32 board. |
@ -0,0 +1,139 @@ |
|||
.. _esp32_intro: |
|||
|
|||
Getting started with MicroPython on the ESP32 |
|||
============================================= |
|||
|
|||
Using MicroPython is a great way to get the most of your ESP32 board. And |
|||
vice versa, the ESP32 chip is a great platform for using MicroPython. This |
|||
tutorial will guide you through setting up MicroPython, getting a prompt, using |
|||
WebREPL, connecting to the network and communicating with the Internet, using |
|||
the hardware peripherals, and controlling some external components. |
|||
|
|||
Let's get started! |
|||
|
|||
Requirements |
|||
------------ |
|||
|
|||
The first thing you need is a board with an ESP32 chip. The MicroPython |
|||
software supports the ESP32 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 convertor 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 |
|||
-------------------- |
|||
|
|||
The first thing you need to do is download the most recent MicroPython firmware |
|||
.bin file to load onto your ESP32 device. You can download it from the |
|||
`MicroPython downloads page <https://micropython.org/download#esp32>`_. |
|||
From here, you have 3 main choices: |
|||
|
|||
* Stable firmware builds |
|||
* Daily firmware builds |
|||
* Daily firmware builds with SPIRAM support |
|||
|
|||
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 ESP32 user |
|||
who would like to follow development closely and help with testing new |
|||
features, there are daily builds. If your board has SPIRAM support you can |
|||
use either the standard firmware or the firmware with SPIRAM support, and in |
|||
the latter case you will have access to more RAM for Python objects. |
|||
|
|||
Deploying the firmware |
|||
---------------------- |
|||
|
|||
Once you have the MicroPython firmware you need to load it onto your ESP32 device. |
|||
There are two main steps to do this: first you need to put your device in |
|||
bootloader mode, and second you need to copy across the firmware. The exact |
|||
procedure for these steps is highly dependent on the particular board and you will |
|||
need to refer to its documentation for details. |
|||
|
|||
Fortunately, most boards have a USB connector, a USB-serial convertor, and the DTR |
|||
and RTS pins wired in a special way then deploying the firmware should be easy as |
|||
all steps can be done automatically. Boards that have such features |
|||
include the Adafruit Feather HUZZAH32, M5Stack, Wemos LOLIN32, and TinyPICO |
|||
boards, along with the Espressif DevKitC, PICO-KIT, WROVER-KIT dev-kits. |
|||
|
|||
For best results it is recommended to first erase the entire flash of your |
|||
device before putting on new MicroPython firmware. |
|||
|
|||
Currently we only support esptool.py to copy across the firmware. You can find |
|||
this tool here: `<https://github.com/espressif/esptool/>`__, or install it |
|||
using pip:: |
|||
|
|||
pip install esptool |
|||
|
|||
Versions starting with 1.3 support both Python 2.7 and Python 3.4 (or newer). |
|||
An older version (at least 1.2.1 is needed) works fine but will require Python |
|||
2.7. |
|||
|
|||
Using esptool.py you can erase the flash with the command:: |
|||
|
|||
esptool.py --port /dev/ttyUSB0 erase_flash |
|||
|
|||
And then deploy the new firmware using:: |
|||
|
|||
esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash -z 0x1000 esp32-20180511-v1.9.4.bin |
|||
|
|||
Notes: |
|||
|
|||
* You might need to change the "port" setting to something else relevant for your |
|||
PC |
|||
* You may need to reduce the baudrate if you get errors when flashing |
|||
(eg down to 115200 by adding ``--baud 115200`` into the command) |
|||
* For some boards with a particular FlashROM configuration you may need to |
|||
change the flash mode (eg by adding ``-fm dio`` into the command) |
|||
* The filename of the firmware should match the file that you have |
|||
|
|||
If the above commands run without error then MicroPython should be installed on |
|||
your board! |
|||
|
|||
Serial prompt |
|||
------------- |
|||
|
|||
Once you have the firmware on the device you can access the REPL (Python prompt) |
|||
over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial |
|||
convertor, depending on your board. The baudrate is 115200. |
|||
|
|||
From here you can now follow the ESP8266 tutorial, because these two Espressif chips |
|||
are very similar when it comes to using MicroPython on them. The ESP8266 tutorial |
|||
is found at :ref:`esp8266_tutorial` (but skip the Introduction section). |
|||
|
|||
Troubleshooting installation problems |
|||
------------------------------------- |
|||
|
|||
If you experience problems during flashing or with running firmware immediately |
|||
after it, here are troubleshooting recommendations: |
|||
|
|||
* Be aware of and try to exclude hardware problems. There are 2 common |
|||
problems: bad power source quality, and worn-out/defective FlashROM. |
|||
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. |
|||
|
|||
* The flashing instructions above use flashing speed of 460800 baud, which is |
|||
good compromise between speed and stability. However, depending on your |
|||
module/board, USB-UART convertor, cables, host OS, etc., the above baud |
|||
rate may be too high and lead to errors. Try a more common 115200 baud |
|||
rate instead in such cases. |
|||
|
|||
* To catch incorrect flash content (e.g. from a defective sector on a chip), |
|||
add ``--verify`` switch to the commands above. |
|||
|
|||
* If you still experience problems with flashing the firmware please |
|||
refer to esptool.py project page, https://github.com/espressif/esptool |
|||
for additional documentation and a bug tracker where you can report problems. |
|||
|
|||
* If you are able to flash the firmware but the ``--verify`` option returns |
|||
errors even after multiple retries the you may have a defective FlashROM chip. |
@ -0,0 +1,197 @@ |
|||
.. _esp8266_general: |
|||
|
|||
General information about the ESP8266 port |
|||
========================================== |
|||
|
|||
ESP8266 is a popular WiFi-enabled System-on-Chip (SoC) by Espressif Systems. |
|||
|
|||
Multitude of boards |
|||
------------------- |
|||
|
|||
There is a multitude of modules and boards from different sources which carry |
|||
the ESP8266 chip. MicroPython tries to provide a generic port which would run on |
|||
as many boards/modules as possible, but there may be limitations. Adafruit |
|||
Feather HUZZAH board is taken as a reference board for the port (for example, |
|||
testing is performed on it). If you have another board, please make sure you |
|||
have a datasheet, schematics and other reference materials for your board |
|||
handy to look up various aspects of your board functioning. |
|||
|
|||
To make a generic ESP8266 port and support as many boards as possible, |
|||
the following design and implementation decision were made: |
|||
|
|||
* GPIO pin numbering is based on ESP8266 chip numbering, not some "logical" |
|||
numbering of a particular board. Please have the manual/pin diagram of your board |
|||
at hand to find correspondence between your board pins and actual ESP8266 pins. |
|||
We also encourage users of various boards to share this mapping via MicroPython |
|||
forum, with the idea to collect community-maintained reference materials |
|||
eventually. |
|||
* All pins which make sense to support, are supported by MicroPython |
|||
(for example, pins which are used to connect SPI flash |
|||
are not exposed, as they're unlikely useful for anything else, and |
|||
operating on them will lead to board lock-up). However, any particular |
|||
board may expose only subset of pins. Consult your board reference manual. |
|||
* Some boards may lack external pins/internal connectivity to support |
|||
ESP8266 deepsleep mode. |
|||
|
|||
|
|||
Technical specifications and SoC datasheets |
|||
------------------------------------------- |
|||
|
|||
The datasheets and other reference material for ESP8266 chip are available |
|||
from the vendor site: http://bbs.espressif.com/viewtopic.php?f=67&t=225 . |
|||
They are the primary reference for the chip technical specifications, capabilities, |
|||
operating modes, internal functioning, etc. |
|||
|
|||
For your convenience, some of technical specifications are provided below: |
|||
|
|||
* Architecture: Xtensa lx106 |
|||
* CPU frequency: 80MHz overclockable to 160MHz |
|||
* Total RAM available: 96KB (part of it reserved for system) |
|||
* BootROM: 64KB |
|||
* Internal FlashROM: None |
|||
* External FlashROM: code and data, via SPI Flash. Normal sizes 512KB-4MB. |
|||
* GPIO: 16 + 1 (GPIOs are multiplexed with other functions, including |
|||
external FlashROM, UART, deep sleep wake-up, etc.) |
|||
* UART: One RX/TX UART (no hardware handshaking), one TX-only UART. |
|||
* SPI: 2 SPI interfaces (one used for FlashROM). |
|||
* I2C: No native external I2C (bitbang implementation available on any pins). |
|||
* I2S: 1. |
|||
* Programming: using BootROM bootloader from UART. Due to external FlashROM |
|||
and always-available BootROM bootloader, ESP8266 is not brickable. |
|||
|
|||
|
|||
Scarcity of runtime resources |
|||
----------------------------- |
|||
|
|||
ESP8266 has very modest resources (first of all, RAM memory). So, please |
|||
avoid allocating too big container objects (lists, dictionaries) and |
|||
buffers. There is also no full-fledged OS to keep track of resources |
|||
and automatically clean them up, so that's the task of a user/user |
|||
application: please be sure to close open files, sockets, etc. as soon |
|||
as possible after use. |
|||
|
|||
|
|||
Boot process |
|||
------------ |
|||
|
|||
On boot, MicroPython EPS8266 port executes ``_boot.py`` script from internal |
|||
frozen modules. It mounts filesystem in FlashROM, or if it's not available, |
|||
performs first-time setup of the module and creates the filesystem. This |
|||
part of the boot process is considered fixed, and not available for customization |
|||
for end users (even if you build from source, please refrain from changes to |
|||
it; customization of early boot process is available only to advanced users |
|||
and developers, who can diagnose themselves any issues arising from |
|||
modifying the standard process). |
|||
|
|||
Once the filesystem is mounted, ``boot.py`` is executed from it. The standard |
|||
version of this file is created during first-time module set up and has |
|||
commands to start a WebREPL daemon (disabled by default, configurable |
|||
with ``webrepl_setup`` module), etc. This |
|||
file is customizable by end users (for example, you may want to set some |
|||
parameters or add other services which should be run on |
|||
a module start-up). But keep in mind that incorrect modifications to boot.py |
|||
may still lead to boot loops or lock ups, requiring to reflash a module |
|||
from scratch. (In particular, it's recommended that you use either |
|||
``webrepl_setup`` module or manual editing to configure WebREPL, but not |
|||
both). |
|||
|
|||
As a final step of boot procedure, ``main.py`` is executed from filesystem, |
|||
if exists. This file is a hook to start up a user application each time |
|||
on boot (instead of going to REPL). For small test applications, you may |
|||
name them directly as ``main.py``, and upload to module, but instead it's |
|||
recommended to keep your application(s) in separate files, and have just |
|||
the following in ``main.py``:: |
|||
|
|||
import my_app |
|||
my_app.main() |
|||
|
|||
This will allow to keep the structure of your application clear, as well as |
|||
allow to install multiple applications on a board, and switch among them. |
|||
|
|||
|
|||
Known Issues |
|||
------------ |
|||
|
|||
Real-time clock |
|||
~~~~~~~~~~~~~~~ |
|||
|
|||
RTC in ESP8266 has very bad accuracy, drift may be seconds per minute. As |
|||
a workaround, to measure short enough intervals you can use |
|||
``utime.time()``, etc. functions, and for wall clock time, synchronize from |
|||
the net using included ``ntptime.py`` module. |
|||
|
|||
Due to limitations of the ESP8266 chip the internal real-time clock (RTC) |
|||
will overflow every 7:45h. If a long-term working RTC time is required then |
|||
``time()`` or ``localtime()`` must be called at least once within 7 hours. |
|||
MicroPython will then handle the overflow. |
|||
|
|||
Sockets and WiFi buffers overflow |
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|||
|
|||
Socket instances remain active until they are explicitly closed. This has two |
|||
consequences. Firstly they occupy RAM, so an application which opens sockets |
|||
without closing them may eventually run out of memory. Secondly not properly |
|||
closed socket can cause the low-level part of the vendor WiFi stack to emit |
|||
``Lmac`` errors. This occurs if data comes in for a socket and is not |
|||
processed in a timely manner. This can overflow the WiFi stack input queue |
|||
and lead to a deadlock. The only recovery is by a hard reset. |
|||
|
|||
The above may also happen after an application terminates and quits to the REPL |
|||
for any reason including an exception. Subsequent arrival of data provokes the |
|||
failure with the above error message repeatedly issued. So, sockets should be |
|||
closed in any case, regardless whether an application terminates successfully |
|||
or by an exception, for example using try/finally:: |
|||
|
|||
sock = socket(...) |
|||
try: |
|||
# Use sock |
|||
finally: |
|||
sock.close() |
|||
|
|||
|
|||
SSL/TLS limitations |
|||
~~~~~~~~~~~~~~~~~~~ |
|||
|
|||
ESP8266 uses `axTLS <http://axtls.sourceforge.net/>`_ library, which is one |
|||
of the smallest TLS libraries with the compatible licensing. However, it |
|||
also has some known issues/limitations: |
|||
|
|||
1. No support for Diffie-Hellman (DH) key exchange and Elliptic-curve |
|||
cryptography (ECC). This means it can't work with sites which force |
|||
the use of these features (it works ok with classic RSA certificates). |
|||
2. Half-duplex communication nature. axTLS uses a single buffer for both |
|||
sending and receiving, which leads to considerable memory saving and |
|||
works well with protocols like HTTP. But there may be problems with |
|||
protocols which don't follow classic request-response model. |
|||
|
|||
Besides axTLS own limitations, the configuration used for MicroPython is |
|||
highly optimized for code size, which leads to additional limitations |
|||
(these may be lifted in the future): |
|||
|
|||
3. Optimized RSA algorithms are not enabled, which may lead to slow |
|||
SSL handshakes. |
|||
4. Stored sessions are not supported (may allow faster repeated connections |
|||
to the same site in some circumstances). |
|||
|
|||
Besides axTLS specific limitations described above, there's another generic |
|||
limitation with usage of TLS on the low-memory devices: |
|||
|
|||
5. The TLS standard specifies the maximum length of the TLS record (unit |
|||
of TLS communication, the entire record must be buffered before it can |
|||
be processed) as 16KB. That's almost half of the available ESP8266 memory, |
|||
and inside a more or less advanced application would be hard to allocate |
|||
due to memory fragmentation issues. As a compromise, a smaller buffer is |
|||
used, with the idea that the most interesting usage for SSL would be |
|||
accessing various REST APIs, which usually require much smaller messages. |
|||
The buffers size is on the order of 5KB, and is adjusted from time to |
|||
time, taking as a reference being able to access https://google.com . |
|||
The smaller buffer hower means that some sites can't be accessed using |
|||
it, and it's not possible to stream large amounts of data. |
|||
|
|||
There are also some not implemented features specifically in MicroPython's |
|||
``ussl`` module based on axTLS: |
|||
|
|||
6. Certificates are not validated (this may make connections susceptible |
|||
to man-in-the-middle attacks). |
|||
7. There is no support for client certificates (scheduled to be fixed in |
|||
1.9.4 release). |
After Width: | Height: | Size: 78 KiB |
@ -0,0 +1,394 @@ |
|||
.. _esp8266_quickref: |
|||
|
|||
Quick reference for the ESP8266 |
|||
=============================== |
|||
|
|||
.. image:: img/adafruit_products_pinoutstop.jpg |
|||
:alt: Adafruit Feather HUZZAH board |
|||
:width: 640px |
|||
|
|||
The Adafruit Feather HUZZAH board (image attribution: Adafruit). |
|||
|
|||
Below is a quick reference for ESP8266-based boards. If it is your first time |
|||
working with this board please consider reading the following sections first: |
|||
|
|||
.. toctree:: |
|||
:maxdepth: 1 |
|||
|
|||
general.rst |
|||
tutorial/index.rst |
|||
|
|||
Installing MicroPython |
|||
---------------------- |
|||
|
|||
See the corresponding section of tutorial: :ref:`intro`. It also includes |
|||
a troubleshooting subsection. |
|||
|
|||
General board control |
|||
--------------------- |
|||
|
|||
The MicroPython REPL is on UART0 (GPIO1=TX, GPIO3=RX) at baudrate 115200. |
|||
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 |
|||
machine.freq(160000000) # set the CPU frequency to 160 MHz |
|||
|
|||
The :mod:`esp` module:: |
|||
|
|||
import esp |
|||
|
|||
esp.osdebug(None) # turn off vendor O/S debugging messages |
|||
esp.osdebug(0) # redirect vendor O/S debugging messages to UART(0) |
|||
|
|||
Networking |
|||
---------- |
|||
|
|||
The :mod:`network` module:: |
|||
|
|||
import network |
|||
|
|||
wlan = network.WLAN(network.STA_IF) # create station interface |
|||
wlan.active(True) # activate the interface |
|||
wlan.scan() # scan for access points |
|||
wlan.isconnected() # check if the station is connected to an AP |
|||
wlan.connect('essid', 'password') # connect to an AP |
|||
wlan.config('mac') # get the interface's MAC adddress |
|||
wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses |
|||
|
|||
ap = network.WLAN(network.AP_IF) # create access-point interface |
|||
ap.active(True) # activate the interface |
|||
ap.config(essid='ESP-AP') # set the ESSID of the access point |
|||
|
|||
A useful function for connecting to your local WiFi network is:: |
|||
|
|||
def do_connect(): |
|||
import network |
|||
wlan = network.WLAN(network.STA_IF) |
|||
wlan.active(True) |
|||
if not wlan.isconnected(): |
|||
print('connecting to network...') |
|||
wlan.connect('essid', 'password') |
|||
while not wlan.isconnected(): |
|||
pass |
|||
print('network config:', wlan.ifconfig()) |
|||
|
|||
Once the network is established the :mod:`socket <usocket>` module can be used |
|||
to create and use TCP/UDP sockets as usual. |
|||
|
|||
Delay and timing |
|||
---------------- |
|||
|
|||
Use the :mod:`time <utime>` 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 |
|||
------ |
|||
|
|||
Virtual (RTOS-based) timers are supported. Use the :ref:`machine.Timer <machine.Timer>` class |
|||
with timer ID of -1:: |
|||
|
|||
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)) |
|||
|
|||
The period is in milliseconds. |
|||
|
|||
Pins and GPIO |
|||
------------- |
|||
|
|||
Use the :ref:`machine.Pin <machine.Pin>` class:: |
|||
|
|||
from machine import Pin |
|||
|
|||
p0 = Pin(0, 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(2, Pin.IN) # create input pin on GPIO2 |
|||
print(p2.value()) # get value, 0 or 1 |
|||
|
|||
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 |
|||
|
|||
Available pins are: 0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16, which correspond |
|||
to the actual GPIO pin numbers of ESP8266 chip. Note that many end-user |
|||
boards use their own adhoc pin numbering (marked e.g. D0, D1, ...). As |
|||
MicroPython supports different boards and modules, physical pin numbering |
|||
was chosen as the lowest common denominator. For mapping between board |
|||
logical pins and physical chip pins, consult your board documentation. |
|||
|
|||
Note that Pin(1) and Pin(3) are REPL UART TX and RX respectively. |
|||
Also note that Pin(16) is a special pin (used for wakeup from deepsleep |
|||
mode) and may be not available for use with higher-level classes like |
|||
``Neopixel``. |
|||
|
|||
PWM (pulse width modulation) |
|||
---------------------------- |
|||
|
|||
PWM can be enabled on all pins except Pin(16). There is a single frequency |
|||
for all channels, with range between 1 and 1000 (measured in Hz). The duty |
|||
cycle is between 0 and 1023 inclusive. |
|||
|
|||
Use the ``machine.PWM`` class:: |
|||
|
|||
from machine import Pin, PWM |
|||
|
|||
pwm0 = PWM(Pin(0)) # create PWM object from a pin |
|||
pwm0.freq() # get current frequency |
|||
pwm0.freq(1000) # set frequency |
|||
pwm0.duty() # get current duty cycle |
|||
pwm0.duty(200) # set duty cycle |
|||
pwm0.deinit() # turn off PWM on the pin |
|||
|
|||
pwm2 = PWM(Pin(2), freq=500, duty=512) # create and configure in one go |
|||
|
|||
ADC (analog to digital conversion) |
|||
---------------------------------- |
|||
|
|||
ADC is available on a dedicated pin. |
|||
Note that input voltages on the ADC pin must be between 0v and 1.0v. |
|||
|
|||
Use the :ref:`machine.ADC <machine.ADC>` class:: |
|||
|
|||
from machine import ADC |
|||
|
|||
adc = ADC(0) # create ADC object on ADC pin |
|||
adc.read() # read value, 0-1024 |
|||
|
|||
Software SPI bus |
|||
---------------- |
|||
|
|||
There are two SPI drivers. One is implemented in software (bit-banging) |
|||
and works on all pins, and is accessed via the :ref:`machine.SPI <machine.SPI>` |
|||
class:: |
|||
|
|||
from machine import Pin, SPI |
|||
|
|||
# construct an SPI 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 = SPI(-1, 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 |
|||
|
|||
|
|||
Hardware SPI bus |
|||
---------------- |
|||
|
|||
The hardware SPI is faster (up to 80Mhz), but only works on following pins: |
|||
``MISO`` is GPIO12, ``MOSI`` is GPIO13, and ``SCK`` is GPIO14. It has the same |
|||
methods as the bitbanging SPI class above, except for the pin parameters for the |
|||
constructor and init (as those are fixed):: |
|||
|
|||
from machine import Pin, SPI |
|||
|
|||
hspi = SPI(1, baudrate=80000000, polarity=0, phase=0) |
|||
|
|||
(``SPI(0)`` is used for FlashROM and not available to users.) |
|||
|
|||
I2C bus |
|||
------- |
|||
|
|||
The I2C driver is implemented in software and works on all pins, |
|||
and is accessed via the :ref:`machine.I2C <machine.I2C>` class:: |
|||
|
|||
from machine import Pin, I2C |
|||
|
|||
# construct an I2C bus |
|||
i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000) |
|||
|
|||
i2c.readfrom(0x3a, 4) # read 4 bytes from slave device with address 0x3a |
|||
i2c.writeto(0x3a, '12') # write '12' to slave device with address 0x3a |
|||
|
|||
buf = bytearray(10) # create a buffer with 10 bytes |
|||
i2c.writeto(0x3a, buf) # write the given buffer to the slave |
|||
|
|||
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 |
|||
|
|||
# synchronize with ntp |
|||
# need to be connected to wifi |
|||
import ntptime |
|||
ntptime.settime() # set the rtc datetime from the remote server |
|||
rtc.datetime() # get the date and time in UTC |
|||
|
|||
.. note:: Not all methods are implemented: `RTC.now()`, `RTC.irq(handler=*) <RTC.irq>` |
|||
(using a custom handler), `RTC.init()` and `RTC.deinit()` are |
|||
currently not supported. |
|||
|
|||
Deep-sleep mode |
|||
--------------- |
|||
|
|||
Connect GPIO16 to the reset pin (RST on HUZZAH). Then the following code |
|||
can be used to sleep, wake and check the reset cause:: |
|||
|
|||
import machine |
|||
|
|||
# configure RTC.ALARM0 to be able to wake the device |
|||
rtc = machine.RTC() |
|||
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP) |
|||
|
|||
# check if the device woke from a deep sleep |
|||
if machine.reset_cause() == machine.DEEPSLEEP_RESET: |
|||
print('woke from a deep sleep') |
|||
|
|||
# set RTC.ALARM0 to fire after 10 seconds (waking the device) |
|||
rtc.alarm(rtc.ALARM0, 10000) |
|||
|
|||
# put the device to sleep |
|||
machine.deepsleep() |
|||
|
|||
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. |
|||
|
|||
NeoPixel driver |
|||
--------------- |
|||
|
|||
Use the ``neopixel`` module:: |
|||
|
|||
from machine import Pin |
|||
from neopixel import NeoPixel |
|||
|
|||
pin = Pin(0, Pin.OUT) # set GPIO0 to output to drive NeoPixels |
|||
np = NeoPixel(pin, 8) # create NeoPixel driver on GPIO0 for 8 pixels |
|||
np[0] = (255, 255, 255) # set the first pixel to white |
|||
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) |
|||
|
|||
APA102 driver |
|||
------------- |
|||
|
|||
Use the ``apa102`` module:: |
|||
|
|||
from machine import Pin |
|||
from apa102 import APA102 |
|||
|
|||
clock = Pin(14, Pin.OUT) # set GPIO14 to output to drive the clock |
|||
data = Pin(13, Pin.OUT) # set GPIO13 to output to drive the data |
|||
apa = APA102(clock, data, 8) # create APA102 driver on the clock and the data pin for 8 pixels |
|||
apa[0] = (255, 255, 255, 31) # set the first pixel to white with a maximum brightness of 31 |
|||
apa.write() # write data to all pixels |
|||
r, g, b, brightness = apa[0] # get first pixel colour |
|||
|
|||
For low-level driving of an APA102:: |
|||
|
|||
import esp |
|||
esp.apa102_write(clock_pin, data_pin, rgbi_buf) |
|||
|
|||
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) |
|||
|
|||
WebREPL (web browser interactive prompt) |
|||
---------------------------------------- |
|||
|
|||
WebREPL (REPL over WebSockets, accessible via a web browser) is an |
|||
experimental feature available in ESP8266 port. Download web client |
|||
from https://github.com/micropython/webrepl (hosted version available |
|||
at http://micropython.org/webrepl), and configure it by executing:: |
|||
|
|||
import webrepl_setup |
|||
|
|||
and following on-screen instructions. After reboot, it will be available |
|||
for connection. If you disabled automatic start-up on boot, you may |
|||
run configured daemon on demand using:: |
|||
|
|||
import webrepl |
|||
webrepl.start() |
|||
|
|||
The supported way to use WebREPL is by connecting to ESP8266 access point, |
|||
but the daemon is also started on STA interface if it is active, so if your |
|||
router is set up and works correctly, you may also use WebREPL while connected |
|||
to your normal Internet access point (use the ESP8266 AP connection method |
|||
if you face any issues). |
|||
|
|||
Besides terminal/command prompt access, WebREPL also has provision for file |
|||
transfer (both upload and download). Web client has buttons for the |
|||
corresponding functions, or you can use command-line client ``webrepl_cli.py`` |
|||
from the repository above. |
|||
|
|||
See the MicroPython forum for other community-supported alternatives |
|||
to transfer files to ESP8266. |
@ -0,0 +1,19 @@ |
|||
Analog to Digital Conversion |
|||
============================ |
|||
|
|||
The ESP8266 has a single pin (separate to the GPIO pins) which can be used to |
|||
read analog voltages and convert them to a digital value. You can construct |
|||
such an ADC pin object using:: |
|||
|
|||
>>> import machine |
|||
>>> adc = machine.ADC(0) |
|||
|
|||
Then read its value with:: |
|||
|
|||
>>> adc.read() |
|||
58 |
|||
|
|||
The values returned from the ``read()`` function are between 0 (for 0.0 volts) |
|||
and 1024 (for 1.0 volts). Please note that this input can only tolerate a |
|||
maximum of 1.0 volts and you must use a voltage divider circuit to measure |
|||
larger voltages. |
@ -0,0 +1,91 @@ |
|||
Controlling APA102 LEDs |
|||
======================= |
|||
|
|||
APA102 LEDs, also known as DotStar LEDs, are individually addressable |
|||
full-colour RGB LEDs, generally in a string formation. They differ from |
|||
NeoPixels in that they require two pins to control - both a Clock and Data pin. |
|||
They can operate at a much higher data and PWM frequencies than NeoPixels and |
|||
are more suitable for persistence-of-vision effects. |
|||
|
|||
To create an APA102 object do the following:: |
|||
|
|||
>>> import machine, apa102 |
|||
>>> strip = apa102.APA102(machine.Pin(5), machine.Pin(4), 60) |
|||
|
|||
This configures an 60 pixel APA102 strip with clock on GPIO5 and data on GPIO4. |
|||
You can adjust the pin numbers and the number of pixels to suit your needs. |
|||
|
|||
The RGB colour data, as well as a brightness level, is sent to the APA102 in a |
|||
certain order. Usually this is ``(Red, Green, Blue, Brightness)``. |
|||
If you are using one of the newer APA102C LEDs the green and blue are swapped, |
|||
so the order is ``(Red, Blue, Green, Brightness)``. |
|||
The APA102 has more of a square lens while the APA102C has more of a round one. |
|||
If you are using a APA102C strip and would prefer to provide colours in RGB |
|||
order instead of RBG, you can customise the tuple colour order like so:: |
|||
|
|||
>>> strip.ORDER = (0, 2, 1, 3) |
|||
|
|||
To set the colour of pixels use:: |
|||
|
|||
>>> strip[0] = (255, 255, 255, 31) # set to white, full brightness |
|||
>>> strip[1] = (255, 0, 0, 31) # set to red, full brightness |
|||
>>> strip[2] = (0, 255, 0, 15) # set to green, half brightness |
|||
>>> strip[3] = (0, 0, 255, 7) # set to blue, quarter brightness |
|||
|
|||
Use the ``write()`` method to output the colours to the LEDs:: |
|||
|
|||
>>> strip.write() |
|||
|
|||
Demonstration:: |
|||
|
|||
import time |
|||
import machine, apa102 |
|||
|
|||
# 1M strip with 60 LEDs |
|||
strip = apa102.APA102(machine.Pin(5), machine.Pin(4), 60) |
|||
|
|||
brightness = 1 # 0 is off, 1 is dim, 31 is max |
|||
|
|||
# Helper for converting 0-255 offset to a colour tuple |
|||
def wheel(offset, brightness): |
|||
# The colours are a transition r - g - b - back to r |
|||
offset = 255 - offset |
|||
if offset < 85: |
|||
return (255 - offset * 3, 0, offset * 3, brightness) |
|||
if offset < 170: |
|||
offset -= 85 |
|||
return (0, offset * 3, 255 - offset * 3, brightness) |
|||
offset -= 170 |
|||
return (offset * 3, 255 - offset * 3, 0, brightness) |
|||
|
|||
# Demo 1: RGB RGB RGB |
|||
red = 0xff0000 |
|||
green = red >> 8 |
|||
blue = red >> 16 |
|||
for i in range(strip.n): |
|||
colour = red >> (i % 3) * 8 |
|||
strip[i] = ((colour & red) >> 16, (colour & green) >> 8, (colour & blue), brightness) |
|||
strip.write() |
|||
|
|||
# Demo 2: Show all colours of the rainbow |
|||
for i in range(strip.n): |
|||
strip[i] = wheel((i * 256 // strip.n) % 255, brightness) |
|||
strip.write() |
|||
|
|||
# Demo 3: Fade all pixels together through rainbow colours, offset each pixel |
|||
for r in range(5): |
|||
for n in range(256): |
|||
for i in range(strip.n): |
|||
strip[i] = wheel(((i * 256 // strip.n) + n) & 255, brightness) |
|||
strip.write() |
|||
time.sleep_ms(25) |
|||
|
|||
# Demo 4: Same colour, different brightness levels |
|||
for b in range(31,-1,-1): |
|||
strip[0] = (255, 153, 0, b) |
|||
strip.write() |
|||
time.sleep_ms(250) |
|||
|
|||
# End: Turn off all the LEDs |
|||
strip.fill((0, 0, 0, 0)) |
|||
strip.write() |
@ -0,0 +1,65 @@ |
|||
Temperature and Humidity |
|||
======================== |
|||
|
|||
DHT (Digital Humidity & Temperature) sensors are low cost digital sensors with |
|||
capacitive humidity sensors and thermistors to measure the surrounding air. |
|||
They feature a chip that handles analog to digital conversion and provide a |
|||
1-wire interface. Newer sensors additionally provide an I2C interface. |
|||
|
|||
The DHT11 (blue) and DHT22 (white) sensors provide the same 1-wire interface, |
|||
however, the DHT22 requires a separate object as it has more complex |
|||
calculation. DHT22 have 1 decimal place resolution for both humidity and |
|||
temperature readings. DHT11 have whole number for both. |
|||
|
|||
A custom 1-wire protocol, which is different to Dallas 1-wire, is used to get |
|||
the measurements from the sensor. The payload consists of a humidity value, |
|||
a temperature value and a checksum. |
|||
|
|||
To use the 1-wire interface, construct the objects referring to their data pin:: |
|||
|
|||
>>> import dht |
|||
>>> import machine |
|||
>>> d = dht.DHT11(machine.Pin(4)) |
|||
|
|||
>>> import dht |
|||
>>> import machine |
|||
>>> d = dht.DHT22(machine.Pin(4)) |
|||
|
|||
Then measure and read their values with:: |
|||
|
|||
>>> d.measure() |
|||
>>> d.temperature() |
|||
>>> d.humidity() |
|||
|
|||
Values returned from ``temperature()`` are in degrees Celsius and values |
|||
returned from ``humidity()`` are a percentage of relative humidity. |
|||
|
|||
The DHT11 can be called no more than once per second and the DHT22 once every |
|||
two seconds for most accurate results. Sensor accuracy will degrade over time. |
|||
Each sensor supports a different operating range. Refer to the product |
|||
datasheets for specifics. |
|||
|
|||
In 1-wire mode, only three of the four pins are used and in I2C mode, all four |
|||
pins are used. Older sensors may still have 4 pins even though they do not |
|||
support I2C. The 3rd pin is simply not connected. |
|||
|
|||
Pin configurations: |
|||
|
|||
Sensor without I2C in 1-wire mode (eg. DHT11, DHT22, AM2301, AM2302): |
|||
|
|||
1=VDD, 2=Data, 3=NC, 4=GND |
|||
|
|||
Sensor with I2C in 1-wire mode (eg. DHT12, AM2320, AM2321, AM2322): |
|||
|
|||
1=VDD, 2=Data, 3=GND, 4=GND |
|||
|
|||
Sensor with I2C in I2C mode (eg. DHT12, AM2320, AM2321, AM2322): |
|||
|
|||
1=VDD, 2=SDA, 3=GND, 4=SCL |
|||
|
|||
You should use pull-up resistors for the Data, SDA and SCL pins. |
|||
|
|||
To make newer I2C sensors work in backwards compatible 1-wire mode, you must |
|||
connect both pins 3 and 4 to GND. This disables the I2C interface. |
|||
|
|||
DHT22 sensors are now sold under the name AM2302 and are otherwise identical. |
@ -0,0 +1,69 @@ |
|||
The internal filesystem |
|||
======================= |
|||
|
|||
If your devices has 1Mbyte or more of storage then it will be set up (upon first |
|||
boot) to contain a filesystem. This filesystem uses the FAT format and is |
|||
stored in the flash after the MicroPython firmware. |
|||
|
|||
Creating and reading files |
|||
-------------------------- |
|||
|
|||
MicroPython on the ESP8266 supports the standard way of accessing files in |
|||
Python, using the built-in ``open()`` function. |
|||
|
|||
To create a file try:: |
|||
|
|||
>>> f = open('data.txt', 'w') |
|||
>>> f.write('some data') |
|||
9 |
|||
>>> f.close() |
|||
|
|||
The "9" is the number of bytes that were written with the ``write()`` method. |
|||
Then you can read back the contents of this new file using:: |
|||
|
|||
>>> f = open('data.txt') |
|||
>>> f.read() |
|||
'some data' |
|||
>>> f.close() |
|||
|
|||
Note that the default mode when opening a file is to open it in read-only mode, |
|||
and as a text file. Specify ``'wb'`` as the second argument to ``open()`` to |
|||
open for writing in binary mode, and ``'rb'`` to open for reading in binary |
|||
mode. |
|||
|
|||
Listing file and more |
|||
--------------------- |
|||
|
|||
The os module can be used for further control over the filesystem. First |
|||
import the module:: |
|||
|
|||
>>> import os |
|||
|
|||
Then try listing the contents of the filesystem:: |
|||
|
|||
>>> os.listdir() |
|||
['boot.py', 'port_config.py', 'data.txt'] |
|||
|
|||
You can make directories:: |
|||
|
|||
>>> os.mkdir('dir') |
|||
|
|||
And remove entries:: |
|||
|
|||
>>> os.remove('data.txt') |
|||
|
|||
Start up scripts |
|||
---------------- |
|||
|
|||
There are two files that are treated specially by the ESP8266 when it starts up: |
|||
boot.py and main.py. The boot.py script is executed first (if it exists) and |
|||
then once it completes the main.py script is executed. You can create these |
|||
files yourself and populate them with the code that you want to run when the |
|||
device starts up. |
|||
|
|||
Accessing the filesystem via WebREPL |
|||
------------------------------------ |
|||
|
|||
You can access the filesystem over WebREPL using the web client in a browser |
|||
or via the command-line tool. Please refer to Quick Reference and Tutorial |
|||
sections for more information about WebREPL. |
@ -0,0 +1,34 @@ |
|||
.. _esp8266_tutorial: |
|||
|
|||
MicroPython tutorial for ESP8266 |
|||
================================ |
|||
|
|||
This tutorial is intended to get you started using MicroPython on the ESP8266 |
|||
system-on-a-chip. If it is your first time it is recommended to follow the |
|||
tutorial through in the order below. Otherwise the sections are mostly self |
|||
contained, so feel free to skip to those that interest you. |
|||
|
|||
The tutorial does not assume that you know Python, but it also does not attempt |
|||
to explain any of the details of the Python language. Instead it provides you |
|||
with commands that are ready to run, and hopes that you will gain a bit of |
|||
Python knowledge along the way. To learn more about Python itself please refer |
|||
to `<https://www.python.org>`__. |
|||
|
|||
.. toctree:: |
|||
:maxdepth: 1 |
|||
:numbered: |
|||
|
|||
intro.rst |
|||
repl.rst |
|||
filesystem.rst |
|||
network_basics.rst |
|||
network_tcp.rst |
|||
pins.rst |
|||
pwm.rst |
|||
adc.rst |
|||
powerctrl.rst |
|||
onewire.rst |
|||
neopixel.rst |
|||
apa102.rst |
|||
dht.rst |
|||
nextsteps.rst |
@ -0,0 +1,202 @@ |
|||
.. _intro: |
|||
|
|||
Getting started with MicroPython on the ESP8266 |
|||
=============================================== |
|||
|
|||
Using MicroPython is a great way to get the most of your ESP8266 board. And |
|||
vice versa, the ESP8266 chip is a great platform for using MicroPython. This |
|||
tutorial will guide you through setting up MicroPython, getting a prompt, using |
|||
WebREPL, connecting to the network and communicating with the Internet, using |
|||
the hardware peripherals, and controlling some external components. |
|||
|
|||
Let's get started! |
|||
|
|||
Requirements |
|||
------------ |
|||
|
|||
The first thing you need is a board with an ESP8266 chip. The MicroPython |
|||
software supports the ESP8266 chip itself and any board should work. The main |
|||
characteristic of a board is how much flash it has, how the GPIO pins are |
|||
connected to the outside world, and whether it includes a built-in USB-serial |
|||
convertor to make the UART available to your PC. |
|||
|
|||
The minimum requirement for flash size is 1Mbyte. There is also a special |
|||
build for boards with 512KB, but it is highly limited comparing to the |
|||
normal build: there is no support for filesystem, and thus features which |
|||
depend on it won't work (WebREPL, upip, etc.). As such, 512KB build will |
|||
be more interesting for users who build from source and fine-tune parameters |
|||
for their particular application. |
|||
|
|||
Names of pins will be given in this tutorial using the chip names (eg GPIO0) |
|||
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 |
|||
-------------------- |
|||
|
|||
The first thing you need to do is download the most recent MicroPython firmware |
|||
.bin file to load onto your ESP8266 device. You can download it from the |
|||
`MicroPython downloads page <http://micropython.org/download#esp8266>`_. |
|||
From here, you have 3 main choices |
|||
|
|||
* Stable firmware builds for 1024kb modules and above. |
|||
* Daily firmware builds for 1024kb modules and above. |
|||
* Daily firmware builds for 512kb modules. |
|||
|
|||
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 ESP8266 user |
|||
who would like to follow development closely and help with testing new |
|||
features, there are daily builds (note: you actually may need some |
|||
development experience, e.g. being ready to follow git history to know |
|||
what new changes and features were introduced). |
|||
|
|||
Support for 512kb modules is provided on a feature preview basis. For end |
|||
users, it's recommended to use modules with flash of 1024kb or more. As |
|||
such, only daily builds for 512kb modules are provided. |
|||
|
|||
Deploying the firmware |
|||
---------------------- |
|||
|
|||
Once you have the MicroPython firmware (compiled code), you need to load it onto |
|||
your ESP8266 device. There are two main steps to do this: first you |
|||
need to put your device in boot-loader mode, and second you need to copy across |
|||
the firmware. The exact procedure for these steps is highly dependent on the |
|||
particular board and you will need to refer to its documentation for details. |
|||
|
|||
If you have a board that has a USB connector, a USB-serial convertor, and has |
|||
the DTR and RTS pins wired in a special way then deploying the firmware should |
|||
be easy as all steps can be done automatically. Boards that have such features |
|||
include the Adafruit Feather HUZZAH and NodeMCU boards. |
|||
|
|||
For best results it is recommended to first erase the entire flash of your |
|||
device before putting on new MicroPython firmware. |
|||
|
|||
Currently we only support esptool.py to copy across the firmware. You can find |
|||
this tool here: `<https://github.com/espressif/esptool/>`__, or install it |
|||
using pip:: |
|||
|
|||
pip install esptool |
|||
|
|||
Versions starting with 1.3 support both Python 2.7 and Python 3.4 (or newer). |
|||
An older version (at least 1.2.1 is needed) works fine but will require Python |
|||
2.7. |
|||
|
|||
Any other flashing program should work, so feel free to try them out or refer |
|||
to the documentation for your board to see its recommendations. |
|||
|
|||
Using esptool.py you can erase the flash with the command:: |
|||
|
|||
esptool.py --port /dev/ttyUSB0 erase_flash |
|||
|
|||
And then deploy the new firmware using:: |
|||
|
|||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-20170108-v1.8.7.bin |
|||
|
|||
You might need to change the "port" setting to something else relevant for your |
|||
PC. You may also need to reduce the baudrate if you get errors when flashing |
|||
(eg down to 115200). The filename of the firmware should also match the file |
|||
that you have. |
|||
|
|||
For some boards with a particular FlashROM configuration (e.g. some variants of |
|||
a NodeMCU board) you may need to use the following command to deploy |
|||
the firmware (note the ``-fm dio`` option):: |
|||
|
|||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect -fm dio 0 esp8266-20170108-v1.8.7.bin |
|||
|
|||
If the above commands run without error then MicroPython should be installed on |
|||
your board! |
|||
|
|||
Serial prompt |
|||
------------- |
|||
|
|||
Once you have the firmware on the device you can access the REPL (Python prompt) |
|||
over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial |
|||
convertor, depending on your board. The baudrate is 115200. The next part of |
|||
the tutorial will discuss the prompt in more detail. |
|||
|
|||
WiFi |
|||
---- |
|||
|
|||
After a fresh install and boot the device configures itself as a WiFi access |
|||
point (AP) that you can connect to. The ESSID is of the form MicroPython-xxxxxx |
|||
where the x's are replaced with part of the MAC address of your device (so will |
|||
be the same everytime, and most likely different for all ESP8266 chips). The |
|||
password for the WiFi is micropythoN (note the upper-case N). Its IP address |
|||
will be 192.168.4.1 once you connect to its network. WiFi configuration will |
|||
be discussed in more detail later in the tutorial. |
|||
|
|||
Troubleshooting installation problems |
|||
------------------------------------- |
|||
|
|||
If you experience problems during flashing or with running firmware immediately |
|||
after it, here are troubleshooting recommendations: |
|||
|
|||
* Be aware of and try to exclude hardware problems. There are 2 common problems: |
|||
bad power source quality and worn-out/defective FlashROM. Speaking of power |
|||
source, not just raw amperage is important, but also low ripple and noise/EMI |
|||
in general. If you experience issues with self-made or wall-wart style power |
|||
supply, try USB power from a computer. Unearthed power supplies are also known |
|||
to cause problems as they source of increased EMI (electromagnetic interference) |
|||
- at the very least, and may lead to electrical devices breakdown. So, you are |
|||
advised to avoid using unearthed power connections when working with ESP8266 |
|||
and other boards. In regard to FlashROM hardware problems, there are independent |
|||
(not related to MicroPython in any way) reports |
|||
`(e.g.) <http://internetofhomethings.com/homethings/?p=538>`_ |
|||
that on some ESP8266 modules, FlashROM can be programmed as little as 20 times |
|||
before programming errors occur. This is *much* less than 100,000 programming |
|||
cycles cited for FlashROM chips of a type used with ESP8266 by reputable |
|||
vendors, which points to either production rejects, or second-hand worn-out |
|||
flash chips to be used on some (apparently cheap) modules/boards. You may want |
|||
to use your best judgement about source, price, documentation, warranty, |
|||
post-sales support for the modules/boards you purchase. |
|||
|
|||
* The flashing instructions above use flashing speed of 460800 baud, which is |
|||
good compromise between speed and stability. However, depending on your |
|||
module/board, USB-UART convertor, cables, host OS, etc., the above baud |
|||
rate may be too high and lead to errors. Try a more common 115200 baud |
|||
rate instead in such cases. |
|||
|
|||
* If lower baud rate didn't help, you may want to try older version of |
|||
esptool.py, which had a different programming algorithm:: |
|||
|
|||
pip install esptool==1.0.1 |
|||
|
|||
This version doesn't support ``--flash_size=detect`` option, so you will |
|||
need to specify FlashROM size explicitly (in megabits). It also requires |
|||
Python 2.7, so you may need to use ``pip2`` instead of ``pip`` in the |
|||
command above. |
|||
|
|||
* The ``--flash_size`` option in the commands above is mandatory. Omitting |
|||
it will lead to a corrupted firmware. |
|||
|
|||
* To catch incorrect flash content (e.g. from a defective sector on a chip), |
|||
add ``--verify`` switch to the commands above. |
|||
|
|||
* Additionally, you can check the firmware integrity from a MicroPython REPL |
|||
prompt (assuming you were able to flash it and ``--verify`` option doesn't |
|||
report errors):: |
|||
|
|||
import esp |
|||
esp.check_fw() |
|||
|
|||
If the last output value is True, the firmware is OK. Otherwise, it's |
|||
corrupted and need to be reflashed correctly. |
|||
|
|||
* If you experience any issues with another flashing application (not |
|||
esptool.py), try esptool.py, it is a generally accepted flashing |
|||
application in the ESP8266 community. |
|||
|
|||
* If you still experience problems with even flashing the firmware, please |
|||
refer to esptool.py project page, https://github.com/espressif/esptool |
|||
for additional documentation and bug tracker where you can report problems. |
|||
|
|||
* If you are able to flash firmware, but ``--verify`` option or |
|||
``esp.check_fw()`` return errors even after multiple retries, you |
|||
may have a defective FlashROM chip, as explained above. |
@ -0,0 +1,84 @@ |
|||
Controlling NeoPixels |
|||
===================== |
|||
|
|||
NeoPixels, also known as WS2812 LEDs, are full-colour LEDs that are connected in |
|||
serial, are individually addressable, and can have their red, green and blue |
|||
components set between 0 and 255. They require precise timing to control them |
|||
and there is a special neopixel module to do just this. |
|||
|
|||
To create a NeoPixel object do the following:: |
|||
|
|||
>>> import machine, neopixel |
|||
>>> np = neopixel.NeoPixel(machine.Pin(4), 8) |
|||
|
|||
This configures a NeoPixel strip on GPIO4 with 8 pixels. You can adjust the |
|||
"4" (pin number) and the "8" (number of pixel) to suit your set up. |
|||
|
|||
To set the colour of pixels use:: |
|||
|
|||
>>> np[0] = (255, 0, 0) # set to red, full brightness |
|||
>>> np[1] = (0, 128, 0) # set to green, half brightness |
|||
>>> np[2] = (0, 0, 64) # set to blue, quarter brightness |
|||
|
|||
For LEDs with more than 3 colours, such as RGBW pixels or RGBY pixels, the |
|||
NeoPixel class takes a ``bpp`` parameter. To setup a NeoPixel object for an |
|||
RGBW Pixel, do the following:: |
|||
|
|||
>>> import machine, neopixel |
|||
>>> np = neopixel.NeoPixel(machine.Pin(4), 8, bpp=4) |
|||
|
|||
In a 4-bpp mode, remember to use 4-tuples instead of 3-tuples to set the colour. |
|||
For example to set the first three pixels use:: |
|||
|
|||
>>> np[0] = (255, 0, 0, 128) # Orange in an RGBY Setup |
|||
>>> np[1] = (0, 255, 0, 128) # Yellow-green in an RGBY Setup |
|||
>>> np[2] = (0, 0, 255, 128) # Green-blue in an RGBY Setup |
|||
|
|||
Then use the ``write()`` method to output the colours to the LEDs:: |
|||
|
|||
>>> np.write() |
|||
|
|||
The following demo function makes a fancy show on the LEDs:: |
|||
|
|||
import time |
|||
|
|||
def demo(np): |
|||
n = np.n |
|||
|
|||
# cycle |
|||
for i in range(4 * n): |
|||
for j in range(n): |
|||
np[j] = (0, 0, 0) |
|||
np[i % n] = (255, 255, 255) |
|||
np.write() |
|||
time.sleep_ms(25) |
|||
|
|||
# bounce |
|||
for i in range(4 * n): |
|||
for j in range(n): |
|||
np[j] = (0, 0, 128) |
|||
if (i // n) % 2 == 0: |
|||
np[i % n] = (0, 0, 0) |
|||
else: |
|||
np[n - 1 - (i % n)] = (0, 0, 0) |
|||
np.write() |
|||
time.sleep_ms(60) |
|||
|
|||
# fade in/out |
|||
for i in range(0, 4 * 256, 8): |
|||
for j in range(n): |
|||
if (i // 256) % 2 == 0: |
|||
val = i & 0xff |
|||
else: |
|||
val = 255 - (i & 0xff) |
|||
np[j] = (val, 0, 0) |
|||
np.write() |
|||
|
|||
# clear |
|||
for i in range(n): |
|||
np[i] = (0, 0, 0) |
|||
np.write() |
|||
|
|||
Execute it using:: |
|||
|
|||
>>> demo(np) |
@ -0,0 +1,81 @@ |
|||
Network basics |
|||
============== |
|||
|
|||
The network module is used to configure the WiFi connection. There are two WiFi |
|||
interfaces, one for the station (when the ESP8266 connects to a router) and one |
|||
for the access point (for other devices to connect to the ESP8266). Create |
|||
instances of these objects using:: |
|||
|
|||
>>> import network |
|||
>>> sta_if = network.WLAN(network.STA_IF) |
|||
>>> ap_if = network.WLAN(network.AP_IF) |
|||
|
|||
You can check if the interfaces are active by:: |
|||
|
|||
>>> sta_if.active() |
|||
False |
|||
>>> ap_if.active() |
|||
True |
|||
|
|||
You can also check the network settings of the interface by:: |
|||
|
|||
>>> ap_if.ifconfig() |
|||
('192.168.4.1', '255.255.255.0', '192.168.4.1', '8.8.8.8') |
|||
|
|||
The returned values are: IP address, netmask, gateway, DNS. |
|||
|
|||
Configuration of the WiFi |
|||
------------------------- |
|||
|
|||
Upon a fresh install the ESP8266 is configured in access point mode, so the |
|||
AP_IF interface is active and the STA_IF interface is inactive. You can |
|||
configure the module to connect to your own network using the STA_IF interface. |
|||
|
|||
First activate the station interface:: |
|||
|
|||
>>> sta_if.active(True) |
|||
|
|||
Then connect to your WiFi network:: |
|||
|
|||
>>> sta_if.connect('<your ESSID>', '<your password>') |
|||
|
|||
To check if the connection is established use:: |
|||
|
|||
>>> sta_if.isconnected() |
|||
|
|||
Once established you can check the IP address:: |
|||
|
|||
>>> sta_if.ifconfig() |
|||
('192.168.0.2', '255.255.255.0', '192.168.0.1', '8.8.8.8') |
|||
|
|||
You can then disable the access-point interface if you no longer need it:: |
|||
|
|||
>>> ap_if.active(False) |
|||
|
|||
Here is a function you can run (or put in your boot.py file) to automatically |
|||
connect to your WiFi network:: |
|||
|
|||
def do_connect(): |
|||
import network |
|||
sta_if = network.WLAN(network.STA_IF) |
|||
if not sta_if.isconnected(): |
|||
print('connecting to network...') |
|||
sta_if.active(True) |
|||
sta_if.connect('<essid>', '<password>') |
|||
while not sta_if.isconnected(): |
|||
pass |
|||
print('network config:', sta_if.ifconfig()) |
|||
|
|||
Sockets |
|||
------- |
|||
|
|||
Once the WiFi is set up the way to access the network is by using sockets. |
|||
A socket represents an endpoint on a network device, and when two sockets are |
|||
connected together communication can proceed. |
|||
Internet protocols are built on top of sockets, such as email (SMTP), the web |
|||
(HTTP), telnet, ssh, among many others. Each of these protocols is assigned |
|||
a specific port, which is just an integer. Given an IP address and a port |
|||
number you can connect to a remote device and start talking with it. |
|||
|
|||
The next part of the tutorial discusses how to use sockets to do some common |
|||
and useful network tasks. |
@ -0,0 +1,122 @@ |
|||
Network - TCP sockets |
|||
===================== |
|||
|
|||
The building block of most of the internet is the TCP socket. These sockets |
|||
provide a reliable stream of bytes between the connected network devices. |
|||
This part of the tutorial will show how to use TCP sockets in a few different |
|||
cases. |
|||
|
|||
Star Wars Asciimation |
|||
--------------------- |
|||
|
|||
The simplest thing to do is to download data from the internet. In this case |
|||
we will use the Star Wars Asciimation service provided by the blinkenlights.nl |
|||
website. It uses the telnet protocol on port 23 to stream data to anyone that |
|||
connects. It's very simple to use because it doesn't require you to |
|||
authenticate (give a username or password), you can just start downloading data |
|||
straight away. |
|||
|
|||
The first thing to do is make sure we have the socket module available:: |
|||
|
|||
>>> import socket |
|||
|
|||
Then get the IP address of the server:: |
|||
|
|||
>>> addr_info = socket.getaddrinfo("towel.blinkenlights.nl", 23) |
|||
|
|||
The ``getaddrinfo`` function actually returns a list of addresses, and each |
|||
address has more information than we need. We want to get just the first valid |
|||
address, and then just the IP address and port of the server. To do this use:: |
|||
|
|||
>>> addr = addr_info[0][-1] |
|||
|
|||
If you type ``addr_info`` and ``addr`` at the prompt you will see exactly what |
|||
information they hold. |
|||
|
|||
Using the IP address we can make a socket and connect to the server:: |
|||
|
|||
>>> s = socket.socket() |
|||
>>> s.connect(addr) |
|||
|
|||
Now that we are connected we can download and display the data:: |
|||
|
|||
>>> while True: |
|||
... data = s.recv(500) |
|||
... print(str(data, 'utf8'), end='') |
|||
... |
|||
|
|||
When this loop executes it should start showing the animation (use ctrl-C to |
|||
interrupt it). |
|||
|
|||
You should also be able to run this same code on your PC using normal Python if |
|||
you want to try it out there. |
|||
|
|||
HTTP GET request |
|||
---------------- |
|||
|
|||
The next example shows how to download a webpage. HTTP uses port 80 and you |
|||
first need to send a "GET" request before you can download anything. As part |
|||
of the request you need to specify the page to retrieve. |
|||
|
|||
Let's define a function that can download and print a URL:: |
|||
|
|||
def http_get(url): |
|||
import socket |
|||
_, _, host, path = url.split('/', 3) |
|||
addr = socket.getaddrinfo(host, 80)[0][-1] |
|||
s = socket.socket() |
|||
s.connect(addr) |
|||
s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8')) |
|||
while True: |
|||
data = s.recv(100) |
|||
if data: |
|||
print(str(data, 'utf8'), end='') |
|||
else: |
|||
break |
|||
s.close() |
|||
|
|||
Then you can try:: |
|||
|
|||
>>> http_get('http://micropython.org/ks/test.html') |
|||
|
|||
This should retrieve the webpage and print the HTML to the console. |
|||
|
|||
Simple HTTP server |
|||
------------------ |
|||
|
|||
The following code creates an simple HTTP server which serves a single webpage |
|||
that contains a table with the state of all the GPIO pins:: |
|||
|
|||
import machine |
|||
pins = [machine.Pin(i, machine.Pin.IN) for i in (0, 2, 4, 5, 12, 13, 14, 15)] |
|||
|
|||
html = """<!DOCTYPE html> |
|||
<html> |
|||
<head> <title>ESP8266 Pins</title> </head> |
|||
<body> <h1>ESP8266 Pins</h1> |
|||
<table border="1"> <tr><th>Pin</th><th>Value</th></tr> %s </table> |
|||
</body> |
|||
</html> |
|||
""" |
|||
|
|||
import socket |
|||
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] |
|||
|
|||
s = socket.socket() |
|||
s.bind(addr) |
|||
s.listen(1) |
|||
|
|||
print('listening on', addr) |
|||
|
|||
while True: |
|||
cl, addr = s.accept() |
|||
print('client connected from', addr) |
|||
cl_file = cl.makefile('rwb', 0) |
|||
while True: |
|||
line = cl_file.readline() |
|||
if not line or line == b'\r\n': |
|||
break |
|||
rows = ['<tr><td>%s</td><td>%d</td></tr>' % (str(p), p.value()) for p in pins] |
|||
response = html % '\n'.join(rows) |
|||
cl.send(response) |
|||
cl.close() |
@ -0,0 +1,12 @@ |
|||
Next steps |
|||
========== |
|||
|
|||
That brings us to the end of the tutorial! Hopefully by now you have a good |
|||
feel for the capabilities of MicroPython on the ESP8266 and understand how to |
|||
control both the WiFi and IO aspects of the chip. |
|||
|
|||
There are many features that were not covered in this tutorial. The best way |
|||
to learn about them is to read the full documentation of the modules, and to |
|||
experiment! |
|||
|
|||
Good luck creating your Internet of Things devices! |
@ -0,0 +1,37 @@ |
|||
Controlling 1-wire devices |
|||
========================== |
|||
|
|||
The 1-wire bus is a serial bus that uses just a single wire for communication |
|||
(in addition to wires for ground and power). The DS18B20 temperature sensor |
|||
is a very popular 1-wire device, and here we show how to use the onewire module |
|||
to read from such a device. |
|||
|
|||
For the following code to work you need to have at least one DS18S20 or DS18B20 temperature |
|||
sensor with its data line connected to GPIO12. You must also power the sensors |
|||
and connect a 4.7k Ohm resistor between the data pin and the power pin. :: |
|||
|
|||
import time |
|||
import machine |
|||
import onewire, ds18x20 |
|||
|
|||
# the device is on GPIO12 |
|||
dat = machine.Pin(12) |
|||
|
|||
# create the onewire object |
|||
ds = ds18x20.DS18X20(onewire.OneWire(dat)) |
|||
|
|||
# scan for devices on the bus |
|||
roms = ds.scan() |
|||
print('found devices:', roms) |
|||
|
|||
# loop 10 times and print all temperatures |
|||
for i in range(10): |
|||
print('temperatures:', end=' ') |
|||
ds.convert_temp() |
|||
time.sleep_ms(750) |
|||
for rom in roms: |
|||
print(ds.read_temp(rom), end=' ') |
|||
print() |
|||
|
|||
Note that you must execute the ``convert_temp()`` function to initiate a |
|||
temperature reading, then wait at least 750ms before reading the value. |
@ -0,0 +1,76 @@ |
|||
GPIO Pins |
|||
========= |
|||
|
|||
The way to connect your board to the external world, and control other |
|||
components, is through the GPIO pins. Not all pins are available to use, |
|||
in most cases only pins 0, 2, 4, 5, 12, 13, 14, 15, and 16 can be used. |
|||
|
|||
The pins are available in the machine module, so make sure you import that |
|||
first. Then you can create a pin using:: |
|||
|
|||
>>> pin = machine.Pin(0) |
|||
|
|||
Here, the "0" is the pin that you want to access. Usually you want to |
|||
configure the pin to be input or output, and you do this when constructing |
|||
it. To make an input pin use:: |
|||
|
|||
>>> pin = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP) |
|||
|
|||
You can either use PULL_UP or None for the input pull-mode. If it's |
|||
not specified then it defaults to None, which is no pull resistor. GPIO16 |
|||
has no pull-up mode. |
|||
You can read the value on the pin using:: |
|||
|
|||
>>> pin.value() |
|||
0 |
|||
|
|||
The pin on your board may return 0 or 1 here, depending on what it's connected |
|||
to. To make an output pin use:: |
|||
|
|||
>>> pin = machine.Pin(0, machine.Pin.OUT) |
|||
|
|||
Then set its value using:: |
|||
|
|||
>>> pin.value(0) |
|||
>>> pin.value(1) |
|||
|
|||
Or:: |
|||
|
|||
>>> pin.off() |
|||
>>> pin.on() |
|||
|
|||
External interrupts |
|||
------------------- |
|||
|
|||
All pins except number 16 can be configured to trigger a hard interrupt if their |
|||
input changes. You can set code (a callback function) to be executed on the |
|||
trigger. |
|||
|
|||
Let's first define a callback function, which must take a single argument, |
|||
being the pin that triggered the function. We will make the function just print |
|||
the pin:: |
|||
|
|||
>>> def callback(p): |
|||
... print('pin change', p) |
|||
|
|||
Next we will create two pins and configure them as inputs:: |
|||
|
|||
>>> from machine import Pin |
|||
>>> p0 = Pin(0, Pin.IN) |
|||
>>> p2 = Pin(2, Pin.IN) |
|||
|
|||
An finally we need to tell the pins when to trigger, and the function to call |
|||
when they detect an event:: |
|||
|
|||
>>> p0.irq(trigger=Pin.IRQ_FALLING, handler=callback) |
|||
>>> p2.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=callback) |
|||
|
|||
We set pin 0 to trigger only on a falling edge of the input (when it goes from |
|||
high to low), and set pin 2 to trigger on both a rising and falling edge. After |
|||
entering this code you can apply high and low voltages to pins 0 and 2 to see |
|||
the interrupt being executed. |
|||
|
|||
A hard interrupt will trigger as soon as the event occurs and will interrupt any |
|||
running code, including Python code. As such your callback functions are |
|||
limited in what they can do (they cannot allocate memory, for example) and |
|||
should be as short and simple as possible. |
@ -0,0 +1,61 @@ |
|||
Power control |
|||
============= |
|||
|
|||
The ESP8266 provides the ability to change the CPU frequency on the fly, and |
|||
enter a deep-sleep state. Both can be used to manage power consumption. |
|||
|
|||
Changing the CPU frequency |
|||
-------------------------- |
|||
|
|||
The machine module has a function to get and set the CPU frequency. To get the |
|||
current frequency use:: |
|||
|
|||
>>> import machine |
|||
>>> machine.freq() |
|||
80000000 |
|||
|
|||
By default the CPU runs at 80MHz. It can be changed to 160MHz if you need more |
|||
processing power, at the expense of current consumption:: |
|||
|
|||
>>> machine.freq(160000000) |
|||
>>> machine.freq() |
|||
160000000 |
|||
|
|||
You can change to the higher frequency just while your code does the heavy |
|||
processing and then change back when it's finished. |
|||
|
|||
Deep-sleep mode |
|||
--------------- |
|||
|
|||
The deep-sleep mode will shut down the ESP8266 and all its peripherals, |
|||
including the WiFi (but not including the real-time-clock, which is used to wake |
|||
the chip). This drastically reduces current consumption and is a good way to |
|||
make devices that can run for a while on a battery. |
|||
|
|||
To be able to use the deep-sleep feature you must connect GPIO16 to the reset |
|||
pin (RST on the Adafruit Feather HUZZAH board). Then the following code can be |
|||
used to sleep and wake the device:: |
|||
|
|||
import machine |
|||
|
|||
# configure RTC.ALARM0 to be able to wake the device |
|||
rtc = machine.RTC() |
|||
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP) |
|||
|
|||
# set RTC.ALARM0 to fire after 10 seconds (waking the device) |
|||
rtc.alarm(rtc.ALARM0, 10000) |
|||
|
|||
# put the device to sleep |
|||
machine.deepsleep() |
|||
|
|||
Note that when the chip wakes from a deep-sleep it is completely reset, |
|||
including all of the memory. The boot scripts will run as usual and you can |
|||
put code in them to check the reset cause to perhaps do something different if |
|||
the device just woke from a deep-sleep. For example, to print the reset cause |
|||
you can use:: |
|||
|
|||
if machine.reset_cause() == machine.DEEPSLEEP_RESET: |
|||
print('woke from a deep sleep') |
|||
else: |
|||
print('power on or hard reset') |
|||
|
@ -0,0 +1,87 @@ |
|||
Pulse Width Modulation |
|||
====================== |
|||
|
|||
Pulse width modulation (PWM) is a way to get an artificial analog output on a |
|||
digital pin. It achieves this by rapidly toggling the pin from low to high. |
|||
There are two parameters associated with this: the frequency of the toggling, |
|||
and the duty cycle. The duty cycle is defined to be how long the pin is high |
|||
compared with the length of a single period (low plus high time). Maximum |
|||
duty cycle is when the pin is high all of the time, and minimum is when it is |
|||
low all of the time. |
|||
|
|||
On the ESP8266 the pins 0, 2, 4, 5, 12, 13, 14 and 15 all support PWM. The |
|||
limitation is that they must all be at the same frequency, and the frequency |
|||
must be between 1Hz and 1kHz. |
|||
|
|||
To use PWM on a pin you must first create the pin object, for example:: |
|||
|
|||
>>> import machine |
|||
>>> p12 = machine.Pin(12) |
|||
|
|||
Then create the PWM object using:: |
|||
|
|||
>>> pwm12 = machine.PWM(p12) |
|||
|
|||
You can set the frequency and duty cycle using:: |
|||
|
|||
>>> pwm12.freq(500) |
|||
>>> pwm12.duty(512) |
|||
|
|||
Note that the duty cycle is between 0 (all off) and 1023 (all on), with 512 |
|||
being a 50% duty. Values beyond this min/max will be clipped. If you |
|||
print the PWM object then it will tell you its current configuration:: |
|||
|
|||
>>> pwm12 |
|||
PWM(12, freq=500, duty=512) |
|||
|
|||
You can also call the ``freq()`` and ``duty()`` methods with no arguments to |
|||
get their current values. |
|||
|
|||
The pin will continue to be in PWM mode until you deinitialise it using:: |
|||
|
|||
>>> pwm12.deinit() |
|||
|
|||
Fading an LED |
|||
------------- |
|||
|
|||
Let's use the PWM feature to fade an LED. Assuming your board has an LED |
|||
connected to pin 2 (ESP-12 modules do) we can create an LED-PWM object using:: |
|||
|
|||
>>> led = machine.PWM(machine.Pin(2), freq=1000) |
|||
|
|||
Notice that we can set the frequency in the PWM constructor. |
|||
|
|||
For the next part we will use timing and some math, so import these modules:: |
|||
|
|||
>>> import time, math |
|||
|
|||
Then create a function to pulse the LED:: |
|||
|
|||
>>> def pulse(l, t): |
|||
... for i in range(20): |
|||
... l.duty(int(math.sin(i / 10 * math.pi) * 500 + 500)) |
|||
... time.sleep_ms(t) |
|||
|
|||
You can try this function out using:: |
|||
|
|||
>>> pulse(led, 50) |
|||
|
|||
For a nice effect you can pulse many times in a row:: |
|||
|
|||
>>> for i in range(10): |
|||
... pulse(led, 20) |
|||
|
|||
Remember you can use ctrl-C to interrupt the code. |
|||
|
|||
Control a hobby servo |
|||
--------------------- |
|||
|
|||
Hobby servo motors can be controlled using PWM. They require a frequency of |
|||
50Hz and then a duty between about 40 and 115, with 77 being the centre value. |
|||
If you connect a servo to the power and ground pins, and then the signal line |
|||
to pin 12 (other pins will work just as well), you can control the motor using:: |
|||
|
|||
>>> servo = machine.PWM(machine.Pin(12), freq=50) |
|||
>>> servo.duty(40) |
|||
>>> servo.duty(115) |
|||
>>> servo.duty(77) |
@ -0,0 +1,212 @@ |
|||
Getting a MicroPython REPL prompt |
|||
================================= |
|||
|
|||
REPL stands for Read Evaluate Print Loop, and is the name given to the |
|||
interactive MicroPython prompt that you can access on the ESP8266. Using the |
|||
REPL is by far the easiest way to test out your code and run commands. |
|||
|
|||
There are two ways to access the REPL: either via a wired connection through the |
|||
UART serial port, or via WiFi. |
|||
|
|||
REPL over the serial port |
|||
------------------------- |
|||
|
|||
The REPL is always available on the UART0 serial peripheral, which is connected |
|||
to the pins GPIO1 for TX and GPIO3 for RX. The baudrate of the REPL is 115200. |
|||
If your board has a USB-serial convertor on it then you should be able to access |
|||
the REPL directly from your PC. Otherwise you will need to have a way of |
|||
communicating with the UART. |
|||
|
|||
To access the prompt over USB-serial you need to use a terminal emulator program. |
|||
On Windows TeraTerm is a good choice, on Mac you can use the built-in screen |
|||
program, and Linux has picocom and minicom. Of course, there are many other |
|||
terminal programs that will work, so pick your favourite! |
|||
|
|||
For example, on Linux you can try running:: |
|||
|
|||
picocom /dev/ttyUSB0 -b115200 |
|||
|
|||
Once you have made the connection over the serial port you can test if it is |
|||
working by hitting enter a few times. You should see the Python REPL prompt, |
|||
indicated by ``>>>``. |
|||
|
|||
WebREPL - a prompt over WiFi |
|||
---------------------------- |
|||
|
|||
WebREPL allows you to use the Python prompt over WiFi, connecting through a |
|||
browser. The latest versions of Firefox and Chrome are supported. |
|||
|
|||
For your convenience, WebREPL client is hosted at |
|||
`<http://micropython.org/webrepl>`__ . Alternatively, you can install it |
|||
locally from the the GitHub repository |
|||
`<https://github.com/micropython/webrepl>`__ . |
|||
|
|||
Before connecting to WebREPL, you should set a password and enable it via |
|||
a normal serial connection. Initial versions of MicroPython for ESP8266 |
|||
came with WebREPL automatically enabled on the boot and with the |
|||
ability to set a password via WiFi on the first connection, but as WebREPL |
|||
was becoming more widely known and popular, the initial setup has switched |
|||
to a wired connection for improved security:: |
|||
|
|||
import webrepl_setup |
|||
|
|||
Follow the on-screen instructions and prompts. To make any changes active, |
|||
you will need to reboot your device. |
|||
|
|||
To use WebREPL connect your computer to the ESP8266's access point |
|||
(MicroPython-xxxxxx, see the previous section about this). If you have |
|||
already reconfigured your ESP8266 to connect to a router then you can |
|||
skip this part. |
|||
|
|||
Once you are on the same network as the ESP8266 you click the "Connect" button |
|||
(if you are connecting via a router then you may need to change the IP address, |
|||
by default the IP address is correct when connected to the ESP8266's access |
|||
point). If the connection succeeds then you should see a password prompt. |
|||
|
|||
Once you type the password configured at the setup step above, press Enter once |
|||
more and you should get a prompt looking like ``>>>``. You can now start |
|||
typing Python commands! |
|||
|
|||
Using the REPL |
|||
-------------- |
|||
|
|||
Once you have a prompt you can start experimenting! Anything you type at the |
|||
prompt will be executed after you press the Enter key. MicroPython will run |
|||
the code that you enter and print the result (if there is one). If there is an |
|||
error with the text that you enter then an error message is printed. |
|||
|
|||
Try typing the following at the prompt:: |
|||
|
|||
>>> print('hello esp8266!') |
|||
hello esp8266! |
|||
|
|||
Note that you shouldn't type the ``>>>`` arrows, they are there to indicate that |
|||
you should type the text after it at the prompt. And then the line following is |
|||
what the device should respond with. In the end, once you have entered the text |
|||
``print("hello esp8266!")`` and pressed the Enter key, the output on your screen |
|||
should look exactly like it does above. |
|||
|
|||
If you already know some python you can now try some basic commands here. For |
|||
example:: |
|||
|
|||
>>> 1 + 2 |
|||
3 |
|||
>>> 1 / 2 |
|||
0.5 |
|||
>>> 12**34 |
|||
4922235242952026704037113243122008064 |
|||
|
|||
If your board has an LED attached to GPIO2 (the ESP-12 modules do) then you can |
|||
turn it on and off using the following code:: |
|||
|
|||
>>> import machine |
|||
>>> pin = machine.Pin(2, machine.Pin.OUT) |
|||
>>> pin.on() |
|||
>>> pin.off() |
|||
|
|||
Note that ``on`` method of a Pin might turn the LED off and ``off`` might |
|||
turn it on (or vice versa), depending on how the LED is wired on your board. |
|||
To resolve this, machine.Signal class is provided. |
|||
|
|||
Line editing |
|||
~~~~~~~~~~~~ |
|||
|
|||
You can edit the current line that you are entering using the left and right |
|||
arrow keys to move the cursor, as well as the delete and backspace keys. Also, |
|||
pressing Home or ctrl-A moves the cursor to the start of the line, and pressing |
|||
End or ctrl-E moves to the end of the line. |
|||
|
|||
Input history |
|||
~~~~~~~~~~~~~ |
|||
|
|||
The REPL remembers a certain number of previous lines of text that you entered |
|||
(up to 8 on the ESP8266). To recall previous lines use the up and down arrow |
|||
keys. |
|||
|
|||
Tab completion |
|||
~~~~~~~~~~~~~~ |
|||
|
|||
Pressing the Tab key will do an auto-completion of the current word that you are |
|||
entering. This can be very useful to find out functions and methods that a |
|||
module or object has. Try it out by typing "ma" and then pressing Tab. It |
|||
should complete to "machine" (assuming you imported machine in the above |
|||
example). Then type "." and press Tab again to see a list of all the functions |
|||
that the machine module has. |
|||
|
|||
Line continuation and auto-indent |
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|||
|
|||
Certain things that you type will need "continuing", that is, will need more |
|||
lines of text to make a proper Python statement. In this case the prompt will |
|||
change to ``...`` and the cursor will auto-indent the correct amount so you can |
|||
start typing the next line straight away. Try this by defining the following |
|||
function:: |
|||
|
|||
>>> def toggle(p): |
|||
... p.value(not p.value()) |
|||
... |
|||
... |
|||
... |
|||
>>> |
|||
|
|||
In the above, you needed to press the Enter key three times in a row to finish |
|||
the compound statement (that's the three lines with just dots on them). The |
|||
other way to finish a compound statement is to press backspace to get to the |
|||
start of the line, then press the Enter key. (If you did something wrong and |
|||
want to escape the continuation mode then press ctrl-C; all lines will be |
|||
ignored.) |
|||
|
|||
The function you just defined allows you to toggle a pin. The pin object you |
|||
created earlier should still exist (recreate it if it doesn't) and you can |
|||
toggle the LED using:: |
|||
|
|||
>>> toggle(pin) |
|||
|
|||
Let's now toggle the LED in a loop (if you don't have an LED then you can just |
|||
print some text instead of calling toggle, to see the effect):: |
|||
|
|||
>>> import time |
|||
>>> while True: |
|||
... toggle(pin) |
|||
... time.sleep_ms(500) |
|||
... |
|||
... |
|||
... |
|||
>>> |
|||
|
|||
This will toggle the LED at 1Hz (half a second on, half a second off). To stop |
|||
the toggling press ctrl-C, which will raise a KeyboardInterrupt exception and |
|||
break out of the loop. |
|||
|
|||
The time module provides some useful functions for making delays and doing |
|||
timing. Use tab completion to find out what they are and play around with them! |
|||
|
|||
Paste mode |
|||
~~~~~~~~~~ |
|||
|
|||
Pressing ctrl-E will enter a special paste mode. This allows you to copy and |
|||
paste a chunk of text into the REPL. If you press ctrl-E you will see the |
|||
paste-mode prompt:: |
|||
|
|||
paste mode; Ctrl-C to cancel, Ctrl-D to finish |
|||
=== |
|||
|
|||
You can then paste (or type) your text in. Note that none of the special keys |
|||
or commands work in paste mode (eg Tab or backspace), they are just accepted |
|||
as-is. Press ctrl-D to finish entering the text and execute it. |
|||
|
|||
Other control commands |
|||
~~~~~~~~~~~~~~~~~~~~~~ |
|||
|
|||
There are four other control commands: |
|||
|
|||
* Ctrl-A on a blank line will enter raw REPL mode. This is like a permanent |
|||
paste mode, except that characters are not echoed back. |
|||
|
|||
* Ctrl-B on a blank like goes to normal REPL mode. |
|||
|
|||
* Ctrl-C cancels any input, or interrupts the currently running code. |
|||
|
|||
* Ctrl-D on a blank line will do a soft reset. |
|||
|
|||
Note that ctrl-A and ctrl-D do not work with WebREPL. |
@ -0,0 +1,14 @@ |
|||
MicroPython documentation and references |
|||
======================================== |
|||
|
|||
.. toctree:: |
|||
|
|||
library/index.rst |
|||
reference/index.rst |
|||
genrst/index.rst |
|||
develop/index.rst |
|||
license.rst |
|||
pyboard/quickref.rst |
|||
esp8266/quickref.rst |
|||
esp32/quickref.rst |
|||
wipy/quickref.rst |
@ -0,0 +1,12 @@ |
|||
:mod:`_thread` -- multithreading support |
|||
======================================== |
|||
|
|||
.. module:: _thread |
|||
:synopsis: multithreading support |
|||
|
|||
|see_cpython_module| :mod:`python:_thread`. |
|||
|
|||
This module implements multithreading support. |
|||
|
|||
This module is highly experimental and its API is not yet fully settled |
|||
and not yet described in this documentation. |
@ -0,0 +1,159 @@ |
|||
:mod:`btree` -- simple BTree database |
|||
===================================== |
|||
|
|||
.. module:: btree |
|||
:synopsis: simple BTree database |
|||
|
|||
The ``btree`` module implements a simple key-value database using external |
|||
storage (disk files, or in general case, a random-access `stream`). Keys are |
|||
stored sorted in the database, and besides efficient retrieval by a key |
|||
value, a database also supports efficient ordered range scans (retrieval |
|||
of values with the keys in a given range). On the application interface |
|||
side, BTree database work as close a possible to a way standard `dict` |
|||
type works, one notable difference is that both keys and values must |
|||
be `bytes` objects (so, if you want to store objects of other types, you |
|||
need to serialize them to `bytes` first). |
|||
|
|||
The module is based on the well-known BerkelyDB library, version 1.xx. |
|||
|
|||
Example:: |
|||
|
|||
import btree |
|||
|
|||
# First, we need to open a stream which holds a database |
|||
# This is usually a file, but can be in-memory database |
|||
# using uio.BytesIO, a raw flash partition, etc. |
|||
# Oftentimes, you want to create a database file if it doesn't |
|||
# exist and open if it exists. Idiom below takes care of this. |
|||
# DO NOT open database with "a+b" access mode. |
|||
try: |
|||
f = open("mydb", "r+b") |
|||
except OSError: |
|||
f = open("mydb", "w+b") |
|||
|
|||
# Now open a database itself |
|||
db = btree.open(f) |
|||
|
|||
# The keys you add will be sorted internally in the database |
|||
db[b"3"] = b"three" |
|||
db[b"1"] = b"one" |
|||
db[b"2"] = b"two" |
|||
|
|||
# Assume that any changes are cached in memory unless |
|||
# explicitly flushed (or database closed). Flush database |
|||
# at the end of each "transaction". |
|||
db.flush() |
|||
|
|||
# Prints b'two' |
|||
print(db[b"2"]) |
|||
|
|||
# Iterate over sorted keys in the database, starting from b"2" |
|||
# until the end of the database, returning only values. |
|||
# Mind that arguments passed to values() method are *key* values. |
|||
# Prints: |
|||
# b'two' |
|||
# b'three' |
|||
for word in db.values(b"2"): |
|||
print(word) |
|||
|
|||
del db[b"2"] |
|||
|
|||
# No longer true, prints False |
|||
print(b"2" in db) |
|||
|
|||
# Prints: |
|||
# b"1" |
|||
# b"3" |
|||
for key in db: |
|||
print(key) |
|||
|
|||
db.close() |
|||
|
|||
# Don't forget to close the underlying stream! |
|||
f.close() |
|||
|
|||
|
|||
Functions |
|||
--------- |
|||
|
|||
.. function:: open(stream, \*, flags=0, pagesize=0, cachesize=0, minkeypage=0) |
|||
|
|||
Open a database from a random-access `stream` (like an open file). All |
|||
other parameters are optional and keyword-only, and allow to tweak advanced |
|||
parameters of the database operation (most users will not need them): |
|||
|
|||
* *flags* - Currently unused. |
|||
* *pagesize* - Page size used for the nodes in BTree. Acceptable range |
|||
is 512-65536. If 0, a port-specific default will be used, optimized for |
|||
port's memory usage and/or performance. |
|||
* *cachesize* - Suggested memory cache size in bytes. For a |
|||
board with enough memory using larger values may improve performance. |
|||
Cache policy is as follows: entire cache is not allocated at once; |
|||
instead, accessing a new page in database will allocate a memory buffer |
|||
for it, until value specified by *cachesize* is reached. Then, these |
|||
buffers will be managed using LRU (least recently used) policy. More |
|||
buffers may still be allocated if needed (e.g., if a database contains |
|||
big keys and/or values). Allocated cache buffers aren't reclaimed. |
|||
* *minkeypage* - Minimum number of keys to store per page. Default value |
|||
of 0 equivalent to 2. |
|||
|
|||
Returns a BTree object, which implements a dictionary protocol (set |
|||
of methods), and some additional methods described below. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: btree.close() |
|||
|
|||
Close the database. It's mandatory to close the database at the end of |
|||
processing, as some unwritten data may be still in the cache. Note that |
|||
this does not close underlying stream with which the database was opened, |
|||
it should be closed separately (which is also mandatory to make sure that |
|||
data flushed from buffer to the underlying storage). |
|||
|
|||
.. method:: btree.flush() |
|||
|
|||
Flush any data in cache to the underlying stream. |
|||
|
|||
.. method:: btree.__getitem__(key) |
|||
btree.get(key, default=None) |
|||
btree.__setitem__(key, val) |
|||
btree.__detitem__(key) |
|||
btree.__contains__(key) |
|||
|
|||
Standard dictionary methods. |
|||
|
|||
.. method:: btree.__iter__() |
|||
|
|||
A BTree object can be iterated over directly (similar to a dictionary) |
|||
to get access to all keys in order. |
|||
|
|||
.. method:: btree.keys([start_key, [end_key, [flags]]]) |
|||
btree.values([start_key, [end_key, [flags]]]) |
|||
btree.items([start_key, [end_key, [flags]]]) |
|||
|
|||
These methods are similar to standard dictionary methods, but also can |
|||
take optional parameters to iterate over a key sub-range, instead of |
|||
the entire database. Note that for all 3 methods, *start_key* and |
|||
*end_key* arguments represent key values. For example, `values()` |
|||
method will iterate over values corresponding to they key range |
|||
given. None values for *start_key* means "from the first key", no |
|||
*end_key* or its value of None means "until the end of database". |
|||
By default, range is inclusive of *start_key* and exclusive of |
|||
*end_key*, you can include *end_key* in iteration by passing *flags* |
|||
of `btree.INCL`. You can iterate in descending key direction |
|||
by passing *flags* of `btree.DESC`. The flags values can be ORed |
|||
together. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: INCL |
|||
|
|||
A flag for `keys()`, `values()`, `items()` methods to specify that |
|||
scanning should be inclusive of the end key. |
|||
|
|||
.. data:: DESC |
|||
|
|||
A flag for `keys()`, `values()`, `items()` methods to specify that |
|||
scanning should be in descending direction of keys. |
@ -0,0 +1,199 @@ |
|||
Builtin functions and exceptions |
|||
================================ |
|||
|
|||
All builtin functions and exceptions are described here. They are also |
|||
available via ``builtins`` module. |
|||
|
|||
Functions and types |
|||
------------------- |
|||
|
|||
.. function:: abs() |
|||
|
|||
.. function:: all() |
|||
|
|||
.. function:: any() |
|||
|
|||
.. function:: bin() |
|||
|
|||
.. class:: bool() |
|||
|
|||
.. class:: bytearray() |
|||
|
|||
.. class:: bytes() |
|||
|
|||
|see_cpython| `python:bytes`. |
|||
|
|||
.. function:: callable() |
|||
|
|||
.. function:: chr() |
|||
|
|||
.. function:: classmethod() |
|||
|
|||
.. function:: compile() |
|||
|
|||
.. class:: complex() |
|||
|
|||
.. function:: delattr(obj, name) |
|||
|
|||
The argument *name* should be a string, and this function deletes the named |
|||
attribute from the object given by *obj*. |
|||
|
|||
.. class:: dict() |
|||
|
|||
.. function:: dir() |
|||
|
|||
.. function:: divmod() |
|||
|
|||
.. function:: enumerate() |
|||
|
|||
.. function:: eval() |
|||
|
|||
.. function:: exec() |
|||
|
|||
.. function:: filter() |
|||
|
|||
.. class:: float() |
|||
|
|||
.. class:: frozenset() |
|||
|
|||
.. function:: getattr() |
|||
|
|||
.. function:: globals() |
|||
|
|||
.. function:: hasattr() |
|||
|
|||
.. function:: hash() |
|||
|
|||
.. function:: hex() |
|||
|
|||
.. function:: id() |
|||
|
|||
.. function:: input() |
|||
|
|||
.. class:: int() |
|||
|
|||
.. classmethod:: from_bytes(bytes, byteorder) |
|||
|
|||
In MicroPython, `byteorder` parameter must be positional (this is |
|||
compatible with CPython). |
|||
|
|||
.. method:: to_bytes(size, byteorder) |
|||
|
|||
In MicroPython, `byteorder` parameter must be positional (this is |
|||
compatible with CPython). |
|||
|
|||
.. function:: isinstance() |
|||
|
|||
.. function:: issubclass() |
|||
|
|||
.. function:: iter() |
|||
|
|||
.. function:: len() |
|||
|
|||
.. class:: list() |
|||
|
|||
.. function:: locals() |
|||
|
|||
.. function:: map() |
|||
|
|||
.. function:: max() |
|||
|
|||
.. class:: memoryview() |
|||
|
|||
.. function:: min() |
|||
|
|||
.. function:: next() |
|||
|
|||
.. class:: object() |
|||
|
|||
.. function:: oct() |
|||
|
|||
.. function:: open() |
|||
|
|||
.. function:: ord() |
|||
|
|||
.. function:: pow() |
|||
|
|||
.. function:: print() |
|||
|
|||
.. function:: property() |
|||
|
|||
.. function:: range() |
|||
|
|||
.. function:: repr() |
|||
|
|||
.. function:: reversed() |
|||
|
|||
.. function:: round() |
|||
|
|||
.. class:: set() |
|||
|
|||
.. function:: setattr() |
|||
|
|||
.. class:: slice() |
|||
|
|||
The *slice* builtin is the type that slice objects have. |
|||
|
|||
.. function:: sorted() |
|||
|
|||
.. function:: staticmethod() |
|||
|
|||
.. class:: str() |
|||
|
|||
.. function:: sum() |
|||
|
|||
.. function:: super() |
|||
|
|||
.. class:: tuple() |
|||
|
|||
.. function:: type() |
|||
|
|||
.. function:: zip() |
|||
|
|||
|
|||
Exceptions |
|||
---------- |
|||
|
|||
.. exception:: AssertionError |
|||
|
|||
.. exception:: AttributeError |
|||
|
|||
.. exception:: Exception |
|||
|
|||
.. exception:: ImportError |
|||
|
|||
.. exception:: IndexError |
|||
|
|||
.. exception:: KeyboardInterrupt |
|||
|
|||
.. exception:: KeyError |
|||
|
|||
.. exception:: MemoryError |
|||
|
|||
.. exception:: NameError |
|||
|
|||
.. exception:: NotImplementedError |
|||
|
|||
.. exception:: OSError |
|||
|
|||
|see_cpython| `python:OSError`. MicroPython doesn't implement ``errno`` |
|||
attribute, instead use the standard way to access exception arguments: |
|||
``exc.args[0]``. |
|||
|
|||
.. exception:: RuntimeError |
|||
|
|||
.. exception:: StopIteration |
|||
|
|||
.. exception:: SyntaxError |
|||
|
|||
.. exception:: SystemExit |
|||
|
|||
|see_cpython| `python:SystemExit`. |
|||
|
|||
.. exception:: TypeError |
|||
|
|||
|see_cpython| `python:TypeError`. |
|||
|
|||
.. exception:: ValueError |
|||
|
|||
.. exception:: ZeroDivisionError |
@ -0,0 +1,63 @@ |
|||
:mod:`cmath` -- mathematical functions for complex numbers |
|||
========================================================== |
|||
|
|||
.. module:: cmath |
|||
:synopsis: mathematical functions for complex numbers |
|||
|
|||
|see_cpython_module| :mod:`python:cmath`. |
|||
|
|||
The ``cmath`` module provides some basic mathematical functions for |
|||
working with complex numbers. |
|||
|
|||
Availability: not available on WiPy and ESP8266. Floating point support |
|||
required for this module. |
|||
|
|||
Functions |
|||
--------- |
|||
|
|||
.. function:: cos(z) |
|||
|
|||
Return the cosine of ``z``. |
|||
|
|||
.. function:: exp(z) |
|||
|
|||
Return the exponential of ``z``. |
|||
|
|||
.. function:: log(z) |
|||
|
|||
Return the natural logarithm of ``z``. The branch cut is along the negative real axis. |
|||
|
|||
.. function:: log10(z) |
|||
|
|||
Return the base-10 logarithm of ``z``. The branch cut is along the negative real axis. |
|||
|
|||
.. function:: phase(z) |
|||
|
|||
Returns the phase of the number ``z``, in the range (-pi, +pi]. |
|||
|
|||
.. function:: polar(z) |
|||
|
|||
Returns, as a tuple, the polar form of ``z``. |
|||
|
|||
.. function:: rect(r, phi) |
|||
|
|||
Returns the complex number with modulus ``r`` and phase ``phi``. |
|||
|
|||
.. function:: sin(z) |
|||
|
|||
Return the sine of ``z``. |
|||
|
|||
.. function:: sqrt(z) |
|||
|
|||
Return the square-root of ``z``. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: e |
|||
|
|||
base of the natural logarithm |
|||
|
|||
.. data:: pi |
|||
|
|||
the ratio of a circle's circumference to its diameter |
@ -0,0 +1,101 @@ |
|||
:mod:`esp` --- functions related to the ESP8266 and ESP32 |
|||
========================================================= |
|||
|
|||
.. module:: esp |
|||
:synopsis: functions related to the ESP8266 and ESP32 |
|||
|
|||
The ``esp`` module contains specific functions related to both the ESP8266 and |
|||
ESP32 modules. Some functions are only available on one or the other of these |
|||
ports. |
|||
|
|||
|
|||
Functions |
|||
--------- |
|||
|
|||
.. function:: sleep_type([sleep_type]) |
|||
|
|||
**Note**: ESP8266 only |
|||
|
|||
Get or set the sleep type. |
|||
|
|||
If the *sleep_type* parameter is provided, sets the sleep type to its |
|||
value. If the function is called without parameters, returns the current |
|||
sleep type. |
|||
|
|||
The possible sleep types are defined as constants: |
|||
|
|||
* ``SLEEP_NONE`` -- all functions enabled, |
|||
* ``SLEEP_MODEM`` -- modem sleep, shuts down the WiFi Modem circuit. |
|||
* ``SLEEP_LIGHT`` -- light sleep, shuts down the WiFi Modem circuit |
|||
and suspends the processor periodically. |
|||
|
|||
The system enters the set sleep mode automatically when possible. |
|||
|
|||
.. function:: deepsleep(time=0) |
|||
|
|||
**Note**: ESP8266 only - use `machine.deepsleep()` on ESP32 |
|||
|
|||
Enter deep sleep. |
|||
|
|||
The whole module powers down, except for the RTC clock circuit, which can |
|||
be used to restart the module after the specified time if the pin 16 is |
|||
connected to the reset pin. Otherwise the module will sleep until manually |
|||
reset. |
|||
|
|||
.. function:: flash_id() |
|||
|
|||
**Note**: ESP8266 only |
|||
|
|||
Read the device ID of the flash memory. |
|||
|
|||
.. function:: flash_size() |
|||
|
|||
Read the total size of the flash memory. |
|||
|
|||
.. function:: flash_user_start() |
|||
|
|||
Read the memory offset at which the user flash space begins. |
|||
|
|||
.. function:: flash_read(byte_offset, length_or_buffer) |
|||
|
|||
.. function:: flash_write(byte_offset, bytes) |
|||
|
|||
.. function:: flash_erase(sector_no) |
|||
|
|||
.. function:: set_native_code_location(start, length) |
|||
|
|||
**Note**: ESP8266 only |
|||
|
|||
Set the location that native code will be placed for execution after it is |
|||
compiled. Native code is emitted when the ``@micropython.native``, |
|||
``@micropython.viper`` and ``@micropython.asm_xtensa`` decorators are applied |
|||
to a function. The ESP8266 must execute code from either iRAM or the lower |
|||
1MByte of flash (which is memory mapped), and this function controls the |
|||
location. |
|||
|
|||
If *start* and *length* are both ``None`` then the native code location is |
|||
set to the unused portion of memory at the end of the iRAM1 region. The |
|||
size of this unused portion depends on the firmware and is typically quite |
|||
small (around 500 bytes), and is enough to store a few very small |
|||
functions. The advantage of using this iRAM1 region is that it does not |
|||
get worn out by writing to it. |
|||
|
|||
If neither *start* nor *length* are ``None`` then they should be integers. |
|||
*start* should specify the byte offset from the beginning of the flash at |
|||
which native code should be stored. *length* specifies how many bytes of |
|||
flash from *start* can be used to store native code. *start* and *length* |
|||
should be multiples of the sector size (being 4096 bytes). The flash will |
|||
be automatically erased before writing to it so be sure to use a region of |
|||
flash that is not otherwise used, for example by the firmware or the |
|||
filesystem. |
|||
|
|||
When using the flash to store native code *start+length* must be less |
|||
than or equal to 1MByte. Note that the flash can be worn out if repeated |
|||
erasures (and writes) are made so use this feature sparingly. |
|||
In particular, native code needs to be recompiled and rewritten to flash |
|||
on each boot (including wake from deepsleep). |
|||
|
|||
In both cases above, using iRAM1 or flash, if there is no more room left |
|||
in the specified region then the use of a native decorator on a function |
|||
will lead to `MemoryError` exception being raised during compilation of |
|||
that function. |
@ -0,0 +1,202 @@ |
|||
.. currentmodule:: esp32 |
|||
|
|||
:mod:`esp32` --- functionality specific to the ESP32 |
|||
==================================================== |
|||
|
|||
.. module:: esp32 |
|||
:synopsis: functionality specific to the ESP32 |
|||
|
|||
The ``esp32`` module contains functions and classes specifically aimed at |
|||
controlling ESP32 modules. |
|||
|
|||
|
|||
Functions |
|||
--------- |
|||
|
|||
.. function:: wake_on_touch(wake) |
|||
|
|||
Configure whether or not a touch will wake the device from sleep. |
|||
*wake* should be a boolean value. |
|||
|
|||
.. function:: wake_on_ext0(pin, level) |
|||
|
|||
Configure how EXT0 wakes the device from sleep. *pin* can be ``None`` |
|||
or a valid Pin object. *level* should be ``esp32.WAKEUP_ALL_LOW`` or |
|||
``esp32.WAKEUP_ANY_HIGH``. |
|||
|
|||
.. function:: wake_on_ext1(pins, level) |
|||
|
|||
Configure how EXT1 wakes the device from sleep. *pins* can be ``None`` |
|||
or a tuple/list of valid Pin objects. *level* should be ``esp32.WAKEUP_ALL_LOW`` |
|||
or ``esp32.WAKEUP_ANY_HIGH``. |
|||
|
|||
.. function:: raw_temperature() |
|||
|
|||
Read the raw value of the internal temperature sensor, returning an integer. |
|||
|
|||
.. function:: hall_sensor() |
|||
|
|||
Read the raw value of the internal Hall sensor, returning an integer. |
|||
|
|||
Flash partitions |
|||
---------------- |
|||
|
|||
This class gives access to the partitions in the device's flash memory. |
|||
|
|||
.. class:: Partition(id) |
|||
|
|||
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``. |
|||
|
|||
.. classmethod:: Partition.find(type=TYPE_APP, subtype=0xff, label=None) |
|||
|
|||
Find a partition specified by *type*, *subtype* and *label*. Returns a |
|||
(possibly empty) list of Partition objects. |
|||
|
|||
.. method:: Partition.info() |
|||
|
|||
Returns a 6-tuple ``(type, subtype, addr, size, label, encrypted)``. |
|||
|
|||
.. method:: Partition.readblocks(block_num, buf) |
|||
.. method:: Partition.readblocks(block_num, buf, offset) |
|||
.. method:: Partition.writeblocks(block_num, buf) |
|||
.. method:: Partition.writeblocks(block_num, buf, offset) |
|||
.. method:: Partition.ioctl(cmd, arg) |
|||
|
|||
These methods implement the simple and :ref:`extended |
|||
<block-device-interface>` block protocol defined by |
|||
:class:`uos.AbstractBlockDev`. |
|||
|
|||
.. method:: Partition.set_boot() |
|||
|
|||
Sets the partition as the boot partition. |
|||
|
|||
.. method:: Partition.get_next_update() |
|||
|
|||
Gets the next update partition after this one, and returns a new Partition object. |
|||
|
|||
Constants |
|||
~~~~~~~~~ |
|||
|
|||
.. data:: Partition.BOOT |
|||
Partition.RUNNING |
|||
|
|||
Used in the `Partition` constructor to fetch various partitions. |
|||
|
|||
.. data:: Partition.TYPE_APP |
|||
Partition.TYPE_DATA |
|||
|
|||
Used in `Partition.find` to specify the partition type. |
|||
|
|||
|
|||
.. _esp32.RMT: |
|||
|
|||
RMT |
|||
--- |
|||
|
|||
The RMT (Remote Control) module, specific to the ESP32, was originally designed |
|||
to send and receive infrared remote control signals. However, due to a flexible |
|||
design and very accurate (as low as 12.5ns) pulse generation, it can also be |
|||
used to transmit or receive many other types of digital signals:: |
|||
|
|||
import esp32 |
|||
from machine import Pin |
|||
|
|||
r = esp32.RMT(0, pin=Pin(18), clock_div=8) |
|||
r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8) |
|||
# The channel resolution is 100ns (1/(source_freq/clock_div)). |
|||
r.write_pulses((1, 20, 2, 40), start=0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns |
|||
|
|||
The input to the RMT module is an 80MHz clock (in the future it may be able to |
|||
configure the input clock but, for now, it's fixed). ``clock_div`` *divides* |
|||
the clock input which determines the resolution of the RMT channel. The |
|||
numbers specificed in ``write_pulses`` are multiplied by the resolution to |
|||
define the pulses. |
|||
|
|||
``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by |
|||
multiplying the resolution by a 15-bit (0-32,768) number. There are eight |
|||
channels (0-7) and each can have a different clock divider. |
|||
|
|||
So, in the example above, the 80MHz clock is divided by 8. Thus the |
|||
resolution is (1/(80Mhz/8)) 100ns. Since the ``start`` level is 0 and toggles |
|||
with each number, the bitstream is ``0101`` with durations of [100ns, 2000ns, |
|||
100ns, 4000ns]. |
|||
|
|||
For more details see Espressif's `ESP-IDF RMT documentation. |
|||
<https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/rmt.html>`_. |
|||
|
|||
.. Warning:: |
|||
The current MicroPython RMT implementation lacks some features, most notably |
|||
receiving pulses and carrier transmit. RMT should be considered a |
|||
*beta feature* and the interface may change in the future. |
|||
|
|||
|
|||
.. class:: RMT(channel, \*, pin=None, clock_div=8) |
|||
|
|||
This class provides access to one of the eight RMT channels. *channel* is |
|||
required and identifies which RMT channel (0-7) will be configured. *pin*, |
|||
also required, configures which Pin is bound to the RMT channel. *clock_div* |
|||
is an 8-bit clock divider that divides the source clock (80MHz) to the RMT |
|||
channel allowing the resolution to be specified. |
|||
|
|||
.. method:: RMT.source_freq() |
|||
|
|||
Returns the source clock frequency. Currently the source clock is not |
|||
configurable so this will always return 80MHz. |
|||
|
|||
.. method:: RMT.clock_div() |
|||
|
|||
Return the clock divider. Note that the channel resolution is |
|||
``1 / (source_freq / clock_div)``. |
|||
|
|||
.. method:: RMT.wait_done(timeout=0) |
|||
|
|||
Returns True if `RMT.write_pulses` has completed. |
|||
|
|||
If *timeout* (defined in ticks of ``source_freq / clock_div``) is specified |
|||
the method will wait for *timeout* or until `RMT.write_pulses` is complete, |
|||
returning ``False`` if the channel continues to transmit. |
|||
|
|||
.. Warning:: |
|||
Avoid using ``wait_done()`` if looping is enabled. |
|||
|
|||
.. method:: RMT.loop(enable_loop) |
|||
|
|||
Configure looping on the channel, allowing a stream of pulses to be |
|||
indefinitely repeated. *enable_loop* is bool, set to True to enable looping. |
|||
|
|||
.. method:: RMT.write_pulses(pulses, start) |
|||
|
|||
Begin sending *pulses*, a list or tuple defining the stream of pulses. The |
|||
length of each pulse is defined by a number to be multiplied by the channel |
|||
resolution ``(1 / (source_freq / clock_div))``. *start* defines whether the |
|||
stream starts at 0 or 1. |
|||
|
|||
|
|||
The Ultra-Low-Power co-processor |
|||
-------------------------------- |
|||
|
|||
.. class:: ULP() |
|||
|
|||
This class provides access to the Ultra-Low-Power co-processor. |
|||
|
|||
.. method:: ULP.set_wakeup_period(period_index, period_us) |
|||
|
|||
Set the wake-up period. |
|||
|
|||
.. method:: ULP.load_binary(load_addr, program_binary) |
|||
|
|||
Load a *program_binary* into the ULP at the given *load_addr*. |
|||
|
|||
.. method:: ULP.run(entry_point) |
|||
|
|||
Start the ULP running at the given *entry_point*. |
|||
|
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: esp32.WAKEUP_ALL_LOW |
|||
esp32.WAKEUP_ANY_HIGH |
|||
|
|||
Selects the wake level for pins. |
@ -0,0 +1,161 @@ |
|||
:mod:`framebuf` --- Frame buffer manipulation |
|||
============================================= |
|||
|
|||
.. module:: framebuf |
|||
:synopsis: Frame buffer manipulation |
|||
|
|||
This module provides a general frame buffer which can be used to create |
|||
bitmap images, which can then be sent to a display. |
|||
|
|||
class FrameBuffer |
|||
----------------- |
|||
|
|||
The FrameBuffer class provides a pixel buffer which can be drawn upon with |
|||
pixels, lines, rectangles, text and even other FrameBuffer's. It is useful |
|||
when generating output for displays. |
|||
|
|||
For example:: |
|||
|
|||
import framebuf |
|||
|
|||
# FrameBuffer needs 2 bytes for every RGB565 pixel |
|||
fbuf = framebuf.FrameBuffer(bytearray(10 * 100 * 2), 10, 100, framebuf.RGB565) |
|||
|
|||
fbuf.fill(0) |
|||
fbuf.text('MicroPython!', 0, 0, 0xffff) |
|||
fbuf.hline(0, 10, 96, 0xffff) |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: FrameBuffer(buffer, width, height, format, stride=width) |
|||
|
|||
Construct a FrameBuffer object. The parameters are: |
|||
|
|||
- *buffer* is an object with a buffer protocol which must be large |
|||
enough to contain every pixel defined by the width, height and |
|||
format of the FrameBuffer. |
|||
- *width* is the width of the FrameBuffer in pixels |
|||
- *height* is the height of the FrameBuffer in pixels |
|||
- *format* specifies the type of pixel used in the FrameBuffer; |
|||
permissible values are listed under Constants below. These set the |
|||
number of bits used to encode a color value and the layout of these |
|||
bits in *buffer*. |
|||
Where a color value c is passed to a method, c is a small integer |
|||
with an encoding that is dependent on the format of the FrameBuffer. |
|||
- *stride* is the number of pixels between each horizontal line |
|||
of pixels in the FrameBuffer. This defaults to *width* but may |
|||
need adjustments when implementing a FrameBuffer within another |
|||
larger FrameBuffer or screen. The *buffer* size must accommodate |
|||
an increased step size. |
|||
|
|||
One must specify valid *buffer*, *width*, *height*, *format* and |
|||
optionally *stride*. Invalid *buffer* size or dimensions may lead to |
|||
unexpected errors. |
|||
|
|||
Drawing primitive shapes |
|||
------------------------ |
|||
|
|||
The following methods draw shapes onto the FrameBuffer. |
|||
|
|||
.. method:: FrameBuffer.fill(c) |
|||
|
|||
Fill the entire FrameBuffer with the specified color. |
|||
|
|||
.. method:: FrameBuffer.pixel(x, y[, c]) |
|||
|
|||
If *c* is not given, get the color value of the specified pixel. |
|||
If *c* is given, set the specified pixel to the given color. |
|||
|
|||
.. method:: FrameBuffer.hline(x, y, w, c) |
|||
.. method:: FrameBuffer.vline(x, y, h, c) |
|||
.. method:: FrameBuffer.line(x1, y1, x2, y2, c) |
|||
|
|||
Draw a line from a set of coordinates using the given color and |
|||
a thickness of 1 pixel. The `line` method draws the line up to |
|||
a second set of coordinates whereas the `hline` and `vline` |
|||
methods draw horizontal and vertical lines respectively up to |
|||
a given length. |
|||
|
|||
.. method:: FrameBuffer.rect(x, y, w, h, c) |
|||
.. method:: FrameBuffer.fill_rect(x, y, w, h, c) |
|||
|
|||
Draw a rectangle at the given location, size and color. The `rect` |
|||
method draws only a 1 pixel outline whereas the `fill_rect` method |
|||
draws both the outline and interior. |
|||
|
|||
Drawing text |
|||
------------ |
|||
|
|||
.. method:: FrameBuffer.text(s, x, y[, c]) |
|||
|
|||
Write text to the FrameBuffer using the the coordinates as the upper-left |
|||
corner of the text. The color of the text can be defined by the optional |
|||
argument but is otherwise a default value of 1. All characters have |
|||
dimensions of 8x8 pixels and there is currently no way to change the font. |
|||
|
|||
|
|||
Other methods |
|||
------------- |
|||
|
|||
.. method:: FrameBuffer.scroll(xstep, ystep) |
|||
|
|||
Shift the contents of the FrameBuffer by the given vector. This may |
|||
leave a footprint of the previous colors in the FrameBuffer. |
|||
|
|||
.. method:: FrameBuffer.blit(fbuf, x, y[, key]) |
|||
|
|||
Draw another FrameBuffer on top of the current one at the given coordinates. |
|||
If *key* is specified then it should be a color integer and the |
|||
corresponding color will be considered transparent: all pixels with that |
|||
color value will not be drawn. |
|||
|
|||
This method works between FrameBuffer instances utilising different formats, |
|||
but the resulting colors may be unexpected due to the mismatch in color |
|||
formats. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: framebuf.MONO_VLSB |
|||
|
|||
Monochrome (1-bit) color format |
|||
This defines a mapping where the bits in a byte are vertically mapped with |
|||
bit 0 being nearest the top of the screen. Consequently each byte occupies |
|||
8 vertical pixels. Subsequent bytes appear at successive horizontal |
|||
locations until the rightmost edge is reached. Further bytes are rendered |
|||
at locations starting at the leftmost edge, 8 pixels lower. |
|||
|
|||
.. data:: framebuf.MONO_HLSB |
|||
|
|||
Monochrome (1-bit) color format |
|||
This defines a mapping where the bits in a byte are horizontally mapped. |
|||
Each byte occupies 8 horizontal pixels with bit 0 being the leftmost. |
|||
Subsequent bytes appear at successive horizontal locations until the |
|||
rightmost edge is reached. Further bytes are rendered on the next row, one |
|||
pixel lower. |
|||
|
|||
.. data:: framebuf.MONO_HMSB |
|||
|
|||
Monochrome (1-bit) color format |
|||
This defines a mapping where the bits in a byte are horizontally mapped. |
|||
Each byte occupies 8 horizontal pixels with bit 7 being the leftmost. |
|||
Subsequent bytes appear at successive horizontal locations until the |
|||
rightmost edge is reached. Further bytes are rendered on the next row, one |
|||
pixel lower. |
|||
|
|||
.. data:: framebuf.RGB565 |
|||
|
|||
Red Green Blue (16-bit, 5+6+5) color format |
|||
|
|||
.. data:: framebuf.GS2_HMSB |
|||
|
|||
Grayscale (2-bit) color format |
|||
|
|||
.. data:: framebuf.GS4_HMSB |
|||
|
|||
Grayscale (4-bit) color format |
|||
|
|||
.. data:: framebuf.GS8 |
|||
|
|||
Grayscale (8-bit) color format |
@ -0,0 +1,66 @@ |
|||
:mod:`gc` -- control the garbage collector |
|||
========================================== |
|||
|
|||
.. module:: gc |
|||
:synopsis: control the garbage collector |
|||
|
|||
|see_cpython_module| :mod:`python:gc`. |
|||
|
|||
Functions |
|||
--------- |
|||
|
|||
.. function:: enable() |
|||
|
|||
Enable automatic garbage collection. |
|||
|
|||
.. function:: disable() |
|||
|
|||
Disable automatic garbage collection. Heap memory can still be allocated, |
|||
and garbage collection can still be initiated manually using :meth:`gc.collect`. |
|||
|
|||
.. function:: collect() |
|||
|
|||
Run a garbage collection. |
|||
|
|||
.. function:: mem_alloc() |
|||
|
|||
Return the number of bytes of heap RAM that are allocated. |
|||
|
|||
.. admonition:: Difference to CPython |
|||
:class: attention |
|||
|
|||
This function is MicroPython extension. |
|||
|
|||
.. function:: mem_free() |
|||
|
|||
Return the number of bytes of available heap RAM, or -1 if this amount |
|||
is not known. |
|||
|
|||
.. admonition:: Difference to CPython |
|||
:class: attention |
|||
|
|||
This function is MicroPython extension. |
|||
|
|||
.. function:: threshold([amount]) |
|||
|
|||
Set or query the additional GC allocation threshold. Normally, a collection |
|||
is triggered only when a new allocation cannot be satisfied, i.e. on an |
|||
out-of-memory (OOM) condition. If this function is called, in addition to |
|||
OOM, a collection will be triggered each time after *amount* bytes have been |
|||
allocated (in total, since the previous time such an amount of bytes |
|||
have been allocated). *amount* is usually specified as less than the |
|||
full heap size, with the intention to trigger a collection earlier than when the |
|||
heap becomes exhausted, and in the hope that an early collection will prevent |
|||
excessive memory fragmentation. This is a heuristic measure, the effect |
|||
of which will vary from application to application, as well as |
|||
the optimal value of the *amount* parameter. |
|||
|
|||
Calling the function without argument will return the current value of |
|||
the threshold. A value of -1 means a disabled allocation threshold. |
|||
|
|||
.. admonition:: Difference to CPython |
|||
:class: attention |
|||
|
|||
This function is a MicroPython extension. CPython has a similar |
|||
function - ``set_threshold()``, but due to different GC |
|||
implementations, its signature and semantics are different. |
@ -0,0 +1,166 @@ |
|||
.. _micropython_lib: |
|||
|
|||
MicroPython libraries |
|||
===================== |
|||
|
|||
.. warning:: |
|||
|
|||
Important summary of this section |
|||
|
|||
* MicroPython implements a subset of Python functionality for each module. |
|||
* To ease extensibility, MicroPython versions of standard Python modules |
|||
usually have ``u`` ("micro") prefix. |
|||
* Any particular MicroPython variant or port may miss any feature/function |
|||
described in this general documentation (due to resource constraints or |
|||
other limitations). |
|||
|
|||
|
|||
This chapter describes modules (function and class libraries) which are built |
|||
into MicroPython. There are a few categories of such modules: |
|||
|
|||
* Modules which implement a subset of standard Python functionality and are not |
|||
intended to be extended by the user. |
|||
* Modules which implement a subset of Python functionality, with a provision |
|||
for extension by the user (via Python code). |
|||
* Modules which implement MicroPython extensions to the Python standard libraries. |
|||
* Modules specific to a particular `MicroPython port` and thus not portable. |
|||
|
|||
Note about the availability of the modules and their contents: This documentation |
|||
in general aspires to describe all modules and functions/classes which are |
|||
implemented in MicroPython project. However, MicroPython is highly configurable, and |
|||
each port to a particular board/embedded system makes available only a subset |
|||
of MicroPython libraries. For officially supported ports, there is an effort |
|||
to either filter out non-applicable items, or mark individual descriptions |
|||
with "Availability:" clauses describing which ports provide a given feature. |
|||
|
|||
With that in mind, please still be warned that some functions/classes |
|||
in a module (or even the entire module) described in this documentation **may be |
|||
unavailable** in a particular build of MicroPython on a particular system. The |
|||
best place to find general information of the availability/non-availability |
|||
of a particular feature is the "General Information" section which contains |
|||
information pertaining to a specific `MicroPython port`. |
|||
|
|||
On some ports you are able to discover the available, built-in libraries that |
|||
can be imported by entering the following at the REPL:: |
|||
|
|||
help('modules') |
|||
|
|||
Beyond the built-in libraries described in this documentation, many more |
|||
modules from the Python standard library, as well as further MicroPython |
|||
extensions to it, can be found in `micropython-lib`. |
|||
|
|||
Python standard libraries and micro-libraries |
|||
--------------------------------------------- |
|||
|
|||
The following standard Python libraries have been "micro-ified" to fit in with |
|||
the philosophy of MicroPython. They provide the core functionality of that |
|||
module and are intended to be a drop-in replacement for the standard Python |
|||
library. Some modules below use a standard Python name, but prefixed with "u", |
|||
e.g. ``ujson`` instead of ``json``. This is to signify that such a module is |
|||
micro-library, i.e. implements only a subset of CPython module functionality. |
|||
By naming them differently, a user has a choice to write a Python-level module |
|||
to extend functionality for better compatibility with CPython (indeed, this is |
|||
what done by the `micropython-lib` project mentioned above). |
|||
|
|||
On some embedded platforms, where it may be cumbersome to add Python-level |
|||
wrapper modules to achieve naming compatibility with CPython, micro-modules |
|||
are available both by their u-name, and also by their non-u-name. The |
|||
non-u-name can be overridden by a file of that name in your library path (``sys.path``). |
|||
For example, ``import json`` will first search for a file ``json.py`` (or package |
|||
directory ``json``) and load that module if it is found. If nothing is found, |
|||
it will fallback to loading the built-in ``ujson`` module. |
|||
|
|||
.. toctree:: |
|||
:maxdepth: 1 |
|||
|
|||
builtins.rst |
|||
cmath.rst |
|||
gc.rst |
|||
math.rst |
|||
sys.rst |
|||
uarray.rst |
|||
ubinascii.rst |
|||
ucollections.rst |
|||
uerrno.rst |
|||
uhashlib.rst |
|||
uheapq.rst |
|||
uio.rst |
|||
ujson.rst |
|||
uos.rst |
|||
ure.rst |
|||
uselect.rst |
|||
usocket.rst |
|||
ussl.rst |
|||
ustruct.rst |
|||
utime.rst |
|||
uzlib.rst |
|||
_thread.rst |
|||
|
|||
|
|||
MicroPython-specific libraries |
|||
------------------------------ |
|||
|
|||
Functionality specific to the MicroPython implementation is available in |
|||
the following libraries. |
|||
|
|||
.. toctree:: |
|||
:maxdepth: 1 |
|||
|
|||
btree.rst |
|||
framebuf.rst |
|||
machine.rst |
|||
micropython.rst |
|||
network.rst |
|||
ubluetooth.rst |
|||
ucryptolib.rst |
|||
uctypes.rst |
|||
|
|||
|
|||
Port-specific libraries |
|||
----------------------- |
|||
|
|||
In some cases the following port/board-specific libraries have functions or |
|||
classes similar to those in the :mod:`machine` library. Where this occurs, the |
|||
entry in the port specific library exposes hardware functionality unique to |
|||
that platform. |
|||
|
|||
To write portable code use functions and classes from the :mod:`machine` module. |
|||
To access platform-specific hardware use the appropriate library, e.g. |
|||
:mod:`pyb` in the case of the Pyboard. |
|||
|
|||
|
|||
Libraries specific to the pyboard |
|||
--------------------------------- |
|||
|
|||
The following libraries are specific to the pyboard. |
|||
|
|||
.. toctree:: |
|||
:maxdepth: 2 |
|||
|
|||
pyb.rst |
|||
lcd160cr.rst |
|||
|
|||
|
|||
Libraries specific to the WiPy |
|||
------------------------------ |
|||
|
|||
The following libraries and classes are specific to the WiPy. |
|||
|
|||
.. toctree:: |
|||
:maxdepth: 2 |
|||
|
|||
wipy.rst |
|||
machine.ADCWiPy.rst |
|||
machine.TimerWiPy.rst |
|||
|
|||
|
|||
Libraries specific to the ESP8266 and ESP32 |
|||
------------------------------------------- |
|||
|
|||
The following libraries are specific to the ESP8266 and ESP32. |
|||
|
|||
.. toctree:: |
|||
:maxdepth: 2 |
|||
|
|||
esp.rst |
|||
esp32.rst |
@ -0,0 +1,394 @@ |
|||
:mod:`lcd160cr` --- control of LCD160CR display |
|||
=============================================== |
|||
|
|||
.. module:: lcd160cr |
|||
:synopsis: control of LCD160CR display |
|||
|
|||
This module provides control of the MicroPython LCD160CR display. |
|||
|
|||
.. image:: http://micropython.org/resources/LCD160CRv10-persp.jpg |
|||
:alt: LCD160CRv1.0 picture |
|||
:width: 640px |
|||
|
|||
Further resources are available via the following links: |
|||
|
|||
* `LCD160CRv1.0 reference manual <http://micropython.org/resources/LCD160CRv10-refmanual.pdf>`_ (100KiB PDF) |
|||
* `LCD160CRv1.0 schematics <http://micropython.org/resources/LCD160CRv10-schematics.pdf>`_ (1.6MiB PDF) |
|||
|
|||
class LCD160CR |
|||
-------------- |
|||
|
|||
The LCD160CR class provides an interface to the display. Create an |
|||
instance of this class and use its methods to draw to the LCD and get |
|||
the status of the touch panel. |
|||
|
|||
For example:: |
|||
|
|||
import lcd160cr |
|||
|
|||
lcd = lcd160cr.LCD160CR('X') |
|||
lcd.set_orient(lcd160cr.PORTRAIT) |
|||
lcd.set_pos(0, 0) |
|||
lcd.set_text_color(lcd.rgb(255, 0, 0), lcd.rgb(0, 0, 0)) |
|||
lcd.set_font(1) |
|||
lcd.write('Hello MicroPython!') |
|||
print('touch:', lcd.get_touch()) |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: LCD160CR(connect=None, \*, pwr=None, i2c=None, spi=None, i2c_addr=98) |
|||
|
|||
Construct an LCD160CR object. The parameters are: |
|||
|
|||
- *connect* is a string specifying the physical connection of the LCD |
|||
display to the board; valid values are "X", "Y", "XY", "YX". |
|||
Use "X" when the display is connected to a pyboard in the X-skin |
|||
position, and "Y" when connected in the Y-skin position. "XY" |
|||
and "YX" are used when the display is connected to the right or |
|||
left side of the pyboard, respectively. |
|||
- *pwr* is a Pin object connected to the LCD's power/enabled pin. |
|||
- *i2c* is an I2C object connected to the LCD's I2C interface. |
|||
- *spi* is an SPI object connected to the LCD's SPI interface. |
|||
- *i2c_addr* is the I2C address of the display. |
|||
|
|||
One must specify either a valid *connect* or all of *pwr*, *i2c* and *spi*. |
|||
If a valid *connect* is given then any of *pwr*, *i2c* or *spi* which are |
|||
not passed as parameters (i.e. they are ``None``) will be created based on the |
|||
value of *connect*. This allows to override the default interface to the |
|||
display if needed. |
|||
|
|||
The default values are: |
|||
|
|||
- "X" is for the X-skin and uses: |
|||
``pwr=Pin("X4")``, ``i2c=I2C("X")``, ``spi=SPI("X")`` |
|||
- "Y" is for the Y-skin and uses: |
|||
``pwr=Pin("Y4")``, ``i2c=I2C("Y")``, ``spi=SPI("Y")`` |
|||
- "XY" is for the right-side and uses: |
|||
``pwr=Pin("X4")``, ``i2c=I2C("Y")``, ``spi=SPI("X")`` |
|||
- "YX" is for the left-side and uses: |
|||
``pwr=Pin("Y4")``, ``i2c=I2C("X")``, ``spi=SPI("Y")`` |
|||
|
|||
See `this image <http://micropython.org/resources/LCD160CRv10-positions.jpg>`_ |
|||
for how the display can be connected to the pyboard. |
|||
|
|||
Static methods |
|||
-------------- |
|||
|
|||
.. staticmethod:: LCD160CR.rgb(r, g, b) |
|||
|
|||
Return a 16-bit integer representing the given rgb color values. The |
|||
16-bit value can be used to set the font color (see |
|||
:meth:`LCD160CR.set_text_color`) pen color (see :meth:`LCD160CR.set_pen`) |
|||
and draw individual pixels. |
|||
|
|||
.. staticmethod:: LCD160CR.clip_line(data, w, h): |
|||
|
|||
Clip the given line data. This is for internal use. |
|||
|
|||
Instance members |
|||
---------------- |
|||
|
|||
The following instance members are publicly accessible. |
|||
|
|||
.. data:: LCD160CR.w |
|||
.. data:: LCD160CR.h |
|||
|
|||
The width and height of the display, respectively, in pixels. These |
|||
members are updated when calling :meth:`LCD160CR.set_orient` and should |
|||
be considered read-only. |
|||
|
|||
Setup commands |
|||
-------------- |
|||
|
|||
.. method:: LCD160CR.set_power(on) |
|||
|
|||
Turn the display on or off, depending on the given value of *on*: 0 or ``False`` |
|||
will turn the display off, and 1 or ``True`` will turn it on. |
|||
|
|||
.. method:: LCD160CR.set_orient(orient) |
|||
|
|||
Set the orientation of the display. The *orient* parameter can be one |
|||
of `PORTRAIT`, `LANDSCAPE`, `PORTRAIT_UPSIDEDOWN`, `LANDSCAPE_UPSIDEDOWN`. |
|||
|
|||
.. method:: LCD160CR.set_brightness(value) |
|||
|
|||
Set the brightness of the display, between 0 and 31. |
|||
|
|||
.. method:: LCD160CR.set_i2c_addr(addr) |
|||
|
|||
Set the I2C address of the display. The *addr* value must have the |
|||
lower 2 bits cleared. |
|||
|
|||
.. method:: LCD160CR.set_uart_baudrate(baudrate) |
|||
|
|||
Set the baudrate of the UART interface. |
|||
|
|||
.. method:: LCD160CR.set_startup_deco(value) |
|||
|
|||
Set the start-up decoration of the display. The *value* parameter can be a |
|||
logical or of `STARTUP_DECO_NONE`, `STARTUP_DECO_MLOGO`, `STARTUP_DECO_INFO`. |
|||
|
|||
.. method:: LCD160CR.save_to_flash() |
|||
|
|||
Save the following parameters to flash so they persist on restart and power up: |
|||
initial decoration, orientation, brightness, UART baud rate, I2C address. |
|||
|
|||
Pixel access methods |
|||
-------------------- |
|||
|
|||
The following methods manipulate individual pixels on the display. |
|||
|
|||
.. method:: LCD160CR.set_pixel(x, y, c) |
|||
|
|||
Set the specified pixel to the given color. The color should be a 16-bit |
|||
integer and can be created by :meth:`LCD160CR.rgb`. |
|||
|
|||
.. method:: LCD160CR.get_pixel(x, y) |
|||
|
|||
Get the 16-bit value of the specified pixel. |
|||
|
|||
.. method:: LCD160CR.get_line(x, y, buf) |
|||
|
|||
Low-level method to get a line of pixels into the given buffer. |
|||
To read *n* pixels *buf* should be *2*n+1* bytes in length. The first byte |
|||
is a dummy byte and should be ignored, and subsequent bytes represent the |
|||
pixels in the line starting at coordinate *(x, y)*. |
|||
|
|||
.. method:: LCD160CR.screen_dump(buf, x=0, y=0, w=None, h=None) |
|||
|
|||
Dump the contents of the screen to the given buffer. The parameters *x* and *y* |
|||
specify the starting coordinate, and *w* and *h* the size of the region. If *w* |
|||
or *h* are ``None`` then they will take on their maximum values, set by the size |
|||
of the screen minus the given *x* and *y* values. *buf* should be large enough |
|||
to hold ``2*w*h`` bytes. If it's smaller then only the initial horizontal lines |
|||
will be stored. |
|||
|
|||
.. method:: LCD160CR.screen_load(buf) |
|||
|
|||
Load the entire screen from the given buffer. |
|||
|
|||
Drawing text |
|||
------------ |
|||
|
|||
To draw text one sets the position, color and font, and then uses |
|||
`LCD160CR.write` to draw the text. |
|||
|
|||
.. method:: LCD160CR.set_pos(x, y) |
|||
|
|||
Set the position for text output using :meth:`LCD160CR.write`. The position |
|||
is the upper-left corner of the text. |
|||
|
|||
.. method:: LCD160CR.set_text_color(fg, bg) |
|||
|
|||
Set the foreground and background color of the text. |
|||
|
|||
.. method:: LCD160CR.set_font(font, scale=0, bold=0, trans=0, scroll=0) |
|||
|
|||
Set the font for the text. Subsequent calls to `write` will use the newly |
|||
configured font. The parameters are: |
|||
|
|||
- *font* is the font family to use, valid values are 0, 1, 2, 3. |
|||
- *scale* is a scaling value for each character pixel, where the pixels |
|||
are drawn as a square with side length equal to *scale + 1*. The value |
|||
can be between 0 and 63. |
|||
- *bold* controls the number of pixels to overdraw each character pixel, |
|||
making a bold effect. The lower 2 bits of *bold* are the number of |
|||
pixels to overdraw in the horizontal direction, and the next 2 bits are |
|||
for the vertical direction. For example, a *bold* value of 5 will |
|||
overdraw 1 pixel in both the horizontal and vertical directions. |
|||
- *trans* can be either 0 or 1 and if set to 1 the characters will be |
|||
drawn with a transparent background. |
|||
- *scroll* can be either 0 or 1 and if set to 1 the display will do a |
|||
soft scroll if the text moves to the next line. |
|||
|
|||
.. method:: LCD160CR.write(s) |
|||
|
|||
Write text to the display, using the current position, color and font. |
|||
As text is written the position is automatically incremented. The |
|||
display supports basic VT100 control codes such as newline and backspace. |
|||
|
|||
Drawing primitive shapes |
|||
------------------------ |
|||
|
|||
Primitive drawing commands use a foreground and background color set by the |
|||
`set_pen` method. |
|||
|
|||
.. method:: LCD160CR.set_pen(line, fill) |
|||
|
|||
Set the line and fill color for primitive shapes. |
|||
|
|||
.. method:: LCD160CR.erase() |
|||
|
|||
Erase the entire display to the pen fill color. |
|||
|
|||
.. method:: LCD160CR.dot(x, y) |
|||
|
|||
Draw a single pixel at the given location using the pen line color. |
|||
|
|||
.. method:: LCD160CR.rect(x, y, w, h) |
|||
.. method:: LCD160CR.rect_outline(x, y, w, h) |
|||
.. method:: LCD160CR.rect_interior(x, y, w, h) |
|||
|
|||
Draw a rectangle at the given location and size using the pen line |
|||
color for the outline, and the pen fill color for the interior. |
|||
The `rect` method draws the outline and interior, while the other methods |
|||
just draw one or the other. |
|||
|
|||
.. method:: LCD160CR.line(x1, y1, x2, y2) |
|||
|
|||
Draw a line between the given coordinates using the pen line color. |
|||
|
|||
.. method:: LCD160CR.dot_no_clip(x, y) |
|||
.. method:: LCD160CR.rect_no_clip(x, y, w, h) |
|||
.. method:: LCD160CR.rect_outline_no_clip(x, y, w, h) |
|||
.. method:: LCD160CR.rect_interior_no_clip(x, y, w, h) |
|||
.. method:: LCD160CR.line_no_clip(x1, y1, x2, y2) |
|||
|
|||
These methods are as above but don't do any clipping on the input |
|||
coordinates. They are faster than the clipping versions and can be |
|||
used when you know that the coordinates are within the display. |
|||
|
|||
.. method:: LCD160CR.poly_dot(data) |
|||
|
|||
Draw a sequence of dots using the pen line color. |
|||
The *data* should be a buffer of bytes, with each successive pair of |
|||
bytes corresponding to coordinate pairs (x, y). |
|||
|
|||
.. method:: LCD160CR.poly_line(data) |
|||
|
|||
Similar to :meth:`LCD160CR.poly_dot` but draws lines between the dots. |
|||
|
|||
Touch screen methods |
|||
-------------------- |
|||
|
|||
.. method:: LCD160CR.touch_config(calib=False, save=False, irq=None) |
|||
|
|||
Configure the touch panel: |
|||
|
|||
- If *calib* is ``True`` then the call will trigger a touch calibration of |
|||
the resistive touch sensor. This requires the user to touch various |
|||
parts of the screen. |
|||
- If *save* is ``True`` then the touch parameters will be saved to NVRAM |
|||
to persist across reset/power up. |
|||
- If *irq* is ``True`` then the display will be configured to pull the IRQ |
|||
line low when a touch force is detected. If *irq* is ``False`` then this |
|||
feature is disabled. If *irq* is ``None`` (the default value) then no |
|||
change is made to this setting. |
|||
|
|||
.. method:: LCD160CR.is_touched() |
|||
|
|||
Returns a boolean: ``True`` if there is currently a touch force on the screen, |
|||
``False`` otherwise. |
|||
|
|||
.. method:: LCD160CR.get_touch() |
|||
|
|||
Returns a 3-tuple of: *(active, x, y)*. If there is currently a touch force |
|||
on the screen then *active* is 1, otherwise it is 0. The *x* and *y* values |
|||
indicate the position of the current or most recent touch. |
|||
|
|||
Advanced commands |
|||
----------------- |
|||
|
|||
.. method:: LCD160CR.set_spi_win(x, y, w, h) |
|||
|
|||
Set the window that SPI data is written to. |
|||
|
|||
.. method:: LCD160CR.fast_spi(flush=True) |
|||
|
|||
Ready the display to accept RGB pixel data on the SPI bus, resetting the location |
|||
of the first byte to go to the top-left corner of the window set by |
|||
:meth:`LCD160CR.set_spi_win`. |
|||
The method returns an SPI object which can be used to write the pixel data. |
|||
|
|||
Pixels should be sent as 16-bit RGB values in the 5-6-5 format. The destination |
|||
counter will increase as data is sent, and data can be sent in arbitrary sized |
|||
chunks. Once the destination counter reaches the end of the window specified by |
|||
:meth:`LCD160CR.set_spi_win` it will wrap around to the top-left corner of that window. |
|||
|
|||
.. method:: LCD160CR.show_framebuf(buf) |
|||
|
|||
Show the given buffer on the display. *buf* should be an array of bytes containing |
|||
the 16-bit RGB values for the pixels, and they will be written to the area |
|||
specified by :meth:`LCD160CR.set_spi_win`, starting from the top-left corner. |
|||
|
|||
The `framebuf <framebuf.html>`_ module can be used to construct frame buffers |
|||
and provides drawing primitives. Using a frame buffer will improve |
|||
performance of animations when compared to drawing directly to the screen. |
|||
|
|||
.. method:: LCD160CR.set_scroll(on) |
|||
|
|||
Turn scrolling on or off. This controls globally whether any window regions will |
|||
scroll. |
|||
|
|||
.. method:: LCD160CR.set_scroll_win(win, x=-1, y=0, w=0, h=0, vec=0, pat=0, fill=0x07e0, color=0) |
|||
|
|||
Configure a window region for scrolling: |
|||
|
|||
- *win* is the window id to configure. There are 0..7 standard windows for |
|||
general purpose use. Window 8 is the text scroll window (the ticker). |
|||
- *x*, *y*, *w*, *h* specify the location of the window in the display. |
|||
- *vec* specifies the direction and speed of scroll: it is a 16-bit value |
|||
of the form ``0bF.ddSSSSSSSSSSSS``. *dd* is 0, 1, 2, 3 for +x, +y, -x, |
|||
-y scrolling. *F* sets the speed format, with 0 meaning that the window |
|||
is shifted *S % 256* pixel every frame, and 1 meaning that the window |
|||
is shifted 1 pixel every *S* frames. |
|||
- *pat* is a 16-bit pattern mask for the background. |
|||
- *fill* is the fill color. |
|||
- *color* is the extra color, either of the text or pattern foreground. |
|||
|
|||
.. method:: LCD160CR.set_scroll_win_param(win, param, value) |
|||
|
|||
Set a single parameter of a scrolling window region: |
|||
|
|||
- *win* is the window id, 0..8. |
|||
- *param* is the parameter number to configure, 0..7, and corresponds |
|||
to the parameters in the `set_scroll_win` method. |
|||
- *value* is the value to set. |
|||
|
|||
.. method:: LCD160CR.set_scroll_buf(s) |
|||
|
|||
Set the string for scrolling in window 8. The parameter *s* must be a string |
|||
with length 32 or less. |
|||
|
|||
.. method:: LCD160CR.jpeg(buf) |
|||
|
|||
Display a JPEG. *buf* should contain the entire JPEG data. JPEG data should |
|||
not include EXIF information. The following encodings are supported: Baseline |
|||
DCT, Huffman coding, 8 bits per sample, 3 color components, YCbCr4:2:2. |
|||
The origin of the JPEG is set by :meth:`LCD160CR.set_pos`. |
|||
|
|||
.. method:: LCD160CR.jpeg_start(total_len) |
|||
.. method:: LCD160CR.jpeg_data(buf) |
|||
|
|||
Display a JPEG with the data split across multiple buffers. There must be |
|||
a single call to `jpeg_start` to begin with, specifying the total number of |
|||
bytes in the JPEG. Then this number of bytes must be transferred to the |
|||
display using one or more calls to the `jpeg_data` command. |
|||
|
|||
.. method:: LCD160CR.feed_wdt() |
|||
|
|||
The first call to this method will start the display's internal watchdog |
|||
timer. Subsequent calls will feed the watchdog. The timeout is roughly 30 |
|||
seconds. |
|||
|
|||
.. method:: LCD160CR.reset() |
|||
|
|||
Reset the display. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: lcd160cr.PORTRAIT |
|||
lcd160cr.LANDSCAPE |
|||
lcd160cr.PORTRAIT_UPSIDEDOWN |
|||
lcd160cr.LANDSCAPE_UPSIDEDOWN |
|||
|
|||
Orientations of the display, used by :meth:`LCD160CR.set_orient`. |
|||
|
|||
.. data:: lcd160cr.STARTUP_DECO_NONE |
|||
lcd160cr.STARTUP_DECO_MLOGO |
|||
lcd160cr.STARTUP_DECO_INFO |
|||
|
|||
Types of start-up decoration, can be OR'ed together, used by |
|||
:meth:`LCD160CR.set_startup_deco`. |
@ -0,0 +1,35 @@ |
|||
.. currentmodule:: machine |
|||
.. _machine.ADC: |
|||
|
|||
class ADC -- analog to digital conversion |
|||
========================================= |
|||
|
|||
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. |
|||
|
|||
Example usage:: |
|||
|
|||
import machine |
|||
|
|||
adc = machine.ADC(pin) # create an ADC object acting on a pin |
|||
val = adc.read_u16() # read a raw analog value in the range 0-65535 |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: ADC(id) |
|||
|
|||
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. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. 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. |
@ -0,0 +1,81 @@ |
|||
.. currentmodule:: machine |
|||
.. _machine.ADCWiPy: |
|||
|
|||
class ADCWiPy -- analog to digital conversion |
|||
============================================= |
|||
|
|||
.. note:: |
|||
|
|||
This class is a non-standard ADC implementation for the WiPy. |
|||
It is available simply as ``machine.ADC`` on the WiPy but is named in the |
|||
documentation below as ``machine.ADCWiPy`` to distinguish it from the |
|||
more general :ref:`machine.ADC <machine.ADC>` class. |
|||
|
|||
Usage:: |
|||
|
|||
import machine |
|||
|
|||
adc = machine.ADC() # create an ADC object |
|||
apin = adc.channel(pin='GP3') # create an analog pin on GP3 |
|||
val = apin() # read an analog value |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: ADCWiPy(id=0, \*, bits=12) |
|||
|
|||
Create an ADC object associated with the given pin. |
|||
This allows you to then read analog values on that pin. |
|||
For more info check the `pinout and alternate functions |
|||
table. <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_ |
|||
|
|||
.. warning:: |
|||
|
|||
ADC pin input range is 0-1.4V (being 1.8V the absolute maximum that it |
|||
can withstand). When GP2, GP3, GP4 or GP5 are remapped to the |
|||
ADC block, 1.8 V is the maximum. If these pins are used in digital mode, |
|||
then the maximum allowed input is 3.6V. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: ADCWiPy.channel(id, \*, pin) |
|||
|
|||
Create an analog pin. If only channel ID is given, the correct pin will |
|||
be selected. Alternatively, only the pin can be passed and the correct |
|||
channel will be selected. Examples:: |
|||
|
|||
# all of these are equivalent and enable ADC channel 1 on GP3 |
|||
apin = adc.channel(1) |
|||
apin = adc.channel(pin='GP3') |
|||
apin = adc.channel(id=1, pin='GP3') |
|||
|
|||
.. method:: ADCWiPy.init() |
|||
|
|||
Enable the ADC block. |
|||
|
|||
.. method:: ADCWiPy.deinit() |
|||
|
|||
Disable the ADC block. |
|||
|
|||
class ADCChannel --- read analog values from internal or external sources |
|||
========================================================================= |
|||
|
|||
ADC channels can be connected to internal points of the MCU or to GPIO pins. |
|||
ADC channels are created using the ADC.channel method. |
|||
|
|||
.. method:: adcchannel() |
|||
|
|||
Fast method to read the channel value. |
|||
|
|||
.. method:: adcchannel.value() |
|||
|
|||
Read the channel value. |
|||
|
|||
.. method:: adcchannel.init() |
|||
|
|||
Re-init (and effectively enable) the ADC channel. |
|||
|
|||
.. method:: adcchannel.deinit() |
|||
|
|||
Disable the ADC channel. |
@ -0,0 +1,180 @@ |
|||
.. currentmodule:: machine |
|||
.. _machine.I2C: |
|||
|
|||
class I2C -- a two-wire serial protocol |
|||
======================================= |
|||
|
|||
I2C is a two-wire protocol for communicating between devices. At the physical |
|||
level it consists of 2 wires: SCL and SDA, the clock and data lines respectively. |
|||
|
|||
I2C objects are created attached to a specific bus. They can be initialised |
|||
when created, or initialised later on. |
|||
|
|||
Printing the I2C object gives you information about its configuration. |
|||
|
|||
Example usage:: |
|||
|
|||
from machine import I2C |
|||
|
|||
i2c = I2C(freq=400000) # create I2C peripheral at frequency of 400kHz |
|||
# depending on the port, extra parameters may be required |
|||
# to select the peripheral and/or pins to use |
|||
|
|||
i2c.scan() # scan for slaves, returning a list of 7-bit addresses |
|||
|
|||
i2c.writeto(42, b'123') # write 3 bytes to slave with 7-bit address 42 |
|||
i2c.readfrom(42, 4) # read 4 bytes from slave with 7-bit address 42 |
|||
|
|||
i2c.readfrom_mem(42, 8, 3) # read 3 bytes from memory of slave 42, |
|||
# starting at memory-address 8 in the slave |
|||
i2c.writeto_mem(42, 2, b'\x10') # write 1 byte to memory of slave 42 |
|||
# starting at address 2 in the slave |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: I2C(id=-1, \*, scl, sda, freq=400000) |
|||
|
|||
Construct and return a new I2C object using the following parameters: |
|||
|
|||
- *id* identifies a particular I2C peripheral. The default |
|||
value of -1 selects a software implementation of I2C which can |
|||
work (in most cases) with arbitrary pins for SCL and SDA. |
|||
If *id* is -1 then *scl* and *sda* must be specified. Other |
|||
allowed values for *id* depend on the particular port/board, |
|||
and specifying *scl* and *sda* may or may not be required or |
|||
allowed in this case. |
|||
- *scl* should be a pin object specifying the pin to use for SCL. |
|||
- *sda* should be a pin object specifying the pin to use for SDA. |
|||
- *freq* should be an integer which sets the maximum frequency |
|||
for SCL. |
|||
|
|||
General Methods |
|||
--------------- |
|||
|
|||
.. method:: I2C.init(scl, sda, \*, freq=400000) |
|||
|
|||
Initialise the I2C bus with the given arguments: |
|||
|
|||
- *scl* is a pin object for the SCL line |
|||
- *sda* is a pin object for the SDA line |
|||
- *freq* is the SCL clock rate |
|||
|
|||
.. method:: I2C.deinit() |
|||
|
|||
Turn off the I2C bus. |
|||
|
|||
Availability: WiPy. |
|||
|
|||
.. method:: I2C.scan() |
|||
|
|||
Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of |
|||
those that respond. A device responds if it pulls the SDA line low after |
|||
its address (including a write bit) is sent on the bus. |
|||
|
|||
Primitive I2C operations |
|||
------------------------ |
|||
|
|||
The following methods implement the primitive I2C master bus operations and can |
|||
be combined to make any I2C transaction. They are provided if you need more |
|||
control over the bus, otherwise the standard methods (see below) can be used. |
|||
|
|||
These methods are available on software I2C only. |
|||
|
|||
.. method:: I2C.start() |
|||
|
|||
Generate a START condition on the bus (SDA transitions to low while SCL is high). |
|||
|
|||
.. method:: I2C.stop() |
|||
|
|||
Generate a STOP condition on the bus (SDA transitions to high while SCL is high). |
|||
|
|||
.. method:: I2C.readinto(buf, nack=True) |
|||
|
|||
Reads bytes from the bus and stores them into *buf*. The number of bytes |
|||
read is the length of *buf*. An ACK will be sent on the bus after |
|||
receiving all but the last byte. After the last byte is received, if *nack* |
|||
is true then a NACK will be sent, otherwise an ACK will be sent (and in this |
|||
case the slave assumes more bytes are going to be read in a later call). |
|||
|
|||
.. method:: I2C.write(buf) |
|||
|
|||
Write the bytes from *buf* to the bus. Checks that an ACK is received |
|||
after each byte and stops transmitting the remaining bytes if a NACK is |
|||
received. The function returns the number of ACKs that were received. |
|||
|
|||
Standard bus operations |
|||
----------------------- |
|||
|
|||
The following methods implement the standard I2C master read and write |
|||
operations that target a given slave device. |
|||
|
|||
.. method:: I2C.readfrom(addr, nbytes, stop=True) |
|||
|
|||
Read *nbytes* from the slave specified by *addr*. |
|||
If *stop* is true then a STOP condition is generated at the end of the transfer. |
|||
Returns a `bytes` object with the data read. |
|||
|
|||
.. method:: I2C.readfrom_into(addr, buf, stop=True) |
|||
|
|||
Read into *buf* from the slave specified by *addr*. |
|||
The number of bytes read will be the length of *buf*. |
|||
If *stop* is true then a STOP condition is generated at the end of the transfer. |
|||
|
|||
The method returns ``None``. |
|||
|
|||
.. method:: I2C.writeto(addr, buf, stop=True) |
|||
|
|||
Write the bytes from *buf* to the slave specified by *addr*. If a |
|||
NACK is received following the write of a byte from *buf* then the |
|||
remaining bytes are not sent. If *stop* is true then a STOP condition is |
|||
generated at the end of the transfer, even if a NACK is received. |
|||
The function returns the number of ACKs that were received. |
|||
|
|||
.. method:: I2C.writevto(addr, vector, stop=True) |
|||
|
|||
Write the bytes contained in *vector* to the slave specified by *addr*. |
|||
*vector* should be a tuple or list of objects with the buffer protocol. |
|||
The *addr* is sent once and then the bytes from each object in *vector* |
|||
are written out sequentially. The objects in *vector* may be zero bytes |
|||
in length in which case they don't contribute to the output. |
|||
|
|||
If a NACK is received following the write of a byte from one of the |
|||
objects in *vector* then the remaining bytes, and any remaining objects, |
|||
are not sent. If *stop* is true then a STOP condition is generated at |
|||
the end of the transfer, even if a NACK is received. The function |
|||
returns the number of ACKs that were received. |
|||
|
|||
Memory operations |
|||
----------------- |
|||
|
|||
Some I2C devices act as a memory device (or set of registers) that can be read |
|||
from and written to. In this case there are two addresses associated with an |
|||
I2C transaction: the slave address and the memory address. The following |
|||
methods are convenience functions to communicate with such devices. |
|||
|
|||
.. method:: I2C.readfrom_mem(addr, memaddr, nbytes, \*, addrsize=8) |
|||
|
|||
Read *nbytes* from the slave specified by *addr* starting from the memory |
|||
address specified by *memaddr*. |
|||
The argument *addrsize* specifies the address size in bits. |
|||
Returns a `bytes` object with the data read. |
|||
|
|||
.. method:: I2C.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8) |
|||
|
|||
Read into *buf* from the slave specified by *addr* starting from the |
|||
memory address specified by *memaddr*. The number of bytes read is the |
|||
length of *buf*. |
|||
The argument *addrsize* specifies the address size in bits (on ESP8266 |
|||
this argument is not recognised and the address size is always 8 bits). |
|||
|
|||
The method returns ``None``. |
|||
|
|||
.. method:: I2C.writeto_mem(addr, memaddr, buf, \*, addrsize=8) |
|||
|
|||
Write *buf* to the slave specified by *addr* starting from the |
|||
memory address specified by *memaddr*. |
|||
The argument *addrsize* specifies the address size in bits (on ESP8266 |
|||
this argument is not recognised and the address size is always 8 bits). |
|||
|
|||
The method returns ``None``. |
@ -0,0 +1,254 @@ |
|||
.. currentmodule:: machine |
|||
.. _machine.Pin: |
|||
|
|||
class Pin -- control I/O pins |
|||
============================= |
|||
|
|||
A pin object is used to control I/O pins (also known as GPIO - general-purpose |
|||
input/output). Pin objects are commonly associated with a physical pin that can |
|||
drive an output voltage and read input voltages. The pin class has methods to set the mode of |
|||
the pin (IN, OUT, etc) and methods to get and set the digital logic level. |
|||
For analog control of a pin, see the :class:`ADC` class. |
|||
|
|||
A pin object is constructed by using an identifier which unambiguously |
|||
specifies a certain I/O pin. The allowed forms of the identifier and the |
|||
physical pin that the identifier maps to are port-specific. Possibilities |
|||
for the identifier are an integer, a string or a tuple with port and pin |
|||
number. |
|||
|
|||
Usage Model:: |
|||
|
|||
from machine import Pin |
|||
|
|||
# create an output pin on pin #0 |
|||
p0 = Pin(0, Pin.OUT) |
|||
|
|||
# set the value low then high |
|||
p0.value(0) |
|||
p0.value(1) |
|||
|
|||
# create an input pin on pin #2, with a pull up resistor |
|||
p2 = Pin(2, Pin.IN, Pin.PULL_UP) |
|||
|
|||
# read and print the pin value |
|||
print(p2.value()) |
|||
|
|||
# reconfigure pin #0 in input mode |
|||
p0.mode(p0.IN) |
|||
|
|||
# configure an irq callback |
|||
p0.irq(lambda p:print(p)) |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: Pin(id, mode=-1, pull=-1, \*, value, drive, alt) |
|||
|
|||
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 |
|||
the pin. Any settings that are not specified will remain in their previous state. |
|||
|
|||
The arguments are: |
|||
|
|||
- ``id`` is mandatory and can be an arbitrary object. Among possible value |
|||
types are: int (an internal Pin identifier), str (a Pin name), and tuple |
|||
(pair of [port, pin]). |
|||
|
|||
- ``mode`` specifies the pin mode, which can be one of: |
|||
|
|||
- ``Pin.IN`` - Pin is configured for input. If viewed as an output the pin |
|||
is in high-impedance state. |
|||
|
|||
- ``Pin.OUT`` - Pin is configured for (normal) output. |
|||
|
|||
- ``Pin.OPEN_DRAIN`` - Pin is configured for open-drain output. Open-drain |
|||
output works in the following way: if the output value is set to 0 the pin |
|||
is active at a low level; if the output value is 1 the pin is in a high-impedance |
|||
state. Not all ports implement this mode, or some might only on certain pins. |
|||
|
|||
- ``Pin.ALT`` - Pin is configured to perform an alternative function, which is |
|||
port specific. For a pin configured in such a way any other Pin methods |
|||
(except :meth:`Pin.init`) are not applicable (calling them will lead to undefined, |
|||
or a hardware-specific, result). Not all ports implement this mode. |
|||
|
|||
- ``Pin.ALT_OPEN_DRAIN`` - The Same as ``Pin.ALT``, but the pin is configured as |
|||
open-drain. Not all ports implement this mode. |
|||
|
|||
- ``pull`` specifies if the pin has a (weak) pull resistor attached, and can be |
|||
one of: |
|||
|
|||
- ``None`` - No pull up or down resistor. |
|||
- ``Pin.PULL_UP`` - Pull up resistor enabled. |
|||
- ``Pin.PULL_DOWN`` - Pull down resistor enabled. |
|||
|
|||
- ``value`` is valid only for Pin.OUT and Pin.OPEN_DRAIN modes and specifies initial |
|||
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. |
|||
|
|||
- ``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`` |
|||
modes. It may be used when a pin supports more than one alternate function. If only |
|||
one pin alternate function is supported the this argument is not required. Not all |
|||
ports implement this argument. |
|||
|
|||
As specified above, the Pin class allows to set an alternate function for a particular |
|||
pin, but it does not specify any further operations on such a pin. Pins configured in |
|||
alternate-function mode are usually not used as GPIO but are instead driven by other |
|||
hardware peripherals. The only operation supported on such a pin is re-initialising, |
|||
by calling the constructor or :meth:`Pin.init` method. If a pin that is configured in |
|||
alternate-function mode is re-initialised with ``Pin.IN``, ``Pin.OUT``, or |
|||
``Pin.OPEN_DRAIN``, the alternate function will be removed from the pin. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: Pin.init(mode=-1, pull=-1, \*, value, drive, alt) |
|||
|
|||
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 |
|||
unchanged. See the constructor documentation for details of the arguments. |
|||
|
|||
Returns ``None``. |
|||
|
|||
.. method:: Pin.value([x]) |
|||
|
|||
This method allows to set and get the value of the pin, depending on whether |
|||
the argument ``x`` is supplied or not. |
|||
|
|||
If the argument is omitted then this method gets the digital logic level of |
|||
the pin, returning 0 or 1 corresponding to low and high voltage signals |
|||
respectively. The behaviour of this method depends on the mode of the pin: |
|||
|
|||
- ``Pin.IN`` - The method returns the actual input value currently present |
|||
on the pin. |
|||
- ``Pin.OUT`` - The behaviour and return value of the method is undefined. |
|||
- ``Pin.OPEN_DRAIN`` - If the pin is in state '0' then the behaviour and |
|||
return value of the method is undefined. Otherwise, if the pin is in |
|||
state '1', the method returns the actual input value currently present |
|||
on the pin. |
|||
|
|||
If the argument is supplied then this method sets the digital logic level of |
|||
the pin. The argument ``x`` can be anything that converts to a boolean. |
|||
If it converts to ``True``, the pin is set to state '1', otherwise it is set |
|||
to state '0'. The behaviour of this method depends on the mode of the pin: |
|||
|
|||
- ``Pin.IN`` - The value is stored in the output buffer for the pin. The |
|||
pin state does not change, it remains in the high-impedance state. The |
|||
stored value will become active on the pin as soon as it is changed to |
|||
``Pin.OUT`` or ``Pin.OPEN_DRAIN`` mode. |
|||
- ``Pin.OUT`` - The output buffer is set to the given value immediately. |
|||
- ``Pin.OPEN_DRAIN`` - If the value is '0' the pin is set to a low voltage |
|||
state. Otherwise the pin is set to high-impedance state. |
|||
|
|||
When setting the value this method returns ``None``. |
|||
|
|||
.. method:: Pin.__call__([x]) |
|||
|
|||
Pin objects are callable. The call method provides a (fast) shortcut to set |
|||
and get the value of the pin. It is equivalent to Pin.value([x]). |
|||
See :meth:`Pin.value` for more details. |
|||
|
|||
.. method:: Pin.on() |
|||
|
|||
Set pin to "1" output level. |
|||
|
|||
.. method:: Pin.off() |
|||
|
|||
Set pin to "0" output level. |
|||
|
|||
.. method:: Pin.mode([mode]) |
|||
|
|||
Get or set the pin mode. |
|||
See the constructor documentation for details of the ``mode`` argument. |
|||
|
|||
.. method:: Pin.pull([pull]) |
|||
|
|||
Get or set the pin pull state. |
|||
See the constructor documentation for details of the ``pull`` argument. |
|||
|
|||
.. method:: Pin.drive([drive]) |
|||
|
|||
Get or set the pin drive strength. |
|||
See the constructor documentation for details of the ``drive`` argument. |
|||
|
|||
Not all ports implement this method. |
|||
|
|||
Availability: WiPy. |
|||
|
|||
.. method:: Pin.irq(handler=None, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING), \*, priority=1, wake=None, hard=False) |
|||
|
|||
Configure an interrupt handler to be called when the trigger source of the |
|||
pin is active. If the pin mode is ``Pin.IN`` then the trigger source is |
|||
the external value on the pin. If the pin mode is ``Pin.OUT`` then the |
|||
trigger source is the output buffer of the pin. Otherwise, if the pin mode |
|||
is ``Pin.OPEN_DRAIN`` then the trigger source is the output buffer for |
|||
state '0' and the external pin value for state '1'. |
|||
|
|||
The arguments are: |
|||
|
|||
- ``handler`` is an optional function to be called when the interrupt |
|||
triggers. The handler must take exactly one argument which is the |
|||
``Pin`` instance. |
|||
|
|||
- ``trigger`` configures the event which can generate an interrupt. |
|||
Possible values are: |
|||
|
|||
- ``Pin.IRQ_FALLING`` interrupt on falling edge. |
|||
- ``Pin.IRQ_RISING`` interrupt on rising edge. |
|||
- ``Pin.IRQ_LOW_LEVEL`` interrupt on low level. |
|||
- ``Pin.IRQ_HIGH_LEVEL`` interrupt on high level. |
|||
|
|||
These values can be OR'ed together to trigger on multiple events. |
|||
|
|||
- ``priority`` sets the priority level of the interrupt. The values it |
|||
can take are port-specific, but higher values always represent higher |
|||
priorities. |
|||
|
|||
- ``wake`` selects the power mode in which this interrupt can wake up the |
|||
system. It can be ``machine.IDLE``, ``machine.SLEEP`` or ``machine.DEEPSLEEP``. |
|||
These values can also be OR'ed together to make a pin generate interrupts in |
|||
more than one power mode. |
|||
|
|||
- ``hard`` if true a hardware interrupt is used. This reduces the delay |
|||
between the pin change and the handler being called. Hard interrupt |
|||
handlers may not allocate memory; see :ref:`isr_rules`. |
|||
|
|||
This method returns a callback object. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
The following constants are used to configure the pin objects. Note that |
|||
not all constants are available on all ports. |
|||
|
|||
.. data:: Pin.IN |
|||
Pin.OUT |
|||
Pin.OPEN_DRAIN |
|||
Pin.ALT |
|||
Pin.ALT_OPEN_DRAIN |
|||
|
|||
Selects the pin mode. |
|||
|
|||
.. data:: Pin.PULL_UP |
|||
Pin.PULL_DOWN |
|||
Pin.PULL_HOLD |
|||
|
|||
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 |
|||
|
|||
Selects the pin drive strength. |
|||
|
|||
.. data:: Pin.IRQ_FALLING |
|||
Pin.IRQ_RISING |
|||
Pin.IRQ_LOW_LEVEL |
|||
Pin.IRQ_HIGH_LEVEL |
|||
|
|||
Selects the IRQ trigger type. |
@ -0,0 +1,69 @@ |
|||
.. currentmodule:: machine |
|||
.. _machine.RTC: |
|||
|
|||
class RTC -- real time clock |
|||
============================ |
|||
|
|||
The RTC is and independent clock that keeps track of the date |
|||
and time. |
|||
|
|||
Example usage:: |
|||
|
|||
rtc = machine.RTC() |
|||
rtc.init((2014, 5, 1, 4, 13, 0, 0, 0)) |
|||
print(rtc.now()) |
|||
|
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: RTC(id=0, ...) |
|||
|
|||
Create an RTC object. See init for parameters of initialization. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: RTC.init(datetime) |
|||
|
|||
Initialise the RTC. Datetime is a tuple of the form: |
|||
|
|||
``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])`` |
|||
|
|||
.. method:: RTC.now() |
|||
|
|||
Get get the current datetime tuple. |
|||
|
|||
.. method:: RTC.deinit() |
|||
|
|||
Resets the RTC to the time of January 1, 2015 and starts running it again. |
|||
|
|||
.. method:: RTC.alarm(id, time, \*, repeat=False) |
|||
|
|||
Set the RTC alarm. Time might be either a millisecond value to program the alarm to |
|||
current time + time_in_ms in the future, or a datetimetuple. If the time passed is in |
|||
milliseconds, repeat can be set to ``True`` to make the alarm periodic. |
|||
|
|||
.. method:: RTC.alarm_left(alarm_id=0) |
|||
|
|||
Get the number of milliseconds left before the alarm expires. |
|||
|
|||
.. method:: RTC.cancel(alarm_id=0) |
|||
|
|||
Cancel a running alarm. |
|||
|
|||
.. method:: RTC.irq(\*, trigger, handler=None, wake=machine.IDLE) |
|||
|
|||
Create an irq object triggered by a real time clock alarm. |
|||
|
|||
- ``trigger`` must be ``RTC.ALARM0`` |
|||
- ``handler`` is the function to be called when the callback is triggered. |
|||
- ``wake`` specifies the sleep mode from where this interrupt can wake |
|||
up the system. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: RTC.ALARM0 |
|||
|
|||
irq trigger source |
@ -0,0 +1,47 @@ |
|||
.. currentmodule:: machine |
|||
.. _machine.SD: |
|||
|
|||
class SD -- secure digital memory card (cc3200 port only) |
|||
========================================================= |
|||
|
|||
.. warning:: |
|||
|
|||
This is a non-standard class and is only available on the cc3200 port. |
|||
|
|||
|
|||
The SD card class allows to configure and enable the memory card |
|||
module of the WiPy and automatically mount it as ``/sd`` as part |
|||
of the file system. There are several pin combinations that can be |
|||
used to wire the SD card socket to the WiPy and the pins used can |
|||
be specified in the constructor. Please check the `pinout and alternate functions |
|||
table. <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_ for |
|||
more info regarding the pins which can be remapped to be used with a SD card. |
|||
|
|||
Example usage:: |
|||
|
|||
from machine import SD |
|||
import os |
|||
# clk cmd and dat0 pins must be passed along with |
|||
# their respective alternate functions |
|||
sd = machine.SD(pins=('GP10', 'GP11', 'GP15')) |
|||
os.mount(sd, '/sd') |
|||
# do normal file operations |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: SD(id,... ) |
|||
|
|||
Create a SD card object. See ``init()`` for parameters if initialization. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: SD.init(id=0, pins=('GP10', 'GP11', 'GP15')) |
|||
|
|||
Enable the SD card. In order to initialize the card, give it a 3-tuple: |
|||
``(clk_pin, cmd_pin, dat0_pin)``. |
|||
|
|||
.. method:: SD.deinit() |
|||
|
|||
Disable the SD card. |
@ -0,0 +1,122 @@ |
|||
.. currentmodule:: machine |
|||
.. _machine.SDCard: |
|||
|
|||
class SDCard -- secure digital memory card |
|||
========================================== |
|||
|
|||
SD cards are one of the most common small form factor removable storage media. |
|||
SD cards come in a variety of sizes and physical form factors. MMC cards are |
|||
similar removable storage devices while eMMC devices are electrically similar |
|||
storage devices designed to be embedded into other systems. All three form |
|||
share a common protocol for communication with their host system and high-level |
|||
support looks the same for them all. As such in MicroPython they are implemented |
|||
in a single class called :class:`machine.SDCard` . |
|||
|
|||
Both SD and MMC interfaces support being accessed with a variety of bus widths. |
|||
When being accessed with a 1-bit wide interface they can be accessed using the |
|||
SPI protocol. Different MicroPython hardware platforms support different widths |
|||
and pin configurations but for most platforms there is a standard configuration |
|||
for any given hardware. In general constructing an ``SDCard`` object with without |
|||
passing any parameters will initialise the interface to the default card slot |
|||
for the current hardware. The arguments listed below represent the common |
|||
arguments that might need to be set in order to use either a non-standard slot |
|||
or a non-standard pin assignment. The exact subset of arguments supported will |
|||
vary from platform to platform. |
|||
|
|||
.. class:: SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None, cs=None) |
|||
|
|||
This class provides access to SD or MMC storage cards using either |
|||
a dedicated SD/MMC interface hardware or through an SPI channel. |
|||
The class implements the block protocol defined by :class:`uos.AbstractBlockDev`. |
|||
This allows the mounting of an SD card to be as simple as:: |
|||
|
|||
uos.mount(machine.SDCard(), "/sd") |
|||
|
|||
The constructor takes the following parameters: |
|||
|
|||
- *slot* selects which of the available interfaces to use. Leaving this |
|||
unset will select the default interface. |
|||
|
|||
- *width* selects the bus width for the SD/MMC interface. |
|||
|
|||
- *cd* can be used to specify a card-detect pin. |
|||
|
|||
- *wp* can be used to specify a write-protect pin. |
|||
|
|||
- *sck* can be used to specify an SPI clock pin. |
|||
|
|||
- *miso* can be used to specify an SPI miso pin. |
|||
|
|||
- *mosi* can be used to specify an SPI mosi pin. |
|||
|
|||
- *cs* can be used to specify an SPI chip select pin. |
|||
|
|||
Implementation-specific details |
|||
------------------------------- |
|||
|
|||
Different implementations of the ``SDCard`` class on different hardware support |
|||
varying subsets of the options above. |
|||
|
|||
PyBoard |
|||
``````` |
|||
|
|||
The standard PyBoard has just one slot. No arguments are necessary or supported. |
|||
|
|||
ESP32 |
|||
````` |
|||
|
|||
The ESP32 provides two channels of SD/MMC hardware and also supports |
|||
access to SD Cards through either of the two SPI ports that are |
|||
generally available to the user. As a result the *slot* argument can |
|||
take a value between 0 and 3, inclusive. Slots 0 and 1 use the |
|||
built-in SD/MMC hardware while slots 2 and 3 use the SPI ports. Slot 0 |
|||
supports 1, 4 or 8-bit wide access while slot 1 supports 1 or 4-bit |
|||
access; the SPI slots only support 1-bit access. |
|||
|
|||
.. note:: Slot 0 is used to communicate with on-board flash memory |
|||
on most ESP32 modules and so will be unavailable to the |
|||
user. |
|||
|
|||
.. note:: Most ESP32 modules that provide an SD card slot using the |
|||
dedicated hardware only wire up 1 data pin, so the default |
|||
value for *width* is 1. |
|||
|
|||
The pins used by the dedicated SD/MMC hardware are fixed. The pins |
|||
used by the SPI hardware can be reassigned. |
|||
|
|||
.. note:: If any of the SPI signals are remapped then all of the SPI |
|||
signals will pass through a GPIO multiplexer unit which |
|||
can limit the performance of high frequency signals. Since |
|||
the normal operating speed for SD cards is 40MHz this can |
|||
cause problems on some cards. |
|||
|
|||
The default (and preferred) pin assignment are as follows: |
|||
|
|||
====== ====== ====== ====== ====== |
|||
Slot 0 1 2 3 |
|||
------ ------ ------ ------ ------ |
|||
Signal Pin Pin Pin Pin |
|||
====== ====== ====== ====== ====== |
|||
sck 6 14 18 14 |
|||
cmd 11 15 |
|||
cs 5 15 |
|||
miso 19 12 |
|||
mosi 23 13 |
|||
D0 7 2 |
|||
D1 8 4 |
|||
D2 9 12 |
|||
D3 10 13 |
|||
D4 16 |
|||
D5 17 |
|||
D6 5 |
|||
D7 18 |
|||
====== ====== ====== ====== ====== |
|||
|
|||
cc3200 |
|||
`````` |
|||
|
|||
You can set the pins used for SPI access by passing a tuple as the |
|||
*pins* argument. |
|||
|
|||
*Note:* The current cc3200 SD card implementation names the this class |
|||
:class:`machine.SD` rather than :class:`machine.SDCard` . |
@ -0,0 +1,101 @@ |
|||
.. currentmodule:: machine |
|||
.. _machine.SPI: |
|||
|
|||
class SPI -- a Serial Peripheral Interface bus protocol (master side) |
|||
===================================================================== |
|||
|
|||
SPI is a synchronous serial protocol that is driven by a master. At the |
|||
physical level, a bus consists of 3 lines: SCK, MOSI, MISO. Multiple devices |
|||
can share the same bus. Each device should have a separate, 4th signal, |
|||
SS (Slave Select), to select a particular device on a bus with which |
|||
communication takes place. Management of an SS signal should happen in |
|||
user code (via machine.Pin class). |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: SPI(id, ...) |
|||
|
|||
Construct an SPI object on the given bus, ``id``. Values of ``id`` depend |
|||
on a particular port and its hardware. Values 0, 1, etc. are commonly used |
|||
to select hardware SPI block #0, #1, etc. Value -1 can be used for |
|||
bitbanging (software) implementation of SPI (if supported by a port). |
|||
|
|||
With no additional parameters, the SPI object is created but not |
|||
initialised (it has the settings from the last initialisation of |
|||
the bus, if any). If extra arguments are given, the bus is initialised. |
|||
See ``init`` for parameters of initialisation. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: SPI.init(baudrate=1000000, \*, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=None, mosi=None, miso=None, pins=(SCK, MOSI, MISO)) |
|||
|
|||
Initialise the SPI bus with the given parameters: |
|||
|
|||
- ``baudrate`` is the SCK clock rate. |
|||
- ``polarity`` can be 0 or 1, and is the level the idle clock line sits at. |
|||
- ``phase`` can be 0 or 1 to sample data on the first or second clock edge |
|||
respectively. |
|||
- ``bits`` is the width in bits of each transfer. Only 8 is guaranteed to be supported by all hardware. |
|||
- ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``. |
|||
- ``sck``, ``mosi``, ``miso`` are pins (machine.Pin) objects to use for bus signals. For most |
|||
hardware SPI blocks (as selected by ``id`` parameter to the constructor), pins are fixed |
|||
and cannot be changed. In some cases, hardware blocks allow 2-3 alternative pin sets for |
|||
a hardware SPI block. Arbitrary pin assignments are possible only for a bitbanging SPI driver |
|||
(``id`` = -1). |
|||
- ``pins`` - WiPy port doesn't ``sck``, ``mosi``, ``miso`` arguments, and instead allows to |
|||
specify them as a tuple of ``pins`` parameter. |
|||
|
|||
In the case of hardware SPI the actual clock frequency may be lower than the |
|||
requested baudrate. This is dependant on the platform hardware. The actual |
|||
rate may be determined by printing the SPI object. |
|||
|
|||
.. method:: SPI.deinit() |
|||
|
|||
Turn off the SPI bus. |
|||
|
|||
.. method:: SPI.read(nbytes, write=0x00) |
|||
|
|||
Read a number of bytes specified by ``nbytes`` while continuously writing |
|||
the single byte given by ``write``. |
|||
Returns a ``bytes`` object with the data that was read. |
|||
|
|||
.. method:: SPI.readinto(buf, write=0x00) |
|||
|
|||
Read into the buffer specified by ``buf`` while continuously writing the |
|||
single byte given by ``write``. |
|||
Returns ``None``. |
|||
|
|||
Note: on WiPy this function returns the number of bytes read. |
|||
|
|||
.. method:: SPI.write(buf) |
|||
|
|||
Write the bytes contained in ``buf``. |
|||
Returns ``None``. |
|||
|
|||
Note: on WiPy this function returns the number of bytes written. |
|||
|
|||
.. method:: SPI.write_readinto(write_buf, read_buf) |
|||
|
|||
Write the bytes from ``write_buf`` while reading into ``read_buf``. The |
|||
buffers can be the same or different, but both buffers must have the |
|||
same length. |
|||
Returns ``None``. |
|||
|
|||
Note: on WiPy this function returns the number of bytes written. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: SPI.MASTER |
|||
|
|||
for initialising the SPI bus to master; this is only used for the WiPy |
|||
|
|||
.. data:: SPI.MSB |
|||
|
|||
set the first bit to be the most significant bit |
|||
|
|||
.. data:: SPI.LSB |
|||
|
|||
set the first bit to be the least significant bit |
@ -0,0 +1,123 @@ |
|||
.. currentmodule:: machine |
|||
.. _machine.Signal: |
|||
|
|||
class Signal -- control and sense external I/O devices |
|||
====================================================== |
|||
|
|||
The Signal class is a simple extension of the `Pin` class. Unlike Pin, which |
|||
can be only in "absolute" 0 and 1 states, a Signal can be in "asserted" |
|||
(on) or "deasserted" (off) states, while being inverted (active-low) or |
|||
not. In other words, it adds logical inversion support to Pin functionality. |
|||
While this may seem a simple addition, it is exactly what is needed to |
|||
support wide array of simple digital devices in a way portable across |
|||
different boards, which is one of the major MicroPython goals. Regardless |
|||
of whether different users have an active-high or active-low LED, a normally |
|||
open or normally closed relay - you can develop a single, nicely looking |
|||
application which works with each of them, and capture hardware |
|||
configuration differences in few lines in the config file of your app. |
|||
|
|||
Example:: |
|||
|
|||
from machine import Pin, Signal |
|||
|
|||
# Suppose you have an active-high LED on pin 0 |
|||
led1_pin = Pin(0, Pin.OUT) |
|||
# ... and active-low LED on pin 1 |
|||
led2_pin = Pin(1, Pin.OUT) |
|||
|
|||
# Now to light up both of them using Pin class, you'll need to set |
|||
# them to different values |
|||
led1_pin.value(1) |
|||
led2_pin.value(0) |
|||
|
|||
# Signal class allows to abstract away active-high/active-low |
|||
# difference |
|||
led1 = Signal(led1_pin, invert=False) |
|||
led2 = Signal(led2_pin, invert=True) |
|||
|
|||
# Now lighting up them looks the same |
|||
led1.value(1) |
|||
led2.value(1) |
|||
|
|||
# Even better: |
|||
led1.on() |
|||
led2.on() |
|||
|
|||
Following is the guide when Signal vs Pin should be used: |
|||
|
|||
* Use Signal: If you want to control a simple on/off (including software |
|||
PWM!) devices like LEDs, multi-segment indicators, relays, buzzers, or |
|||
read simple binary sensors, like normally open or normally closed buttons, |
|||
pulled high or low, Reed switches, moisture/flame detectors, etc. etc. |
|||
Summing up, if you have a real physical device/sensor requiring GPIO |
|||
access, you likely should use a Signal. |
|||
|
|||
* Use Pin: If you implement a higher-level protocol or bus to communicate |
|||
with more complex devices. |
|||
|
|||
The split between Pin and Signal come from the usecases above and the |
|||
architecture of MicroPython: Pin offers the lowest overhead, which may |
|||
be important when bit-banging protocols. But Signal adds additional |
|||
flexibility on top of Pin, at the cost of minor overhead (much smaller |
|||
than if you implemented active-high vs active-low device differences in |
|||
Python manually!). Also, Pin is a low-level object which needs to be |
|||
implemented for each support board, while Signal is a high-level object |
|||
which comes for free once Pin is implemented. |
|||
|
|||
If in doubt, give the Signal a try! Once again, it is offered to save |
|||
developers from the need to handle unexciting differences like active-low |
|||
vs active-high signals, and allow other users to share and enjoy your |
|||
application, instead of being frustrated by the fact that it doesn't |
|||
work for them simply because their LEDs or relays are wired in a slightly |
|||
different way. |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: Signal(pin_obj, invert=False) |
|||
Signal(pin_arguments..., \*, invert=False) |
|||
|
|||
Create a Signal object. There're two ways to create it: |
|||
|
|||
* By wrapping existing Pin object - universal method which works for |
|||
any board. |
|||
* By passing required Pin parameters directly to Signal constructor, |
|||
skipping the need to create intermediate Pin object. Available on |
|||
many, but not all boards. |
|||
|
|||
The arguments are: |
|||
|
|||
- ``pin_obj`` is existing Pin object. |
|||
|
|||
- ``pin_arguments`` are the same arguments as can be passed to Pin constructor. |
|||
|
|||
- ``invert`` - if True, the signal will be inverted (active low). |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: Signal.value([x]) |
|||
|
|||
This method allows to set and get the value of the signal, depending on whether |
|||
the argument ``x`` is supplied or not. |
|||
|
|||
If the argument is omitted then this method gets the signal level, 1 meaning |
|||
signal is asserted (active) and 0 - signal inactive. |
|||
|
|||
If the argument is supplied then this method sets the signal level. The |
|||
argument ``x`` can be anything that converts to a boolean. If it converts |
|||
to ``True``, the signal is active, otherwise it is inactive. |
|||
|
|||
Correspondence between signal being active and actual logic level on the |
|||
underlying pin depends on whether signal is inverted (active-low) or not. |
|||
For non-inverted signal, active status corresponds to logical 1, inactive - |
|||
to logical 0. For inverted/active-low signal, active status corresponds |
|||
to logical 0, while inactive - to logical 1. |
|||
|
|||
.. method:: Signal.on() |
|||
|
|||
Activate signal. |
|||
|
|||
.. method:: Signal.off() |
|||
|
|||
Deactivate signal. |
@ -0,0 +1,64 @@ |
|||
.. currentmodule:: machine |
|||
.. _machine.Timer: |
|||
|
|||
class Timer -- control hardware timers |
|||
====================================== |
|||
|
|||
Hardware timers deal with timing of periods and events. Timers are perhaps |
|||
the most flexible and heterogeneous kind of hardware in MCUs and SoCs, |
|||
differently greatly from a model to a model. MicroPython's Timer class |
|||
defines a baseline operation of executing a callback with a given period |
|||
(or once after some delay), and allow specific boards to define more |
|||
non-standard behavior (which thus won't be portable to other boards). |
|||
|
|||
See discussion of :ref:`important constraints <machine_callbacks>` on |
|||
Timer callbacks. |
|||
|
|||
.. note:: |
|||
|
|||
Memory can't be allocated inside irq handlers (an interrupt) and so |
|||
exceptions raised within a handler don't give much information. See |
|||
:func:`micropython.alloc_emergency_exception_buf` for how to get around this |
|||
limitation. |
|||
|
|||
If you are using a WiPy board please refer to :ref:`machine.TimerWiPy <machine.TimerWiPy>` |
|||
instead of this class. |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: Timer(id, ...) |
|||
|
|||
Construct a new timer object of the given id. Id of -1 constructs a |
|||
virtual timer (if supported by a board). |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: Timer.init(\*, mode=Timer.PERIODIC, period=-1, callback=None) |
|||
|
|||
Initialise the timer. Example:: |
|||
|
|||
tim.init(period=100) # periodic with 100ms period |
|||
tim.init(mode=Timer.ONE_SHOT, period=1000) # one shot firing after 1000ms |
|||
|
|||
Keyword arguments: |
|||
|
|||
- ``mode`` can be one of: |
|||
|
|||
- ``Timer.ONE_SHOT`` - The timer runs once until the configured |
|||
period of the channel expires. |
|||
- ``Timer.PERIODIC`` - The timer runs periodically at the configured |
|||
frequency of the channel. |
|||
|
|||
.. method:: Timer.deinit() |
|||
|
|||
Deinitialises the timer. Stops the timer, and disables the timer peripheral. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: Timer.ONE_SHOT |
|||
Timer.PERIODIC |
|||
|
|||
Timer operating mode. |
@ -0,0 +1,159 @@ |
|||
.. currentmodule:: machine |
|||
.. _machine.TimerWiPy: |
|||
|
|||
class TimerWiPy -- control hardware timers |
|||
========================================== |
|||
|
|||
.. note:: |
|||
|
|||
This class is a non-standard Timer implementation for the WiPy. |
|||
It is available simply as ``machine.Timer`` on the WiPy but is named in the |
|||
documentation below as ``machine.TimerWiPy`` to distinguish it from the |
|||
more general :ref:`machine.Timer <machine.Timer>` class. |
|||
|
|||
Hardware timers deal with timing of periods and events. Timers are perhaps |
|||
the most flexible and heterogeneous kind of hardware in MCUs and SoCs, |
|||
differently greatly from a model to a model. MicroPython's Timer class |
|||
defines a baseline operation of executing a callback with a given period |
|||
(or once after some delay), and allow specific boards to define more |
|||
non-standard behavior (which thus won't be portable to other boards). |
|||
|
|||
See discussion of :ref:`important constraints <machine_callbacks>` on |
|||
Timer callbacks. |
|||
|
|||
.. note:: |
|||
|
|||
Memory can't be allocated inside irq handlers (an interrupt) and so |
|||
exceptions raised within a handler don't give much information. See |
|||
:func:`micropython.alloc_emergency_exception_buf` for how to get around this |
|||
limitation. |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: TimerWiPy(id, ...) |
|||
|
|||
Construct a new timer object of the given id. Id of -1 constructs a |
|||
virtual timer (if supported by a board). |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: TimerWiPy.init(mode, \*, width=16) |
|||
|
|||
Initialise the timer. Example:: |
|||
|
|||
tim.init(Timer.PERIODIC) # periodic 16-bit timer |
|||
tim.init(Timer.ONE_SHOT, width=32) # one shot 32-bit timer |
|||
|
|||
Keyword arguments: |
|||
|
|||
- ``mode`` can be one of: |
|||
|
|||
- ``TimerWiPy.ONE_SHOT`` - The timer runs once until the configured |
|||
period of the channel expires. |
|||
- ``TimerWiPy.PERIODIC`` - The timer runs periodically at the configured |
|||
frequency of the channel. |
|||
- ``TimerWiPy.PWM`` - Output a PWM signal on a pin. |
|||
|
|||
- ``width`` must be either 16 or 32 (bits). For really low frequencies < 5Hz |
|||
(or large periods), 32-bit timers should be used. 32-bit mode is only available |
|||
for ``ONE_SHOT`` AND ``PERIODIC`` modes. |
|||
|
|||
.. method:: TimerWiPy.deinit() |
|||
|
|||
Deinitialises the timer. Stops the timer, and disables the timer peripheral. |
|||
|
|||
.. method:: TimerWiPy.channel(channel, \**, freq, period, polarity=TimerWiPy.POSITIVE, duty_cycle=0) |
|||
|
|||
If only a channel identifier passed, then a previously initialized channel |
|||
object is returned (or ``None`` if there is no previous channel). |
|||
|
|||
Otherwise, a TimerChannel object is initialized and returned. |
|||
|
|||
The operating mode is is the one configured to the Timer object that was used to |
|||
create the channel. |
|||
|
|||
- ``channel`` if the width of the timer is 16-bit, then must be either ``TIMER.A``, ``TIMER.B``. |
|||
If the width is 32-bit then it **must be** ``TIMER.A | TIMER.B``. |
|||
|
|||
Keyword only arguments: |
|||
|
|||
- ``freq`` sets the frequency in Hz. |
|||
- ``period`` sets the period in microseconds. |
|||
|
|||
.. note:: |
|||
|
|||
Either ``freq`` or ``period`` must be given, never both. |
|||
|
|||
- ``polarity`` this is applicable for ``PWM``, and defines the polarity of the duty cycle |
|||
- ``duty_cycle`` only applicable to ``PWM``. It's a percentage (0.00-100.00). Since the WiPy |
|||
doesn't support floating point numbers the duty cycle must be specified in the range 0-10000, |
|||
where 10000 would represent 100.00, 5050 represents 50.50, and so on. |
|||
|
|||
.. note:: |
|||
|
|||
When the channel is in PWM mode, the corresponding pin is assigned automatically, therefore |
|||
there's no need to assign the alternate function of the pin via the ``Pin`` class. The pins which |
|||
support PWM functionality are the following: |
|||
|
|||
- ``GP24`` on Timer 0 channel A. |
|||
- ``GP25`` on Timer 1 channel A. |
|||
- ``GP9`` on Timer 2 channel B. |
|||
- ``GP10`` on Timer 3 channel A. |
|||
- ``GP11`` on Timer 3 channel B. |
|||
|
|||
class TimerChannel --- setup a channel for a timer |
|||
================================================== |
|||
|
|||
Timer channels are used to generate/capture a signal using a timer. |
|||
|
|||
TimerChannel objects are created using the Timer.channel() method. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: timerchannel.irq(\*, trigger, priority=1, handler=None) |
|||
|
|||
The behavior of this callback is heavily dependent on the operating |
|||
mode of the timer channel: |
|||
|
|||
- If mode is ``TimerWiPy.PERIODIC`` the callback is executed periodically |
|||
with the configured frequency or period. |
|||
- If mode is ``TimerWiPy.ONE_SHOT`` the callback is executed once when |
|||
the configured timer expires. |
|||
- If mode is ``TimerWiPy.PWM`` the callback is executed when reaching the duty |
|||
cycle value. |
|||
|
|||
The accepted params are: |
|||
|
|||
- ``priority`` level of the interrupt. Can take values in the range 1-7. |
|||
Higher values represent higher priorities. |
|||
- ``handler`` is an optional function to be called when the interrupt is triggered. |
|||
- ``trigger`` must be ``TimerWiPy.TIMEOUT`` when the operating mode is either ``TimerWiPy.PERIODIC`` or |
|||
``TimerWiPy.ONE_SHOT``. In the case that mode is ``TimerWiPy.PWM`` then trigger must be equal to |
|||
``TimerWiPy.MATCH``. |
|||
|
|||
Returns a callback object. |
|||
|
|||
.. method:: timerchannel.freq([value]) |
|||
|
|||
Get or set the timer channel frequency (in Hz). |
|||
|
|||
.. method:: timerchannel.period([value]) |
|||
|
|||
Get or set the timer channel period (in microseconds). |
|||
|
|||
.. method:: timerchannel.duty_cycle([value]) |
|||
|
|||
Get or set the duty cycle of the PWM signal. It's a percentage (0.00-100.00). Since the WiPy |
|||
doesn't support floating point numbers the duty cycle must be specified in the range 0-10000, |
|||
where 10000 would represent 100.00, 5050 represents 50.50, and so on. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: TimerWiPy.ONE_SHOT |
|||
.. data:: TimerWiPy.PERIODIC |
|||
|
|||
Timer operating mode. |
@ -0,0 +1,152 @@ |
|||
.. currentmodule:: machine |
|||
.. _machine.UART: |
|||
|
|||
class UART -- duplex serial communication bus |
|||
============================================= |
|||
|
|||
UART implements the standard UART/USART duplex serial communications protocol. At |
|||
the physical level it consists of 2 lines: RX and TX. The unit of communication |
|||
is a character (not to be confused with a string character) which can be 8 or 9 |
|||
bits wide. |
|||
|
|||
UART objects can be created and initialised using:: |
|||
|
|||
from machine import UART |
|||
|
|||
uart = UART(1, 9600) # init with given baudrate |
|||
uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters |
|||
|
|||
Supported parameters differ on a board: |
|||
|
|||
Pyboard: Bits can be 7, 8 or 9. Stop can be 1 or 2. With *parity=None*, |
|||
only 8 and 9 bits are supported. With parity enabled, only 7 and 8 bits |
|||
are supported. |
|||
|
|||
WiPy/CC3200: Bits can be 5, 6, 7, 8. Stop can be 1 or 2. |
|||
|
|||
A UART object acts like a `stream` object and reading and writing is done |
|||
using the standard stream methods:: |
|||
|
|||
uart.read(10) # read 10 characters, returns a bytes object |
|||
uart.read() # read all available characters |
|||
uart.readline() # read a line |
|||
uart.readinto(buf) # read and store into the given buffer |
|||
uart.write('abc') # write the 3 characters |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: UART(id, ...) |
|||
|
|||
Construct a UART object of the given id. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: UART.init(baudrate=9600, bits=8, parity=None, stop=1, \*, ...) |
|||
|
|||
Initialise the UART bus with the given parameters: |
|||
|
|||
- *baudrate* is the clock rate. |
|||
- *bits* is the number of bits per character, 7, 8 or 9. |
|||
- *parity* is the parity, ``None``, 0 (even) or 1 (odd). |
|||
- *stop* is the number of stop bits, 1 or 2. |
|||
|
|||
Additional keyword-only parameters that may be supported by a port are: |
|||
|
|||
- *tx* specifies the TX pin to use. |
|||
- *rx* specifies the RX pin to use. |
|||
- *txbuf* specifies the length in characters of the TX buffer. |
|||
- *rxbuf* specifies the length in characters of the RX buffer. |
|||
|
|||
On the WiPy only the following keyword-only parameter is supported: |
|||
|
|||
- *pins* is a 4 or 2 item list indicating the TX, RX, RTS and CTS pins (in that order). |
|||
Any of the pins can be None if one wants the UART to operate with limited functionality. |
|||
If the RTS pin is given the the RX pin must be given as well. The same applies to CTS. |
|||
When no pins are given, then the default set of TX and RX pins is taken, and hardware |
|||
flow control will be disabled. If *pins* is ``None``, no pin assignment will be made. |
|||
|
|||
.. method:: UART.deinit() |
|||
|
|||
Turn off the UART bus. |
|||
|
|||
.. method:: UART.any() |
|||
|
|||
Returns an integer counting the number of characters that can be read without |
|||
blocking. It will return 0 if there are no characters available and a positive |
|||
number if there are characters. The method may return 1 even if there is more |
|||
than one character available for reading. |
|||
|
|||
For more sophisticated querying of available characters use select.poll:: |
|||
|
|||
poll = select.poll() |
|||
poll.register(uart, select.POLLIN) |
|||
poll.poll(timeout) |
|||
|
|||
.. method:: UART.read([nbytes]) |
|||
|
|||
Read characters. If ``nbytes`` is specified then read at most that many bytes, |
|||
otherwise read as much data as possible. |
|||
|
|||
Return value: a bytes object containing the bytes read in. Returns ``None`` |
|||
on timeout. |
|||
|
|||
.. method:: UART.readinto(buf[, nbytes]) |
|||
|
|||
Read bytes into the ``buf``. If ``nbytes`` is specified then read at most |
|||
that many bytes. Otherwise, read at most ``len(buf)`` bytes. |
|||
|
|||
Return value: number of bytes read and stored into ``buf`` or ``None`` on |
|||
timeout. |
|||
|
|||
.. method:: UART.readline() |
|||
|
|||
Read a line, ending in a newline character. |
|||
|
|||
Return value: the line read or ``None`` on timeout. |
|||
|
|||
.. method:: UART.write(buf) |
|||
|
|||
Write the buffer of bytes to the bus. |
|||
|
|||
Return value: number of bytes written or ``None`` on timeout. |
|||
|
|||
.. method:: UART.sendbreak() |
|||
|
|||
Send a break condition on the bus. This drives the bus low for a duration |
|||
longer than required for a normal transmission of a character. |
|||
|
|||
.. method:: UART.irq(trigger, priority=1, handler=None, wake=machine.IDLE) |
|||
|
|||
Create a callback to be triggered when data is received on the UART. |
|||
|
|||
- *trigger* can only be ``UART.RX_ANY`` |
|||
- *priority* level of the interrupt. Can take values in the range 1-7. |
|||
Higher values represent higher priorities. |
|||
- *handler* an optional function to be called when new characters arrive. |
|||
- *wake* can only be ``machine.IDLE``. |
|||
|
|||
.. note:: |
|||
|
|||
The handler will be called whenever any of the following two conditions are met: |
|||
|
|||
- 8 new characters have been received. |
|||
- At least 1 new character is waiting in the Rx buffer and the Rx line has been |
|||
silent for the duration of 1 complete frame. |
|||
|
|||
This means that when the handler function is called there will be between 1 to 8 |
|||
characters waiting. |
|||
|
|||
Returns an irq object. |
|||
|
|||
Availability: WiPy. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: UART.RX_ANY |
|||
|
|||
IRQ trigger sources |
|||
|
|||
Availability: WiPy. |
@ -0,0 +1,36 @@ |
|||
.. currentmodule:: machine |
|||
.. _machine.WDT: |
|||
|
|||
class WDT -- watchdog timer |
|||
=========================== |
|||
|
|||
The WDT is used to restart the system when the application crashes and ends |
|||
up into a non recoverable state. Once started it cannot be stopped or |
|||
reconfigured in any way. After enabling, the application must "feed" the |
|||
watchdog periodically to prevent it from expiring and resetting the system. |
|||
|
|||
Example usage:: |
|||
|
|||
from machine import WDT |
|||
wdt = WDT(timeout=2000) # enable it with a timeout of 2s |
|||
wdt.feed() |
|||
|
|||
Availability of this class: pyboard, WiPy. |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: WDT(id=0, timeout=5000) |
|||
|
|||
Create a WDT object and start it. The timeout must be given in seconds and |
|||
the minimum value that is accepted is 1 second. Once it is running the timeout |
|||
cannot be changed and the WDT cannot be stopped either. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. 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 |
|||
only fed after verifying that everything is functioning correctly. |
@ -0,0 +1,171 @@ |
|||
:mod:`machine` --- functions related to the hardware |
|||
==================================================== |
|||
|
|||
.. module:: machine |
|||
:synopsis: functions related to the hardware |
|||
|
|||
The ``machine`` module contains specific functions related to the hardware |
|||
on a particular board. Most functions in this module allow to achieve direct |
|||
and unrestricted access to and control of hardware blocks on a system |
|||
(like CPU, timers, buses, etc.). Used incorrectly, this can lead to |
|||
malfunction, lockups, crashes of your board, and in extreme cases, hardware |
|||
damage. |
|||
|
|||
.. _machine_callbacks: |
|||
|
|||
A note of callbacks used by functions and class methods of :mod:`machine` module: |
|||
all these callbacks should be considered as executing in an interrupt context. |
|||
This is true for both physical devices with IDs >= 0 and "virtual" devices |
|||
with negative IDs like -1 (these "virtual" devices are still thin shims on |
|||
top of real hardware and real hardware interrupts). See :ref:`isr_rules`. |
|||
|
|||
Reset related functions |
|||
----------------------- |
|||
|
|||
.. function:: reset() |
|||
|
|||
Resets the device in a manner similar to pushing the external RESET |
|||
button. |
|||
|
|||
.. function:: reset_cause() |
|||
|
|||
Get the reset cause. See :ref:`constants <machine_constants>` for the possible return values. |
|||
|
|||
Interrupt related functions |
|||
--------------------------- |
|||
|
|||
.. function:: disable_irq() |
|||
|
|||
Disable interrupt requests. |
|||
Returns the previous IRQ state which should be considered an opaque value. |
|||
This return value should be passed to the `enable_irq()` function to restore |
|||
interrupts to their original state, before `disable_irq()` was called. |
|||
|
|||
.. function:: enable_irq(state) |
|||
|
|||
Re-enable interrupt requests. |
|||
The *state* parameter should be the value that was returned from the most |
|||
recent call to the `disable_irq()` function. |
|||
|
|||
Power related functions |
|||
----------------------- |
|||
|
|||
.. function:: freq() |
|||
|
|||
Returns CPU frequency in hertz. |
|||
|
|||
.. function:: idle() |
|||
|
|||
Gates the clock to the CPU, useful to reduce power consumption at any time during |
|||
short or long periods. Peripherals continue working and execution resumes as soon |
|||
as any interrupt is triggered (on many ports this includes system timer |
|||
interrupt occurring at regular intervals on the order of millisecond). |
|||
|
|||
.. function:: sleep() |
|||
|
|||
.. note:: This function is deprecated, use `lightsleep()` instead with no arguments. |
|||
|
|||
.. function:: lightsleep([time_ms]) |
|||
deepsleep([time_ms]) |
|||
|
|||
Stops execution in an attempt to enter a low power state. |
|||
|
|||
If *time_ms* is specified then this will be the maximum time in milliseconds that |
|||
the sleep will last for. Otherwise the sleep can last indefinitely. |
|||
|
|||
With or without a timout, execution may resume at any time if there are events |
|||
that require processing. Such events, or wake sources, should be configured before |
|||
sleeping, like `Pin` change or `RTC` timeout. |
|||
|
|||
The precise behaviour and power-saving capabilities of lightsleep and deepsleep is |
|||
highly dependent on the underlying hardware, but the general properties are: |
|||
|
|||
* A lightsleep has full RAM and state retention. Upon wake execution is resumed |
|||
from the point where the sleep was requested, with all subsystems operational. |
|||
|
|||
* A deepsleep may not retain RAM or any other state of the system (for example |
|||
peripherals or network interfaces). Upon wake execution is resumed from the main |
|||
script, similar to a hard or power-on reset. The `reset_cause()` function will |
|||
return `machine.DEEPSLEEP` and this can be used to distinguish a deepsleep wake |
|||
from other resets. |
|||
|
|||
.. function:: wake_reason() |
|||
|
|||
Get the wake reason. See :ref:`constants <machine_constants>` for the possible return values. |
|||
|
|||
Availability: ESP32, WiPy. |
|||
|
|||
Miscellaneous functions |
|||
----------------------- |
|||
|
|||
.. function:: unique_id() |
|||
|
|||
Returns a byte string with a unique identifier of a board/SoC. It will vary |
|||
from a board/SoC instance to another, if underlying hardware allows. Length |
|||
varies by hardware (so use substring of a full value if you expect a short |
|||
ID). In some MicroPython ports, ID corresponds to the network MAC address. |
|||
|
|||
.. function:: time_pulse_us(pin, pulse_level, timeout_us=1000000) |
|||
|
|||
Time a pulse on the given *pin*, and return the duration of the pulse in |
|||
microseconds. The *pulse_level* argument should be 0 to time a low pulse |
|||
or 1 to time a high pulse. |
|||
|
|||
If the current input value of the pin is different to *pulse_level*, |
|||
the function first (*) waits until the pin input becomes equal to *pulse_level*, |
|||
then (**) times the duration that the pin is equal to *pulse_level*. |
|||
If the pin is already equal to *pulse_level* then timing starts straight away. |
|||
|
|||
The function will return -2 if there was timeout waiting for condition marked |
|||
(*) above, and -1 if there was timeout during the main measurement, marked (**) |
|||
above. The timeout is the same for both cases and given by *timeout_us* (which |
|||
is in microseconds). |
|||
|
|||
.. function:: rng() |
|||
|
|||
Return a 24-bit software generated random number. |
|||
|
|||
Availability: WiPy. |
|||
|
|||
.. _machine_constants: |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: machine.IDLE |
|||
machine.SLEEP |
|||
machine.DEEPSLEEP |
|||
|
|||
IRQ wake values. |
|||
|
|||
.. data:: machine.PWRON_RESET |
|||
machine.HARD_RESET |
|||
machine.WDT_RESET |
|||
machine.DEEPSLEEP_RESET |
|||
machine.SOFT_RESET |
|||
|
|||
Reset causes. |
|||
|
|||
.. data:: machine.WLAN_WAKE |
|||
machine.PIN_WAKE |
|||
machine.RTC_WAKE |
|||
|
|||
Wake-up reasons. |
|||
|
|||
Classes |
|||
------- |
|||
|
|||
.. toctree:: |
|||
:maxdepth: 1 |
|||
|
|||
machine.Pin.rst |
|||
machine.Signal.rst |
|||
machine.ADC.rst |
|||
machine.UART.rst |
|||
machine.SPI.rst |
|||
machine.I2C.rst |
|||
machine.RTC.rst |
|||
machine.Timer.rst |
|||
machine.WDT.rst |
|||
machine.SD.rst |
|||
machine.SDCard.rst |
@ -0,0 +1,185 @@ |
|||
:mod:`math` -- mathematical functions |
|||
===================================== |
|||
|
|||
.. module:: math |
|||
:synopsis: mathematical functions |
|||
|
|||
|see_cpython_module| :mod:`python:math`. |
|||
|
|||
The ``math`` module provides some basic mathematical functions for |
|||
working with floating-point numbers. |
|||
|
|||
*Note:* On the pyboard, floating-point numbers have 32-bit precision. |
|||
|
|||
Availability: not available on WiPy. Floating point support required |
|||
for this module. |
|||
|
|||
Functions |
|||
--------- |
|||
|
|||
.. function:: acos(x) |
|||
|
|||
Return the inverse cosine of ``x``. |
|||
|
|||
.. function:: acosh(x) |
|||
|
|||
Return the inverse hyperbolic cosine of ``x``. |
|||
|
|||
.. function:: asin(x) |
|||
|
|||
Return the inverse sine of ``x``. |
|||
|
|||
.. function:: asinh(x) |
|||
|
|||
Return the inverse hyperbolic sine of ``x``. |
|||
|
|||
.. function:: atan(x) |
|||
|
|||
Return the inverse tangent of ``x``. |
|||
|
|||
.. function:: atan2(y, x) |
|||
|
|||
Return the principal value of the inverse tangent of ``y/x``. |
|||
|
|||
.. function:: atanh(x) |
|||
|
|||
Return the inverse hyperbolic tangent of ``x``. |
|||
|
|||
.. function:: ceil(x) |
|||
|
|||
Return an integer, being ``x`` rounded towards positive infinity. |
|||
|
|||
.. function:: copysign(x, y) |
|||
|
|||
Return ``x`` with the sign of ``y``. |
|||
|
|||
.. function:: cos(x) |
|||
|
|||
Return the cosine of ``x``. |
|||
|
|||
.. function:: cosh(x) |
|||
|
|||
Return the hyperbolic cosine of ``x``. |
|||
|
|||
.. function:: degrees(x) |
|||
|
|||
Return radians ``x`` converted to degrees. |
|||
|
|||
.. function:: erf(x) |
|||
|
|||
Return the error function of ``x``. |
|||
|
|||
.. function:: erfc(x) |
|||
|
|||
Return the complementary error function of ``x``. |
|||
|
|||
.. function:: exp(x) |
|||
|
|||
Return the exponential of ``x``. |
|||
|
|||
.. function:: expm1(x) |
|||
|
|||
Return ``exp(x) - 1``. |
|||
|
|||
.. function:: fabs(x) |
|||
|
|||
Return the absolute value of ``x``. |
|||
|
|||
.. function:: floor(x) |
|||
|
|||
Return an integer, being ``x`` rounded towards negative infinity. |
|||
|
|||
.. function:: fmod(x, y) |
|||
|
|||
Return the remainder of ``x/y``. |
|||
|
|||
.. function:: frexp(x) |
|||
|
|||
Decomposes a floating-point number into its mantissa and exponent. |
|||
The returned value is the tuple ``(m, e)`` such that ``x == m * 2**e`` |
|||
exactly. If ``x == 0`` then the function returns ``(0.0, 0)``, otherwise |
|||
the relation ``0.5 <= abs(m) < 1`` holds. |
|||
|
|||
.. function:: gamma(x) |
|||
|
|||
Return the gamma function of ``x``. |
|||
|
|||
.. function:: isfinite(x) |
|||
|
|||
Return ``True`` if ``x`` is finite. |
|||
|
|||
.. function:: isinf(x) |
|||
|
|||
Return ``True`` if ``x`` is infinite. |
|||
|
|||
.. function:: isnan(x) |
|||
|
|||
Return ``True`` if ``x`` is not-a-number |
|||
|
|||
.. function:: ldexp(x, exp) |
|||
|
|||
Return ``x * (2**exp)``. |
|||
|
|||
.. function:: lgamma(x) |
|||
|
|||
Return the natural logarithm of the gamma function of ``x``. |
|||
|
|||
.. function:: log(x) |
|||
|
|||
Return the natural logarithm of ``x``. |
|||
|
|||
.. function:: log10(x) |
|||
|
|||
Return the base-10 logarithm of ``x``. |
|||
|
|||
.. function:: log2(x) |
|||
|
|||
Return the base-2 logarithm of ``x``. |
|||
|
|||
.. function:: modf(x) |
|||
|
|||
Return a tuple of two floats, being the fractional and integral parts of |
|||
``x``. Both return values have the same sign as ``x``. |
|||
|
|||
.. function:: pow(x, y) |
|||
|
|||
Returns ``x`` to the power of ``y``. |
|||
|
|||
.. function:: radians(x) |
|||
|
|||
Return degrees ``x`` converted to radians. |
|||
|
|||
.. function:: sin(x) |
|||
|
|||
Return the sine of ``x``. |
|||
|
|||
.. function:: sinh(x) |
|||
|
|||
Return the hyperbolic sine of ``x``. |
|||
|
|||
.. function:: sqrt(x) |
|||
|
|||
Return the square root of ``x``. |
|||
|
|||
.. function:: tan(x) |
|||
|
|||
Return the tangent of ``x``. |
|||
|
|||
.. function:: tanh(x) |
|||
|
|||
Return the hyperbolic tangent of ``x``. |
|||
|
|||
.. function:: trunc(x) |
|||
|
|||
Return an integer, being ``x`` rounded towards 0. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: e |
|||
|
|||
base of the natural logarithm |
|||
|
|||
.. data:: pi |
|||
|
|||
the ratio of a circle's circumference to its diameter |
@ -0,0 +1,140 @@ |
|||
:mod:`micropython` -- access and control MicroPython internals |
|||
============================================================== |
|||
|
|||
.. module:: micropython |
|||
:synopsis: access and control MicroPython internals |
|||
|
|||
Functions |
|||
--------- |
|||
|
|||
.. function:: const(expr) |
|||
|
|||
Used to declare that the expression is a constant so that the compile can |
|||
optimise it. The use of this function should be as follows:: |
|||
|
|||
from micropython import const |
|||
|
|||
CONST_X = const(123) |
|||
CONST_Y = const(2 * CONST_X + 1) |
|||
|
|||
Constants declared this way are still accessible as global variables from |
|||
outside the module they are declared in. On the other hand, if a constant |
|||
begins with an underscore then it is hidden, it is not available as a global |
|||
variable, and does not take up any memory during execution. |
|||
|
|||
This `const` function is recognised directly by the MicroPython parser and is |
|||
provided as part of the :mod:`micropython` module mainly so that scripts can be |
|||
written which run under both CPython and MicroPython, by following the above |
|||
pattern. |
|||
|
|||
.. function:: opt_level([level]) |
|||
|
|||
If *level* is given then this function sets the optimisation level for subsequent |
|||
compilation of scripts, and returns ``None``. Otherwise it returns the current |
|||
optimisation level. |
|||
|
|||
The optimisation level controls the following compilation features: |
|||
|
|||
- Assertions: at level 0 assertion statements are enabled and compiled into the |
|||
bytecode; at levels 1 and higher assertions are not compiled. |
|||
- Built-in ``__debug__`` variable: at level 0 this variable expands to ``True``; |
|||
at levels 1 and higher it expands to ``False``. |
|||
- Source-code line numbers: at levels 0, 1 and 2 source-code line number are |
|||
stored along with the bytecode so that exceptions can report the line number |
|||
they occurred at; at levels 3 and higher line numbers are not stored. |
|||
|
|||
The default optimisation level is usually level 0. |
|||
|
|||
.. function:: alloc_emergency_exception_buf(size) |
|||
|
|||
Allocate *size* bytes of RAM for the emergency exception buffer (a good |
|||
size is around 100 bytes). The buffer is used to create exceptions in cases |
|||
when normal RAM allocation would fail (eg within an interrupt handler) and |
|||
therefore give useful traceback information in these situations. |
|||
|
|||
A good way to use this function is to put it at the start of your main script |
|||
(eg ``boot.py`` or ``main.py``) and then the emergency exception buffer will be active |
|||
for all the code following it. |
|||
|
|||
.. function:: mem_info([verbose]) |
|||
|
|||
Print information about currently used memory. If the *verbose* argument |
|||
is given then extra information is printed. |
|||
|
|||
The information that is printed is implementation dependent, but currently |
|||
includes the amount of stack and heap used. In verbose mode it prints out |
|||
the entire heap indicating which blocks are used and which are free. |
|||
|
|||
.. function:: qstr_info([verbose]) |
|||
|
|||
Print information about currently interned strings. If the *verbose* |
|||
argument is given then extra information is printed. |
|||
|
|||
The information that is printed is implementation dependent, but currently |
|||
includes the number of interned strings and the amount of RAM they use. In |
|||
verbose mode it prints out the names of all RAM-interned strings. |
|||
|
|||
.. function:: stack_use() |
|||
|
|||
Return an integer representing the current amount of stack that is being |
|||
used. The absolute value of this is not particularly useful, rather it |
|||
should be used to compute differences in stack usage at different points. |
|||
|
|||
.. function:: heap_lock() |
|||
.. function:: heap_unlock() |
|||
|
|||
Lock or unlock the heap. When locked no memory allocation can occur and a |
|||
`MemoryError` will be raised if any heap allocation is attempted. |
|||
|
|||
These functions can be nested, ie `heap_lock()` can be called multiple times |
|||
in a row and the lock-depth will increase, and then `heap_unlock()` must be |
|||
called the same number of times to make the heap available again. |
|||
|
|||
If the REPL becomes active with the heap locked then it will be forcefully |
|||
unlocked. |
|||
|
|||
.. function:: kbd_intr(chr) |
|||
|
|||
Set the character that will raise a `KeyboardInterrupt` exception. By |
|||
default this is set to 3 during script execution, corresponding to Ctrl-C. |
|||
Passing -1 to this function will disable capture of Ctrl-C, and passing 3 |
|||
will restore it. |
|||
|
|||
This function can be used to prevent the capturing of Ctrl-C on the |
|||
incoming stream of characters that is usually used for the REPL, in case |
|||
that stream is used for other purposes. |
|||
|
|||
.. function:: schedule(func, arg) |
|||
|
|||
Schedule the function *func* to be executed "very soon". The function |
|||
is passed the value *arg* as its single argument. "Very soon" means that |
|||
the MicroPython runtime will do its best to execute the function at the |
|||
earliest possible time, given that it is also trying to be efficient, and |
|||
that the following conditions hold: |
|||
|
|||
- A scheduled function will never preempt another scheduled function. |
|||
- Scheduled functions are always executed "between opcodes" which means |
|||
that all fundamental Python operations (such as appending to a list) |
|||
are guaranteed to be atomic. |
|||
- A given port may define "critical regions" within which scheduled |
|||
functions will never be executed. Functions may be scheduled within |
|||
a critical region but they will not be executed until that region |
|||
is exited. An example of a critical region is a preempting interrupt |
|||
handler (an IRQ). |
|||
|
|||
A use for this function is to schedule a callback from a preempting IRQ. |
|||
Such an IRQ puts restrictions on the code that runs in the IRQ (for example |
|||
the heap may be locked) and scheduling a function to call later will lift |
|||
those restrictions. |
|||
|
|||
Note: If `schedule()` is called from a preempting IRQ, when memory |
|||
allocation is not allowed and the callback to be passed to `schedule()` is |
|||
a bound method, passing this directly will fail. This is because creating a |
|||
reference to a bound method causes memory allocation. A solution is to |
|||
create a reference to the method in the class constructor and to pass that |
|||
reference to `schedule()`. This is discussed in detail here |
|||
:ref:`reference documentation <isr_rules>` under "Creation of Python |
|||
objects". |
|||
|
|||
There is a finite queue to hold the scheduled functions and `schedule()` |
|||
will raise a `RuntimeError` if the queue is full. |
@ -0,0 +1,89 @@ |
|||
.. currentmodule:: network |
|||
.. _network.CC3K: |
|||
|
|||
class CC3K -- control CC3000 WiFi modules |
|||
========================================= |
|||
|
|||
This class provides a driver for CC3000 WiFi modules. Example usage:: |
|||
|
|||
import network |
|||
nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) |
|||
nic.connect('your-ssid', 'your-password') |
|||
while not nic.isconnected(): |
|||
pyb.delay(50) |
|||
print(nic.ifconfig()) |
|||
|
|||
# now use socket as usual |
|||
... |
|||
|
|||
For this example to work the CC3000 module must have the following connections: |
|||
|
|||
- MOSI connected to Y8 |
|||
- MISO connected to Y7 |
|||
- CLK connected to Y6 |
|||
- CS connected to Y5 |
|||
- VBEN connected to Y4 |
|||
- IRQ connected to Y3 |
|||
|
|||
It is possible to use other SPI busses and other pins for CS, VBEN and IRQ. |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: CC3K(spi, pin_cs, pin_en, pin_irq) |
|||
|
|||
Create a CC3K driver object, initialise the CC3000 module using the given SPI bus |
|||
and pins, and return the CC3K object. |
|||
|
|||
Arguments are: |
|||
|
|||
- *spi* is an :ref:`SPI object <pyb.SPI>` which is the SPI bus that the CC3000 is |
|||
connected to (the MOSI, MISO and CLK pins). |
|||
- *pin_cs* is a :ref:`Pin object <pyb.Pin>` which is connected to the CC3000 CS pin. |
|||
- *pin_en* is a :ref:`Pin object <pyb.Pin>` which is connected to the CC3000 VBEN pin. |
|||
- *pin_irq* is a :ref:`Pin object <pyb.Pin>` which is connected to the CC3000 IRQ pin. |
|||
|
|||
All of these objects will be initialised by the driver, so there is no need to |
|||
initialise them yourself. For example, you can use:: |
|||
|
|||
nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: CC3K.connect(ssid, key=None, \*, security=WPA2, bssid=None) |
|||
|
|||
Connect to a WiFi access point using the given SSID, and other security |
|||
parameters. |
|||
|
|||
.. method:: CC3K.disconnect() |
|||
|
|||
Disconnect from the WiFi access point. |
|||
|
|||
.. method:: CC3K.isconnected() |
|||
|
|||
Returns True if connected to a WiFi access point and has a valid IP address, |
|||
False otherwise. |
|||
|
|||
.. method:: CC3K.ifconfig() |
|||
|
|||
Returns a 7-tuple with (ip, subnet mask, gateway, DNS server, DHCP server, |
|||
MAC address, SSID). |
|||
|
|||
.. method:: CC3K.patch_version() |
|||
|
|||
Return the version of the patch program (firmware) on the CC3000. |
|||
|
|||
.. method:: CC3K.patch_program('pgm') |
|||
|
|||
Upload the current firmware to the CC3000. You must pass 'pgm' as the first |
|||
argument in order for the upload to proceed. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: CC3K.WEP |
|||
.. data:: CC3K.WPA |
|||
.. data:: CC3K.WPA2 |
|||
|
|||
security type to use |
@ -0,0 +1,71 @@ |
|||
.. currentmodule:: network |
|||
.. _network.WIZNET5K: |
|||
|
|||
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 |
|||
option. |
|||
|
|||
Example usage:: |
|||
|
|||
import network |
|||
nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4) |
|||
print(nic.ifconfig()) |
|||
|
|||
# now use socket as usual |
|||
... |
|||
|
|||
For this example to work the WIZnet5x00 module must have the following connections: |
|||
|
|||
- MOSI connected to X8 |
|||
- MISO connected to X7 |
|||
- SCLK connected to X6 |
|||
- nSS connected to X5 |
|||
- nRESET connected to X4 |
|||
|
|||
It is possible to use other SPI busses and other pins for nSS and nRESET. |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: WIZNET5K(spi, pin_cs, pin_rst) |
|||
|
|||
Create a WIZNET5K driver object, initialise the WIZnet5x00 module using the given |
|||
SPI bus and pins, and return the WIZNET5K object. |
|||
|
|||
Arguments are: |
|||
|
|||
- *spi* is an :ref:`SPI object <pyb.SPI>` which is the SPI bus that the WIZnet5x00 is |
|||
connected to (the MOSI, MISO and SCLK pins). |
|||
- *pin_cs* is a :ref:`Pin object <pyb.Pin>` which is connected to the WIZnet5x00 nSS pin. |
|||
- *pin_rst* is a :ref:`Pin object <pyb.Pin>` which is connected to the WIZnet5x00 nRESET pin. |
|||
|
|||
All of these objects will be initialised by the driver, so there is no need to |
|||
initialise them yourself. For example, you can use:: |
|||
|
|||
nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4) |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: WIZNET5K.isconnected() |
|||
|
|||
Returns ``True`` if the physical Ethernet link is connected and up. |
|||
Returns ``False`` otherwise. |
|||
|
|||
.. method:: WIZNET5K.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:: WIZNET5K.regs() |
|||
|
|||
Dump the WIZnet5x00 registers. Useful for debugging. |
@ -0,0 +1,132 @@ |
|||
.. currentmodule:: network |
|||
.. _network.WLAN: |
|||
|
|||
class WLAN -- control built-in WiFi interfaces |
|||
============================================== |
|||
|
|||
This class provides a driver for WiFi network processors. Example usage:: |
|||
|
|||
import network |
|||
# enable station interface and connect to WiFi access point |
|||
nic = network.WLAN(network.STA_IF) |
|||
nic.active(True) |
|||
nic.connect('your-ssid', 'your-password') |
|||
# now use sockets as usual |
|||
|
|||
Constructors |
|||
------------ |
|||
.. class:: WLAN(interface_id) |
|||
|
|||
Create a WLAN network interface object. Supported interfaces are |
|||
``network.STA_IF`` (station aka client, connects to upstream WiFi access |
|||
points) and ``network.AP_IF`` (access point, allows other WiFi clients to |
|||
connect). Availability of the methods below depends on interface type. |
|||
For example, only STA interface may `WLAN.connect()` to an access point. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: WLAN.active([is_active]) |
|||
|
|||
Activate ("up") or deactivate ("down") network interface, if boolean |
|||
argument is passed. Otherwise, query current state if no argument is |
|||
provided. Most other methods require active interface. |
|||
|
|||
.. method:: WLAN.connect(ssid=None, password=None, \*, bssid=None) |
|||
|
|||
Connect to the specified wireless network, using the specified password. |
|||
If *bssid* is given then the connection will be restricted to the |
|||
access-point with that MAC address (the *ssid* must also be specified |
|||
in this case). |
|||
|
|||
.. method:: WLAN.disconnect() |
|||
|
|||
Disconnect from the currently connected wireless network. |
|||
|
|||
.. method:: WLAN.scan() |
|||
|
|||
Scan for the available wireless networks. |
|||
|
|||
Scanning is only possible on STA interface. Returns list of tuples with |
|||
the information about WiFi access points: |
|||
|
|||
(ssid, bssid, channel, RSSI, authmode, hidden) |
|||
|
|||
*bssid* is hardware address of an access point, in binary form, returned as |
|||
bytes object. You can use `ubinascii.hexlify()` to convert it to ASCII form. |
|||
|
|||
There are five values for authmode: |
|||
|
|||
* 0 -- open |
|||
* 1 -- WEP |
|||
* 2 -- WPA-PSK |
|||
* 3 -- WPA2-PSK |
|||
* 4 -- WPA/WPA2-PSK |
|||
|
|||
and two for hidden: |
|||
|
|||
* 0 -- visible |
|||
* 1 -- hidden |
|||
|
|||
.. method:: WLAN.status([param]) |
|||
|
|||
Return the current status of the wireless connection. |
|||
|
|||
When called with no argument the return value describes the network link status. |
|||
The possible statuses are defined as constants: |
|||
|
|||
* ``STAT_IDLE`` -- no connection and no activity, |
|||
* ``STAT_CONNECTING`` -- connecting in progress, |
|||
* ``STAT_WRONG_PASSWORD`` -- failed due to incorrect password, |
|||
* ``STAT_NO_AP_FOUND`` -- failed because no access point replied, |
|||
* ``STAT_CONNECT_FAIL`` -- failed due to other problems, |
|||
* ``STAT_GOT_IP`` -- connection successful. |
|||
|
|||
When called with one argument *param* should be a string naming the status |
|||
parameter to retrieve. Supported parameters in WiFI STA mode are: ``'rssi'``. |
|||
|
|||
.. method:: WLAN.isconnected() |
|||
|
|||
In case of STA mode, returns ``True`` if connected to a WiFi access |
|||
point and has a valid IP address. In AP mode returns ``True`` when a |
|||
station is connected. Returns ``False`` otherwise. |
|||
|
|||
.. method:: WLAN.ifconfig([(ip, subnet, gateway, dns)]) |
|||
|
|||
Get/set IP-level network interface parameters: IP address, subnet mask, |
|||
gateway and DNS server. 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:: WLAN.config('param') |
|||
.. method:: WLAN.config(param=value, ...) |
|||
|
|||
Get or set general network interface parameters. These methods allow to work |
|||
with additional parameters beyond standard IP configuration (as dealt with by |
|||
`WLAN.ifconfig()`). These include network-specific and hardware-specific |
|||
parameters. For setting parameters, keyword argument syntax should be used, |
|||
multiple parameters can be set at once. For querying, parameters name should |
|||
be quoted as a string, and only one parameter can be queries at time:: |
|||
|
|||
# Set WiFi access point name (formally known as ESSID) and WiFi channel |
|||
ap.config(essid='My AP', channel=11) |
|||
# Query params one by one |
|||
print(ap.config('essid')) |
|||
print(ap.config('channel')) |
|||
|
|||
Following are commonly supported parameters (availability of a specific parameter |
|||
depends on network technology type, driver, and `MicroPython port`). |
|||
|
|||
============= =========== |
|||
Parameter Description |
|||
============= =========== |
|||
mac MAC address (bytes) |
|||
essid WiFi access point name (string) |
|||
channel WiFi channel (integer) |
|||
hidden Whether ESSID is hidden (boolean) |
|||
authmode Authentication mode supported (enumeration, see module constants) |
|||
password Access password (string) |
|||
dhcp_hostname The DHCP hostname to use |
|||
============= =========== |
@ -0,0 +1,161 @@ |
|||
.. currentmodule:: network |
|||
.. _network.WLANWiPy: |
|||
|
|||
class WLANWiPy -- WiPy specific WiFi control |
|||
============================================ |
|||
|
|||
.. note:: |
|||
|
|||
This class is a non-standard WLAN implementation for the WiPy. |
|||
It is available simply as ``network.WLAN`` on the WiPy but is named in the |
|||
documentation below as ``network.WLANWiPy`` to distinguish it from the |
|||
more general :ref:`network.WLAN <network.WLAN>` class. |
|||
|
|||
This class provides a driver for the WiFi network processor in the WiPy. Example usage:: |
|||
|
|||
import network |
|||
import time |
|||
# setup as a station |
|||
wlan = network.WLAN(mode=WLAN.STA) |
|||
wlan.connect('your-ssid', auth=(WLAN.WPA2, 'your-key')) |
|||
while not wlan.isconnected(): |
|||
time.sleep_ms(50) |
|||
print(wlan.ifconfig()) |
|||
|
|||
# now use socket as usual |
|||
... |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: WLANWiPy(id=0, ...) |
|||
|
|||
Create a WLAN object, and optionally configure it. See `init()` for params of configuration. |
|||
|
|||
.. note:: |
|||
|
|||
The ``WLAN`` constructor is special in the sense that if no arguments besides the id are given, |
|||
it will return the already existing ``WLAN`` instance without re-configuring it. This is |
|||
because ``WLAN`` is a system feature of the WiPy. If the already existing instance is not |
|||
initialized it will do the same as the other constructors an will initialize it with default |
|||
values. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: WLANWiPy.init(mode, \*, ssid, auth, channel, antenna) |
|||
|
|||
Set or get the WiFi network processor configuration. |
|||
|
|||
Arguments are: |
|||
|
|||
- *mode* can be either ``WLAN.STA`` or ``WLAN.AP``. |
|||
- *ssid* is a string with the ssid name. Only needed when mode is ``WLAN.AP``. |
|||
- *auth* is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``, |
|||
``WLAN.WPA`` or ``WLAN.WPA2``. The key is a string with the network password. |
|||
If ``sec`` is ``WLAN.WEP`` the key must be a string representing hexadecimal |
|||
values (e.g. 'ABC1DE45BF'). Only needed when mode is ``WLAN.AP``. |
|||
- *channel* a number in the range 1-11. Only needed when mode is ``WLAN.AP``. |
|||
- *antenna* selects between the internal and the external antenna. Can be either |
|||
``WLAN.INT_ANT`` or ``WLAN.EXT_ANT``. |
|||
|
|||
For example, you can do:: |
|||
|
|||
# create and configure as an access point |
|||
wlan.init(mode=WLAN.AP, ssid='wipy-wlan', auth=(WLAN.WPA2,'www.wipy.io'), channel=7, antenna=WLAN.INT_ANT) |
|||
|
|||
or:: |
|||
|
|||
# configure as an station |
|||
wlan.init(mode=WLAN.STA) |
|||
|
|||
.. method:: WLANWiPy.connect(ssid, \*, auth=None, bssid=None, timeout=None) |
|||
|
|||
Connect to a WiFi access point using the given SSID, and other security |
|||
parameters. |
|||
|
|||
- *auth* is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``, |
|||
``WLAN.WPA`` or ``WLAN.WPA2``. The key is a string with the network password. |
|||
If ``sec`` is ``WLAN.WEP`` the key must be a string representing hexadecimal |
|||
values (e.g. 'ABC1DE45BF'). |
|||
- *bssid* is the MAC address of the AP to connect to. Useful when there are several |
|||
APs with the same ssid. |
|||
- *timeout* is the maximum time in milliseconds to wait for the connection to succeed. |
|||
|
|||
.. method:: WLANWiPy.scan() |
|||
|
|||
Performs a network scan and returns a list of named tuples with (ssid, bssid, sec, channel, rssi). |
|||
Note that channel is always ``None`` since this info is not provided by the WiPy. |
|||
|
|||
.. method:: WLANWiPy.disconnect() |
|||
|
|||
Disconnect from the WiFi access point. |
|||
|
|||
.. method:: WLANWiPy.isconnected() |
|||
|
|||
In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address. |
|||
In AP mode returns ``True`` when a station is connected, ``False`` otherwise. |
|||
|
|||
.. method:: WLANWiPy.ifconfig(if_id=0, config=['dhcp' or configtuple]) |
|||
|
|||
With no parameters given returns a 4-tuple of *(ip, subnet_mask, gateway, DNS_server)*. |
|||
|
|||
if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params |
|||
are negotiated with the AP. |
|||
|
|||
If the 4-tuple config is given then a static IP is configured. For instance:: |
|||
|
|||
wlan.ifconfig(config=('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) |
|||
|
|||
.. method:: WLANWiPy.mode([mode]) |
|||
|
|||
Get or set the WLAN mode. |
|||
|
|||
.. method:: WLANWiPy.ssid([ssid]) |
|||
|
|||
Get or set the SSID when in AP mode. |
|||
|
|||
.. method:: WLANWiPy.auth([auth]) |
|||
|
|||
Get or set the authentication type when in AP mode. |
|||
|
|||
.. method:: WLANWiPy.channel([channel]) |
|||
|
|||
Get or set the channel (only applicable in AP mode). |
|||
|
|||
.. method:: WLANWiPy.antenna([antenna]) |
|||
|
|||
Get or set the antenna type (external or internal). |
|||
|
|||
.. method:: WLANWiPy.mac([mac_addr]) |
|||
|
|||
Get or set a 6-byte long bytes object with the MAC address. |
|||
|
|||
.. method:: WLANWiPy.irq(\*, handler, wake) |
|||
|
|||
Create a callback to be triggered when a WLAN event occurs during ``machine.SLEEP`` |
|||
mode. Events are triggered by socket activity or by WLAN connection/disconnection. |
|||
|
|||
- *handler* is the function that gets called when the IRQ is triggered. |
|||
- *wake* must be ``machine.SLEEP``. |
|||
|
|||
Returns an IRQ object. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: WLANWiPy.STA |
|||
.. data:: WLANWiPy.AP |
|||
|
|||
selects the WLAN mode |
|||
|
|||
.. data:: WLANWiPy.WEP |
|||
.. data:: WLANWiPy.WPA |
|||
.. data:: WLANWiPy.WPA2 |
|||
|
|||
selects the network security |
|||
|
|||
.. data:: WLANWiPy.INT_ANT |
|||
.. data:: WLANWiPy.EXT_ANT |
|||
|
|||
selects the antenna type |
@ -0,0 +1,173 @@ |
|||
**************************************** |
|||
:mod:`network` --- network configuration |
|||
**************************************** |
|||
|
|||
.. module:: network |
|||
:synopsis: network configuration |
|||
|
|||
This module provides network drivers and routing configuration. To use this |
|||
module, a MicroPython variant/build with network capabilities must be installed. |
|||
Network drivers for specific hardware are available within this module and are |
|||
used to configure hardware network interface(s). Network services provided |
|||
by configured interfaces are then available for use via the :mod:`usocket` |
|||
module. |
|||
|
|||
For example:: |
|||
|
|||
# connect/ show IP config a specific network interface |
|||
# see below for examples of specific drivers |
|||
import network |
|||
import utime |
|||
nic = network.Driver(...) |
|||
if not nic.isconnected(): |
|||
nic.connect() |
|||
print("Waiting for connection...") |
|||
while not nic.isconnected(): |
|||
utime.sleep(1) |
|||
print(nic.ifconfig()) |
|||
|
|||
# now use usocket as usual |
|||
import usocket as socket |
|||
addr = socket.getaddrinfo('micropython.org', 80)[0][-1] |
|||
s = socket.socket() |
|||
s.connect(addr) |
|||
s.send(b'GET / HTTP/1.1\r\nHost: micropython.org\r\n\r\n') |
|||
data = s.recv(1000) |
|||
s.close() |
|||
|
|||
Common network adapter interface |
|||
================================ |
|||
|
|||
This section describes an (implied) abstract base class for all network |
|||
interface classes implemented by `MicroPython ports <MicroPython port>` |
|||
for different hardware. This means that MicroPython does not actually |
|||
provide ``AbstractNIC`` class, but any actual NIC class, as described |
|||
in the following sections, implements methods as described here. |
|||
|
|||
.. class:: AbstractNIC(id=None, ...) |
|||
|
|||
Instantiate a network interface object. Parameters are network interface |
|||
dependent. If there are more than one interface of the same type, the first |
|||
parameter should be `id`. |
|||
|
|||
.. method:: AbstractNIC.active([is_active]) |
|||
|
|||
Activate ("up") or deactivate ("down") the network interface, if |
|||
a boolean argument is passed. Otherwise, query current state if |
|||
no argument is provided. Most other methods require an active |
|||
interface (behavior of calling them on inactive interface is |
|||
undefined). |
|||
|
|||
.. method:: AbstractNIC.connect([service_id, key=None, \*, ...]) |
|||
|
|||
Connect the interface to a network. This method is optional, and |
|||
available only for interfaces which are not "always connected". |
|||
If no parameters are given, connect to the default (or the only) |
|||
service. If a single parameter is given, it is the primary identifier |
|||
of a service to connect to. It may be accompanied by a key |
|||
(password) required to access said service. There can be further |
|||
arbitrary keyword-only parameters, depending on the networking medium |
|||
type and/or particular device. Parameters can be used to: a) |
|||
specify alternative service identifier types; b) provide additional |
|||
connection parameters. For various medium types, there are different |
|||
sets of predefined/recommended parameters, among them: |
|||
|
|||
* WiFi: *bssid* keyword to connect to a specific BSSID (MAC address) |
|||
|
|||
.. method:: AbstractNIC.disconnect() |
|||
|
|||
Disconnect from network. |
|||
|
|||
.. method:: AbstractNIC.isconnected() |
|||
|
|||
Returns ``True`` if connected to network, otherwise returns ``False``. |
|||
|
|||
.. method:: AbstractNIC.scan(\*, ...) |
|||
|
|||
Scan for the available network services/connections. Returns a |
|||
list of tuples with discovered service parameters. For various |
|||
network media, there are different variants of predefined/ |
|||
recommended tuple formats, among them: |
|||
|
|||
* WiFi: (ssid, bssid, channel, RSSI, authmode, hidden). There |
|||
may be further fields, specific to a particular device. |
|||
|
|||
The function may accept additional keyword arguments to filter scan |
|||
results (e.g. scan for a particular service, on a particular channel, |
|||
for services of a particular set, etc.), and to affect scan |
|||
duration and other parameters. Where possible, parameter names |
|||
should match those in connect(). |
|||
|
|||
.. method:: AbstractNIC.status([param]) |
|||
|
|||
Query dynamic status information of the interface. When called with no |
|||
argument the return value describes the network link status. Otherwise |
|||
*param* should be a string naming the particular status parameter to |
|||
retrieve. |
|||
|
|||
The return types and values are dependent on the network |
|||
medium/technology. Some of the parameters that may be supported are: |
|||
|
|||
* WiFi STA: use ``'rssi'`` to retrieve the RSSI of the AP signal |
|||
* WiFi AP: use ``'stations'`` to retrieve a list of all the STAs |
|||
connected to the AP. The list contains tuples of the form |
|||
(MAC, RSSI). |
|||
|
|||
.. method:: AbstractNIC.ifconfig([(ip, subnet, gateway, dns)]) |
|||
|
|||
Get/set IP-level network interface parameters: IP address, subnet mask, |
|||
gateway and DNS server. 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:: AbstractNIC.config('param') |
|||
AbstractNIC.config(param=value, ...) |
|||
|
|||
Get or set general network interface parameters. These methods allow to work |
|||
with additional parameters beyond standard IP configuration (as dealt with by |
|||
`ifconfig()`). These include network-specific and hardware-specific |
|||
parameters. For setting parameters, the keyword argument |
|||
syntax should be used, and multiple parameters can be set at once. For |
|||
querying, a parameter name should be quoted as a string, and only one |
|||
parameter can be queried at a time:: |
|||
|
|||
# Set WiFi access point name (formally known as ESSID) and WiFi channel |
|||
ap.config(essid='My AP', channel=11) |
|||
# Query params one by one |
|||
print(ap.config('essid')) |
|||
print(ap.config('channel')) |
|||
|
|||
Specific network class implementations |
|||
====================================== |
|||
|
|||
The following concrete classes implement the AbstractNIC interface and |
|||
provide a way to control networking interfaces of various kinds. |
|||
|
|||
.. toctree:: |
|||
:maxdepth: 1 |
|||
|
|||
network.WLAN.rst |
|||
network.WLANWiPy.rst |
|||
network.CC3K.rst |
|||
network.WIZNET5K.rst |
|||
|
|||
Network functions |
|||
================= |
|||
|
|||
The following are functions available in the network module. |
|||
|
|||
.. function:: phy_mode([mode]) |
|||
|
|||
Get or set the PHY mode. |
|||
|
|||
If the *mode* parameter is provided, sets the mode to its value. If |
|||
the function is called without parameters, returns the current mode. |
|||
|
|||
The possible modes are defined as constants: |
|||
* ``MODE_11B`` -- IEEE 802.11b, |
|||
* ``MODE_11G`` -- IEEE 802.11g, |
|||
* ``MODE_11N`` -- IEEE 802.11n. |
|||
|
|||
Availability: ESP8266. |
@ -0,0 +1,167 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.ADC: |
|||
|
|||
class ADC -- analog to digital conversion |
|||
========================================= |
|||
|
|||
Usage:: |
|||
|
|||
import pyb |
|||
|
|||
adc = pyb.ADC(pin) # create an analog object from a pin |
|||
val = adc.read() # read an analog value |
|||
|
|||
adc = pyb.ADCAll(resolution) # create an ADCAll object |
|||
adc = pyb.ADCAll(resolution, mask) # create an ADCAll object for selected analog channels |
|||
val = adc.read_channel(channel) # read the given channel |
|||
val = adc.read_core_temp() # read MCU temperature |
|||
val = adc.read_core_vbat() # read MCU VBAT |
|||
val = adc.read_core_vref() # read MCU VREF |
|||
val = adc.read_vref() # read MCU supply voltage |
|||
|
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.ADC(pin) |
|||
|
|||
Create an ADC object associated with the given pin. |
|||
This allows you to then read analog values on that pin. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: ADC.read() |
|||
|
|||
Read the value on the analog pin and return it. The returned value |
|||
will be between 0 and 4095. |
|||
|
|||
.. method:: ADC.read_timed(buf, timer) |
|||
|
|||
Read analog values into ``buf`` at a rate set by the ``timer`` object. |
|||
|
|||
``buf`` can be bytearray or array.array for example. The ADC values have |
|||
12-bit resolution and are stored directly into ``buf`` if its element size is |
|||
16 bits or greater. If ``buf`` has only 8-bit elements (eg a bytearray) then |
|||
the sample resolution will be reduced to 8 bits. |
|||
|
|||
``timer`` should be a Timer object, and a sample is read each time the timer |
|||
triggers. The timer must already be initialised and running at the desired |
|||
sampling frequency. |
|||
|
|||
To support previous behaviour of this function, ``timer`` can also be an |
|||
integer which specifies the frequency (in Hz) to sample at. In this case |
|||
Timer(6) will be automatically configured to run at the given frequency. |
|||
|
|||
Example using a Timer object (preferred way):: |
|||
|
|||
adc = pyb.ADC(pyb.Pin.board.X19) # create an ADC on pin X19 |
|||
tim = pyb.Timer(6, freq=10) # create a timer running at 10Hz |
|||
buf = bytearray(100) # creat a buffer to store the samples |
|||
adc.read_timed(buf, tim) # sample 100 values, taking 10s |
|||
|
|||
Example using an integer for the frequency:: |
|||
|
|||
adc = pyb.ADC(pyb.Pin.board.X19) # create an ADC on pin X19 |
|||
buf = bytearray(100) # create a buffer of 100 bytes |
|||
adc.read_timed(buf, 10) # read analog values into buf at 10Hz |
|||
# this will take 10 seconds to finish |
|||
for val in buf: # loop over all values |
|||
print(val) # print the value out |
|||
|
|||
This function does not allocate any heap memory. It has blocking behaviour: |
|||
it does not return to the calling program until the buffer is full. |
|||
|
|||
.. method:: ADC.read_timed_multi((adcx, adcy, ...), (bufx, bufy, ...), timer) |
|||
|
|||
This is a static method. It can be used to extract relative timing or |
|||
phase data from multiple ADC's. |
|||
|
|||
It reads analog values from multiple ADC's into buffers at a rate set by |
|||
the *timer* object. Each time the timer triggers a sample is rapidly |
|||
read from each ADC in turn. |
|||
|
|||
ADC and buffer instances are passed in tuples with each ADC having an |
|||
associated buffer. All buffers must be of the same type and length and |
|||
the number of buffers must equal the number of ADC's. |
|||
|
|||
Buffers can be ``bytearray`` or ``array.array`` for example. The ADC values |
|||
have 12-bit resolution and are stored directly into the buffer if its element |
|||
size is 16 bits or greater. If buffers have only 8-bit elements (eg a |
|||
``bytearray``) then the sample resolution will be reduced to 8 bits. |
|||
|
|||
*timer* must be a Timer object. The timer must already be initialised |
|||
and running at the desired sampling frequency. |
|||
|
|||
Example reading 3 ADC's:: |
|||
|
|||
adc0 = pyb.ADC(pyb.Pin.board.X1) # Create ADC's |
|||
adc1 = pyb.ADC(pyb.Pin.board.X2) |
|||
adc2 = pyb.ADC(pyb.Pin.board.X3) |
|||
tim = pyb.Timer(8, freq=100) # Create timer |
|||
rx0 = array.array('H', (0 for i in range(100))) # ADC buffers of |
|||
rx1 = array.array('H', (0 for i in range(100))) # 100 16-bit words |
|||
rx2 = array.array('H', (0 for i in range(100))) |
|||
# read analog values into buffers at 100Hz (takes one second) |
|||
pyb.ADC.read_timed_multi((adc0, adc1, adc2), (rx0, rx1, rx2), tim) |
|||
for n in range(len(rx0)): |
|||
print(rx0[n], rx1[n], rx2[n]) |
|||
|
|||
This function does not allocate any heap memory. It has blocking behaviour: |
|||
it does not return to the calling program until the buffers are full. |
|||
|
|||
The function returns ``True`` if all samples were acquired with correct |
|||
timing. At high sample rates the time taken to acquire a set of samples |
|||
can exceed the timer period. In this case the function returns ``False``, |
|||
indicating a loss of precision in the sample interval. In extreme cases |
|||
samples may be missed. |
|||
|
|||
The maximum rate depends on factors including the data width and the |
|||
number of ADC's being read. In testing two ADC's were sampled at a timer |
|||
rate of 210kHz without overrun. Samples were missed at 215kHz. For three |
|||
ADC's the limit is around 140kHz, and for four it is around 110kHz. |
|||
At high sample rates disabling interrupts for the duration can reduce the |
|||
risk of sporadic data loss. |
|||
|
|||
The ADCAll Object |
|||
----------------- |
|||
|
|||
Instantiating this changes all masked ADC pins to analog inputs. The preprocessed MCU temperature, |
|||
VREF and VBAT data can be accessed on ADC channels 16, 17 and 18 respectively. |
|||
Appropriate scaling is handled according to reference voltage used (usually 3.3V). |
|||
The temperature sensor on the chip is factory calibrated and allows to read the die temperature |
|||
to +/- 1 degree centigrade. Although this sounds pretty accurate, don't forget that the MCU's internal |
|||
temperature is measured. Depending on processing loads and I/O subsystems active the die temperature |
|||
may easily be tens of degrees above ambient temperature. On the other hand a pyboard woken up after a |
|||
long standby period will show correct ambient temperature within limits mentioned above. |
|||
|
|||
The ``ADCAll`` ``read_core_vbat()``, ``read_vref()`` and ``read_core_vref()`` methods read |
|||
the backup battery voltage, reference voltage and the (1.21V nominal) reference voltage using the |
|||
actual supply as a reference. All results are floating point numbers giving direct voltage values. |
|||
|
|||
``read_core_vbat()`` returns the voltage of the backup battery. This voltage is also adjusted according |
|||
to the actual supply voltage. To avoid analog input overload the battery voltage is measured |
|||
via a voltage divider and scaled according to the divider value. To prevent excessive loads |
|||
to the backup battery, the voltage divider is only active during ADC conversion. |
|||
|
|||
``read_vref()`` is evaluated by measuring the internal voltage reference and backscale it using |
|||
factory calibration value of the internal voltage reference. In most cases the reading would be close |
|||
to 3.3V. If the pyboard is operated from a battery, the supply voltage may drop to values below 3.3V. |
|||
The pyboard will still operate fine as long as the operating conditions are met. With proper settings |
|||
of MCU clock, flash access speed and programming mode it is possible to run the pyboard down to |
|||
2 V and still get useful ADC conversion. |
|||
|
|||
It is very important to make sure analog input voltages never exceed actual supply voltage. |
|||
|
|||
Other analog input channels (0..15) will return unscaled integer values according to the selected |
|||
precision. |
|||
|
|||
To avoid unwanted activation of analog inputs (channel 0..15) a second parameter can be specified. |
|||
This parameter is a binary pattern where each requested analog input has the corresponding bit set. |
|||
The default value is 0xffffffff which means all analog inputs are active. If just the internal |
|||
channels (16..18) are required, the mask value should be 0x70000. |
|||
|
|||
Example:: |
|||
|
|||
adcall = pyb.ADCAll(12, 0x70000) # 12 bit resolution, internal channels |
|||
temp = adcall.read_core_temp() |
@ -0,0 +1,57 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.Accel: |
|||
|
|||
class Accel -- accelerometer control |
|||
==================================== |
|||
|
|||
Accel is an object that controls the accelerometer. Example usage:: |
|||
|
|||
accel = pyb.Accel() |
|||
for i in range(10): |
|||
print(accel.x(), accel.y(), accel.z()) |
|||
|
|||
Raw values are between -32 and 31. |
|||
|
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.Accel() |
|||
|
|||
Create and return an accelerometer object. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: Accel.filtered_xyz() |
|||
|
|||
Get a 3-tuple of filtered x, y and z values. |
|||
|
|||
Implementation note: this method is currently implemented as taking the |
|||
sum of 4 samples, sampled from the 3 previous calls to this function along |
|||
with the sample from the current call. Returned values are therefore 4 |
|||
times the size of what they would be from the raw x(), y() and z() calls. |
|||
|
|||
.. method:: Accel.tilt() |
|||
|
|||
Get the tilt register. |
|||
|
|||
.. method:: Accel.x() |
|||
|
|||
Get the x-axis value. |
|||
|
|||
.. method:: Accel.y() |
|||
|
|||
Get the y-axis value. |
|||
|
|||
.. method:: Accel.z() |
|||
|
|||
Get the z-axis value. |
|||
|
|||
Hardware Note |
|||
------------- |
|||
|
|||
The accelerometer uses I2C bus 1 to communicate with the processor. Consequently |
|||
when readings are being taken pins X9 and X10 should be unused (other than for |
|||
I2C). Other devices using those pins, and which therefore cannot be used |
|||
concurrently, are UART 1 and Timer 4 channels 1 and 2. |
@ -0,0 +1,300 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.CAN: |
|||
|
|||
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 |
|||
voltage levels on the bus. |
|||
|
|||
Example usage (works without anything connected):: |
|||
|
|||
from pyb import CAN |
|||
can = CAN(1, CAN.LOOPBACK) |
|||
can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126)) # set a filter to receive messages with id=123, 124, 125 and 126 |
|||
can.send('message!', 123) # send a message with id 123 |
|||
can.recv(0) # receive message on FIFO 0 |
|||
|
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.CAN(bus, ...) |
|||
|
|||
Construct a CAN object on the given bus. *bus* can be 1-2, or ``'YA'`` or ``'YB'``. |
|||
With no additional parameters, the CAN object is created but not |
|||
initialised (it has the settings from the last initialisation of |
|||
the bus, if any). If extra arguments are given, the bus is initialised. |
|||
See :meth:`CAN.init` for parameters of initialisation. |
|||
|
|||
The physical pins of the CAN busses are: |
|||
|
|||
- ``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) |
|||
|
|||
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 |
|||
- *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 |
|||
|
|||
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); |
|||
see :meth:`pyb.freq()` to determine PCLK1. |
|||
|
|||
A single bit is made up of the synchronisation segment, which is always 1 tq. |
|||
Then follows bit segment 1, then bit segment 2. The sample point is after bit |
|||
segment 1 finishes. The transmit point is after bit segment 2 finishes. |
|||
The baud rate will be 1/bittime, where the bittime is 1 + BS1 + BS2 multiplied |
|||
by the time quanta tq. |
|||
|
|||
For example, with PCLK1=42MHz, prescaler=100, sjw=1, bs1=6, bs2=8, the value of |
|||
tq is 2.38 microseconds. The bittime is 35.7 microseconds, and the baudrate |
|||
is 28kHz. |
|||
|
|||
See page 680 of the STM32F405 datasheet for more details. |
|||
|
|||
.. method:: CAN.deinit() |
|||
|
|||
Turn off the CAN bus. |
|||
|
|||
.. method:: CAN.restart() |
|||
|
|||
Force a software restart of the CAN controller without resetting its |
|||
configuration. |
|||
|
|||
If the controller enters the bus-off state then it will no longer participate |
|||
in bus activity. If the controller is not configured to automatically restart |
|||
(see :meth:`~CAN.init()`) then this method can be used to trigger a restart, |
|||
and the controller will follow the CAN protocol to leave the bus-off state and |
|||
go into the error active state. |
|||
|
|||
.. method:: CAN.state() |
|||
|
|||
Return the state of the controller. The return value can be one of: |
|||
|
|||
- ``CAN.STOPPED`` -- the controller is completely off and reset; |
|||
- ``CAN.ERROR_ACTIVE`` -- the controller is on and in the Error Active state |
|||
(both TEC and REC are less than 96); |
|||
- ``CAN.ERROR_WARNING`` -- the controller is on and in the Error Warning state |
|||
(at least one of TEC or REC is 96 or greater); |
|||
- ``CAN.ERROR_PASSIVE`` -- the controller is on and in the Error Passive state |
|||
(at least one of TEC or REC is 128 or greater); |
|||
- ``CAN.BUS_OFF`` -- the controller is on but not participating in bus activity |
|||
(TEC overflowed beyond 255). |
|||
|
|||
.. method:: CAN.info([list]) |
|||
|
|||
Get information about the controller's error states and TX and RX buffers. |
|||
If *list* is provided then it should be a list object with at least 8 entries, |
|||
which will be filled in with the information. Otherwise a new list will be |
|||
created and filled in. In both cases the return value of the method is the |
|||
populated list. |
|||
|
|||
The values in the list are: |
|||
|
|||
- TEC value |
|||
- REC value |
|||
- number of times the controller enterted the Error Warning state (wrapped |
|||
around to 0 after 65535) |
|||
- number of times the controller enterted the Error Passive state (wrapped |
|||
around to 0 after 65535) |
|||
- number of times the controller enterted the Bus Off state (wrapped |
|||
around to 0 after 65535) |
|||
- number of pending TX messages |
|||
- number of pending RX messages on fifo 0 |
|||
- number of pending RX messages on fifo 1 |
|||
|
|||
.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) |
|||
|
|||
Configure a filter bank: |
|||
|
|||
- *bank* is the filter bank that is to be configured. |
|||
- *mode* is the mode the filter should operate in. |
|||
- *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 | |
|||
+===========+=========================================================+ |
|||
|CAN.LIST16 |Four 16 bit ids that will be accepted | |
|||
+-----------+---------------------------------------------------------+ |
|||
|CAN.LIST32 |Two 32 bit ids that will be accepted | |
|||
+-----------+---------------------------------------------------------+ |
|||
|CAN.MASK16 |Two 16 bit id/mask pairs. E.g. (1, 3, 4, 4) | |
|||
| | | The first pair, 1 and 3 will accept all ids | |
|||
| | | that have bit 0 = 1 and bit 1 = 0. | |
|||
| | | The second pair, 4 and 4, will accept all ids | |
|||
| | | that have bit 2 = 1. | |
|||
+-----------+---------------------------------------------------------+ |
|||
|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* |length of *rtr* array | |
|||
+===========+======================+ |
|||
|CAN.LIST16 |4 | |
|||
+-----------+----------------------+ |
|||
|CAN.LIST32 |2 | |
|||
+-----------+----------------------+ |
|||
|CAN.MASK16 |2 | |
|||
+-----------+----------------------+ |
|||
|CAN.MASK32 |1 | |
|||
+-----------+----------------------+ |
|||
|
|||
.. method:: CAN.clearfilter(bank) |
|||
|
|||
Clear and disables a filter bank: |
|||
|
|||
- *bank* is the filter bank that is to be cleared. |
|||
|
|||
.. method:: CAN.any(fifo) |
|||
|
|||
Return ``True`` if any message waiting on the FIFO, else ``False``. |
|||
|
|||
.. method:: CAN.recv(fifo, list=None, \*, timeout=5000) |
|||
|
|||
Receive data on the bus: |
|||
|
|||
- *fifo* is an integer, which is the FIFO to receive on |
|||
- *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. |
|||
|
|||
- The id of the message. |
|||
- 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). |
|||
|
|||
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 |
|||
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 |
|||
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. |
|||
For example:: |
|||
|
|||
buf = bytearray(8) |
|||
lst = [0, 0, 0, memoryview(buf)] |
|||
# No heap memory is allocated in the following call |
|||
can.recv(0, lst) |
|||
|
|||
.. method:: CAN.send(data, id, \*, timeout=0, rtr=False) |
|||
|
|||
Send a message on the bus: |
|||
|
|||
- *data* is the data to send (an integer to send, or a buffer object). |
|||
- *id* is the id of the message to be sent. |
|||
- *timeout* is the timeout in milliseconds to wait for the send. |
|||
- *rtr* is a boolean that specifies if the message shall be sent as |
|||
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. |
|||
|
|||
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 |
|||
an exception is thrown. If timeout is not 0, the method waits until the |
|||
message is transmitted. If the message can't be transmitted within the |
|||
specified time an exception is thrown. |
|||
|
|||
Return value: ``None``. |
|||
|
|||
.. method:: CAN.rxcallback(fifo, fun) |
|||
|
|||
Register a function to be called when a message is accepted into a empty fifo: |
|||
|
|||
- *fifo* is the receiving fifo. |
|||
- *fun* is the function to be called when the fifo becomes non empty. |
|||
|
|||
The callback function takes two arguments the first is the can object it self the second is |
|||
a integer that indicates the reason for the callback. |
|||
|
|||
+--------+------------------------------------------------+ |
|||
| Reason | | |
|||
+========+================================================+ |
|||
| 0 | A message has been accepted into a empty FIFO. | |
|||
+--------+------------------------------------------------+ |
|||
| 1 | The FIFO is full | |
|||
+--------+------------------------------------------------+ |
|||
| 2 | A message has been lost due to a full FIFO | |
|||
+--------+------------------------------------------------+ |
|||
|
|||
Example use of rxcallback:: |
|||
|
|||
def cb0(bus, reason): |
|||
print('cb0') |
|||
if reason == 0: |
|||
print('pending') |
|||
if reason == 1: |
|||
print('full') |
|||
if reason == 2: |
|||
print('overflow') |
|||
|
|||
can = CAN(1, CAN.LOOPBACK) |
|||
can.rxcallback(0, cb0) |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: CAN.NORMAL |
|||
CAN.LOOPBACK |
|||
CAN.SILENT |
|||
CAN.SILENT_LOOPBACK |
|||
|
|||
The mode of the CAN bus used in :meth:`~CAN.init()`. |
|||
|
|||
.. data:: CAN.STOPPED |
|||
CAN.ERROR_ACTIVE |
|||
CAN.ERROR_WARNING |
|||
CAN.ERROR_PASSIVE |
|||
CAN.BUS_OFF |
|||
|
|||
Possible states of the CAN controller returned from :meth:`~CAN.state()`. |
|||
|
|||
.. data:: CAN.LIST16 |
|||
CAN.MASK16 |
|||
CAN.LIST32 |
|||
CAN.MASK32 |
|||
|
|||
The operation mode of a filter used in :meth:`~CAN.setfilter()`. |
@ -0,0 +1,124 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.DAC: |
|||
|
|||
class DAC -- digital to analog conversion |
|||
========================================= |
|||
|
|||
The DAC is used to output analog values (a specific voltage) on pin X5 or pin X6. |
|||
The voltage will be between 0 and 3.3V. |
|||
|
|||
*This module will undergo changes to the API.* |
|||
|
|||
Example usage:: |
|||
|
|||
from pyb import DAC |
|||
|
|||
dac = DAC(1) # create DAC 1 on pin X5 |
|||
dac.write(128) # write a value to the DAC (makes X5 1.65V) |
|||
|
|||
dac = DAC(1, bits=12) # use 12 bit resolution |
|||
dac.write(4095) # output maximum value, 3.3V |
|||
|
|||
To output a continuous sine-wave:: |
|||
|
|||
import math |
|||
from pyb import DAC |
|||
|
|||
# create a buffer containing a sine-wave |
|||
buf = bytearray(100) |
|||
for i in range(len(buf)): |
|||
buf[i] = 128 + int(127 * math.sin(2 * math.pi * i / len(buf))) |
|||
|
|||
# output the sine-wave at 400Hz |
|||
dac = DAC(1) |
|||
dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR) |
|||
|
|||
To output a continuous sine-wave at 12-bit resolution:: |
|||
|
|||
import math |
|||
from array import array |
|||
from pyb import DAC |
|||
|
|||
# create a buffer containing a sine-wave, using half-word samples |
|||
buf = array('H', 2048 + int(2047 * math.sin(2 * math.pi * i / 128)) for i in range(128)) |
|||
|
|||
# output the sine-wave at 400Hz |
|||
dac = DAC(1, bits=12) |
|||
dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR) |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.DAC(port, bits=8, \*, buffering=None) |
|||
|
|||
Construct a new DAC object. |
|||
|
|||
``port`` can be a pin object, or an integer (1 or 2). |
|||
DAC(1) is on pin X5 and DAC(2) is on pin X6. |
|||
|
|||
``bits`` is an integer specifying the resolution, and can be 8 or 12. |
|||
The maximum value for the write and write_timed methods will be |
|||
2\*\*``bits``-1. |
|||
|
|||
The *buffering* parameter selects the behaviour of the DAC op-amp output |
|||
buffer, whose purpose is to reduce the output impedance. It can be |
|||
``None`` to select the default (buffering enabled for :meth:`DAC.noise`, |
|||
:meth:`DAC.triangle` and :meth:`DAC.write_timed`, and disabled for |
|||
:meth:`DAC.write`), ``False`` to disable buffering completely, or ``True`` |
|||
to enable output buffering. |
|||
|
|||
When buffering is enabled the DAC pin can drive loads down to 5KΩ. |
|||
Otherwise it has an output impedance of 15KΩ maximum: consequently |
|||
to achieve a 1% accuracy without buffering requires the applied load |
|||
to be less than 1.5MΩ. Using the buffer incurs a penalty in accuracy, |
|||
especially near the extremes of range. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: DAC.init(bits=8, \*, buffering=None) |
|||
|
|||
Reinitialise the DAC. *bits* can be 8 or 12. *buffering* can be |
|||
``None``, ``False`` or ``True``; see above constructor for the meaning |
|||
of this parameter. |
|||
|
|||
.. method:: DAC.deinit() |
|||
|
|||
De-initialise the DAC making its pin available for other uses. |
|||
|
|||
.. method:: DAC.noise(freq) |
|||
|
|||
Generate a pseudo-random noise signal. A new random sample is written |
|||
to the DAC output at the given frequency. |
|||
|
|||
.. method:: DAC.triangle(freq) |
|||
|
|||
Generate a triangle wave. The value on the DAC output changes at the given |
|||
frequency and ramps through the full 12-bit range (up and down). Therefore |
|||
the frequency of the repeating triangle wave itself is 8192 times smaller. |
|||
|
|||
.. method:: DAC.write(value) |
|||
|
|||
Direct access to the DAC output. The minimum value is 0. The maximum |
|||
value is 2\*\*``bits``-1, where ``bits`` is set when creating the DAC |
|||
object or by using the ``init`` method. |
|||
|
|||
.. method:: DAC.write_timed(data, freq, \*, mode=DAC.NORMAL) |
|||
|
|||
Initiates a burst of RAM to DAC using a DMA transfer. |
|||
The input data is treated as an array of bytes in 8-bit mode, and |
|||
an array of unsigned half-words (array typecode 'H') in 12-bit mode. |
|||
|
|||
``freq`` can be an integer specifying the frequency to write the DAC |
|||
samples at, using Timer(6). Or it can be an already-initialised |
|||
Timer object which is used to trigger the DAC sample. Valid timers |
|||
are 2, 4, 5, 6, 7 and 8. |
|||
|
|||
``mode`` can be ``DAC.NORMAL`` or ``DAC.CIRCULAR``. |
|||
|
|||
Example using both DACs at the same time:: |
|||
|
|||
dac1 = DAC(1) |
|||
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) |
@ -0,0 +1,114 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.ExtInt: |
|||
|
|||
class ExtInt -- configure I/O pins to interrupt on external events |
|||
================================================================== |
|||
|
|||
There are a total of 22 interrupt lines. 16 of these can come from GPIO pins |
|||
and the remaining 6 are from internal sources. |
|||
|
|||
For lines 0 through 15, a given line can map to the corresponding line from an |
|||
arbitrary port. So line 0 can map to Px0 where x is A, B, C, ... and |
|||
line 1 can map to Px1 where x is A, B, C, ... :: |
|||
|
|||
def callback(line): |
|||
print("line =", line) |
|||
|
|||
Note: ExtInt will automatically configure the gpio line as an input. :: |
|||
|
|||
extint = pyb.ExtInt(pin, pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, callback) |
|||
|
|||
Now every time a falling edge is seen on the X1 pin, the callback will be |
|||
called. Caution: mechanical pushbuttons have "bounce" and pushing or |
|||
releasing a switch will often generate multiple edges. |
|||
See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed |
|||
explanation, along with various techniques for debouncing. |
|||
|
|||
Trying to register 2 callbacks onto the same pin will throw an exception. |
|||
|
|||
If pin is passed as an integer, then it is assumed to map to one of the |
|||
internal interrupt sources, and must be in the range 16 through 22. |
|||
|
|||
All other pin objects go through the pin mapper to come up with one of the |
|||
gpio pins. :: |
|||
|
|||
extint = pyb.ExtInt(pin, mode, pull, callback) |
|||
|
|||
Valid modes are pyb.ExtInt.IRQ_RISING, pyb.ExtInt.IRQ_FALLING, |
|||
pyb.ExtInt.IRQ_RISING_FALLING, pyb.ExtInt.EVT_RISING, |
|||
pyb.ExtInt.EVT_FALLING, and pyb.ExtInt.EVT_RISING_FALLING. |
|||
|
|||
Only the IRQ_xxx modes have been tested. The EVT_xxx modes have |
|||
something to do with sleep mode and the WFE instruction. |
|||
|
|||
Valid pull values are pyb.Pin.PULL_UP, pyb.Pin.PULL_DOWN, pyb.Pin.PULL_NONE. |
|||
|
|||
There is also a C API, so that drivers which require EXTI interrupt lines |
|||
can also use this code. See extint.h for the available functions and |
|||
usrsw.h for an example of using this. |
|||
|
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.ExtInt(pin, mode, pull, callback) |
|||
|
|||
Create an ExtInt object: |
|||
|
|||
- ``pin`` is the pin on which to enable the interrupt (can be a pin object or any valid pin name). |
|||
- ``mode`` can be one of: |
|||
- ``ExtInt.IRQ_RISING`` - trigger on a rising edge; |
|||
- ``ExtInt.IRQ_FALLING`` - trigger on a falling edge; |
|||
- ``ExtInt.IRQ_RISING_FALLING`` - trigger on a rising or falling edge. |
|||
- ``pull`` can be one of: |
|||
- ``pyb.Pin.PULL_NONE`` - no pull up or down resistors; |
|||
- ``pyb.Pin.PULL_UP`` - enable the pull-up resistor; |
|||
- ``pyb.Pin.PULL_DOWN`` - enable the pull-down resistor. |
|||
- ``callback`` is the function to call when the interrupt triggers. The |
|||
callback function must accept exactly 1 argument, which is the line that |
|||
triggered the interrupt. |
|||
|
|||
|
|||
Class methods |
|||
------------- |
|||
|
|||
.. classmethod:: ExtInt.regs() |
|||
|
|||
Dump the values of the EXTI registers. |
|||
|
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: ExtInt.disable() |
|||
|
|||
Disable the interrupt associated with the ExtInt object. |
|||
This could be useful for debouncing. |
|||
|
|||
.. method:: ExtInt.enable() |
|||
|
|||
Enable a disabled interrupt. |
|||
|
|||
.. method:: ExtInt.line() |
|||
|
|||
Return the line number that the pin is mapped to. |
|||
|
|||
.. method:: ExtInt.swint() |
|||
|
|||
Trigger the callback from software. |
|||
|
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: ExtInt.IRQ_FALLING |
|||
|
|||
interrupt on a falling edge |
|||
|
|||
.. data:: ExtInt.IRQ_RISING |
|||
|
|||
interrupt on a rising edge |
|||
|
|||
.. data:: ExtInt.IRQ_RISING_FALLING |
|||
|
|||
interrupt on a rising or falling edge |
@ -0,0 +1,52 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.Flash: |
|||
|
|||
class Flash -- access to built-in flash storage |
|||
=============================================== |
|||
|
|||
The Flash class allows direct access to the primary flash device on the pyboard. |
|||
|
|||
In most cases, to store persistent data on the device, you'll want to use a |
|||
higher-level abstraction, for example the filesystem via Python's standard file |
|||
API, but this interface is useful to :ref:`customise the filesystem |
|||
configuration <filesystem>` or implement a low-level storage system for your |
|||
application. |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.Flash() |
|||
|
|||
Create and return a block device that represents the flash device presented |
|||
to the USB mass storage interface. |
|||
|
|||
It includes a virtual partition table at the start, and the actual flash |
|||
starts at block ``0x100``. |
|||
|
|||
This constructor is deprecated and will be removed in a future version of MicroPython. |
|||
|
|||
.. class:: pyb.Flash(\*, start=-1, len=-1) |
|||
|
|||
Create and return a block device that accesses the flash at the specified offset. The length defaults to the remaining size of the device. |
|||
|
|||
The *start* and *len* offsets are in bytes, and must be a multiple of the block size (typically 512 for internal flash). |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: Flash.readblocks(block_num, buf) |
|||
.. method:: Flash.readblocks(block_num, buf, offset) |
|||
.. method:: Flash.writeblocks(block_num, buf) |
|||
.. method:: Flash.writeblocks(block_num, buf, offset) |
|||
.. method:: Flash.ioctl(cmd, arg) |
|||
|
|||
These methods implement the simple and :ref:`extended |
|||
<block-device-interface>` block protocol defined by |
|||
:class:`uos.AbstractBlockDev`. |
|||
|
|||
Hardware Note |
|||
------------- |
|||
|
|||
On boards with external spiflash (e.g. Pyboard D), the MicroPython firmware will |
|||
be configured to use that as the primary flash storage. On all other boards, the |
|||
internal flash inside the :term:`MCU` will be used. |
@ -0,0 +1,165 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.I2C: |
|||
|
|||
class I2C -- a two-wire serial protocol |
|||
======================================= |
|||
|
|||
I2C is a two-wire protocol for communicating between devices. At the physical |
|||
level it consists of 2 wires: SCL and SDA, the clock and data lines respectively. |
|||
|
|||
I2C objects are created attached to a specific bus. They can be initialised |
|||
when created, or initialised later on. |
|||
|
|||
Example:: |
|||
|
|||
from pyb import I2C |
|||
|
|||
i2c = I2C(1) # create on bus 1 |
|||
i2c = I2C(1, I2C.MASTER) # create and init as a master |
|||
i2c.init(I2C.MASTER, baudrate=20000) # init as a master |
|||
i2c.init(I2C.SLAVE, addr=0x42) # init as a slave with given address |
|||
i2c.deinit() # turn off the peripheral |
|||
|
|||
Printing the i2c object gives you information about its configuration. |
|||
|
|||
The basic methods are send and recv:: |
|||
|
|||
i2c.send('abc') # send 3 bytes |
|||
i2c.send(0x42) # send a single byte, given by the number |
|||
data = i2c.recv(3) # receive 3 bytes |
|||
|
|||
To receive inplace, first create a bytearray:: |
|||
|
|||
data = bytearray(3) # create a buffer |
|||
i2c.recv(data) # receive 3 bytes, writing them into data |
|||
|
|||
You can specify a timeout (in ms):: |
|||
|
|||
i2c.send(b'123', timeout=2000) # timeout after 2 seconds |
|||
|
|||
A master must specify the recipient's address:: |
|||
|
|||
i2c.init(I2C.MASTER) |
|||
i2c.send('123', 0x42) # send 3 bytes to slave with address 0x42 |
|||
i2c.send(b'456', addr=0x42) # keyword for address |
|||
|
|||
Master also has other methods:: |
|||
|
|||
i2c.is_ready(0x42) # check if slave 0x42 is ready |
|||
i2c.scan() # scan for slaves on the bus, returning |
|||
# a list of valid addresses |
|||
i2c.mem_read(3, 0x42, 2) # read 3 bytes from memory of slave 0x42, |
|||
# starting at address 2 in the slave |
|||
i2c.mem_write('abc', 0x42, 2, timeout=1000) # write 'abc' (3 bytes) to memory of slave 0x42 |
|||
# starting at address 2 in the slave, timeout after 1 second |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.I2C(bus, ...) |
|||
|
|||
Construct an I2C object on the given bus. ``bus`` can be 1 or 2, 'X' or |
|||
'Y'. With no additional parameters, the I2C object is created but not |
|||
initialised (it has the settings from the last initialisation of |
|||
the bus, if any). If extra arguments are given, the bus is initialised. |
|||
See ``init`` for parameters of initialisation. |
|||
|
|||
The physical pins of the I2C busses on Pyboards V1.0 and V1.1 are: |
|||
|
|||
- ``I2C(1)`` is on the X position: ``(SCL, SDA) = (X9, X10) = (PB6, PB7)`` |
|||
- ``I2C(2)`` is on the Y position: ``(SCL, SDA) = (Y9, Y10) = (PB10, PB11)`` |
|||
|
|||
On the Pyboard Lite: |
|||
|
|||
- ``I2C(1)`` is on the X position: ``(SCL, SDA) = (X9, X10) = (PB6, PB7)`` |
|||
- ``I2C(3)`` is on the Y position: ``(SCL, SDA) = (Y9, Y10) = (PA8, PB8)`` |
|||
|
|||
Calling the constructor with 'X' or 'Y' enables portability between Pyboard |
|||
types. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: I2C.deinit() |
|||
|
|||
Turn off the I2C bus. |
|||
|
|||
.. method:: I2C.init(mode, \*, addr=0x12, baudrate=400000, gencall=False, dma=False) |
|||
|
|||
Initialise the I2C bus with the given parameters: |
|||
|
|||
- ``mode`` must be either ``I2C.MASTER`` or ``I2C.SLAVE`` |
|||
- ``addr`` is the 7-bit address (only sensible for a slave) |
|||
- ``baudrate`` is the SCL clock rate (only sensible for a master) |
|||
- ``gencall`` is whether to support general call mode |
|||
- ``dma`` is whether to allow the use of DMA for the I2C transfers (note |
|||
that DMA transfers have more precise timing but currently do not handle bus |
|||
errors properly) |
|||
|
|||
.. method:: I2C.is_ready(addr) |
|||
|
|||
Check if an I2C device responds to the given address. Only valid when in master mode. |
|||
|
|||
.. method:: I2C.mem_read(data, addr, memaddr, \*, timeout=5000, addr_size=8) |
|||
|
|||
Read from the memory of an I2C device: |
|||
|
|||
- ``data`` can be an integer (number of bytes to read) or a buffer to read into |
|||
- ``addr`` is the I2C device address |
|||
- ``memaddr`` is the memory location within the I2C device |
|||
- ``timeout`` is the timeout in milliseconds to wait for the read |
|||
- ``addr_size`` selects width of memaddr: 8 or 16 bits |
|||
|
|||
Returns the read data. |
|||
This is only valid in master mode. |
|||
|
|||
.. method:: I2C.mem_write(data, addr, memaddr, \*, timeout=5000, addr_size=8) |
|||
|
|||
Write to the memory of an I2C device: |
|||
|
|||
- ``data`` can be an integer or a buffer to write from |
|||
- ``addr`` is the I2C device address |
|||
- ``memaddr`` is the memory location within the I2C device |
|||
- ``timeout`` is the timeout in milliseconds to wait for the write |
|||
- ``addr_size`` selects width of memaddr: 8 or 16 bits |
|||
|
|||
Returns ``None``. |
|||
This is only valid in master mode. |
|||
|
|||
.. method:: I2C.recv(recv, addr=0x00, \*, timeout=5000) |
|||
|
|||
Receive data on the bus: |
|||
|
|||
- ``recv`` can be an integer, which is the number of bytes to receive, |
|||
or a mutable buffer, which will be filled with received bytes |
|||
- ``addr`` is the address to receive from (only required in master mode) |
|||
- ``timeout`` is the timeout in milliseconds to wait for the receive |
|||
|
|||
Return value: if ``recv`` is an integer then a new buffer of the bytes received, |
|||
otherwise the same buffer that was passed in to ``recv``. |
|||
|
|||
.. method:: I2C.send(send, addr=0x00, \*, timeout=5000) |
|||
|
|||
Send data on the bus: |
|||
|
|||
- ``send`` is the data to send (an integer to send, or a buffer object) |
|||
- ``addr`` is the address to send to (only required in master mode) |
|||
- ``timeout`` is the timeout in milliseconds to wait for the send |
|||
|
|||
Return value: ``None``. |
|||
|
|||
.. method:: I2C.scan() |
|||
|
|||
Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond. |
|||
Only valid when in master mode. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: I2C.MASTER |
|||
|
|||
for initialising the bus to master mode |
|||
|
|||
.. data:: I2C.SLAVE |
|||
|
|||
for initialising the bus to slave mode |
@ -0,0 +1,97 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.LCD: |
|||
|
|||
class LCD -- LCD control for the LCD touch-sensor pyskin |
|||
======================================================== |
|||
|
|||
The LCD class is used to control the LCD on the LCD touch-sensor pyskin, |
|||
LCD32MKv1.0. The LCD is a 128x32 pixel monochrome screen, part NHD-C12832A1Z. |
|||
|
|||
The pyskin must be connected in either the X or Y positions, and then |
|||
an LCD object is made using:: |
|||
|
|||
lcd = pyb.LCD('X') # if pyskin is in the X position |
|||
lcd = pyb.LCD('Y') # if pyskin is in the Y position |
|||
|
|||
Then you can use:: |
|||
|
|||
lcd.light(True) # turn the backlight on |
|||
lcd.write('Hello world!\n') # print text to the screen |
|||
|
|||
This driver implements a double buffer for setting/getting pixels. |
|||
For example, to make a bouncing dot, try:: |
|||
|
|||
x = y = 0 |
|||
dx = dy = 1 |
|||
while True: |
|||
# update the dot's position |
|||
x += dx |
|||
y += dy |
|||
|
|||
# make the dot bounce of the edges of the screen |
|||
if x <= 0 or x >= 127: dx = -dx |
|||
if y <= 0 or y >= 31: dy = -dy |
|||
|
|||
lcd.fill(0) # clear the buffer |
|||
lcd.pixel(x, y, 1) # draw the dot |
|||
lcd.show() # show the buffer |
|||
pyb.delay(50) # pause for 50ms |
|||
|
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.LCD(skin_position) |
|||
|
|||
Construct an LCD object in the given skin position. ``skin_position`` can be 'X' or 'Y', and |
|||
should match the position where the LCD pyskin is plugged in. |
|||
|
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: LCD.command(instr_data, buf) |
|||
|
|||
Send an arbitrary command to the LCD. Pass 0 for ``instr_data`` to send an |
|||
instruction, otherwise pass 1 to send data. ``buf`` is a buffer with the |
|||
instructions/data to send. |
|||
|
|||
.. method:: LCD.contrast(value) |
|||
|
|||
Set the contrast of the LCD. Valid values are between 0 and 47. |
|||
|
|||
.. method:: LCD.fill(colour) |
|||
|
|||
Fill the screen with the given colour (0 or 1 for white or black). |
|||
|
|||
This method writes to the hidden buffer. Use ``show()`` to show the buffer. |
|||
|
|||
.. method:: LCD.get(x, y) |
|||
|
|||
Get the pixel at the position ``(x, y)``. Returns 0 or 1. |
|||
|
|||
This method reads from the visible buffer. |
|||
|
|||
.. method:: LCD.light(value) |
|||
|
|||
Turn the backlight on/off. True or 1 turns it on, False or 0 turns it off. |
|||
|
|||
.. method:: LCD.pixel(x, y, colour) |
|||
|
|||
Set the pixel at ``(x, y)`` to the given colour (0 or 1). |
|||
|
|||
This method writes to the hidden buffer. Use ``show()`` to show the buffer. |
|||
|
|||
.. method:: LCD.show() |
|||
|
|||
Show the hidden buffer on the screen. |
|||
|
|||
.. method:: LCD.text(str, x, y, colour) |
|||
|
|||
Draw the given text to the position ``(x, y)`` using the given colour (0 or 1). |
|||
|
|||
This method writes to the hidden buffer. Use ``show()`` to show the buffer. |
|||
|
|||
.. method:: LCD.write(str) |
|||
|
|||
Write the string ``str`` to the screen. It will appear immediately. |
@ -0,0 +1,46 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.LED: |
|||
|
|||
class LED -- LED object |
|||
======================= |
|||
|
|||
The LED object controls an individual LED (Light Emitting Diode). |
|||
|
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.LED(id) |
|||
|
|||
Create an LED object associated with the given LED: |
|||
|
|||
- ``id`` is the LED number, 1-4. |
|||
|
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: LED.intensity([value]) |
|||
|
|||
Get or set the LED intensity. Intensity ranges between 0 (off) and 255 (full on). |
|||
If no argument is given, return the LED intensity. |
|||
If an argument is given, set the LED intensity and return ``None``. |
|||
|
|||
*Note:* Only LED(3) and LED(4) can have a smoothly varying intensity, and |
|||
they use timer PWM to implement it. LED(3) uses Timer(2) and LED(4) uses |
|||
Timer(3). These timers are only configured for PWM if the intensity of the |
|||
relevant LED is set to a value between 1 and 254. Otherwise the timers are |
|||
free for general purpose use. |
|||
|
|||
.. method:: LED.off() |
|||
|
|||
Turn the LED off. |
|||
|
|||
.. method:: LED.on() |
|||
|
|||
Turn the LED on, to maximum intensity. |
|||
|
|||
.. method:: LED.toggle() |
|||
|
|||
Toggle the LED between on (maximum intensity) and off. If the LED is at |
|||
non-zero intensity then it is considered "on" and toggle will turn it off. |
@ -0,0 +1,268 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.Pin: |
|||
|
|||
class Pin -- control I/O pins |
|||
============================= |
|||
|
|||
A pin is the basic object to control I/O pins. It has methods to set |
|||
the mode of the pin (input, output, etc) and methods to get and set the |
|||
digital logic level. For analog control of a pin, see the ADC class. |
|||
|
|||
Usage Model: |
|||
|
|||
All Board Pins are predefined as pyb.Pin.board.Name:: |
|||
|
|||
x1_pin = pyb.Pin.board.X1 |
|||
|
|||
g = pyb.Pin(pyb.Pin.board.X1, pyb.Pin.IN) |
|||
|
|||
CPU pins which correspond to the board pins are available |
|||
as ``pyb.Pin.cpu.Name``. For the CPU pins, the names are the port letter |
|||
followed by the pin number. On the PYBv1.0, ``pyb.Pin.board.X1`` and |
|||
``pyb.Pin.cpu.A0`` are the same pin. |
|||
|
|||
You can also use strings:: |
|||
|
|||
g = pyb.Pin('X1', pyb.Pin.OUT_PP) |
|||
|
|||
Users can add their own names:: |
|||
|
|||
MyMapperDict = { 'LeftMotorDir' : pyb.Pin.cpu.C12 } |
|||
pyb.Pin.dict(MyMapperDict) |
|||
g = pyb.Pin("LeftMotorDir", pyb.Pin.OUT_OD) |
|||
|
|||
and can query mappings:: |
|||
|
|||
pin = pyb.Pin("LeftMotorDir") |
|||
|
|||
Users can also add their own mapping function:: |
|||
|
|||
def MyMapper(pin_name): |
|||
if pin_name == "LeftMotorDir": |
|||
return pyb.Pin.cpu.A0 |
|||
|
|||
pyb.Pin.mapper(MyMapper) |
|||
|
|||
So, if you were to call: ``pyb.Pin("LeftMotorDir", pyb.Pin.OUT_PP)`` |
|||
then ``"LeftMotorDir"`` is passed directly to the mapper function. |
|||
|
|||
To summarise, the following order determines how things get mapped into |
|||
an ordinal pin number: |
|||
|
|||
1. Directly specify a pin object |
|||
2. User supplied mapping function |
|||
3. User supplied mapping (object must be usable as a dictionary key) |
|||
4. Supply a string which matches a board pin |
|||
5. Supply a string which matches a CPU port/pin |
|||
|
|||
You can set ``pyb.Pin.debug(True)`` to get some debug information about |
|||
how a particular object gets mapped to a pin. |
|||
|
|||
When a pin has the ``Pin.PULL_UP`` or ``Pin.PULL_DOWN`` pull-mode enabled, |
|||
that pin has an effective 40k Ohm resistor pulling it to 3V3 or GND |
|||
respectively (except pin Y5 which has 11k Ohm resistors). |
|||
|
|||
Now every time a falling edge is seen on the gpio pin, the callback will be |
|||
executed. Caution: mechanical push buttons have "bounce" and pushing or |
|||
releasing a switch will often generate multiple edges. |
|||
See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed |
|||
explanation, along with various techniques for debouncing. |
|||
|
|||
All pin objects go through the pin mapper to come up with one of the |
|||
gpio pins. |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.Pin(id, ...) |
|||
|
|||
Create a new Pin object associated with the id. If additional arguments are given, |
|||
they are used to initialise the pin. See :meth:`pin.init`. |
|||
|
|||
Class methods |
|||
------------- |
|||
|
|||
.. classmethod:: Pin.debug([state]) |
|||
|
|||
Get or set the debugging state (``True`` or ``False`` for on or off). |
|||
|
|||
.. classmethod:: Pin.dict([dict]) |
|||
|
|||
Get or set the pin mapper dictionary. |
|||
|
|||
.. classmethod:: Pin.mapper([fun]) |
|||
|
|||
Get or set the pin mapper function. |
|||
|
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: Pin.init(mode, pull=Pin.PULL_NONE, af=-1) |
|||
|
|||
Initialise the pin: |
|||
|
|||
- ``mode`` can be one of: |
|||
|
|||
- ``Pin.IN`` - configure the pin for input; |
|||
- ``Pin.OUT_PP`` - configure the pin for output, with push-pull control; |
|||
- ``Pin.OUT_OD`` - configure the pin for output, with open-drain control; |
|||
- ``Pin.AF_PP`` - configure the pin for alternate function, pull-pull; |
|||
- ``Pin.AF_OD`` - configure the pin for alternate function, open-drain; |
|||
- ``Pin.ANALOG`` - configure the pin for analog. |
|||
|
|||
- ``pull`` can be one of: |
|||
|
|||
- ``Pin.PULL_NONE`` - no pull up or down resistors; |
|||
- ``Pin.PULL_UP`` - enable the pull-up resistor; |
|||
- ``Pin.PULL_DOWN`` - enable the pull-down resistor. |
|||
|
|||
- when mode is ``Pin.AF_PP`` or ``Pin.AF_OD``, then af can be the index or name |
|||
of one of the alternate functions associated with a pin. |
|||
|
|||
Returns: ``None``. |
|||
|
|||
.. method:: Pin.value([value]) |
|||
|
|||
Get or set the digital logic level of the pin: |
|||
|
|||
- With no argument, return 0 or 1 depending on the logic level of the pin. |
|||
- With ``value`` given, set the logic level of the pin. ``value`` can be |
|||
anything that converts to a boolean. If it converts to ``True``, the pin |
|||
is set high, otherwise it is set low. |
|||
|
|||
.. method:: Pin.__str__() |
|||
|
|||
Return a string describing the pin object. |
|||
|
|||
.. method:: Pin.af() |
|||
|
|||
Returns the currently configured alternate-function of the pin. The |
|||
integer returned will match one of the allowed constants for the af |
|||
argument to the init function. |
|||
|
|||
.. method:: Pin.af_list() |
|||
|
|||
Returns an array of alternate functions available for this pin. |
|||
|
|||
.. method:: Pin.gpio() |
|||
|
|||
Returns the base address of the GPIO block associated with this pin. |
|||
|
|||
.. method:: Pin.mode() |
|||
|
|||
Returns the currently configured mode of the pin. The integer returned |
|||
will match one of the allowed constants for the mode argument to the init |
|||
function. |
|||
|
|||
.. method:: Pin.name() |
|||
|
|||
Get the pin name. |
|||
|
|||
.. method:: Pin.names() |
|||
|
|||
Returns the cpu and board names for this pin. |
|||
|
|||
.. method:: Pin.pin() |
|||
|
|||
Get the pin number. |
|||
|
|||
.. method:: Pin.port() |
|||
|
|||
Get the pin port. |
|||
|
|||
.. method:: Pin.pull() |
|||
|
|||
Returns the currently configured pull of the pin. The integer returned |
|||
will match one of the allowed constants for the pull argument to the init |
|||
function. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: Pin.AF_OD |
|||
|
|||
initialise the pin to alternate-function mode with an open-drain drive |
|||
|
|||
.. data:: Pin.AF_PP |
|||
|
|||
initialise the pin to alternate-function mode with a push-pull drive |
|||
|
|||
.. data:: Pin.ANALOG |
|||
|
|||
initialise the pin to analog mode |
|||
|
|||
.. data:: Pin.IN |
|||
|
|||
initialise the pin to input mode |
|||
|
|||
.. data:: Pin.OUT_OD |
|||
|
|||
initialise the pin to output mode with an open-drain drive |
|||
|
|||
.. data:: Pin.OUT_PP |
|||
|
|||
initialise the pin to output mode with a push-pull drive |
|||
|
|||
.. data:: Pin.PULL_DOWN |
|||
|
|||
enable the pull-down resistor on the pin |
|||
|
|||
.. data:: Pin.PULL_NONE |
|||
|
|||
don't enable any pull up or down resistors on the pin |
|||
|
|||
.. data:: Pin.PULL_UP |
|||
|
|||
enable the pull-up resistor on the pin |
|||
|
|||
class PinAF -- Pin Alternate Functions |
|||
====================================== |
|||
|
|||
A Pin represents a physical pin on the microprocessor. Each pin |
|||
can have a variety of functions (GPIO, I2C SDA, etc). Each PinAF |
|||
object represents a particular function for a pin. |
|||
|
|||
Usage Model:: |
|||
|
|||
x3 = pyb.Pin.board.X3 |
|||
x3_af = x3.af_list() |
|||
|
|||
x3_af will now contain an array of PinAF objects which are available on |
|||
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. |
|||
|
|||
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) |
|||
|
|||
or:: |
|||
|
|||
pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=1) |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: pinaf.__str__() |
|||
|
|||
Return a string describing the alternate function. |
|||
|
|||
.. method:: pinaf.index() |
|||
|
|||
Return the alternate function index. |
|||
|
|||
.. method:: pinaf.name() |
|||
|
|||
Return the name of the alternate function. |
|||
|
|||
.. method:: pinaf.reg() |
|||
|
|||
Return the base register associated with the peripheral assigned to this |
|||
alternate function. For example, if the alternate function were TIM2_CH3 |
|||
this would return stm.TIM2 |
@ -0,0 +1,78 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.RTC: |
|||
|
|||
class RTC -- real time clock |
|||
============================ |
|||
|
|||
The RTC is and independent clock that keeps track of the date |
|||
and time. |
|||
|
|||
Example usage:: |
|||
|
|||
rtc = pyb.RTC() |
|||
rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0)) |
|||
print(rtc.datetime()) |
|||
|
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.RTC() |
|||
|
|||
Create an RTC object. |
|||
|
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: RTC.datetime([datetimetuple]) |
|||
|
|||
Get or set the date and time of the RTC. |
|||
|
|||
With no arguments, this method returns an 8-tuple with the current |
|||
date and time. With 1 argument (being an 8-tuple) it sets the date |
|||
and time (and ``subseconds`` is reset to 255). |
|||
|
|||
The 8-tuple has the following format: |
|||
|
|||
(year, month, day, weekday, hours, minutes, seconds, subseconds) |
|||
|
|||
``weekday`` is 1-7 for Monday through Sunday. |
|||
|
|||
``subseconds`` counts down from 255 to 0 |
|||
|
|||
.. method:: RTC.wakeup(timeout, callback=None) |
|||
|
|||
Set the RTC wakeup timer to trigger repeatedly at every ``timeout`` |
|||
milliseconds. This trigger can wake the pyboard from both the sleep |
|||
states: :meth:`pyb.stop` and :meth:`pyb.standby`. |
|||
|
|||
If ``timeout`` is ``None`` then the wakeup timer is disabled. |
|||
|
|||
If ``callback`` is given then it is executed at every trigger of the |
|||
wakeup timer. ``callback`` must take exactly one argument. |
|||
|
|||
.. method:: RTC.info() |
|||
|
|||
Get information about the startup time and reset source. |
|||
|
|||
- The lower 0xffff are the number of milliseconds the RTC took to |
|||
start up. |
|||
- Bit 0x10000 is set if a power-on reset occurred. |
|||
- Bit 0x20000 is set if an external reset occurred |
|||
|
|||
.. method:: RTC.calibration(cal) |
|||
|
|||
Get or set RTC calibration. |
|||
|
|||
With no arguments, ``calibration()`` returns the current calibration |
|||
value, which is an integer in the range [-511 : 512]. With one |
|||
argument it sets the RTC calibration. |
|||
|
|||
The RTC Smooth Calibration mechanism adjusts the RTC clock rate by |
|||
adding or subtracting the given number of ticks from the 32768 Hz |
|||
clock over a 32 second period (corresponding to 2^20 clock ticks.) |
|||
Each tick added will speed up the clock by 1 part in 2^20, or 0.954 |
|||
ppm; likewise the RTC clock it slowed by negative values. The |
|||
usable calibration range is: |
|||
(-511 * 0.954) ~= -487.5 ppm up to (512 * 0.954) ~= 488.5 ppm |
@ -0,0 +1,122 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.SPI: |
|||
|
|||
class SPI -- a master-driven serial protocol |
|||
============================================ |
|||
|
|||
SPI is a serial protocol that is driven by a master. At the physical level |
|||
there are 3 lines: SCK, MOSI, MISO. |
|||
|
|||
See usage model of I2C; SPI is very similar. Main difference is |
|||
parameters to init the SPI bus:: |
|||
|
|||
from pyb import SPI |
|||
spi = SPI(1, SPI.MASTER, baudrate=600000, polarity=1, phase=0, crc=0x7) |
|||
|
|||
Only required parameter is mode, SPI.MASTER or SPI.SLAVE. Polarity can be |
|||
0 or 1, and is the level the idle clock line sits at. Phase can be 0 or 1 |
|||
to sample data on the first or second clock edge respectively. Crc can be |
|||
None for no CRC, or a polynomial specifier. |
|||
|
|||
Additional methods for SPI:: |
|||
|
|||
data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes |
|||
buf = bytearray(4) |
|||
spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf |
|||
spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.SPI(bus, ...) |
|||
|
|||
Construct an SPI object on the given bus. ``bus`` can be 1 or 2, or |
|||
'X' or 'Y'. With no additional parameters, the SPI object is created but |
|||
not initialised (it has the settings from the last initialisation of |
|||
the bus, if any). If extra arguments are given, the bus is initialised. |
|||
See ``init`` for parameters of initialisation. |
|||
|
|||
The physical pins of the SPI busses are: |
|||
|
|||
- ``SPI(1)`` is on the X position: ``(NSS, SCK, MISO, MOSI) = (X5, X6, X7, X8) = (PA4, PA5, PA6, PA7)`` |
|||
- ``SPI(2)`` is on the Y position: ``(NSS, SCK, MISO, MOSI) = (Y5, Y6, Y7, Y8) = (PB12, PB13, PB14, PB15)`` |
|||
|
|||
At the moment, the NSS pin is not used by the SPI driver and is free |
|||
for other use. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: SPI.deinit() |
|||
|
|||
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) |
|||
|
|||
Initialise the SPI bus with the given parameters: |
|||
|
|||
- ``mode`` must be either ``SPI.MASTER`` or ``SPI.SLAVE``. |
|||
- ``baudrate`` is the SCK clock rate (only sensible for a master). |
|||
- ``prescaler`` is the prescaler to use to derive SCK from the APB bus frequency; |
|||
use of ``prescaler`` overrides ``baudrate``. |
|||
- ``polarity`` can be 0 or 1, and is the level the idle clock line sits at. |
|||
- ``phase`` can be 0 or 1 to sample data on the first or second clock edge |
|||
respectively. |
|||
- ``bits`` can be 8 or 16, and is the number of bits in each transferred word. |
|||
- ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``. |
|||
- ``crc`` can be None for no CRC, or a polynomial specifier. |
|||
|
|||
Note that the SPI clock frequency will not always be the requested baudrate. |
|||
The hardware only supports baudrates that are the APB bus frequency |
|||
(see :meth:`pyb.freq`) divided by a prescaler, which can be 2, 4, 8, 16, 32, |
|||
64, 128 or 256. SPI(1) is on AHB2, and SPI(2) is on AHB1. For precise |
|||
control over the SPI clock frequency, specify ``prescaler`` instead of |
|||
``baudrate``. |
|||
|
|||
Printing the SPI object will show you the computed baudrate and the chosen |
|||
prescaler. |
|||
|
|||
.. method:: SPI.recv(recv, \*, timeout=5000) |
|||
|
|||
Receive data on the bus: |
|||
|
|||
- ``recv`` can be an integer, which is the number of bytes to receive, |
|||
or a mutable buffer, which will be filled with received bytes. |
|||
- ``timeout`` is the timeout in milliseconds to wait for the receive. |
|||
|
|||
Return value: if ``recv`` is an integer then a new buffer of the bytes received, |
|||
otherwise the same buffer that was passed in to ``recv``. |
|||
|
|||
.. method:: SPI.send(send, \*, timeout=5000) |
|||
|
|||
Send data on the bus: |
|||
|
|||
- ``send`` is the data to send (an integer to send, or a buffer object). |
|||
- ``timeout`` is the timeout in milliseconds to wait for the send. |
|||
|
|||
Return value: ``None``. |
|||
|
|||
.. method:: SPI.send_recv(send, recv=None, \*, timeout=5000) |
|||
|
|||
Send and receive data on the bus at the same time: |
|||
|
|||
- ``send`` is the data to send (an integer to send, or a buffer object). |
|||
- ``recv`` is a mutable buffer which will be filled with received bytes. |
|||
It can be the same as ``send``, or omitted. If omitted, a new buffer will |
|||
be created. |
|||
- ``timeout`` is the timeout in milliseconds to wait for the receive. |
|||
|
|||
Return value: the buffer with the received bytes. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: SPI.MASTER |
|||
.. data:: SPI.SLAVE |
|||
|
|||
for initialising the SPI bus to master or slave mode |
|||
|
|||
.. data:: SPI.LSB |
|||
.. data:: SPI.MSB |
|||
|
|||
set the first bit to be the least or most significant bit |
@ -0,0 +1,80 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.Servo: |
|||
|
|||
class Servo -- 3-wire hobby servo driver |
|||
======================================== |
|||
|
|||
Servo objects control standard hobby servo motors with 3-wires (ground, power, |
|||
signal). There are 4 positions on the pyboard where these motors can be plugged |
|||
in: pins X1 through X4 are the signal pins, and next to them are 4 sets of power |
|||
and ground pins. |
|||
|
|||
Example usage:: |
|||
|
|||
import pyb |
|||
|
|||
s1 = pyb.Servo(1) # create a servo object on position X1 |
|||
s2 = pyb.Servo(2) # create a servo object on position X2 |
|||
|
|||
s1.angle(45) # move servo 1 to 45 degrees |
|||
s2.angle(0) # move servo 2 to 0 degrees |
|||
|
|||
# move servo1 and servo2 synchronously, taking 1500ms |
|||
s1.angle(-60, 1500) |
|||
s2.angle(30, 1500) |
|||
|
|||
.. note:: The Servo objects use Timer(5) to produce the PWM output. You can |
|||
use Timer(5) for Servo control, or your own purposes, but not both at the |
|||
same time. |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.Servo(id) |
|||
|
|||
Create a servo object. ``id`` is 1-4, and corresponds to pins X1 through X4. |
|||
|
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: Servo.angle([angle, time=0]) |
|||
|
|||
If no arguments are given, this function returns the current angle. |
|||
|
|||
If arguments are given, this function sets the angle of the servo: |
|||
|
|||
- ``angle`` is the angle to move to in degrees. |
|||
- ``time`` is the number of milliseconds to take to get to the specified |
|||
angle. If omitted, then the servo moves as quickly as possible to its |
|||
new position. |
|||
|
|||
.. method:: Servo.speed([speed, time=0]) |
|||
|
|||
If no arguments are given, this function returns the current speed. |
|||
|
|||
If arguments are given, this function sets the speed of the servo: |
|||
|
|||
- ``speed`` is the speed to change to, between -100 and 100. |
|||
- ``time`` is the number of milliseconds to take to get to the specified |
|||
speed. If omitted, then the servo accelerates as quickly as possible. |
|||
|
|||
.. method:: Servo.pulse_width([value]) |
|||
|
|||
If no arguments are given, this function returns the current raw pulse-width |
|||
value. |
|||
|
|||
If an argument is given, this function sets the raw pulse-width value. |
|||
|
|||
.. method:: Servo.calibration([pulse_min, pulse_max, pulse_centre, [pulse_angle_90, pulse_speed_100]]) |
|||
|
|||
If no arguments are given, this function returns the current calibration |
|||
data, as a 5-tuple. |
|||
|
|||
If arguments are given, this function sets the timing calibration: |
|||
|
|||
- ``pulse_min`` is the minimum allowed pulse width. |
|||
- ``pulse_max`` is the maximum allowed pulse width. |
|||
- ``pulse_centre`` is the pulse width corresponding to the centre/zero position. |
|||
- ``pulse_angle_90`` is the pulse width corresponding to 90 degrees. |
|||
- ``pulse_speed_100`` is the pulse width corresponding to a speed of 100. |
@ -0,0 +1,46 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.Switch: |
|||
|
|||
class Switch -- switch object |
|||
============================= |
|||
|
|||
A Switch object is used to control a push-button switch. |
|||
|
|||
Usage:: |
|||
|
|||
sw = pyb.Switch() # create a switch object |
|||
sw.value() # get state (True if pressed, False otherwise) |
|||
sw() # shorthand notation to get the switch state |
|||
sw.callback(f) # register a callback to be called when the |
|||
# switch is pressed down |
|||
sw.callback(None) # remove the callback |
|||
|
|||
Example:: |
|||
|
|||
pyb.Switch().callback(lambda: pyb.LED(1).toggle()) |
|||
|
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.Switch() |
|||
|
|||
Create and return a switch object. |
|||
|
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: Switch.__call__() |
|||
|
|||
Call switch object directly to get its state: ``True`` if pressed down, |
|||
``False`` otherwise. |
|||
|
|||
.. method:: Switch.value() |
|||
|
|||
Get the switch state. Returns ``True`` if pressed down, otherwise ``False``. |
|||
|
|||
.. method:: Switch.callback(fun) |
|||
|
|||
Register the given function to be called when the switch is pressed down. |
|||
If ``fun`` is ``None``, then it disables the callback. |
@ -0,0 +1,264 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.Timer: |
|||
|
|||
class Timer -- control internal timers |
|||
====================================== |
|||
|
|||
Timers can be used for a great variety of tasks. At the moment, only |
|||
the simplest case is implemented: that of calling a function periodically. |
|||
|
|||
Each timer consists of a counter that counts up at a certain rate. The rate |
|||
at which it counts is the peripheral clock frequency (in Hz) divided by the |
|||
timer prescaler. When the counter reaches the timer period it triggers an |
|||
event, and the counter resets back to zero. By using the callback method, |
|||
the timer event can call a Python function. |
|||
|
|||
Example usage to toggle an LED at a fixed frequency:: |
|||
|
|||
tim = pyb.Timer(4) # create a timer object using timer 4 |
|||
tim.init(freq=2) # trigger at 2Hz |
|||
tim.callback(lambda t:pyb.LED(1).toggle()) |
|||
|
|||
Example using named function for the callback:: |
|||
|
|||
def tick(timer): # we will receive the timer object when being called |
|||
print(timer.counter()) # show current timer's counter value |
|||
tim = pyb.Timer(4, freq=1) # create a timer object using timer 4 - trigger at 1Hz |
|||
tim.callback(tick) # set the callback to our tick function |
|||
|
|||
Further examples:: |
|||
|
|||
tim = pyb.Timer(4, freq=100) # freq in Hz |
|||
tim = pyb.Timer(4, prescaler=0, period=99) |
|||
tim.counter() # get counter (can also set) |
|||
tim.prescaler(2) # set prescaler (can also get) |
|||
tim.period(199) # set period (can also get) |
|||
tim.callback(lambda t: ...) # set callback for update interrupt (t=tim instance) |
|||
tim.callback(None) # clear callback |
|||
|
|||
*Note:* Timer(2) and Timer(3) are used for PWM to set the intensity of LED(3) |
|||
and LED(4) respectively. But these timers are only configured for PWM if |
|||
the intensity of the relevant LED is set to a value between 1 and 254. If |
|||
the intensity feature of the LEDs is not used then these timers are free for |
|||
general purpose use. Similarly, Timer(5) controls the servo driver, and |
|||
Timer(6) is used for timed ADC/DAC reading/writing. It is recommended to |
|||
use the other timers in your programs. |
|||
|
|||
*Note:* Memory can't be allocated during a callback (an interrupt) and so |
|||
exceptions raised within a callback don't give much information. See |
|||
:func:`micropython.alloc_emergency_exception_buf` for how to get around this |
|||
limitation. |
|||
|
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.Timer(id, ...) |
|||
|
|||
Construct a new timer object of the given id. If additional |
|||
arguments are given, then the timer is initialised by ``init(...)``. |
|||
``id`` can be 1 to 14. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: Timer.init(\*, freq, prescaler, period) |
|||
|
|||
Initialise the timer. Initialisation must be either by frequency (in Hz) |
|||
or by prescaler and period:: |
|||
|
|||
tim.init(freq=100) # set the timer to trigger at 100Hz |
|||
tim.init(prescaler=83, period=999) # set the prescaler and period directly |
|||
|
|||
Keyword arguments: |
|||
|
|||
- ``freq`` --- specifies the periodic frequency of the timer. You might also |
|||
view this as the frequency with which the timer goes through one complete cycle. |
|||
|
|||
- ``prescaler`` [0-0xffff] - specifies the value to be loaded into the |
|||
timer's Prescaler Register (PSC). The timer clock source is divided by |
|||
(``prescaler + 1``) to arrive at the timer clock. Timers 2-7 and 12-14 |
|||
have a clock source of 84 MHz (pyb.freq()[2] \* 2), and Timers 1, and 8-11 |
|||
have a clock source of 168 MHz (pyb.freq()[3] \* 2). |
|||
|
|||
- ``period`` [0-0xffff] for timers 1, 3, 4, and 6-15. [0-0x3fffffff] for timers 2 & 5. |
|||
Specifies the value to be loaded into the timer's AutoReload |
|||
Register (ARR). This determines the period of the timer (i.e. when the |
|||
counter cycles). The timer counter will roll-over after ``period + 1`` |
|||
timer clock cycles. |
|||
|
|||
- ``mode`` can be one of: |
|||
|
|||
- ``Timer.UP`` - configures the timer to count from 0 to ARR (default) |
|||
- ``Timer.DOWN`` - configures the timer to count from ARR down to 0. |
|||
- ``Timer.CENTER`` - configures the timer to count from 0 to ARR and |
|||
then back down to 0. |
|||
|
|||
- ``div`` can be one of 1, 2, or 4. Divides the timer clock to determine |
|||
the sampling clock used by the digital filters. |
|||
|
|||
- ``callback`` - as per Timer.callback() |
|||
|
|||
- ``deadtime`` - specifies the amount of "dead" or inactive time between |
|||
transitions on complimentary channels (both channels will be inactive) |
|||
for this time). ``deadtime`` may be an integer between 0 and 1008, with |
|||
the following restrictions: 0-128 in steps of 1. 128-256 in steps of |
|||
2, 256-512 in steps of 8, and 512-1008 in steps of 16. ``deadtime`` |
|||
measures ticks of ``source_freq`` divided by ``div`` clock ticks. |
|||
``deadtime`` is only available on timers 1 and 8. |
|||
|
|||
You must either specify freq or both of period and prescaler. |
|||
|
|||
.. method:: Timer.deinit() |
|||
|
|||
Deinitialises the timer. |
|||
|
|||
Disables the callback (and the associated irq). |
|||
|
|||
Disables any channel callbacks (and the associated irq). |
|||
Stops the timer, and disables the timer peripheral. |
|||
|
|||
.. method:: Timer.callback(fun) |
|||
|
|||
Set the function to be called when the timer triggers. |
|||
``fun`` is passed 1 argument, the timer object. |
|||
If ``fun`` is ``None`` then the callback will be disabled. |
|||
|
|||
.. method:: Timer.channel(channel, mode, ...) |
|||
|
|||
If only a channel number is passed, then a previously initialized channel |
|||
object is returned (or ``None`` if there is no previous channel). |
|||
|
|||
Otherwise, a TimerChannel object is initialized and returned. |
|||
|
|||
Each channel can be configured to perform pwm, output compare, or |
|||
input capture. All channels share the same underlying timer, which means |
|||
that they share the same timer clock. |
|||
|
|||
Keyword arguments: |
|||
|
|||
- ``mode`` can be one of: |
|||
|
|||
- ``Timer.PWM`` --- configure the timer in PWM mode (active high). |
|||
- ``Timer.PWM_INVERTED`` --- configure the timer in PWM mode (active low). |
|||
- ``Timer.OC_TIMING`` --- indicates that no pin is driven. |
|||
- ``Timer.OC_ACTIVE`` --- the pin will be made active when a compare match occurs (active is determined by polarity) |
|||
- ``Timer.OC_INACTIVE`` --- the pin will be made inactive when a compare match occurs. |
|||
- ``Timer.OC_TOGGLE`` --- the pin will be toggled when an compare match occurs. |
|||
- ``Timer.OC_FORCED_ACTIVE`` --- the pin is forced active (compare match is ignored). |
|||
- ``Timer.OC_FORCED_INACTIVE`` --- the pin is forced inactive (compare match is ignored). |
|||
- ``Timer.IC`` --- configure the timer in Input Capture mode. |
|||
- ``Timer.ENC_A`` --- configure the timer in Encoder mode. The counter only changes when CH1 changes. |
|||
- ``Timer.ENC_B`` --- configure the timer in Encoder mode. The counter only changes when CH2 changes. |
|||
- ``Timer.ENC_AB`` --- configure the timer in Encoder mode. The counter changes when CH1 or CH2 changes. |
|||
|
|||
- ``callback`` - as per TimerChannel.callback() |
|||
|
|||
- ``pin`` None (the default) or a Pin object. If specified (and not None) |
|||
this will cause the alternate function of the the indicated pin |
|||
to be configured for this timer channel. An error will be raised if |
|||
the pin doesn't support any alternate functions for this timer channel. |
|||
|
|||
Keyword arguments for Timer.PWM modes: |
|||
|
|||
- ``pulse_width`` - determines the initial pulse width value to use. |
|||
- ``pulse_width_percent`` - determines the initial pulse width percentage to use. |
|||
|
|||
Keyword arguments for Timer.OC modes: |
|||
|
|||
- ``compare`` - determines the initial value of the compare register. |
|||
|
|||
- ``polarity`` can be one of: |
|||
|
|||
- ``Timer.HIGH`` - output is active high |
|||
- ``Timer.LOW`` - output is active low |
|||
|
|||
Optional keyword arguments for Timer.IC modes: |
|||
|
|||
- ``polarity`` can be one of: |
|||
|
|||
- ``Timer.RISING`` - captures on rising edge. |
|||
- ``Timer.FALLING`` - captures on falling edge. |
|||
- ``Timer.BOTH`` - captures on both edges. |
|||
|
|||
Note that capture only works on the primary channel, and not on the |
|||
complimentary channels. |
|||
|
|||
Notes for Timer.ENC modes: |
|||
|
|||
- Requires 2 pins, so one or both pins will need to be configured to use |
|||
the appropriate timer AF using the Pin API. |
|||
- Read the encoder value using the timer.counter() method. |
|||
- Only works on CH1 and CH2 (and not on CH1N or CH2N) |
|||
- The channel number is ignored when setting the encoder mode. |
|||
|
|||
PWM Example:: |
|||
|
|||
timer = pyb.Timer(2, freq=1000) |
|||
ch2 = timer.channel(2, pyb.Timer.PWM, pin=pyb.Pin.board.X2, pulse_width=8000) |
|||
ch3 = timer.channel(3, pyb.Timer.PWM, pin=pyb.Pin.board.X3, pulse_width=16000) |
|||
|
|||
.. method:: Timer.counter([value]) |
|||
|
|||
Get or set the timer counter. |
|||
|
|||
.. method:: Timer.freq([value]) |
|||
|
|||
Get or set the frequency for the timer (changes prescaler and period if set). |
|||
|
|||
.. method:: Timer.period([value]) |
|||
|
|||
Get or set the period of the timer. |
|||
|
|||
.. method:: Timer.prescaler([value]) |
|||
|
|||
Get or set the prescaler for the timer. |
|||
|
|||
.. method:: Timer.source_freq() |
|||
|
|||
Get the frequency of the source of the timer. |
|||
|
|||
class TimerChannel --- setup a channel for a timer |
|||
================================================== |
|||
|
|||
Timer channels are used to generate/capture a signal using a timer. |
|||
|
|||
TimerChannel objects are created using the Timer.channel() method. |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: timerchannel.callback(fun) |
|||
|
|||
Set the function to be called when the timer channel triggers. |
|||
``fun`` is passed 1 argument, the timer object. |
|||
If ``fun`` is ``None`` then the callback will be disabled. |
|||
|
|||
.. method:: timerchannel.capture([value]) |
|||
|
|||
Get or set the capture value associated with a channel. |
|||
capture, compare, and pulse_width are all aliases for the same function. |
|||
capture is the logical name to use when the channel is in input capture mode. |
|||
|
|||
.. method:: timerchannel.compare([value]) |
|||
|
|||
Get or set the compare value associated with a channel. |
|||
capture, compare, and pulse_width are all aliases for the same function. |
|||
compare is the logical name to use when the channel is in output compare mode. |
|||
|
|||
.. method:: timerchannel.pulse_width([value]) |
|||
|
|||
Get or set the pulse width value associated with a channel. |
|||
capture, compare, and pulse_width are all aliases for the same function. |
|||
pulse_width is the logical name to use when the channel is in PWM mode. |
|||
|
|||
In edge aligned mode, a pulse_width of ``period + 1`` corresponds to a duty cycle of 100% |
|||
In center aligned mode, a pulse width of ``period`` corresponds to a duty cycle of 100% |
|||
|
|||
.. method:: timerchannel.pulse_width_percent([value]) |
|||
|
|||
Get or set the pulse width percentage associated with a channel. The value |
|||
is a number between 0 and 100 and sets the percentage of the timer period |
|||
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%. |
@ -0,0 +1,225 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.UART: |
|||
|
|||
class UART -- duplex serial communication bus |
|||
============================================= |
|||
|
|||
UART implements the standard UART/USART duplex serial communications protocol. At |
|||
the physical level it consists of 2 lines: RX and TX. The unit of communication |
|||
is a character (not to be confused with a string character) which can be 8 or 9 |
|||
bits wide. |
|||
|
|||
UART objects can be created and initialised using:: |
|||
|
|||
from pyb import UART |
|||
|
|||
uart = UART(1, 9600) # init with given baudrate |
|||
uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters |
|||
|
|||
Bits can be 7, 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2. |
|||
|
|||
*Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled, |
|||
only 7 and 8 bits are supported. |
|||
|
|||
A UART object acts like a `stream` object and reading and writing is done |
|||
using the standard stream methods:: |
|||
|
|||
uart.read(10) # read 10 characters, returns a bytes object |
|||
uart.read() # read all available characters |
|||
uart.readline() # read a line |
|||
uart.readinto(buf) # read and store into the given buffer |
|||
uart.write('abc') # write the 3 characters |
|||
|
|||
Individual characters can be read/written using:: |
|||
|
|||
uart.readchar() # read 1 character and returns it as an integer |
|||
uart.writechar(42) # write 1 character |
|||
|
|||
To check if there is anything to be read, use:: |
|||
|
|||
uart.any() # returns the number of characters waiting |
|||
|
|||
|
|||
*Note:* The stream functions ``read``, ``write``, etc. are new in MicroPython v1.3.4. |
|||
Earlier versions use ``uart.send`` and ``uart.recv``. |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.UART(bus, ...) |
|||
|
|||
Construct a UART object on the given bus. ``bus`` can be 1-6, or 'XA', 'XB', 'YA', or 'YB'. |
|||
With no additional parameters, the UART object is created but not |
|||
initialised (it has the settings from the last initialisation of |
|||
the bus, if any). If extra arguments are given, the bus is initialised. |
|||
See ``init`` for parameters of initialisation. |
|||
|
|||
The physical pins of the UART busses are: |
|||
|
|||
- ``UART(4)`` is on ``XA``: ``(TX, RX) = (X1, X2) = (PA0, PA1)`` |
|||
- ``UART(1)`` is on ``XB``: ``(TX, RX) = (X9, X10) = (PB6, PB7)`` |
|||
- ``UART(6)`` is on ``YA``: ``(TX, RX) = (Y1, Y2) = (PC6, PC7)`` |
|||
- ``UART(3)`` is on ``YB``: ``(TX, RX) = (Y9, Y10) = (PB10, PB11)`` |
|||
- ``UART(2)`` is on: ``(TX, RX) = (X3, X4) = (PA2, PA3)`` |
|||
|
|||
The Pyboard Lite supports UART(1), UART(2) and UART(6) only. Pins are as above except: |
|||
|
|||
- ``UART(2)`` is on: ``(TX, RX) = (X1, X2) = (PA2, PA3)`` |
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: UART.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=0, flow=0, timeout_char=0, read_buf_len=64) |
|||
|
|||
Initialise the UART bus with the given parameters: |
|||
|
|||
- ``baudrate`` is the clock rate. |
|||
- ``bits`` is the number of bits per character, 7, 8 or 9. |
|||
- ``parity`` is the parity, ``None``, 0 (even) or 1 (odd). |
|||
- ``stop`` is the number of stop bits, 1 or 2. |
|||
- ``flow`` sets the flow control type. Can be 0, ``UART.RTS``, ``UART.CTS`` |
|||
or ``UART.RTS | UART.CTS``. |
|||
- ``timeout`` is the timeout in milliseconds to wait for writing/reading the first character. |
|||
- ``timeout_char`` is the timeout in milliseconds to wait between characters while writing or reading. |
|||
- ``read_buf_len`` is the character length of the read buffer (0 to disable). |
|||
|
|||
This method will raise an exception if the baudrate could not be set within |
|||
5% of the desired value. The minimum baudrate is dictated by the frequency |
|||
of the bus that the UART is on; UART(1) and UART(6) are APB2, the rest are on |
|||
APB1. The default bus frequencies give a minimum baudrate of 1300 for |
|||
UART(1) and UART(6) and 650 for the others. Use :func:`pyb.freq <pyb.freq>` |
|||
to reduce the bus frequencies to get lower baudrates. |
|||
|
|||
*Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled, |
|||
only 7 and 8 bits are supported. |
|||
|
|||
.. method:: UART.deinit() |
|||
|
|||
Turn off the UART bus. |
|||
|
|||
.. method:: UART.any() |
|||
|
|||
Returns the number of bytes waiting (may be 0). |
|||
|
|||
.. method:: UART.read([nbytes]) |
|||
|
|||
Read characters. If ``nbytes`` is specified then read at most that many bytes. |
|||
If ``nbytes`` are available in the buffer, returns immediately, otherwise returns |
|||
when sufficient characters arrive or the timeout elapses. |
|||
|
|||
If ``nbytes`` is not given then the method reads as much data as possible. It |
|||
returns after the timeout has elapsed. |
|||
|
|||
*Note:* for 9 bit characters each character takes two bytes, ``nbytes`` must |
|||
be even, and the number of characters is ``nbytes/2``. |
|||
|
|||
Return value: a bytes object containing the bytes read in. Returns ``None`` |
|||
on timeout. |
|||
|
|||
.. method:: UART.readchar() |
|||
|
|||
Receive a single character on the bus. |
|||
|
|||
Return value: The character read, as an integer. Returns -1 on timeout. |
|||
|
|||
.. method:: UART.readinto(buf[, nbytes]) |
|||
|
|||
Read bytes into the ``buf``. If ``nbytes`` is specified then read at most |
|||
that many bytes. Otherwise, read at most ``len(buf)`` bytes. |
|||
|
|||
Return value: number of bytes read and stored into ``buf`` or ``None`` on |
|||
timeout. |
|||
|
|||
.. method:: UART.readline() |
|||
|
|||
Read a line, ending in a newline character. If such a line exists, return is |
|||
immediate. If the timeout elapses, all available data is returned regardless |
|||
of whether a newline exists. |
|||
|
|||
Return value: the line read or ``None`` on timeout if no data is available. |
|||
|
|||
.. method:: UART.write(buf) |
|||
|
|||
Write the buffer of bytes to the bus. If characters are 7 or 8 bits wide |
|||
then each byte is one character. If characters are 9 bits wide then two |
|||
bytes are used for each character (little endian), and ``buf`` must contain |
|||
an even number of bytes. |
|||
|
|||
Return value: number of bytes written. If a timeout occurs and no bytes |
|||
were written returns ``None``. |
|||
|
|||
.. method:: UART.writechar(char) |
|||
|
|||
Write a single character on the bus. ``char`` is an integer to write. |
|||
Return value: ``None``. See note below if CTS flow control is used. |
|||
|
|||
.. method:: UART.sendbreak() |
|||
|
|||
Send a break condition on the bus. This drives the bus low for a duration |
|||
of 13 bits. |
|||
Return value: ``None``. |
|||
|
|||
Constants |
|||
--------- |
|||
|
|||
.. data:: UART.RTS |
|||
UART.CTS |
|||
|
|||
to select the flow control type. |
|||
|
|||
Flow Control |
|||
------------ |
|||
|
|||
On Pyboards V1 and V1.1 ``UART(2)`` and ``UART(3)`` support RTS/CTS hardware flow control |
|||
using the following pins: |
|||
|
|||
- ``UART(2)`` is on: ``(TX, RX, nRTS, nCTS) = (X3, X4, X2, X1) = (PA2, PA3, PA1, PA0)`` |
|||
- ``UART(3)`` is on :``(TX, RX, nRTS, nCTS) = (Y9, Y10, Y7, Y6) = (PB10, PB11, PB14, PB13)`` |
|||
|
|||
On the Pyboard Lite only ``UART(2)`` supports flow control on these pins: |
|||
|
|||
``(TX, RX, nRTS, nCTS) = (X1, X2, X4, X3) = (PA2, PA3, PA1, PA0)`` |
|||
|
|||
In the following paragraphs the term "target" refers to the device connected to |
|||
the UART. |
|||
|
|||
When the UART's ``init()`` method is called with ``flow`` set to one or both of |
|||
``UART.RTS`` and ``UART.CTS`` the relevant flow control pins are configured. |
|||
``nRTS`` is an active low output, ``nCTS`` is an active low input with pullup |
|||
enabled. To achieve flow control the Pyboard's ``nCTS`` signal should be connected |
|||
to the target's ``nRTS`` and the Pyboard's ``nRTS`` to the target's ``nCTS``. |
|||
|
|||
CTS: target controls Pyboard transmitter |
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|||
|
|||
If CTS flow control is enabled the write behaviour is as follows: |
|||
|
|||
If the Pyboard's ``UART.write(buf)`` method is called, transmission will stall for |
|||
any periods when ``nCTS`` is ``False``. This will result in a timeout if the entire |
|||
buffer was not transmitted in the timeout period. The method returns the number of |
|||
bytes written, enabling the user to write the remainder of the data if required. In |
|||
the event of a timeout, a character will remain in the UART pending ``nCTS``. The |
|||
number of bytes composing this character will be included in the return value. |
|||
|
|||
If ``UART.writechar()`` is called when ``nCTS`` is ``False`` the method will time |
|||
out unless the target asserts ``nCTS`` in time. If it times out ``OSError 116`` |
|||
will be raised. The character will be transmitted as soon as the target asserts ``nCTS``. |
|||
|
|||
RTS: Pyboard controls target's transmitter |
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|||
|
|||
If RTS flow control is enabled, behaviour is as follows: |
|||
|
|||
If buffered input is used (``read_buf_len`` > 0), incoming characters are buffered. |
|||
If the buffer becomes full, the next character to arrive will cause ``nRTS`` to go |
|||
``False``: the target should cease transmission. ``nRTS`` will go ``True`` when |
|||
characters are read from the buffer. |
|||
|
|||
Note that the ``any()`` method returns the number of bytes in the buffer. Assume a |
|||
buffer length of ``N`` bytes. If the buffer becomes full, and another character arrives, |
|||
``nRTS`` will be set False, and ``any()`` will return the count ``N``. When |
|||
characters are read the additional character will be placed in the buffer and will |
|||
be included in the result of a subsequent ``any()`` call. |
|||
|
|||
If buffered input is not used (``read_buf_len`` == 0) the arrival of a character will |
|||
cause ``nRTS`` to go ``False`` until the character is read. |
@ -0,0 +1,40 @@ |
|||
.. currentmodule:: pyb |
|||
.. _pyb.USB_HID: |
|||
|
|||
class USB_HID -- USB Human Interface Device (HID) |
|||
================================================= |
|||
|
|||
The USB_HID class allows creation of an object representing the USB |
|||
Human Interface Device (HID) interface. It can be used to emulate |
|||
a peripheral such as a mouse or keyboard. |
|||
|
|||
Before you can use this class, you need to use :meth:`pyb.usb_mode()` to set the USB mode to include the HID interface. |
|||
|
|||
Constructors |
|||
------------ |
|||
|
|||
.. class:: pyb.USB_HID() |
|||
|
|||
Create a new USB_HID object. |
|||
|
|||
|
|||
Methods |
|||
------- |
|||
|
|||
.. method:: USB_HID.recv(data, \*, timeout=5000) |
|||
|
|||
Receive data on the bus: |
|||
|
|||
- ``data`` can be an integer, which is the number of bytes to receive, |
|||
or a mutable buffer, which will be filled with received bytes. |
|||
- ``timeout`` is the timeout in milliseconds to wait for the receive. |
|||
|
|||
Return value: if ``data`` is an integer then a new buffer of the bytes received, |
|||
otherwise the number of bytes read into ``data`` is returned. |
|||
|
|||
.. method:: USB_HID.send(data) |
|||
|
|||
Send data over the USB HID interface: |
|||
|
|||
- ``data`` is the data to send (a tuple/list of integers, or a |
|||
bytearray). |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue