Repository: JetBrains/intellij-micropython Branch: master Commit: 17bcc4abb60e Files: 121 Total size: 978.1 KB Directory structure: gitextract_ebr8_o39/ ├── .github/ │ └── workflows/ │ └── check.yml ├── .gitignore ├── CHANGES.md ├── LICENSE.txt ├── Pipfile ├── README.md ├── build.gradle.kts ├── examples/ │ └── rpsls.py ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── licenses/ │ └── microrepl_license.txt ├── scripts/ │ ├── findusb.py │ ├── microcleanfs.py │ ├── microrepl.py │ └── microupload.py ├── src/ │ └── main/ │ ├── kotlin/ │ │ └── com/ │ │ └── jetbrains/ │ │ └── micropython/ │ │ ├── actions/ │ │ │ ├── MicroPythonAction.kt │ │ │ ├── MicroPythonCommandAction.kt │ │ │ ├── RemoveAllFilesFromDeviceAction.kt │ │ │ └── RunMicroReplAction.kt │ │ ├── devices/ │ │ │ ├── Esp8266DeviceProvider.kt │ │ │ ├── MicroBitDeviceProvider.kt │ │ │ ├── MicroBitV2DeviceProvider.kt │ │ │ ├── MicroPythonDeviceProvider.kt │ │ │ ├── PyboardDeviceProvider.kt │ │ │ └── RPiPicoDeviceProvider.kt │ │ ├── inspections/ │ │ │ └── MicroPythonRequirementsInspection.kt │ │ ├── repl/ │ │ │ ├── MicroPythonReplManager.kt │ │ │ ├── StopReplBeforeRunTask.kt │ │ │ └── ToolWindowReplTab.kt │ │ ├── run/ │ │ │ ├── MicroPythonConfigurationType.kt │ │ │ ├── MicroPythonRunConfiguration.kt │ │ │ ├── MicroPythonRunConfigurationEditor.kt │ │ │ ├── MicroPythonRunConfigurationProducer.kt │ │ │ └── MicroUpload.kt │ │ ├── settings/ │ │ │ ├── MicroPythonDevicesConfiguration.kt │ │ │ ├── MicroPythonFacet.kt │ │ │ ├── MicroPythonFacetConfiguration.kt │ │ │ ├── MicroPythonFacetDetector.kt │ │ │ ├── MicroPythonFacetEditorTab.kt │ │ │ ├── MicroPythonFacetType.kt │ │ │ ├── MicroPythonModuleConfigurable.kt │ │ │ ├── MicroPythonProjectConfigurable.kt │ │ │ ├── MicroPythonSettingsPanel.kt │ │ │ ├── MicroPythonTypeHints.kt │ │ │ └── MicroPythonUsbId.kt │ │ └── ui/ │ │ └── MicroPythonToolWindowFactory.kt │ └── resources/ │ ├── META-INF/ │ │ └── plugin.xml │ └── inspectionDescriptions/ │ └── MicroPythonRequirements.html └── typehints/ ├── esp32/ │ ├── esp.pyi │ ├── esp32.pyi │ └── network.pyi ├── esp8266/ │ ├── esp.pyi │ └── network.pyi ├── microbit/ │ ├── microbit/ │ │ ├── __init__.pyi │ │ ├── accelerometer.pyi │ │ ├── compass.pyi │ │ ├── display.pyi │ │ ├── i2c.pyi │ │ ├── spi.pyi │ │ └── uart.pyi │ ├── music.pyi │ ├── neopixel.pyi │ ├── radio.pyi │ └── speech.pyi ├── micropython/ │ ├── bluetooth.pyi │ ├── btree.pyi │ ├── cryptolib.pyi │ ├── framebuf.pyi │ ├── machine.pyi │ ├── micropython.pyi │ ├── neopixel.pyi │ ├── network.pyi │ ├── ubluetooth.pyi │ ├── ucryptolib.pyi │ └── uctypes.pyi ├── pyboard/ │ ├── lcd160cr.pyi │ ├── pyb.pyi │ └── stm.pyi ├── rpi_pico/ │ └── rp2.pyi └── stdlib/ ├── _thread.pyi ├── array.pyi ├── binascii.pyi ├── cmath.pyi ├── collections.pyi ├── errno.pyi ├── gc.pyi ├── hashlib.pyi ├── heapq.pyi ├── io.pyi ├── json.pyi ├── math.pyi ├── os.pyi ├── re.pyi ├── select.pyi ├── socket.pyi ├── ssl.pyi ├── struct.pyi ├── sys.pyi ├── time.pyi ├── uarray.pyi ├── uasyncio.pyi ├── ubinascii.pyi ├── ucollections.pyi ├── uerrno.pyi ├── uhashlib.pyi ├── uheapq.pyi ├── uio.pyi ├── ujson.pyi ├── uos.pyi ├── ure.pyi ├── uselect.pyi ├── usocket.pyi ├── ussl.pyi ├── ustruct.pyi ├── usys.pyi ├── utime.pyi ├── uzlib.pyi └── zlib.pyi ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/check.yml ================================================ name: check on: push: branches: - master pull_request: schedule: - cron: '0 3 * * *' # Allow cancelling all previous runs for the same branch # See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build-plugin: runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v4 with: distribution: corretto java-version: 17 - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 - name: Build plugin run: ./gradlew :buildPlugin -Pversion=SNAPSHOT-${{ github.run_number }} - name: Upload plugin archive uses: actions/upload-artifact@v4 with: name: intellij-micropython-SNAPSHOT-${{ github.run_number }} path: build/distributions/intellij-micropython-SNAPSHOT-${{ github.run_number }}.zip ================================================ FILE: .gitignore ================================================ *.iml .idea/ !/.idea/runConfigurations/ .gradle/ build/ venv/ tmp/ # IntelliJ Platform Gradle Plugin .intellijPlatform/ ================================================ FILE: CHANGES.md ================================================ The Changelog ============= 1.4.6 - 2024-08-28 ------------------ * Support for 2024.2 IDE versions ([#295](https://github.com/JetBrains/intellij-micropython/issues/295)) 1.4.5 - 2024-07-27 ------------------ ### Fixed * Don't interrupt program execution when REPL is started right after the upload ([#313](https://github.com/JetBrains/intellij-micropython/pull/313)) * Update `machine.pyi` ([#291](https://github.com/JetBrains/intellij-micropython/pull/291)) (Thanks to [Lucio Rossi](https://github.com/eigen-value)) * Update `network.pyi` ([#296](https://github.com/JetBrains/intellij-micropython/pull/296)) 1.4.4 - 2024-07-13 ------------------ ### Fixed * Compatibility with 2024.1.x IDEs * REPL should work fine with the latest IDE versions 1.4.2 - 2023-10-11 ------------------ ### Fixed * Metro M4 Airlift Lite support added ([#254](https://github.com/JetBrains/intellij-micropython/pull/254)) (Thanks to [@PierreDeQuebec](https://github.com/PierreDeQuebec)) * Compatibility issue in REPL support is fixed ([#253](https://github.com/JetBrains/intellij-micropython/pull/253)) (Thanks to [@lancelote](https://github.com/lancelote)) 1.4.1 - 2023-03-17 ------------------ ### Added * Type Hints for ESP32 added ([#218](https://github.com/JetBrains/intellij-micropython/pull/218)) (Thanks to [@MrNavaStar](https://github.com/MrNavaStar)) 1.4.0 - 2022-11-21 ------------------ ### Added * MicroPython REPL running in a dedicated tool window ([#139](https://github.com/JetBrains/intellij-micropython/pull/139)) (Thanks to [@lensvol](https://github.com/lensvol)) * Support for the Micro:bit V2 device type ([#186](https://github.com/JetBrains/intellij-micropython/pull/186)) ### Changed * Compatibility with 2021.3-2022.3 1.3.3 — 2022-09-23 ------------------ ### Fixed * Broken compatibility with the older PyCharm versions 1.3.2 — 2022-09-23 ------------------ ### Fixed * An error on opening projects in PyCharm 2022.2.2 ([#205](https://github.com/JetBrains/intellij-micropython/issues/205)) 1.3.1 — 2022-03-18 ------------------ ### Changed * Compatibility with 2020.3-2022.1 ([#184](https://github.com/vlasovskikh/intellij-micropython/issues/184)) 1.3 — 2021-12-01 ---------------- ### Added * Added many stubs for the MicroPython standard library and Pyboard ([#176](https://github.com/vlasovskikh/intellij-micropython/pull/176)) (Thanks to [@hlovatt](https://github.com/hlovatt)) ### Changed * Compatibility with 2020.3-2021.3 ### Fixed * Fixed special keys in REPL on Windows for pyserial>=3.5 ([#175](https://github.com/vlasovskikh/intellij-micropython/issues/175)) 1.2 — 2021-08-05 ---------------- ### Added * Added support for Raspberry Pi Pico devices ([#132](https://github.com/vlasovskikh/intellij-micropython/issues/132)) (Thanks to [@timsavage](https://github.com/timsavage)) * Added type hints for `lcd160cr`, `network`, `ubluetooth`, `ucryptolib`, `uctypes` (Thanks to [@hlovatt](https://github.com/hlovatt)) ### Changed * Compatibility with 2020.3-2021.2 ([#170](https://github.com/vlasovskikh/intellij-micropython/issues/170)) * Updated type hints for `pyb`, `machine`, `micropython`, `uarray`, `btree`, `framebuf` (Thanks to [@hlovatt](https://github.com/hlovatt)) ### Fixed * Fixed handling backslash while flashing files on Windows ([#128](https://github.com/vlasovskikh/intellij-micropython/issues/128)) (Thanks to [@jdjjm](https://github.com/jdjjm)) 1.1.4 — 2021-03-05 ------------------ * Compatibility with 2020.2-2021.1 1.1.3 — 2020-12-12 ------------------ * Added an SVG icon for MicroPython actions * Fixed a regression in 2020.3 that prevented the plugin from updating and persisting your device type on changing it in the settings 1.1.2 — 2020-10-24 ------------------ * Added a type hinting stub for `pyb` * Switched to newer terminal API to fix regression in PyCharm 2020.2 * Compatibility with 2020.2-2020.3 1.1.1 — 2020-06-24 ------------------ * Fixed control characters in REPL on Windows * Fixed path separators for flashing directories on Windows 1.1 — 2020-06-07 ---------------- * Auto-detect a connected MicroPython device with an option to specify the device path manually in the IDE settings for MicroPython * Use the nearest directory marked "Sources Root" as the root of your device while flashing files * Ignore `.git/`, `.idea/` and other files starting with `.` when flashing a directory * Launch a run configuration to flash a directory from its context menu * Compatibility with 2020.1-2020.2 1.0.14 — 2020-01-31 ------------------- * Compatibility with 2019.3-2020.1 1.0.13 — 2019-10-02 ------------------- * Compatibility with 2019.3 only 1.0.12 — 2019-07-23 ------------------- * Compatibility with 2018.3-2019.2 1.0.11 — 2019-02-12 ------------------- * Compatibility with 2018.3-2019.1 1.0.10 — 2018-11-22 ------------------- * Compatibility with 2018.3 only 1.0.9 — 2018-09-10 ------------------ * Compatibility with 2018.2-2018.3 1.0.8 — 2018-07-25 ------------------ * Compatibility with 2018.2 only 1.0.7 — 2018-06-19 ------------------ * Compatibility with 2017.3-2018.2 1.0.6 — 2018-02-23 ------------------ * Fixed several bugs in `machine` stub 1.0.5 — 2018-02-11 ------------------ * Don't delete `boot.py` when removing all files from the device #35 1.0.4 — 2018-01-18 ------------------ * Fixed launching REPL on Windows #12 1.0.3 — 2018-01-16 ------------------ * Fixed the outdated pyserial version in requirements #26 * Fixed the error message when getting `EACCESS` error for the device file #27 1.0.2 — 2018-01-15 ------------------ * Restored compatibility with IntelliJ 1.0.1 — 2018-01-15 ------------------ * Restored compatibility with 2017.2-2018.1 1.0 — 2018-01-15 ---------------- * Run files and REPL for ESP8266 and Pyboard devices * Initial code insight for ESP8266 and MicroPython standard library * Action for detecting the device path in the MicroPython settings * Action for removing all files from the device 0.1 — 2017-06-18 ---------------- * Code insight and documentation for Micro:bit Python API * Run Python files on Micro:bit * Micro:bit Python REPL ================================================ FILE: LICENSE.txt ================================================ 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 2000-2016 JetBrains s.r.o. 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. ================================================ FILE: Pipfile ================================================ [[source]] url = "https://pypi.org/simple" verify_ssl = true name = "pypi" [packages] docopt = "*" adafruit-ampy = "*" pyserial = "*" [dev-packages] [requires] python_version = "3.7" ================================================ FILE: README.md ================================================ # MicroPython Plugin for PyCharm and IntelliJ [![JetBrains team project](http://jb.gg/badges/team.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![JetBrains IntelliJ Plugins](https://img.shields.io/jetbrains/plugin/v/9777-micropython)](https://plugins.jetbrains.com/plugin/9777-micropython) [![JetBrains IntelliJ plugins](https://img.shields.io/jetbrains/plugin/d/9777-micropython)](https://plugins.jetbrains.com/plugin/9777-micropython) [![JetBrains IntelliJ Plugins](https://img.shields.io/jetbrains/plugin/r/rating/9777-micropython)](https://plugins.jetbrains.com/plugin/9777-micropython) [![check](https://github.com/JetBrains/intellij-micropython/actions/workflows/check.yml/badge.svg?branch=master)](https://github.com/JetBrains/intellij-micropython/actions/workflows/check.yml) [![Join the chat at https://gitter.im/intellij-micropython/community](https://badges.gitter.im/intellij-micropython/community.svg)](https://gitter.im/intellij-micropython/community) The Python code development plugin for [MicroPython](http://micropython.org/) devices in [PyCharm](https://www.jetbrains.com/pycharm/) and [IntelliJ](https://www.jetbrains.com/idea/). ## Discontinued - The project is discontinued and is no longer maintained - Kindly use [MicroPython Tools](https://plugins.jetbrains.com/plugin/26227-micropython-tools/) instead ## Supported devices The plugin supports Python development for these devices: * [ESP8266](https://github.com/JetBrains/intellij-micropython/wiki/ESP8266) * [PyBoard](https://github.com/JetBrains/intellij-micropython/wiki/Pyboard) * [BBC Micro:bit](https://github.com/JetBrains/intellij-micropython/wiki/BBC-Micro%3Abit) * [Raspberry Pi Pico](https://www.raspberrypi.org/products/raspberry-pi-pico/) It will support more MicroPython devices and more device-specific and MicroPython-specific modules eventually. We are interested in your contributions to the project. Feel free to open issues and send pull requests! See also [the changelog](CHANGES.md) for the plugin. ## Features ### Code insight for MicroPython modules * Context-aware code completion and documentation * Use Ctrl+Q (F1 on macOS) for quick documentation window, you can dock it permanently ![Code completion](media/code-completion.png) * Syntax checking and type checking * The plugin checks your code while you're typing it ![Type checking](media/type-checking.png) ### Run code on MicroPython devices * Flash Python files or project directories to devices * Right-click on a file or directory and select "Run 'Flash '" to flash this item to your connected device. If you want to flash a sub-directory to the root directory of your device, please mark this sub-directory as a sources root: right-click on it and select "Mark Directory as | Sources Root". Its icon will become blue, see the screenshot. ![Flash directory](media/flash-directory.png) * You can edit your run configurations for flashing files or directories in "Run | Edit Configurations..." menu. ![Run](media/run.png) * MicroPython REPL * Use "Tools | MicroPython | MicroPython REPL" menu to run a MicroPython shell on your device. Or open MicroPython REPL tool window directly ![REPL](media/repl_toolwindow.png) ## Requirements * PyCharm or IntelliJ * Python 3.5+ * The MicroPython language version is 3.5. If you select a newer version, turn on "File | Settings | Editor | Inspections | Python | Code compatibility inspection" and add Python 3.5 to the compatibility list there * Python plugin (IntelliJ only) * Supported MicroPython development board with a recent version of MicroPython firmware flashed to the board ## Installation 1. Install the "MicroPython" plugin from your IDE settings. 2. Create a new project or open an existing folder with your MicroPython code. 3. This step differs for PyCharm and IntelliJ: * PyCharm: Enable MicroPython support in "File | Settings | Languages & Frameworks | MicroPython" and specify the path to your MicroPython device * IntelliJ: Add the MicroPython facet to a Python module in your project structure and specify the path to your MicroPython device ![Configurable](media/configurable.png) 4. Open any Python file in project. You may see a yellow bar on top of the file, notifying you that you don't have some packages required for communicating with your device. In this case click "Install requirements" and wait while the plugin downloads and installs the packages. ## Source Code We write this plugin in Python and [Kotlin](https://kotlinlang.org/). Kotlin a new JVM language by JetBrains, the makers of PyCharm and IntelliJ. Google recommends Kotlin as the best language for developing Android apps. If you are a Python developer, Kotlin may be an interesting language for you to learn. The steps for setting up the development environment: 1. Check out this project from GitHub 2. Create a new project from existing sources in IntelliJ To just run the development version use `./gradlew clean runIde` from the command line or just run **runIde** [run configuration](https://www.jetbrains.com/help/idea/run-debug-configuration.html). Contributions are welcome! ## License The plugin is licensed under the terms of the Apache 2 license. ================================================ FILE: build.gradle.kts ================================================ import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinVersion import org.jetbrains.kotlin.gradle.tasks.KotlinCompile repositories { mavenCentral() intellijPlatform { defaultRepositories() } } plugins { kotlin("jvm") version "2.0.20" id("org.jetbrains.intellij.platform") version "2.0.1" } dependencies { intellijPlatform { val type = project.property("platformType").toString() val version = project.property("platformVersion").toString() val pythonPlugin = project.property("pythonPlugin").toString() create(type, version, useInstaller = false) bundledPlugin("org.jetbrains.plugins.terminal") when (type) { "PC" -> bundledPlugin("PythonCore") "PY" -> bundledPlugin("Pythonid") else -> plugin(pythonPlugin) } } } java { sourceCompatibility = JavaVersion.VERSION_21 targetCompatibility = JavaVersion.VERSION_21 } intellijPlatform { pluginConfiguration { name = "MicroPython" } instrumentCode = false publishing { token = project.property("publishToken").toString() } } tasks { withType { compilerOptions { jvmTarget = JvmTarget.JVM_21 languageVersion = KotlinVersion.DEFAULT apiVersion = KotlinVersion.KOTLIN_1_9 } } prepareSandbox { from("$rootDir") { into("intellij-micropython") include("typehints/") include("scripts/") } } } ================================================ FILE: examples/rpsls.py ================================================ from random import choice import gc import radio from microbit import * CLASSIC_STORY = """ Scissors cuts Paper Paper covers Rock Rock crushes Scissors """ SHELDON_COOPER_STORY = """ Scissors cuts Paper Paper covers Rock Rock crushes Lizard Lizard poisons Spock Spock smashes Scissors Scissors decapitates Lizard Lizard eats Paper Paper disproves Spock Spock vaporizes Rock (and as it always has) Rock crushes Scissors """ STORY = SHELDON_COOPER_STORY # @formatter:off SKETCHES = { 'Scissors': '* :' ' * :' ' *:' ' * :' '* :', 'Paper': '*****:' '* *:' '* *:' '* *:' '*****:', 'Rock': ' *** :' '*****:' '*****:' '*****:' ' *** :', 'Lizard': '** :' ' * :' ' * :' ' * :' ' **:', 'Spock': ' *** :' '*****:' '** **:' '** **:' '** **:', } # @formatter:on def sketch_to_image(sketch): return Image(sketch.replace(' ', '0').replace('*', '9')) IMAGES = {name: sketch_to_image(sketch) for name, sketch in SKETCHES.items()} def parse_story(story): gc.collect() sentences = [line.split()[-3:] for line in story.split('\n') if line.strip()] actors = {s for s, v, o in sentences} victims = {actor: {o for s, v, o in sentences if s == actor} for actor in actors} return actors, victims ACTORS, VICTIMS = parse_story(STORY) def random_outcome(): return choice(list(ACTORS)) def expired(time): return abs(running_time() - time) > 2000 def beats(actor, victim): return victim in VICTIMS.get(actor, []) def wait_for_outcome(): start = running_time() while not expired(start): received = radio.receive() if received: return received def main(): last_received = 0 other_outcome = None radio.on() while True: received = radio.receive() if received: other_outcome = received last_received = running_time() if not accelerometer.was_gesture('face down'): continue my_outcome = random_outcome() radio.send(my_outcome) if not other_outcome or expired(last_received): other_outcome = wait_for_outcome() if other_outcome: sleep(1000) image = IMAGES.get(my_outcome, Image.SAD) if beats(my_outcome, other_outcome): to_show = [Image('00000:' '00000:' '00000:' '00000:' '00000:'), image, image, image] * 5 else: to_show = [image] * 20 display.show(to_show, delay=200, clear=True, wait=False) other_outcome = None if __name__ == '__main__': main() ================================================ FILE: gradle/wrapper/gradle-wrapper.properties ================================================ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists ================================================ FILE: gradle.properties ================================================ version=1.4.6-2024.2 platformType=PC platformVersion=242-EAP-SNAPSHOT pythonPlugin=PythonCore:242.20224.300 publishToken=token # Since kotlin 1.4, stdlib dependency is added by default by kotlin gradle plugin. # But we don't need it because all necessary kotlin libraries are already bundled into IDE. # See https://kotlinlang.org/docs/gradle-configure-project.html#dependency-on-the-standard-library for more details kotlin.stdlib.default.dependency=false ================================================ FILE: gradlew ================================================ #!/bin/sh # # Copyright © 2015-2021 the original authors. # # 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 # # https://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. # # SPDX-License-Identifier: Apache-2.0 # ############################################################################## # # Gradle start up script for POSIX generated by Gradle. # # Important for running: # # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is # noncompliant, but you have some other compliant shell such as ksh or # bash, then to run this script, type that shell name before the whole # command line, like: # # ksh Gradle # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», # «${var#prefix}», «${var%suffix}», and «$( cmd )»; # * compound commands having a testable exit status, especially «case»; # * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # # (2) This script targets any POSIX shell, so it avoids extensions provided # by Bash, Ksh, etc; in particular arrays are avoided. # # The "traditional" practice of packing multiple parameters into a # space-separated string is a well documented source of bugs and security # problems, so this is (mostly) avoided, by progressively accumulating # options in "$@", and eventually passing that to Java. # # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; # see the in-line comments for details. # # There are tweaks for specific operating systems such as AIX, CygWin, # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. # ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link app_path=$0 # Need this for daisy-chained symlinks. while APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path [ -h "$app_path" ] do ls=$( ls -ld "$app_path" ) link=${ls#*' -> '} case $link in #( /*) app_path=$link ;; #( *) app_path=$APP_HOME$link ;; esac done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s ' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum warn () { echo "$*" } >&2 die () { echo echo "$*" echo exit 1 } >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "$( uname )" in #( CYGWIN* ) cygwin=true ;; #( Darwin* ) darwin=true ;; #( MSYS* | MINGW* ) msys=true ;; #( NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD=$JAVA_HOME/jre/sh/java else JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD=java if ! command -v java >/dev/null 2>&1 then die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi # Collect all arguments for the java command, stacking in reverse order: # * args from the command line # * the main class name # * -classpath # * -D...appname settings # * --module-path (only if needed) # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) # Now convert the arguments - kludge to limit ourselves to /bin/sh for arg do if case $arg in #( -*) false ;; # don't mess with options #( /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath [ -e "$t" ] ;; #( *) false ;; esac then arg=$( cygpath --path --ignore --mixed "$arg" ) fi # Roll the args list around exactly as many times as the number of # args, so each arg winds up back in the position where it started, but # possibly modified. # # NB: a `for` loop captures its iteration list before it begins, so # changing the positional parameters here affects neither the number of # iterations, nor the values presented in `arg`. shift # remove old arg set -- "$@" "$arg" # push replacement arg done fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ org.gradle.wrapper.GradleWrapperMain \ "$@" # Stop when "xargs" is not available. if ! command -v xargs >/dev/null 2>&1 then die "xargs is not available" fi # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. # # In Bash we could simply go: # # readarray ARGS < <( xargs -n1 <<<"$var" ) && # set -- "${ARGS[@]}" "$@" # # but POSIX shell has neither arrays nor command substitution, so instead we # post-process each arg (as a line of input to sed) to backslash-escape any # character that might be a shell metacharacter, then use eval to reverse # that process (while maintaining the separation between arguments), and wrap # the whole thing up as a single "set" statement. # # This will of course break if any of these variables contains a newline or # an unmatched quote. # eval "set -- $( printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | xargs -n1 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | tr '\n' ' ' )" '"$@"' exec "$JAVACMD" "$@" ================================================ FILE: gradlew.bat ================================================ @rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem @rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem @rem SPDX-License-Identifier: Apache-2.0 @rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Resolve any "." and ".." in APP_HOME to make it shorter. for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute echo. 1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute echo. 1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 goto fail :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! set EXIT_CODE=%ERRORLEVEL% if %EXIT_CODE% equ 0 set EXIT_CODE=1 if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: licenses/microrepl_license.txt ================================================ Copyright 2015 The Python Software Foundation (http://python.org/) 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. ================================================ FILE: scripts/findusb.py ================================================ # Copyright 2000-2017 JetBrains s.r.o. # # 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. """Find USB devices. Usage: findusb Outputs the list of all USB devices it has managed to find. """ from serial.tools.list_ports import comports def main() -> None: for port in comports(): if port.vid is not None and port.pid is not None: print('0x%02x:0x%02x %s' % (port.vid, port.pid, port.device)) if __name__ == '__main__': main() ================================================ FILE: scripts/microcleanfs.py ================================================ # Copyright 2000-2017 JetBrains s.r.o. # # 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. """Remove the contents of the file system on a MicroPython device. Usage: microcleanfs PORT [options] Options: -f --force Remove ALL files from filesystem w/o preserving excludes """ import traceback from typing import List import sys import time from ampy.files import Files from ampy.pyboard import Pyboard, PyboardError from docopt import docopt def main(args: List[str]) -> None: opts = docopt(__doc__, argv=args) port = opts['PORT'] force = opts['--force'] print('Connecting to {}'.format(port), file=sys.stderr) board = Pyboard(port) files = Files(board) # Specifying subdirectories DOES NOT work as they will be deleted when the # parent directory is deleted. Specifying top level directories DOES work. exclude_files = ['boot.py'] print('Removing the contents of the file system') wait_for_board() for name in files.ls(long_format=False): if force or name not in exclude_files: try: files.rm(name) except (RuntimeError, PyboardError): try: files.rmdir(name) except (RuntimeError, PyboardError): print('Unknown Error removing file {}'.format(name), file=sys.stderr) print('Done') def wait_for_board() -> None: """Wait for some ESP8266 devices to become ready for REPL commands.""" time.sleep(0.5) if __name__ == '__main__': try: main(sys.argv[1:]) exitcode = 0 except: traceback.print_exc() exitcode = 1 finally: input('Press ENTER to continue') sys.exit(exitcode) ================================================ FILE: scripts/microrepl.py ================================================ # Copyright 2015 The Python Software Foundation (http://python.org/) # # 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. """ A simple shim around PySerial that detects the correct port to which the MicroPython device is connected and attempts to make a serial connection to it in order to bring up the Python REPL. Based on https://github.com/ntoll/microrepl by Nicholas H.Tollervey and the contributors. """ import errno import sys from time import sleep import traceback import serial import serial.tools.miniterm from serial.tools.miniterm import Miniterm, key_description BAUDRATE = 115200 PARITY = 'N' if sys.version_info >= (3, 0): def character(b): return b.decode('latin1') else: def character(b): return b def connect_miniterm(port): try: ser = serial.Serial(port, BAUDRATE, parity=PARITY, rtscts=False, xonxoff=False) return Miniterm(ser, echo=False) except serial.SerialException as e: if e.errno == errno.ENOENT: sys.stderr.write( "Device %r not found. Check your " "MicroPython device path settings.\n" % port) elif e.errno == errno.EBUSY: # Device is busy. Explain what to do. sys.stderr.write( "Found the device, but it is busy. " "Wait up to 20 seconds, or " "press the reset button on the " "back of the device next to the yellow light; " "then try again.\n" ) elif e.errno == errno.EACCES: sys.stderr.write("Found the device, but could not connect.\n".format(port)) sys.stderr.write('%s\n' % (str(e),)) sys.stderr.write('On linux, try adding yourself to the "dialout" group:\n') sys.stderr.write('sudo usermod -a -G dialout \n') else: # Try to be as helpful as possible. sys.stderr.write("Found the device, but could not connect via" + " port %r: %s\n" % (port, e)) sys.stderr.write("I'm not sure what to suggest. :-(\n") input("Press ENTER to continue") sys.exit(1) def main(): """ The function that actually runs the REPL. """ if len(sys.argv) not in range(2, 3): print("Usage: microrepl.py /path/to/device [--nointerrupt]") port = sys.argv[1] print('Device path', port) serial.tools.miniterm.EXITCHARCTER = character(b'\x1d') miniterm = connect_miniterm(port) # Emit some helpful information about the program and MicroPython. shortcut_message = 'Quit: {} | Stop program: Ctrl+C | Reset: Ctrl+D\n' help_message = 'Type \'help()\' (without the quotes) then press ENTER.\n' exit_char = key_description(serial.tools.miniterm.EXITCHARCTER) sys.stderr.write(shortcut_message.format(exit_char)) sys.stderr.write(help_message) # Start everything. miniterm.set_rx_encoding('utf-8') miniterm.set_tx_encoding('utf-8') miniterm.start() sleep(0.5) if len(sys.argv) != 3 or sys.argv[2] != '--nointerrupt': miniterm.serial.write(b'\x03') # Connecting stops the running program. try: miniterm.join(True) except KeyboardInterrupt: pass sys.stderr.write('\nEXIT - see you soon... :-)\n') if __name__ == '__main__': try: main() except Exception: sys.stderr.write(traceback.format_exc()) input("Press ENTER to continue") sys.exit(1) ================================================ FILE: scripts/microupload.py ================================================ # Copyright 2000-2017 JetBrains s.r.o. # # 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. """Upload files and directories onto a MicroPython device. Usage: microupload PORT PATH [-X PATH]... [options] Options: -X --exclude=PATH Path to exclude, may be repeated. -C --chdir=PATH Change current directory to path. -v --verbose Verbose output. """ import time import sys import os from contextlib import suppress from typing import List, Iterable, TypeVar, Sequence, Set from docopt import docopt from ampy.pyboard import Pyboard from ampy.files import Files, DirectoryExistsError __all__ = [] verbose = False T = TypeVar('T') def main(args: List[str]) -> None: global verbose opts = docopt(__doc__, argv=args) verbose = opts['--verbose'] root = opts['PATH'] chdir = opts['--chdir'] if chdir: os.chdir(chdir) port = opts['PORT'] print('Connecting to {}'.format(port), file=sys.stderr) board = Pyboard(port) files = Files(board) rel_root = os.path.relpath(root, os.getcwd()) wait_for_board() if os.path.isdir(root): to_upload = [os.path.join(rel_root, x) for x in list_files(root, opts['--exclude'])] else: to_upload = [rel_root] created_cache = set() for path in progress('Uploading files', to_upload): local_path = os.path.abspath(path) remote_path = os.path.normpath(path).replace(os.path.sep, '/') if verbose: print('\n{} -> {}'.format(local_path, remote_path), file=sys.stderr, flush=True) remote_dir = os.path.dirname(path) if remote_dir: make_dirs(files, remote_dir, created_cache) with open(local_path, 'rb') as fd: files.put(remote_path, fd.read()) print('Soft reboot', file=sys.stderr, flush=True) soft_reset(board) def make_dirs(files: Files, path: str, created_cache: Set[str] = None) -> None: """Make all the directories the specified relative path consists of.""" if path == '.': return if created_cache is None: created_cache = set() parent = os.path.dirname(path) if parent and parent not in created_cache: make_dirs(files, parent, created_cache) with suppress(DirectoryExistsError): posix_path = path.replace(os.path.sep, '/') files.mkdir(posix_path) created_cache.add(path) def soft_reset(board: Pyboard) -> None: """Perform soft-reset of the ESP8266 board.""" board.serial.write(b'\x03\x04') def list_files(path: str, excluded: List[str]) -> Iterable[str]: """List relative file paths inside the given path.""" excluded = {os.path.abspath(x) for x in excluded} for root, dirs, files in os.walk(path): abs_root = os.path.abspath(root) for d in list(dirs): if os.path.join(abs_root, d) in excluded or d.startswith('.'): dirs.remove(d) for f in files: if os.path.join(abs_root, f) not in excluded and not f.startswith('.'): yield os.path.relpath(os.path.join(root, f), path) def wait_for_board() -> None: """Wait for some ESP8266 devices to become ready for REPL commands.""" time.sleep(0.5) def progress(msg: str, xs: Sequence[T]) -> Iterable[T]: """Show progress while iterating over a sequence.""" size = len(xs) sys.stderr.write('\r{}: 0% (0/{})'.format(msg, size)) sys.stderr.flush() for i, x in enumerate(xs, 1): yield x s = '{0}: {1}% ({2}/{3})'.format(msg, int(i * 100 / size), i, size) sys.stderr.write('\r' + s) sys.stderr.flush() sys.stderr.write('\n') sys.stderr.flush() if __name__ == '__main__': main(sys.argv[1:]) ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/actions/MicroPythonAction.kt ================================================ package com.jetbrains.micropython.actions import com.intellij.facet.ui.ValidationResult import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.jetbrains.micropython.settings.firstMicroPythonFacet abstract class MicroPythonAction : AnAction() { override fun update(e: AnActionEvent) { val project = e.project ?: return val facet = project.firstMicroPythonFacet if (facet != null) { e.presentation.isEnabledAndVisible = facet.checkValid() == ValidationResult.OK } else { e.presentation.isEnabledAndVisible = false } } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/actions/MicroPythonCommandAction.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.actions import com.intellij.openapi.actionSystem.AnActionEvent import com.jetbrains.micropython.settings.MicroPythonFacet import com.jetbrains.micropython.settings.firstMicroPythonFacet import org.jetbrains.plugins.terminal.LocalTerminalDirectRunner import org.jetbrains.plugins.terminal.TerminalToolWindowManager /** * @author vlan */ abstract class MicroPythonCommandAction : MicroPythonAction() { override fun actionPerformed(e: AnActionEvent) { val project = e.project ?: return val facet = project.firstMicroPythonFacet ?: return val command = getCommand(facet) ?: return TerminalToolWindowManager.getInstance(project).createNewSession(object : LocalTerminalDirectRunner(project) { override fun getInitialCommand(envs: Map): List = command }) } protected abstract fun getCommand(facet: MicroPythonFacet): List? } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/actions/RemoveAllFilesFromDeviceAction.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.actions import com.intellij.openapi.actionSystem.ActionUpdateThread import com.jetbrains.micropython.settings.MicroPythonFacet /** * @author vlan */ class RemoveAllFilesFromDeviceAction : MicroPythonCommandAction() { override fun getCommand(facet: MicroPythonFacet): List? { val pythonPath = facet.pythonPath ?: return null val devicePath = facet.getOrDetectDevicePathSynchronously() ?: return null return listOf(pythonPath, "${MicroPythonFacet.scriptsPath}/microcleanfs.py", devicePath) } override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/actions/RunMicroReplAction.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.actions import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.components.service import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleUtil import com.intellij.openapi.vfs.VirtualFile import com.jetbrains.micropython.repl.MicroPythonReplManager import com.jetbrains.micropython.settings.firstMicroPythonFacet class RunMicroReplAction : MicroPythonAction() { override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT override fun actionPerformed(e: AnActionEvent) { val project = e.project ?: return val editor = FileEditorManagerEx.getInstanceEx(project).selectedTextEditor ?: return /* Here we make our best to find out module which is relevant to the current event. There are two cases to consider: 1) There is an open file present. 2) No files are opened. */ val virtualFile: VirtualFile? = FileDocumentManager.getInstance().getFile(editor.document) val module: Module? = if (virtualFile != null) { ModuleUtil.findModuleForFile(virtualFile, project) } else { project.firstMicroPythonFacet?.module } project.service().startOrRestartRepl() } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/devices/Esp8266DeviceProvider.kt ================================================ package com.jetbrains.micropython.devices import com.intellij.execution.configurations.CommandLineState import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.execution.process.OSProcessHandler import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.openapi.projectRoots.Sdk import com.jetbrains.micropython.run.MicroPythonRunConfiguration import com.jetbrains.micropython.run.getMicroUploadCommand import com.jetbrains.micropython.settings.MicroPythonTypeHints import com.jetbrains.micropython.settings.MicroPythonUsbId import com.jetbrains.python.packaging.PyPackageManager import com.jetbrains.python.packaging.PyRequirement /** * @author vlan */ class Esp8266DeviceProvider : MicroPythonDeviceProvider { override val persistentName: String get() = "ESP8266" override val documentationURL: String get() = "https://github.com/JetBrains/intellij-micropython/wiki/ESP8266" override fun checkUsbId(usbId: MicroPythonUsbId): Boolean = usbIds.contains(usbId) val usbIds: List get() = listOf( MicroPythonUsbId(0x1A86, 0x7523), MicroPythonUsbId(0x10C4, 0xEA60), MicroPythonUsbId(0x0403, 0x6001), MicroPythonUsbId(0x239A, 0x8038), // Metro M4 Airlift Lite ) override val typeHints: MicroPythonTypeHints by lazy { MicroPythonTypeHints(listOf("stdlib", "micropython", "esp8266")) } override fun getPackageRequirements(sdk: Sdk): List { val manager = PyPackageManager.getInstance(sdk) return manager.parseRequirements("""|pyserial>=3.5,<4.0 |docopt>=0.6.2,<0.7 |adafruit-ampy>=1.0.5,<1.1""".trimMargin()) } override fun getRunCommandLineState(configuration: MicroPythonRunConfiguration, environment: ExecutionEnvironment): CommandLineState? { val module = configuration.module ?: return null val command = getMicroUploadCommand(configuration.path, module) ?: return null return object : CommandLineState(environment) { override fun startProcess() = OSProcessHandler(GeneralCommandLine(command)) } } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/devices/MicroBitDeviceProvider.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.devices import com.intellij.execution.configurations.CommandLineState import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.execution.process.OSProcessHandler import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.openapi.projectRoots.Sdk import com.jetbrains.micropython.run.MicroPythonRunConfiguration import com.jetbrains.micropython.settings.MicroPythonTypeHints import com.jetbrains.micropython.settings.MicroPythonUsbId import com.jetbrains.micropython.settings.microPythonFacet import com.jetbrains.python.packaging.PyPackageManager import com.jetbrains.python.packaging.PyRequirement /** * @author vlan */ open class MicroBitDeviceProvider : MicroPythonDeviceProvider { override val persistentName: String get() = "Micro:bit" override val documentationURL: String get() = "https://github.com/JetBrains/intellij-micropython/wiki/BBC-Micro:bit" override fun checkUsbId(usbId: MicroPythonUsbId): Boolean = usbId == MicroPythonUsbId(0x0D28, 0x0204) override fun getPackageRequirements(sdk: Sdk): List { val manager = PyPackageManager.getInstance(sdk) return manager.parseRequirements("""|uflash>=1.2.4,<1.3 |docopt>=0.6.2,<0.7 |pyserial>=3.5,<4.0""".trimMargin()) } override val typeHints: MicroPythonTypeHints by lazy { MicroPythonTypeHints(listOf("microbit")) } override val detectedModuleNames: Set get() = linkedSetOf("microbit") override fun getRunCommandLineState(configuration: MicroPythonRunConfiguration, environment: ExecutionEnvironment): CommandLineState? { val pythonPath = configuration.module?.microPythonFacet?.pythonPath ?: return null return object : CommandLineState(environment) { override fun startProcess() = OSProcessHandler(GeneralCommandLine(pythonPath, "-m", "uflash", configuration.path)) } } override val isDefault: Boolean get() = true } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/devices/MicroBitV2DeviceProvider.kt ================================================ package com.jetbrains.micropython.devices import com.intellij.openapi.projectRoots.Sdk import com.jetbrains.python.packaging.PyPackageManager import com.jetbrains.python.packaging.PyRequirement class MicroBitV2DeviceProvider : MicroBitDeviceProvider() { override val persistentName: String get() = "Micro:bit V2" override fun getPackageRequirements(sdk: Sdk): List { val manager = PyPackageManager.getInstance(sdk) return manager.parseRequirements("""|uflash>=2.0 |docopt>=0.6.2,<0.7 |pyserial>=3.5,<4.0""".trimMargin()) } override val isDefault: Boolean get() = false } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/devices/MicroPythonDeviceProvider.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.devices import com.intellij.execution.configurations.CommandLineState import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.openapi.extensions.ExtensionPointName import com.intellij.openapi.projectRoots.Sdk import com.jetbrains.micropython.run.MicroPythonRunConfiguration import com.jetbrains.micropython.settings.MicroPythonTypeHints import com.jetbrains.micropython.settings.MicroPythonUsbId import com.jetbrains.python.packaging.PyRequirement /** * @author vlan */ interface MicroPythonDeviceProvider { companion object { private val EP_NAME: ExtensionPointName = ExtensionPointName.create("com.jetbrains.micropython.deviceProvider") val providers: List get() = EP_NAME.extensionList val default: MicroPythonDeviceProvider get() = providers.first { it.isDefault } } val persistentName: String val documentationURL: String fun checkUsbId(usbId: MicroPythonUsbId): Boolean val presentableName: String get() = persistentName fun getPackageRequirements(sdk: Sdk): List = emptyList() val typeHints: MicroPythonTypeHints? get() = null val detectedModuleNames: Set get() = emptySet() fun getRunCommandLineState(configuration: MicroPythonRunConfiguration, environment: ExecutionEnvironment): CommandLineState? = null val isDefault: Boolean get() = false } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/devices/PyboardDeviceProvider.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.devices import com.intellij.execution.configurations.CommandLineState import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.execution.process.OSProcessHandler import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.openapi.projectRoots.Sdk import com.jetbrains.micropython.run.MicroPythonRunConfiguration import com.jetbrains.micropython.run.getMicroUploadCommand import com.jetbrains.micropython.settings.MicroPythonTypeHints import com.jetbrains.micropython.settings.MicroPythonUsbId import com.jetbrains.python.packaging.PyPackageManager import com.jetbrains.python.packaging.PyRequirement /** * @author stefanhoelzl */ class PyboardDeviceProvider : MicroPythonDeviceProvider { override val persistentName: String get() = "Pyboard" override val documentationURL: String get() = "https://github.com/JetBrains/intellij-micropython/wiki/Pyboard" override fun checkUsbId(usbId: MicroPythonUsbId): Boolean = usbId == MicroPythonUsbId(0xF055, 0x9800) override val typeHints: MicroPythonTypeHints by lazy { MicroPythonTypeHints(listOf("stdlib", "micropython", "pyboard")) } override fun getPackageRequirements(sdk: Sdk): List { val manager = PyPackageManager.getInstance(sdk) return manager.parseRequirements("""|pyserial>=3.5,<4.0 |docopt>=0.6.2,<0.7 |adafruit-ampy>=1.0.5,<1.1""".trimMargin()) } override fun getRunCommandLineState(configuration: MicroPythonRunConfiguration, environment: ExecutionEnvironment): CommandLineState? { val module = configuration.module ?: return null val command = getMicroUploadCommand(configuration.path, module) ?: return null return object : CommandLineState(environment) { override fun startProcess() = OSProcessHandler(GeneralCommandLine(command)) } } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/devices/RPiPicoDeviceProvider.kt ================================================ package com.jetbrains.micropython.devices import com.intellij.execution.configurations.CommandLineState import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.execution.process.OSProcessHandler import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.openapi.projectRoots.Sdk import com.jetbrains.micropython.run.MicroPythonRunConfiguration import com.jetbrains.micropython.run.getMicroUploadCommand import com.jetbrains.micropython.settings.MicroPythonTypeHints import com.jetbrains.micropython.settings.MicroPythonUsbId import com.jetbrains.python.packaging.PyPackageManager import com.jetbrains.python.packaging.PyRequirement /** * @author timsavage */ class RPiPicoDeviceProvider : MicroPythonDeviceProvider { override val persistentName: String get() = "Raspberry Pi Pico" override val documentationURL: String get() = "https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html" /** * From https://github.com/raspberrypi/usb-pid : * * "The USB-IF have given Raspberry Pi permission to sub-license the USB product ID values for its vendor ID (0x2E8A) * since they are to be used on a common silicon component which will be used within a customer's product (the RP2040 * silicon)." * * Consequently, most usb devices with the vendor id 0x2E8A are likely to be an RP2040, and therefore capable of * running MicroPython. */ override fun checkUsbId(usbId: MicroPythonUsbId): Boolean = usbId.vendorId == 0x2E8A && ProductId.likelyToRunMicroPython(usbId.productId) object ProductId { private const val PICO_WITH_STANDARD_MICROPYTHON_FIRMWARE = 0x05 /** * Raspberry Pi have allocated the productId range 0x1000 - 0x1fff for Commercial RP2040 devices. * See https://github.com/raspberrypi/usb-pid#assignment */ private val COMMERCIAL_RANGE = 0x1000..0x1fff fun likelyToRunMicroPython(productId: Int): Boolean = productId == PICO_WITH_STANDARD_MICROPYTHON_FIRMWARE || productId in COMMERCIAL_RANGE } override val typeHints: MicroPythonTypeHints by lazy { MicroPythonTypeHints(listOf("stdlib", "micropython", "rpi_pico")) } override fun getPackageRequirements(sdk: Sdk): List { val manager = PyPackageManager.getInstance(sdk) return manager.parseRequirements("""|pyserial>=3.5,<4.0 |docopt>=0.6.2,<0.7 |adafruit-ampy>=1.0.5,<1.1""".trimMargin()) } override fun getRunCommandLineState(configuration: MicroPythonRunConfiguration, environment: ExecutionEnvironment): CommandLineState? { val module = configuration.module ?: return null val command = getMicroUploadCommand(configuration.path, module) ?: return null return object : CommandLineState(environment) { override fun startProcess() = OSProcessHandler(GeneralCommandLine(command)) } } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/inspections/MicroPythonRequirementsInspection.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.inspections import com.intellij.codeInspection.* import com.intellij.facet.ui.FacetConfigurationQuickFix import com.intellij.openapi.module.ModuleUtilCore import com.intellij.openapi.project.Project import com.intellij.psi.PsiFile import com.jetbrains.micropython.settings.microPythonFacet /** * @author vlan */ class MicroPythonRequirementsInspection : LocalInspectionTool() { override fun checkFile(file: PsiFile, manager: InspectionManager, isOnTheFly: Boolean): Array? { val module = ModuleUtilCore.findModuleForPsiElement(file) ?: return null val facet = module.microPythonFacet ?: return null val result = facet.checkValid() if (result.isOk) return null val facetFix: FacetConfigurationQuickFix? = result.quickFix val fix = if (facetFix != null) object : LocalQuickFix { override fun getFamilyName() = "Missing required MicroPython packages" override fun applyFix(project: Project, descriptor: ProblemDescriptor) { facetFix.run(null) } } else null val fixes = if (fix != null) arrayOf(fix) else emptyArray() return arrayOf(manager.createProblemDescriptor(file, result.errorMessage, true, fixes, ProblemHighlightType.GENERIC_ERROR_OR_WARNING)) } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/repl/MicroPythonReplManager.kt ================================================ package com.jetbrains.micropython.repl import com.intellij.openapi.components.Service import com.intellij.openapi.project.Project import com.intellij.util.messages.Topic interface MicroPythonReplControl { fun stopRepl() fun startOrRestartRepl(interrupt: Boolean = true) } @Service(Service.Level.PROJECT) class MicroPythonReplManager(private val project: Project) : MicroPythonReplControl { override fun stopRepl() = project.messageBus.syncPublisher(MICROPYTHON_REPL_CONTROL).stopRepl() override fun startOrRestartRepl(interrupt: Boolean) = project.messageBus.syncPublisher(MICROPYTHON_REPL_CONTROL).startOrRestartRepl(interrupt) } val MICROPYTHON_REPL_CONTROL = Topic(MicroPythonReplControl::class.java) ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/repl/StopReplBeforeRunTask.kt ================================================ package com.jetbrains.micropython.repl import com.intellij.execution.BeforeRunTask import com.intellij.execution.BeforeRunTaskProvider import com.intellij.execution.configurations.RunConfiguration import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.service import com.intellij.openapi.util.Key import com.jetbrains.micropython.run.MicroPythonRunConfiguration import com.jetbrains.micropython.settings.MicroPythonFacetType class StopReplBeforeRunTask : BeforeRunTask(StopReplBeforeRunTaskProvider.ID) { init { isEnabled = true } } class StopReplBeforeRunTaskProvider : BeforeRunTaskProvider() { companion object { val ID = Key.create("MicroPython.StopREPL.Before.Run") } override fun getId() = ID override fun getIcon() = MicroPythonFacetType.LOGO override fun getName() = "Stop MicroPython REPL" override fun createTask(runConfiguration: RunConfiguration): StopReplBeforeRunTask? { if (runConfiguration is MicroPythonRunConfiguration) { return StopReplBeforeRunTask() } return null } override fun executeTask( context: DataContext, configuration: RunConfiguration, environment: ExecutionEnvironment, task: StopReplBeforeRunTask ): Boolean { if (configuration is MicroPythonRunConfiguration) { environment.project.service().stopRepl() } return true } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/repl/ToolWindowReplTab.kt ================================================ package com.jetbrains.micropython.repl import com.intellij.icons.AllIcons import com.intellij.ide.ActivityTracker import com.intellij.openapi.Disposable import com.intellij.openapi.actionSystem.* import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ModalityState import com.intellij.openapi.components.service import com.intellij.openapi.module.Module import com.intellij.openapi.project.DumbAwareAction import com.intellij.openapi.util.NlsContexts import com.intellij.util.application import com.jediterm.terminal.TtyConnector import com.jetbrains.micropython.settings.MicroPythonDevicesConfiguration import com.jetbrains.micropython.settings.MicroPythonFacet import com.jetbrains.micropython.settings.microPythonFacet import org.jetbrains.plugins.terminal.JBTerminalSystemSettingsProvider import org.jetbrains.plugins.terminal.LocalTerminalDirectRunner import org.jetbrains.plugins.terminal.ShellStartupOptions import org.jetbrains.plugins.terminal.ShellTerminalWidget import java.awt.BorderLayout import java.util.concurrent.TimeUnit import javax.swing.JPanel class ToolWindowReplTab(val module: Module, parent: Disposable) : MicroPythonReplControl { private val deviceConfiguration = MicroPythonDevicesConfiguration.getInstance(module.project) val terminalWidget: ShellTerminalWidget init { val mySettingsProvider = JBTerminalSystemSettingsProvider() terminalWidget = ShellTerminalWidget(module.project, mySettingsProvider, parent) terminalWidget.isEnabled = false module.project.messageBus.connect(parent).subscribe(MICROPYTHON_REPL_CONTROL, this) } private fun connectWidgetTty(terminalWidget: ShellTerminalWidget, connector: TtyConnector) { terminalWidget.start(connector) val modalityState = ModalityState.stateForComponent(terminalWidget.component) ApplicationManager.getApplication().invokeLater( { try { terminalWidget.component.revalidate() terminalWidget.notifyStarted() } catch (e: RuntimeException) { TODO("You can't cut back on error reporting! You will regret this!") } }, modalityState ) } fun createUI(): JPanel { val actionManager = ActionManager.getInstance() val toolbarActions = DefaultActionGroup().apply { add(replStartAction) add(replStopAction) add(clearReplOnLaunch) } val actionToolbar = actionManager.createActionToolbar("MicroPythonREPL", toolbarActions, false) actionToolbar.targetComponent = terminalWidget.component return JPanel().apply { layout = BorderLayout() add(actionToolbar.component, BorderLayout.WEST) add(terminalWidget.component) } } private val replStopAction = object : DumbAwareAction( "Stop", "Stop REPL session", AllIcons.Actions.Suspend ) { override fun update(e: AnActionEvent) { e.presentation.isEnabled = terminalWidget.isSessionRunning } override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT override fun actionPerformed(e: AnActionEvent) { stopRepl() } } private val replStartAction = object : DumbAwareAction("Restart", "Restart REPL session", AllIcons.Actions.Restart) { override fun update(e: AnActionEvent) { e.presentation.isEnabled = true } override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT override fun actionPerformed(e: AnActionEvent) = module.project.service().startOrRestartRepl() } private val clearReplOnLaunch = object : ToggleAction( "Clear Window On Start", "Clear REPL window on every start", AllIcons.Actions.GC ) { override fun isSelected(e: AnActionEvent): Boolean { return deviceConfiguration.clearReplOnLaunch } override fun setSelected(e: AnActionEvent, state: Boolean) { deviceConfiguration.clearReplOnLaunch = state } override fun getActionUpdateThread(): ActionUpdateThread { return ActionUpdateThread.EDT } } private fun onProcessCreationFailed(@NlsContexts.SystemNotificationText reason: String) { terminalWidget.terminal.nextLine() terminalWidget.terminal.writeCharacters(reason) } private fun interruptBanner() { application.invokeLater( { with(terminalWidget.terminal) { nextLine() writeCharacters("=== SESSION HAS BEEN INTERRUPTED ===") nextLine() } }, { module.isDisposed } ) } override fun stopRepl() { interruptBanner() application.executeOnPooledThread { synchronized(this) { terminalWidget.processTtyConnector?.process?.destroy() } } } override fun startOrRestartRepl(interrupt: Boolean) { interruptBanner() application.executeOnPooledThread { synchronized(this) { terminalWidget.processTtyConnector?.process?.apply { if (isAlive) destroy() waitFor(10, TimeUnit.SECONDS) } } application.invokeLater( { startRepl(interrupt) }, { module.project.isDisposed }) } } private fun startRepl(interrupt: Boolean) { val facet = module.microPythonFacet ?: return val devicePath = facet.getOrDetectDevicePathSynchronously() if (facet.pythonPath == null) { onProcessCreationFailed("Valid Python interpreter is needed to start REPL!") return } if (devicePath == null) { onProcessCreationFailed("Device path is not specified, please check settings.") return } val initialShellCommand = mutableListOf( facet.pythonPath!!, "${MicroPythonFacet.scriptsPath}/microrepl.py", devicePath ).apply { if(!interrupt) add("--nointerrupt") } val terminalRunner = LocalTerminalDirectRunner(module.project) synchronized(this) { val terminalOptions = terminalRunner.configureStartupOptions( ShellStartupOptions.Builder() .shellCommand(initialShellCommand) .build() ) val process = terminalRunner.createProcess(terminalOptions) val ttyConnector = terminalRunner.createTtyConnector(process) process.onExit().whenComplete { _, _ -> ActivityTracker.getInstance().inc() } if (deviceConfiguration.clearReplOnLaunch) { terminalWidget.terminalTextBuffer.clearHistory() terminalWidget.terminal.reset(true) } else { terminalWidget.terminal.nextLine() } connectWidgetTty(terminalWidget, ttyConnector) terminalWidget.isEnabled = true } } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/run/MicroPythonConfigurationType.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.run import com.intellij.execution.configurations.ConfigurationFactory import com.intellij.execution.configurations.ConfigurationType import com.intellij.execution.configurations.ConfigurationTypeUtil import com.intellij.execution.configurations.RunConfiguration import com.intellij.openapi.project.Project import com.jetbrains.micropython.settings.MicroPythonFacetType import com.jetbrains.python.run.PythonConfigurationFactoryBase import javax.swing.Icon /** * @author Mikhail Golubev */ class MicroPythonConfigurationType : ConfigurationType { companion object { fun getInstance(): MicroPythonConfigurationType = ConfigurationTypeUtil.findConfigurationType(MicroPythonConfigurationType::class.java) } internal val factory = object : PythonConfigurationFactoryBase(this) { override fun createTemplateConfiguration(project: Project): RunConfiguration = MicroPythonRunConfiguration(project, this) override fun getId(): String = "MicroPython" } override fun getIcon(): Icon = MicroPythonFacetType.LOGO override fun getConfigurationTypeDescription(): String = "MicroPython run configuration" override fun getId(): String = "MicroPythonConfigurationType" override fun getDisplayName(): String = "MicroPython" override fun getConfigurationFactories(): Array = arrayOf(factory) } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/run/MicroPythonRunConfiguration.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.run import com.intellij.execution.ExecutionResult import com.intellij.execution.Executor import com.intellij.execution.configuration.AbstractRunConfiguration import com.intellij.execution.configurations.ConfigurationFactory import com.intellij.execution.configurations.RunConfigurationWithSuppressedDefaultDebugAction import com.intellij.execution.configurations.RunProfileState import com.intellij.execution.configurations.RuntimeConfigurationError import com.intellij.execution.process.ProcessEvent import com.intellij.execution.process.ProcessListener import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.execution.runners.ProgramRunner import com.intellij.facet.ui.ValidationResult import com.intellij.openapi.actionSystem.LangDataKeys import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.service import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleUtil import com.intellij.openapi.options.ShowSettingsUtil import com.intellij.openapi.project.Project import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService import com.intellij.openapi.util.Key import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.wm.ToolWindowManager import com.intellij.util.PathUtil import com.intellij.util.PlatformUtils import com.jetbrains.micropython.repl.MicroPythonReplManager import com.jetbrains.micropython.settings.MicroPythonProjectConfigurable import com.jetbrains.micropython.settings.microPythonFacet import org.jdom.Element /** * @author Mikhail Golubev */ class RunStateWrapper(private val original: RunProfileState, val block: () -> Unit) : RunProfileState by original { override fun execute(executor: Executor?, runner: ProgramRunner<*>): ExecutionResult? { val result = original.execute(executor, runner) result?.processHandler?.addProcessListener(object : ProcessListener { override fun startNotified(event: ProcessEvent) {} override fun processTerminated(event: ProcessEvent) { if (event.exitCode == 0) { block() } } override fun onTextAvailable(event: ProcessEvent, outputType: Key<*>) {} }) return result } } class MicroPythonRunConfiguration(project: Project, factory: ConfigurationFactory) : AbstractRunConfiguration(project, factory), RunConfigurationWithSuppressedDefaultDebugAction { var path: String = "" var runReplOnSuccess: Boolean = false override fun getValidModules() = allModules.filter { it.microPythonFacet != null }.toMutableList() override fun getConfigurationEditor() = MicroPythonRunConfigurationEditor(this) override fun getState(executor: Executor, environment: ExecutionEnvironment): RunProfileState? { val currentModule = environment.dataContext?.getData(LangDataKeys.MODULE) ?: module val state = currentModule?.microPythonFacet?.configuration?.deviceProvider?.getRunCommandLineState(this, environment) // ComponentManagerImpl if (runReplOnSuccess && state != null) { return RunStateWrapper(state) { ApplicationManager.getApplication().invokeLater { project.service().startOrRestartRepl(false) ToolWindowManager.getInstance(project).getToolWindow("MicroPython")?.show() } } } return state } override fun checkConfiguration() { super.checkConfiguration() if (StringUtil.isEmpty(path)) { throw RuntimeConfigurationError("Path is not specified") } val m = module ?: throw RuntimeConfigurationError("Module for path is not found") val showSettings = Runnable { when { PlatformUtils.isPyCharm() -> ShowSettingsUtil.getInstance().showSettingsDialog(project, MicroPythonProjectConfigurable::class.java) PlatformUtils.isIntelliJ() -> ProjectSettingsService.getInstance(project).openModuleSettings(module) else -> ShowSettingsUtil.getInstance().showSettingsDialog(project) } } val facet = m.microPythonFacet ?: throw RuntimeConfigurationError( "MicroPython support is not enabled for selected module in IDE settings", showSettings ) val validationResult = facet.checkValid() if (validationResult != ValidationResult.OK) { val runQuickFix = Runnable { validationResult.quickFix.run(null) } throw RuntimeConfigurationError(validationResult.errorMessage, runQuickFix) } facet.pythonPath ?: throw RuntimeConfigurationError("Python interpreter is not found") if (!facet.autoDetectDevicePath && facet.devicePath == null) { throw RuntimeConfigurationError("Device path is not specified in IDE settings", showSettings) } } override fun suggestedName() = "Flash ${PathUtil.getFileName(path)}" override fun writeExternal(element: Element) { super.writeExternal(element) element.setAttribute("path", path) element.setAttribute("runReplOnSuccess", if (runReplOnSuccess) "yes" else "no") } override fun readExternal(element: Element) { super.readExternal(element) configurationModule.readExternal(element) element.getAttributeValue("path")?.let { path = it } element.getAttributeValue("runReplOnSuccess")?.let { runReplOnSuccess = it == "yes" } } val module: Module? get() { val file = StandardFileSystems.local().findFileByPath(path) ?: return null return ModuleUtil.findModuleForFile(file, project) } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/run/MicroPythonRunConfigurationEditor.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.run import com.intellij.openapi.fileChooser.FileChooserDescriptor import com.intellij.openapi.options.SettingsEditor import com.intellij.openapi.ui.ComponentWithBrowseButton import com.intellij.openapi.ui.TextComponentAccessor import com.intellij.openapi.ui.TextFieldWithBrowseButton import com.intellij.ui.components.CheckBox import com.intellij.util.ui.FormBuilder import javax.swing.JComponent class MicroPythonRunConfigurationEditor(config: MicroPythonRunConfiguration) : SettingsEditor() { private val pathField = TextFieldWithBrowseButton() private val runReplOnSuccess = CheckBox("Open MicroPython REPL on success", selected = true) init { val descriptor = FileChooserDescriptor(true, true, false, false, false, false) val listener = ComponentWithBrowseButton.BrowseFolderActionListener( "Select Path", "", pathField, config.project, descriptor, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT ) pathField.addActionListener(listener) } override fun createEditor(): JComponent = FormBuilder.createFormBuilder() .addLabeledComponent("Path:", pathField) .addComponent(runReplOnSuccess) .panel override fun applyEditorTo(s: MicroPythonRunConfiguration) { s.path = pathField.text s.runReplOnSuccess = runReplOnSuccess.isSelected } override fun resetEditorFrom(s: MicroPythonRunConfiguration) { pathField.text = s.path runReplOnSuccess.isSelected = s.runReplOnSuccess } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/run/MicroPythonRunConfigurationProducer.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.run import com.intellij.execution.actions.ConfigurationContext import com.intellij.execution.actions.ConfigurationFromContext import com.intellij.execution.actions.LazyRunConfigurationProducer import com.intellij.execution.configurations.ConfigurationFactory import com.intellij.facet.FacetManager import com.intellij.openapi.module.ModuleUtilCore import com.intellij.openapi.project.Project import com.intellij.openapi.util.Ref import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiElement import com.intellij.testFramework.LightVirtualFile import com.jetbrains.micropython.settings.MicroPythonFacetType import com.jetbrains.python.run.AbstractPythonRunConfiguration /** * @author Mikhail Golubev */ class MicroPythonRunConfigurationProducer : LazyRunConfigurationProducer() { override fun getConfigurationFactory(): ConfigurationFactory { return MicroPythonConfigurationType.getInstance().factory } override fun isConfigurationFromContext(configuration: MicroPythonRunConfiguration, context: ConfigurationContext): Boolean { val file = context.location?.virtualFile ?: return false if (!facetEnabledForElement(file, context.project)) return false if (file is LightVirtualFile) return false return configuration.path == file.path } override fun setupConfigurationFromContext(configuration: MicroPythonRunConfiguration, context: ConfigurationContext, sourceElement: Ref): Boolean { val file = context.location?.virtualFile ?: return false if (!facetEnabledForElement(file, context.project)) return false configuration.path = file.path configuration.setGeneratedName() configuration.setModule(ModuleUtilCore.findModuleForFile(file, context.project)) return true } private fun facetEnabledForElement(virtualFile: VirtualFile, project: Project): Boolean { val module = ModuleUtilCore.findModuleForFile(virtualFile, project) ?: return false return FacetManager.getInstance(module)?.getFacetByType(MicroPythonFacetType.ID) != null } override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext) = other.configuration is AbstractPythonRunConfiguration<*> } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/run/MicroUpload.kt ================================================ package com.jetbrains.micropython.run import com.intellij.openapi.module.Module import com.intellij.openapi.project.guessModuleDir import com.intellij.openapi.project.rootManager import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.openapi.vfs.VirtualFile import com.jetbrains.micropython.settings.MicroPythonFacet import com.jetbrains.micropython.settings.microPythonFacet fun getMicroUploadCommand(path: String, module: Module): List? { val facet = module.microPythonFacet ?: return null val pythonPath = facet.pythonPath ?: return null val devicePath = facet.getOrDetectDevicePathSynchronously() ?: return null val file = StandardFileSystems.local().findFileByPath(path) ?: return null val rootDir = getClosestRoot(file, module) ?: return null val excludeRoots = ModuleRootManager.getInstance(module).excludeRoots val excludes = excludeRoots .asSequence() .filter { VfsUtil.isAncestor(file, it, false) } .map { VfsUtilCore.getRelativePath(it, rootDir) } .filterNotNull() .map { listOf("-X", it) } .flatten() .toList() return listOf(pythonPath, "${MicroPythonFacet.scriptsPath}/microupload.py", "-C", rootDir.path) + excludes + listOf("-v", devicePath, path) } private fun getClosestRoot(file: VirtualFile, module: Module): VirtualFile? { val roots = mutableSetOf().apply { val rootManager = module.rootManager addAll(rootManager.contentRoots) addAll(rootManager.sourceRoots) } var parent: VirtualFile? = file while (parent != null) { if (parent in roots) { break } parent = parent.parent } return parent ?: module.guessModuleDir() } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/settings/MicroPythonDevicesConfiguration.kt ================================================ package com.jetbrains.micropython.settings import com.intellij.openapi.components.PersistentStateComponent import com.intellij.openapi.components.State import com.intellij.openapi.components.Storage import com.intellij.openapi.components.StoragePathMacros import com.intellij.openapi.project.Project import com.intellij.util.xmlb.XmlSerializerUtil import com.intellij.util.xmlb.annotations.Attribute /** * @author vlan */ @State(name = "MicroPythonDevices", storages = [Storage(StoragePathMacros.WORKSPACE_FILE)]) class MicroPythonDevicesConfiguration : PersistentStateComponent { companion object { fun getInstance(project: Project): MicroPythonDevicesConfiguration = project.getService(MicroPythonDevicesConfiguration::class.java) } // Currently, the device path is stored per project, not per module @Attribute var devicePath: String = "" @Attribute var autoDetectDevicePath: Boolean = true @Attribute var clearReplOnLaunch: Boolean = true override fun getState() = this override fun loadState(state: MicroPythonDevicesConfiguration) { XmlSerializerUtil.copyBean(state, this) } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/settings/MicroPythonFacet.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.settings import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.execution.process.CapturingProcessHandler import com.intellij.facet.Facet import com.intellij.facet.FacetManager import com.intellij.facet.FacetType import com.intellij.facet.ui.FacetConfigurationQuickFix import com.intellij.facet.ui.ValidationResult import com.intellij.ide.plugins.IdeaPluginDescriptor import com.intellij.ide.plugins.PluginManagerCore import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.extensions.PluginId import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.Project import com.intellij.openapi.ui.Messages import com.intellij.util.text.nullize import com.jetbrains.micropython.devices.MicroPythonDeviceProvider import com.jetbrains.python.facet.FacetLibraryConfigurator import com.jetbrains.python.facet.LibraryContributingFacet import com.jetbrains.python.packaging.PyPackageManager import com.jetbrains.python.packaging.PyPackageManagerUI import com.jetbrains.python.psi.LanguageLevel import com.jetbrains.python.sdk.PySdkUtil import com.jetbrains.python.sdk.PythonSdkUtil import javax.swing.JComponent /** * @author vlan */ class MicroPythonFacet(facetType: FacetType, *>, module: Module, name: String, configuration: MicroPythonFacetConfiguration, underlyingFacet: Facet<*>?) : LibraryContributingFacet(facetType, module, name, configuration, underlyingFacet) { companion object { private const val PLUGIN_ID = "intellij-micropython" val scriptsPath: String get() = "${pluginDescriptor.pluginPath}/scripts" private val pluginDescriptor: IdeaPluginDescriptor get() = PluginManagerCore.getPlugin(PluginId.getId(PLUGIN_ID)) ?: throw RuntimeException("The $PLUGIN_ID plugin cannot find itself") } override fun initFacet() { updateLibrary() } override fun updateLibrary() { val plugin = pluginDescriptor val boardHintsPaths = configuration.deviceProvider.typeHints?.paths?.map { "${plugin.pluginPath}/typehints/$it" } ?: emptyList() ApplicationManager.getApplication().invokeLater { FacetLibraryConfigurator.attachPythonLibrary(module, null, "MicroPython", boardHintsPaths) removeLegacyLibraries() } } override fun removeLibrary() { FacetLibraryConfigurator.detachPythonLibrary(module, "MicroPython") } fun checkValid(): ValidationResult { val provider = configuration.deviceProvider val sdk = PythonSdkUtil.findPythonSdk(module) if (sdk == null || PythonSdkUtil.isInvalid(sdk) || PySdkUtil.getLanguageLevelForSdk(sdk).isOlderThan(LanguageLevel.PYTHON35)) { return ValidationResult("${provider.presentableName} support requires valid Python 3.5+ SDK") } val packageManager = PyPackageManager.getInstance(sdk) val packages = packageManager.packages ?: return ValidationResult.OK val requirements = provider.getPackageRequirements(sdk).filter { it.match(packages) == null }.toList() if (requirements.isNotEmpty()) { val requirementsText = requirements.joinToString(", ") { it.presentableText } return ValidationResult("Packages required for ${provider.presentableName} support not found: $requirementsText", object : FacetConfigurationQuickFix("Install Requirements") { override fun run(place: JComponent?) { PyPackageManagerUI(module.project, sdk, null).install(requirements, emptyList()) } }) } return ValidationResult.OK } private fun findSerialPorts(deviceProvider: MicroPythonDeviceProvider, indicator: ProgressIndicator): List { val timeout = 1_000 val pythonPath = pythonPath ?: return emptyList() val command = listOf(pythonPath, "$scriptsPath/findusb.py") val process = CapturingProcessHandler(GeneralCommandLine(command)) val output = process.runProcessWithProgressIndicator(indicator, timeout) return when { output.isCancelled -> emptyList() output.isTimeout -> emptyList() output.exitCode != 0 -> emptyList() else -> { output.stdoutLines.associate { Pair(MicroPythonUsbId.parse(it.substringBefore(' ')), it.substringAfter(' ')) }.filterKeys { deviceProvider.checkUsbId(it) }.values.toList() } } } val pythonPath: String? get() = PythonSdkUtil.findPythonSdk(module)?.homePath var devicePath: String? get() = MicroPythonDevicesConfiguration.getInstance(module.project).devicePath.nullize(true) set(value) { MicroPythonDevicesConfiguration.getInstance(module.project).devicePath = value ?: "" } var autoDetectDevicePath: Boolean get() = MicroPythonDevicesConfiguration.getInstance(module.project).autoDetectDevicePath set(value) { MicroPythonDevicesConfiguration.getInstance(module.project).autoDetectDevicePath = value } fun getOrDetectDevicePathSynchronously(): String? = if (autoDetectDevicePath) detectDevicePathSynchronously(configuration.deviceProvider) else devicePath fun detectDevicePathSynchronously(deviceProvider: MicroPythonDeviceProvider): String? { ApplicationManager.getApplication().assertIsDispatchThread() var detectedDevicePath: String? = null val deviceProviderName = deviceProvider.presentableName val progress = ProgressManager.getInstance() progress.runProcessWithProgressSynchronously({ progress.progressIndicator.text = "Detecting connected $deviceProviderName devices..." val detected = findSerialPorts(deviceProvider, progress.progressIndicator).firstOrNull() ApplicationManager.getApplication().invokeLater { if (detected == null) { Messages.showErrorDialog(module.project, """Possible solutions: | |- Check if your device is connected to your computer |- Specify the device path manually in the IDE settings for MicroPython""".trimMargin(), "No $deviceProviderName Devices Detected") } detectedDevicePath = detected } }, "Detecting MicroPython devices", true, module.project, null) return detectedDevicePath } private fun removeLegacyLibraries() { FacetLibraryConfigurator.detachPythonLibrary(module, "Micro:bit") } } val Module.microPythonFacet: MicroPythonFacet? get() = FacetManager.getInstance(this).getFacetByType(MicroPythonFacetType.ID) val Project.firstMicroPythonFacet: MicroPythonFacet? get() = ModuleManager.getInstance(this).modules .asSequence() .map { it.microPythonFacet } .firstOrNull() ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/settings/MicroPythonFacetConfiguration.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.settings import com.intellij.facet.FacetConfiguration import com.intellij.facet.ui.FacetEditorContext import com.intellij.facet.ui.FacetEditorTab import com.intellij.facet.ui.FacetEditorValidator import com.intellij.facet.ui.FacetValidatorsManager import com.jetbrains.micropython.devices.MicroPythonDeviceProvider import org.jdom.Element /** * @author vlan */ class MicroPythonFacetConfiguration : FacetConfiguration { var deviceProvider = MicroPythonDeviceProvider.default override fun createEditorTabs(editorContext: FacetEditorContext, validatorsManager: FacetValidatorsManager): Array { val facet = editorContext.facet as MicroPythonFacet validatorsManager.registerValidator(object: FacetEditorValidator() { override fun check() = facet.checkValid() }) return arrayOf(MicroPythonFacetEditorTab(this, facet)) } @Deprecated("Deprecated in Java") override fun readExternal(element: Element?) { val deviceName = element?.getChild("device")?.getAttribute("name")?.value val device = MicroPythonDeviceProvider.providers.firstOrNull { it.persistentName == deviceName } deviceProvider = device ?: MicroPythonDeviceProvider.default } @Deprecated("Deprecated in Java") override fun writeExternal(element: Element?) { val deviceElement = Element("device") deviceElement.setAttribute("name", deviceProvider.persistentName) element?.addContent(deviceElement) } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/settings/MicroPythonFacetDetector.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.settings import com.intellij.framework.detection.FacetBasedFrameworkDetector import com.intellij.framework.detection.FileContentPattern import com.intellij.openapi.fileTypes.FileType import com.intellij.openapi.roots.ProjectRootManager import com.intellij.patterns.PatternCondition import com.intellij.util.ProcessingContext import com.intellij.util.indexing.FileContent import com.jetbrains.micropython.devices.MicroPythonDeviceProvider import com.jetbrains.python.PythonFileType import com.jetbrains.python.psi.PyFile import com.jetbrains.python.psi.PyFromImportStatement import com.jetbrains.python.psi.PyImportStatement /** * @author Mikhail Golubev */ class MicroPythonFacetDetector : FacetBasedFrameworkDetector("MicroPython") { override fun getFacetType() = MicroPythonFacetType.getInstance() override fun createSuitableFilePattern() = FileContentPattern.fileContent().with(object : PatternCondition("Contains MicroPython imports") { override fun accepts(fileContent: FileContent, context: ProcessingContext?): Boolean { val fileIndex = ProjectRootManager.getInstance(fileContent.project).fileIndex if (!fileIndex.isInContent(fileContent.file) || fileIndex.isInLibraryClasses(fileContent.file)) { return false } val detected = MicroPythonDeviceProvider.providers .asSequence() .flatMap { it.detectedModuleNames.asSequence() } .toSet() return when (val psiFile = fileContent.psiFile) { is PyFile -> { return psiFile.importBlock.any { imp -> when (imp) { is PyFromImportStatement -> imp.importSourceQName?.firstComponent in detected is PyImportStatement -> imp.importElements.any { it.importedQName?.firstComponent in detected } else -> false } } } else -> false } } }) override fun getFileType(): FileType = PythonFileType.INSTANCE } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/settings/MicroPythonFacetEditorTab.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.settings import com.intellij.facet.ui.FacetEditorTab import javax.swing.JComponent /** * @author vlan */ class MicroPythonFacetEditorTab(val configuration: MicroPythonFacetConfiguration, private val facet: MicroPythonFacet) : FacetEditorTab() { private val panel: MicroPythonSettingsPanel by lazy { MicroPythonSettingsPanel(facet.module) } override fun isModified(): Boolean = panel.isModified(configuration, facet) override fun getDisplayName(): String = panel.getDisplayName() override fun createComponent(): JComponent = panel override fun apply() { panel.apply(configuration, facet) facet.updateLibrary() } override fun reset() { panel.reset(configuration, facet) } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/settings/MicroPythonFacetType.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.settings import com.intellij.facet.Facet import com.intellij.facet.FacetType import com.intellij.facet.FacetTypeId import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleType import com.intellij.openapi.util.IconLoader import com.jetbrains.python.PythonModuleTypeBase import javax.swing.Icon /** * @author vlan */ class MicroPythonFacetType : FacetType(ID, STRING_ID, PRESENTABLE_NAME) { companion object { const val STRING_ID = "MicroPython" const val PRESENTABLE_NAME = "MicroPython" val ID = FacetTypeId(STRING_ID) val LOGO = IconLoader.getIcon("/icons/micropython.svg", MicroPythonFacetType::class.java) fun getInstance() = findInstance(MicroPythonFacetType::class.java)!! } override fun createDefaultConfiguration() = MicroPythonFacetConfiguration() override fun createFacet(module: Module, name: String, configuration: MicroPythonFacetConfiguration, underlyingFacet: Facet<*>?) = MicroPythonFacet(this, module, name, configuration, underlyingFacet) override fun isSuitableModuleType(moduleType: ModuleType<*>?) = moduleType is PythonModuleTypeBase override fun getIcon(): Icon = LOGO } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/settings/MicroPythonModuleConfigurable.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.settings import com.intellij.facet.FacetManager import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.module.Module import com.intellij.openapi.options.Configurable import com.intellij.util.ui.UIUtil import java.awt.BorderLayout import javax.swing.JCheckBox import javax.swing.JComponent import javax.swing.JPanel /** * @author vlan */ class MicroPythonModuleConfigurable(private val module: Module) : Configurable { private val panel: MicroPythonSettingsPanel by lazy { MicroPythonSettingsPanel(module) } private val enabledCheckbox by lazy { val checkBox = JCheckBox("Enable MicroPython support") checkBox.addActionListener { update() } checkBox } override fun isModified(): Boolean { val facet = module.microPythonFacet val enabled = facet != null if (enabledCheckbox.isSelected != enabled) return true val c = facet?.configuration ?: return false return panel.isModified(c, facet) } override fun getDisplayName() = "MicroPython" override fun apply() { val facet = module.microPythonFacet val application = ApplicationManager.getApplication() val facetManager = FacetManager.getInstance(module) if (enabledCheckbox.isSelected) { if (facet != null) { panel.apply(facet.configuration, facet) FacetManager.getInstance(module).facetConfigurationChanged(facet) facet.updateLibrary() } else { val facetType = MicroPythonFacetType.getInstance() val newFacet = facetManager.createFacet(facetType, facetType.defaultFacetName, null) panel.apply(newFacet.configuration, newFacet) val facetModel = facetManager.createModifiableModel() facetModel.addFacet(newFacet) application.runWriteAction { facetModel.commit() } } } else if (facet != null) { val facetModel = facetManager.createModifiableModel() facetModel.removeFacet(facet) application.runWriteAction { facetModel.commit() } } } override fun createComponent(): JComponent { val mainPanel = JPanel() with(mainPanel) { layout = BorderLayout() add(enabledCheckbox, BorderLayout.NORTH) add(panel, BorderLayout.CENTER) } update() return mainPanel } override fun reset() { val facet = module.microPythonFacet val enabled = facet != null enabledCheckbox.isSelected = enabled panel.isEnabled = enabled update() if (facet != null) { panel.reset(facet.configuration, facet) } } private fun update() { UIUtil.setEnabled(panel, enabledCheckbox.isSelected, true) } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/settings/MicroPythonProjectConfigurable.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.settings import com.intellij.application.options.ModuleAwareProjectConfigurable import com.intellij.openapi.module.Module import com.intellij.openapi.options.Configurable import com.intellij.openapi.project.Project /** * @author vlan */ class MicroPythonProjectConfigurable(project: Project) : ModuleAwareProjectConfigurable(project, "MicroPython", null) { override fun createModuleConfigurable(module: Module?) = MicroPythonModuleConfigurable(module!!) } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/settings/MicroPythonSettingsPanel.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.settings import com.intellij.ide.BrowserUtil import com.intellij.openapi.fileChooser.FileChooserDescriptor import com.intellij.openapi.module.Module import com.intellij.openapi.ui.ComboBox import com.intellij.openapi.ui.TextFieldWithBrowseButton import com.intellij.ui.IdeBorderFactory import com.intellij.ui.SimpleListCellRenderer import com.intellij.ui.components.ActionLink import com.intellij.ui.components.CheckBox import com.intellij.util.text.nullize import com.intellij.util.ui.FormBuilder import com.intellij.util.ui.UIUtil import com.jetbrains.micropython.devices.MicroPythonDeviceProvider import java.awt.BorderLayout import javax.swing.JButton import javax.swing.JList import javax.swing.JPanel /** * @author vlan */ class MicroPythonSettingsPanel(private val module: Module) : JPanel() { private val deviceTypeCombo = ComboBox(MicroPythonDeviceProvider.providers.toTypedArray()) private var docsHyperlink = object : ActionLink() { var url = "" init { addActionListener { BrowserUtil.browse(url) } } } private val devicePath = TextFieldWithBrowseButton() private val autoDetectDevicePath = CheckBox("Auto-detect device path").apply { addActionListener { update() } } private val devicePathPanel: JPanel by lazy { FormBuilder.createFormBuilder() .addLabeledComponent("Device path:", JPanel(BorderLayout()).apply { add(devicePath, BorderLayout.CENTER) add(JButton("Detect").apply { addActionListener { devicePath.text = module.microPythonFacet?.detectDevicePathSynchronously(selectedProvider) ?: "" } }, BorderLayout.EAST) }) .panel } init { layout = BorderLayout() border = IdeBorderFactory.createEmptyBorder(UIUtil.PANEL_SMALL_INSETS) val deviceContentPanel = FormBuilder.createFormBuilder() .addLabeledComponent("Device type:", deviceTypeCombo) .addComponent(autoDetectDevicePath) .addComponent(devicePathPanel) .addComponent(docsHyperlink) .panel add(deviceContentPanel, BorderLayout.NORTH) deviceTypeCombo.apply { renderer = object: SimpleListCellRenderer() { override fun customize(list: JList, value: MicroPythonDeviceProvider?, index: Int, selected: Boolean, hasFocus: Boolean) { text = value?.presentableName ?: return } } addActionListener { docsHyperlink.apply { url = selectedProvider.documentationURL text = "Learn more about setting up ${selectedProvider.presentableName} devices" repaint() } } } devicePath.apply { val descriptor = FileChooserDescriptor(true, false, false, false, false, false) addBrowseFolderListener("My Title", null, module.project, descriptor) } update() } fun isModified(configuration: MicroPythonFacetConfiguration, facet: MicroPythonFacet): Boolean = deviceTypeCombo.selectedItem != configuration.deviceProvider || devicePath.text.nullize(true) != facet.devicePath || autoDetectDevicePath.isSelected != facet.autoDetectDevicePath fun getDisplayName(): String = "MicroPython" fun apply(configuration: MicroPythonFacetConfiguration, facet: MicroPythonFacet) { configuration.deviceProvider = selectedProvider facet.devicePath = devicePath.text.nullize(true) facet.autoDetectDevicePath = autoDetectDevicePath.isSelected } fun reset(configuration: MicroPythonFacetConfiguration, facet: MicroPythonFacet) { deviceTypeCombo.selectedItem = configuration.deviceProvider devicePath.text = facet.devicePath ?: "" autoDetectDevicePath.isSelected = facet.autoDetectDevicePath update() } private fun update() { UIUtil.setEnabled(devicePathPanel, !autoDetectDevicePath.isSelected, true) } private val selectedProvider: MicroPythonDeviceProvider get() = deviceTypeCombo.selectedItem as MicroPythonDeviceProvider } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/settings/MicroPythonTypeHints.kt ================================================ /* * Copyright 2000-2017 JetBrains s.r.o. * * 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. */ package com.jetbrains.micropython.settings /** * @author vlan */ data class MicroPythonTypeHints(val paths: List) ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/settings/MicroPythonUsbId.kt ================================================ package com.jetbrains.micropython.settings /** * @author vlan */ data class MicroPythonUsbId(val vendorId: Int, val productId: Int) { companion object { fun parse(vendorAndProductId: String): MicroPythonUsbId { val ints = vendorAndProductId.split(':').map { Integer.decode(it) } return MicroPythonUsbId(ints[0], ints[1]) } } } ================================================ FILE: src/main/kotlin/com/jetbrains/micropython/ui/MicroPythonToolWindowFactory.kt ================================================ package com.jetbrains.micropython.ui import com.intellij.openapi.components.service import com.intellij.openapi.project.DumbAware import com.intellij.openapi.project.Project import com.intellij.openapi.wm.ToolWindow import com.intellij.openapi.wm.ToolWindowFactory import com.intellij.ui.content.ContentFactory import com.jetbrains.micropython.repl.MicroPythonReplManager import com.jetbrains.micropython.repl.ToolWindowReplTab import com.jetbrains.micropython.settings.firstMicroPythonFacet class MicroPythonToolWindowFactory : ToolWindowFactory, DumbAware { override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) { val contentFactory = ContentFactory.getInstance() val terminalContent = contentFactory.createContent(null, "REPL", false) project.firstMicroPythonFacet?.let { terminalContent.component = ToolWindowReplTab(it.module, terminalContent).createUI() toolWindow.contentManager.addContent(terminalContent) project.service().startOrRestartRepl() } } } ================================================ FILE: src/main/resources/META-INF/plugin.xml ================================================ MicroPython intellij-micropython See CHANGES.md on GitHub.

]]>
Support for MicroPython devices in PyCharm and IntelliJ.


Features:


  • Code completion and docs for some MicroPython-specific modules
  • Flash a Python file or directory to a device
  • Run REPL on a device

Currently the plugin supports ESP8266, Pyboard, Micro:bit, and Raspberry Pi Pico devices. Your feedback and contributions are welcome! See the project page on GitHub.

]]>
SNAPSHOT JetBrains com.intellij.modules.lang com.intellij.modules.python org.jetbrains.plugins.terminal
================================================ FILE: src/main/resources/inspectionDescriptions/MicroPythonRequirements.html ================================================

Detects missing Python packages that are required for communicating with your MicroPython device.

================================================ FILE: typehints/esp32/esp.pyi ================================================ from typing import Optional from typing import Final LOG_NONE: Final[int] = ... LOG_ERROR: Final[int] = ... LOG_WARN: Final[int] = ... LOG_INFO: Final[int] = ... LOG_DEBUG: Final[int] = ... LOG_VERBOSE: Final[int] = ... def flash_size(): """Read the total size of the flash memory.""" ... def flash_user_start(): """Read the memory offset at which the user flash space begins.""" ... def flash_read(byte_offset, length_or_buffer): ... def flash_write(byte_offset, bytes): ... def flash_erase(sector_no): ... def osdebug(level: Optional[int]): """ Turn esp os debugging messages on or off. The level parameter sets the threshold for the log messages for all esp components. The log levels are defined as constants: * ``LOG_NONE`` – No log output * ``LOG_ERROR`` – Critical errors, software module can not recover on its own * ``LOG_WARN`` – Error conditions from which recovery measures have been taken * ``LOG_INFO`` – Information messages which describe normal flow of events * ``LOG_DEBUG`` – Extra information which is not necessary for normal use (values, pointers, sizes, etc) * ``LOG_VERBOSE`` – Bigger chunks of debugging information, or frequent messages which can potentially flood the output """ ... ================================================ FILE: typehints/esp32/esp32.pyi ================================================ from machine import Pin from typing import Optional from typing import overload from typing import Final HEAP_DATA: Final[int] = ... """Used in ``idf_heap_info``.""" HEAP_EXEC: Final[int] = ... """Used in ``idf_heap_info``.""" WAKEUP_ALL_LOW: Final[int] = ... """Selects the wake level for pins.""" WAKEUP_ANY_HIGH: Final[int] = ... """Selects the wake level for pins.""" def wake_on_touch(wake: bool): """ :param wake: Configure whether or not a touch will wake the device from sleep. """ def wake_on_ulp(wake: bool): """ :param wake: Configure whether or not the Ultra-Low-Power co-processor can wake the device from sleep. """ def wake_on_ext0(pin: Pin, level: Optional[int]): """ Configure how EXT0 wakes the device from sleep. :param pin: None or a valid Pin object. :param level: ``esp32.WAKEUP_ALL_LOW`` or ``esp32.WAKEUP_ANY_HIGH``. """ def wake_on_ext1(pin: Pin, level: Optional[int]): """ Configure how EXT1 wakes the device from sleep. :param pin: None or a valid Pin object. :param level: ``esp32.WAKEUP_ALL_LOW`` or ``esp32.WAKEUP_ANY_HIGH``. """ def gpio_deep_sleep_hold(enable: bool): """ :param enable: Whether non-RTC GPIO pin configuration is retained during deep-sleep mode for held pads. """ def raw_temperature() -> int: """ :return: The raw value of the internal temperature sensor. """ def hall_sensor() -> int: """ :return: The raw value of the internal Hall sensor. """ def idf_heap_info(capabilities: Optional[int]) -> list: """ Returns information about the ESP-IDF heap memory regions. One of them contains the MicroPython heap and the others are used by ESP-IDF, e.g., for network buffers and other data. This data is useful to get a sense of how much memory is available to ESP-IDF and the networking stack in particular. It may shed some light on situations where ESP-IDF operations fail due to allocation failures. The information returned is not useful to troubleshoot Python allocation failures, use ``micropython.mem_info()`` instead. The capabilities parameter corresponds to ESP-IDF’s ``MALLOC_CAP_XXX`` values but the two most useful ones are predefined as ``esp32.HEAP_DATA`` for data heap regions and ``esp32.HEAP_EXEC`` for executable regions as used by the native code emitter. The return value is a list of 4-tuples, where each 4-tuple corresponds to one heap and contains: the total bytes, the free bytes, the largest free block, and the minimum free seen over time. """ class Partition: """ This class gives access to the partitions in the device’s flash memory and includes methods to enable over-the-air (OTA) updates. """ BOOT: Final[str] = ... """Used in ``Partition`` constructor - The partition that will be booted at the next reset.""" RUNNING: Final[str] = ... """Used in ``Partition`` constructor - The currently running partition.""" TYPE_APP: Final[int] = ... """ Used in ``Partition.find`` - for bootable firmware partitions (typically labelled ``factory``, ``ota_0``, ``ota_1``) """ TYPE_DATA: Final[int] = ... """ Used in Partition.find - for other partitions, e.g. ``nvs``, ``otadata``, ``phy_init``, ``vfs``. """ def __init__(self, id: str, block_size=4096, /): """ Create an object representing a partition. :param id: Can be a string which is the label of the partition to retrieve or one of the constants: ``BOOT`` or ``RUNNING``. :param block_size: Specifies the byte size of an individual block. """ @classmethod def find(self, type=TYPE_APP, subtype=0xFF, label=None, block_size=4096) -> list: """ Find a partition specified by type, subtype and label. Note: ``subtype=0xff`` matches any subtype and ``label=None`` matches any label. :param block_size: Specifies the byte size of an individual block used by the returned objects. :return: A (possibly empty) list of Partition objects. """ def info(self) -> tuple: """ :return: A 6-tuple ``(type, subtype, addr, size, label, encrypted)``. """ @overload def readblocks(self, block_num, buf): ... @overload def readblocks(self, block_num, buf, offset): ... @overload def writeblocks(self, block_num, buf): ... @overload def writeblocks(self, block_num, buf, offset): ... def ioctl(self, cmd, arg): """These methods implement the simple and extended block protocol defined by ``os.AbstractBlockDev``.""" def set_boot(self): """Sets the partition as the boot partition.""" def get_next_update(self): """ Gets the next update partition after this one, and returns a new Partition object. Typical usage is ``Partition(Partition.RUNNING).get_next_update()``. :return: The next partition to update given the current running one. """ def mark_app_valid_cancel_rollback(self): """ Signals that the current boot is considered successful. Calling ``mark_app_valid_cancel_rollback`` is required on the first boot of a new partition to avoid an automatic rollback at the next boot. This uses the ESP-IDF “app rollback” feature with “CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE” and an ``OSError(-261)`` is raised if called on firmware that doesnt have the feature enabled. It is OK to call ``mark_app_valid_cancel_rollback`` on every boot and it is not necessary when booting firmware that was loaded using esptool. """ class RMT: """ This class provides access to one of the eight RMT channels. WARNING: The current MicroPython RMT implementation lacks some features, most notably receiving pulses. RMT should be considered a beta feature and the interface may change in the future. """ def __init__(self, channel: int, *, pin=None, clock_div=8, idle_level=False, tx_carrier=None): """ :param channel: Identifies which RMT channel (0-7) will be configured. :param pin: Configures which Pin is bound to the RMT channel :param clock_div: An 8-bit clock divider that divides the source clock (80MHz) to the RMT channel allowing the resolution to be specified. :param idle_level: Specifies what level the output will be when no transmission is in progress To enable the transmission carrier feature, ``tx_carrier`` should be a tuple of three positive integers: carrier frequency, duty percent (0 to 100) and the output level to apply the carrier to (a boolean as per idle_level). """ def source_freq(self): """ :return: The source clock frequency. Currently the source clock is not configurable so this will always return 80MHz. """ def clock_div(self): """ :return: The clock divider. Note that the channel resolution is ``1 / (source_freq / clock_div)``. """ def wait_done(self, *, timeout=0): """ If the timeout keyword argument is given then block for up to this many milliseconds for transmission to complete. :return: ``True`` if the channel is idle or ``False`` if a sequence of pulses started with ``RMT.write_pulses`` is being transmitted. """ def loop(self, enable_loop: bool): """ Configure looping on the channel. :param enable_loop: ``True`` to enable looping on the next call to ``RMT.write_pulses``. If called with ``False`` while a looping sequence is currently being transmitted then the current loop iteration will be completed and then transmission will stop. """ def write_pulses(self, duration, data=True): """ Begin transmitting a sequence. There are three ways to specify this: Mode 1: duration is a list or tuple of durations. The optional data argument specifies the initial output level. The output level will toggle after each duration. Mode 2: duration is a positive integer and data is a list or tuple of output levels. duration specifies a fixed duration for each. Mode 3: duration and data are lists or tuples of equal length, specifying individual durations and the output level for each. Durations are in integer units of the channel resolution (as described above), between 1 and 32767 units. Output levels are any value that can be converted to a boolean, with ``True`` representing high voltage and ``False`` representing low. If transmission of an earlier sequence is in progress then this method will block until that transmission is complete before beginning the new sequence. If looping has been enabled with RMT.loop, the sequence will be repeated indefinitely. Further calls to this method will block until the end of the current loop iteration before immediately beginning to loop the new sequence of pulses. Looping sequences longer than 126 pulses is not supported by the hardware. """ @staticmethod def bitstream_channel(value: Optional[int]) -> int: """ Select which RMT channel is used by the ``machine.bitstream`` implementation. :param value: Can be None or a valid RMT channel number. The default RMT channel is the highest numbered one. Passing in None disables the use of RMT and instead selects a bit-banging implementation for ``machine.bitstream``. Passing in no argument will not change the channel. This function returns the current channel number. :type value: int """ class ULP: """This class provides access to the Ultra-Low-Power co-processor.""" def set_wakeup_period(self, period_index: int, period_us): """Set the wake-up period.""" def load_binary(self, load_addr, program_binary): """Load a program_binary into the ULP at the given load_addr.""" def run(self, entry_point): """Start the ULP running at the given entry_point.""" class NVS: """ This class gives access to the Non-Volatile storage managed by ESP-IDF. The NVS is partitioned into namespaces and each namespace contains typed key-value pairs. The keys are strings and the values may be various integer types, strings, and binary blobs. The driver currently only supports 32-bit signed integers and blobs. """ def __init__(self, namespace: str): """Create an object providing access to a namespace (which is automatically created if not present).""" def set_i32(self, key, value): """Sets a 32-bit signed integer value for the specified key. Remember to call commit!""" def get_i32(self, key): """ Returns the signed integer value for the specified key. Raises an OSError if the key does not exist or has a different type. """ def set_blob(self, key, value): """ Sets a binary blob value for the specified key. The value passed in must support the buffer protocol, e.g. bytes, bytearray, str. (Note that esp-idf distinguishes blobs and strings, this method always writes a blob even if a string is passed in as value.) Remember to call commit! """ def get_blob(self, key, buffer): """ Reads the value of the blob for the specified key into the buffer, which must be a bytearray. Returns the actual length read. Raises an OSError if the key does not exist, has a different type, or if the buffer is too small. """ def erase_key(self, key): """Erases a key-value pair.""" def commit(self): """Commits changes made by set_xxx methods to flash.""" ================================================ FILE: typehints/esp32/network.pyi ================================================ """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() """ from typing import overload, Optional, List, Tuple, Union, Any, Final STA_IF: Final[int] = ... AP_IF: Final[int] = ... @overload def phy_mode() -> int: """Get the PHY mode.""" ... @overload def phy_mode(mode: int) -> None: """Set the PHY mode. The possible modes are defined as constants: * ``MODE_11B`` -- IEEE 802.11b, * ``MODE_11G`` -- IEEE 802.11g, * ``MODE_11N`` -- IEEE 802.11n. """ ... class WLAN: def __init__(self, interface_id: int) -> None: """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 `connect()` to an access point. """ ... @overload def active(self) -> bool: """Query current state of the interface.""" ... @overload def active(self, is_active: bool) -> None: """Activate ("up") or deactivate ("down") network interface.""" ... def connect(self, ssid: Optional[Union[bytes, str]] = None, password: Optional[Union[bytes, str]] = None, *, bssid: Optional[Union[bytes, str]] = None) -> 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). """ ... def disconnect(self) -> None: """Disconnect from the currently connected wireless network.""" ... def scan(self) -> List[Tuple[bytes, bytes, int, int, int, int]]: """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 """ ... def status(self) -> int: """Return the current status of the wireless connection. 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. """ ... def isconnected(self) -> bool: """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. """ ... @overload def ifconfig(self) -> Tuple[str, str, str, str]: """Get IP-level network interface parameters: IP address, subnet mask, gateway and DNS server. """ ... @overload def ifconfig(self, ip: str, subnet: str, gateway: str, dns: str) -> None: """Get/set IP-level network interface parameters: IP address, subnet mask, gateway and DNS server. """ ... @overload def config(self, param: str) -> Any: """Get general network interface parameters.""" ... @overload def config(self, **kwargs: Any) -> None: """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 ============= =========== """ ... STA_IF: int AP_IF: int STAT_IDLE: int STAT_CONNECTING: int STAT_WRONG_PASSWORD: int STAT_NO_AP_FOUND: int STAT_CONNECT_FAIL: int STAT_GOT_IP: int MODE_11B: int MODE_11G: int MODE_11N: int ================================================ FILE: typehints/esp8266/esp.pyi ================================================ from typing import Optional def sleep_type(sleep_type: Optional[int]) -> Optional[int]: """ 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,\n * ``SLEEP_MODEM`` – modem sleep, shuts down the WiFi Modem circuit.\n * ``SLEEP_LIGHT`` – light sleep, shuts down the WiFi Modem circuit and suspends the processor periodically.\n The system enters the set sleep mode automatically when possible. :param sleep_type: Sleep type. :type sleep_type: int :return: Current sleep type :rtype: int """ def deepsleep(time: int = 0) -> None: """ 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. :param time: Amount of time in milliseconds to sleep. """ def set_native_code_location(start: Optional[int], length: Optional[int]) -> None: """ 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. :param start: Start of native code region. :param length: End of native code region. """ ================================================ FILE: typehints/esp8266/network.pyi ================================================ """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() """ from typing import overload, Optional, List, Tuple, Union, Any, Final STA_IF: Final[int] = ... AP_IF: Final[int] = ... @overload def phy_mode() -> int: """Get the PHY mode.""" ... @overload def phy_mode(mode: int) -> None: """Set the PHY mode. The possible modes are defined as constants: * ``MODE_11B`` -- IEEE 802.11b, * ``MODE_11G`` -- IEEE 802.11g, * ``MODE_11N`` -- IEEE 802.11n. """ ... class WLAN: def __init__(self, interface_id: int) -> None: """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 `connect()` to an access point. """ ... @overload def active(self) -> bool: """Query current state of the interface.""" ... @overload def active(self, is_active: bool) -> None: """Activate ("up") or deactivate ("down") network interface.""" ... def connect(self, ssid: Optional[Union[bytes, str]] = None, password: Optional[Union[bytes, str]] = None, *, bssid: Optional[Union[bytes, str]] = None) -> 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). """ ... def disconnect(self) -> None: """Disconnect from the currently connected wireless network.""" ... def scan(self) -> List[Tuple[bytes, bytes, int, int, int, int]]: """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 """ ... def status(self) -> int: """Return the current status of the wireless connection. 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. """ ... def isconnected(self) -> bool: """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. """ ... @overload def ifconfig(self) -> Tuple[str, str, str, str]: """Get IP-level network interface parameters: IP address, subnet mask, gateway and DNS server. """ ... @overload def ifconfig(self, ip: str, subnet: str, gateway: str, dns: str) -> None: """Get/set IP-level network interface parameters: IP address, subnet mask, gateway and DNS server. """ ... @overload def config(self, param: str) -> Any: """Get general network interface parameters.""" ... @overload def config(self, **kwargs: Any) -> None: """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 ============= =========== """ ... STA_IF: int AP_IF: int STAT_IDLE: int STAT_CONNECTING: int STAT_WRONG_PASSWORD: int STAT_NO_AP_FOUND: int STAT_CONNECT_FAIL: int STAT_GOT_IP: int MODE_11B: int MODE_11G: int MODE_11N: int ================================================ FILE: typehints/microbit/microbit/__init__.pyi ================================================ """micro:bit Micropython API Everything directly related to interacting with the hardware lives in the `microbit` module. For ease of use it's recommended you start all scripts with:: from microbit import * The following documentation assumes you have done this. There are a few functions available directly:: # sleep for the given number of milliseconds. sleep(ms) # returns the number of milliseconds since the micro:bit was last switched on. running_time() # makes the micro:bit enter panic mode (this usually happens when the DAL runs # out of memory, and causes a sad face to be drawn on the display). The error # code can be any arbitrary integer value. panic(error_code) # resets the micro:bit. reset() The rest of the functionality is provided by objects and classes in the microbit module, as described below. Note that the API exposes integers only (ie no floats are needed, but they may be accepted). We thus use milliseconds for the standard time unit. """ from . import (display as display, uart as uart, spi as spi, i2c as i2c, accelerometer as accelerometer, compass as compass) from typing import Any, List, overload def panic(n: int) -> None: """Enter a panic mode. Requires restart. Pass in an arbitrary integer <= 255 to indicate a status:: microbit.panic(255) """ def reset() -> None: """Restart the board.""" def sleep(n: int) -> None: """Wait for ``n`` milliseconds. One second is 1000 milliseconds, so:: microbit.sleep(1000) will pause the execution for one second. ``n`` can be an integer or a floating point number. """ def running_time() -> int: """Return the number of milliseconds since the board was switched on or restarted. """ def temperature() -> int: """Return the temperature of the micro:bit in degrees Celcius.""" class Button: """Represents a button. .. note:: This class is not actually available to the user, it is only used by the two button instances, which are provided already initialized. """ def is_pressed(self) -> bool: """Returns ``True`` if the specified button ``button`` is pressed, and ``False`` otherwise. """ def was_pressed(self) -> bool: """Returns ``True`` or ``False`` to indicate if the button was pressed since the device started or the last time this method was called. """ def get_presses(self) -> int: """Returns the running total of button presses, and resets this total to zero before returning. """ button_a: Button """A ``Button`` instance (see below) representing the left button.""" button_b: Button """Represents the right button.""" class MicroBitDigitalPin: """ The pull mode for a pin is automatically configured when the pin changes to an input mode. Input modes are when you call ``read_analog`` / ``read_digital`` / ``is_touched``. The pull mode for these is, respectively, ``NO_PULL``, ``PULL_DOWN``, ``PULL_UP``. Only when in ``read_digital`` mode can you call ``set_pull`` to change the pull mode from the default. """ NO_PULL: int = 0 PULL_UP: int = 1 PULL_DOWN: int = 2 def read_digital(self) -> int: """Return 1 if the pin is high, and 0 if it's low.""" def set_pull(self, value: int = (NO_PULL or PULL_UP or PULL_DOWN)) -> None: """Set the pull state to one of three possible values: ``pin.PULL_UP``, ``pin.PULL_DOWN`` or ``pin.NO_PULL`` (where ``pin`` is an instance of a pin). See below for discussion of default pull states. """ def write_digital(self, value: int) -> None: """Set the pin to high if ``value`` is 1, or to low, if it is 0.""" def write_analog(self, value: int) -> None: """Output a PWM signal on the pin, with the duty cycle proportional to the provided ``value``. The ``value`` may be either an integer or a floating point number between 0 (0% duty cycle) and 1023 (100% duty). """ def set_analog_period(self, period: int) -> None: """Set the period of the PWM signal being output to ``period`` in milliseconds. The minimum valid value is 1ms. """ def set_analog_period_microseconds(self, period: int) -> None: """Set the period of the PWM signal being output to ``period`` in microseconds. The minimum valid value is 35µs. """ class MicroBitAnalogDigitalPin(MicroBitDigitalPin): def read_analog(self) -> int: """Read the voltage applied to the pin, and return it as an integer between 0 (meaning 0V) and 1023 (meaning 3.3V). """ class MicroBitTouchPin(MicroBitAnalogDigitalPin): def is_touched(self) -> bool: """Return ``True`` if the pin is being touched with a finger, otherwise return ``False``. This test is done by measuring the capacitance of the pin together with whatever is connected to it. Human body has quite a large capacitance, so touching the pin gives a dramatic change in reading, which can be detected. """ pin0: MicroBitTouchPin """Pad 0.""" pin1: MicroBitTouchPin """Pad 1.""" pin2: MicroBitTouchPin """Pad 2.""" pin3: MicroBitAnalogDigitalPin """Column 1.""" pin4: MicroBitAnalogDigitalPin """Column 2.""" pin5: MicroBitDigitalPin """Button A.""" pin6: MicroBitDigitalPin """Row 2.""" pin7: MicroBitDigitalPin """Row 1.""" pin8: MicroBitDigitalPin pin9: MicroBitDigitalPin """Row 3.""" pin10: MicroBitAnalogDigitalPin """Column 3.""" pin11: MicroBitDigitalPin """Button B.""" pin12: MicroBitDigitalPin pin13: MicroBitDigitalPin """SPI MOSI.""" pin14: MicroBitDigitalPin """SPI MISO.""" pin15: MicroBitDigitalPin """SPI SCK.""" pin16: MicroBitDigitalPin pin19: MicroBitDigitalPin """I2C SCL.""" pin20: MicroBitDigitalPin """I2C SDA.""" class Image: """The ``Image`` class is used to create images that can be displayed easily on the device's LED matrix. Given an image object it's possible to display it via the ``display`` API:: display.show(Image.HAPPY) """ HEART: Image HEART_SMALL: Image HAPPY: Image SMILE: Image SAD: Image CONFUSED: Image ANGRY: Image ASLEEP: Image SURPRISED: Image SILLY: Image FABULOUS: Image MEH: Image YES: Image NO: Image CLOCK12: Image CLOCK11: Image CLOCK10: Image CLOCK9: Image CLOCK8: Image CLOCK7: Image CLOCK6: Image CLOCK5: Image CLOCK4: Image CLOCK3: Image CLOCK2: Image CLOCK1: Image ARROW_N: Image ARROW_NE: Image ARROW_E: Image ARROW_SE: Image ARROW_S: Image ARROW_SW: Image ARROW_W: Image ARROW_NW: Image TRIANGLE: Image TRIANGLE_LEFT: Image CHESSBOARD: Image DIAMOND: Image DIAMOND_SMALL: Image SQUARE: Image SQUARE_SMALL: Image RABBIT: Image COW: Image MUSIC_CROTCHET: Image MUSIC_QUAVER: Image MUSIC_QUAVERS: Image PITCHFORK: Image XMAS: Image PACMAN: Image TARGET: Image TSHIRT: Image ROLLERSKATE: Image DUCK: Image HOUSE: Image TORTOISE: Image BUTTERFLY: Image STICKFIGURE: Image GHOST: Image SWORD: Image GIRAFFE: Image SKULL: Image UMBRELLA: Image SNAKE: Image ALL_CLOCKS: List[Image] ALL_ARROWS: List[Image] @overload def __init__(self, string: str) -> None: """``string`` has to consist of digits 0-9 arranged into lines, describing the image, for example:: image = Image("90009:" "09090:" "00900:" "09090:" "90009") will create a 5×5 image of an X. The end of a line is indicated by a colon. It's also possible to use a newline (\n) to indicate the end of a line like this:: image = Image("90009\n" "09090\n" "00900\n" "09090\n" "90009") """ @overload def __init__(self, width: int = None, height: int = None, buffer: Any = None) -> None: """Create an empty image with ``width`` columns and ``height`` rows. Optionally ``buffer`` can be an array of ``width``×``height`` integers in range 0-9 to initialize the image. """ def width(self) -> int: """Return the number of columns in the image.""" def height(self) -> int: """Return the numbers of rows in the image.""" def set_pixel(self, x: int, y: int, value: int) -> None: """Set the brightness of the pixel at column ``x`` and row ``y`` to the ``value``, which has to be between 0 (dark) and 9 (bright). This method will raise an exception when called on any of the built-in read-only images, like ``Image.HEART``. """ def get_pixel(self, x: int, y: int) -> int: """Return the brightness of pixel at column ``x`` and row ``y`` as an integer between 0 and 9. """ def shift_left(self, n: int) -> Image: """Return a new image created by shifting the picture left by ``n`` columns. """ def shift_right(self, n: int) -> Image: """Same as ``image.shift_left(-n)``.""" def shift_up(self, n: int) -> Image: """Return a new image created by shifting the picture up by ``n`` rows. """ def shift_down(self, n: int) -> Image: """Same as ``image.shift_up(-n)``.""" def crop(self, x: int, y: int, w: int, h: int) -> Image: """Return a new image by cropping the picture to a width of ``w`` and a height of ``h``, starting with the pixel at column ``x`` and row ``y``. """ def copy(self) -> Image: """Return an exact copy of the image.""" def invert(self) -> Image: """Return a new image by inverting the brightness of the pixels in the source image.""" def fill(self, value: int) -> None: """Set the brightness of all the pixels in the image to the ``value``, which has to be between 0 (dark) and 9 (bright). This method will raise an exception when called on any of the built-in read-only images, like ``Image.HEART``. """ def blit(self, src: Image, x: int, y: int, w: int, h: int, xdest: int = 0, ydest: int = 0) -> None: """Copy the rectangle defined by ``x``, ``y``, ``w``, ``h`` from the image ``src`` into this image at ``xdest``, ``ydest``. Areas in the source rectangle, but outside the source image are treated as having a value of 0. ``shift_left()``, ``shift_right()``, ``shift_up()``, ``shift_down()`` and ``crop()`` can are all implemented by using ``blit()``. For example, img.crop(x, y, w, h) can be implemented as:: def crop(self, x, y, w, h): res = Image(w, h) res.blit(self, x, y, w, h) return res """ def __repr__(self) -> str: """Get a compact string representation of the image.""" def __str__(self) -> str: """Get a readable string representation of the image.""" def __add__(self, other: Image) -> Image: """Create a new image by adding the brightness values from the two images for each pixel. """ def __mul__(self, n: float) -> Image: """Create a new image by multiplying the brightness of each pixel by ``n``. """ ================================================ FILE: typehints/microbit/microbit/accelerometer.pyi ================================================ """This object gives you access to the on-board accelerometer. The accelerometer also provides convenience functions for detecting gestures. The recognised gestures are: ``up``, ``down``, ``left``, ``right``, ``face up``, ``face down``, ``freefall``, ``3g``, ``6g``, ``8g``, ``shake``. """ from typing import Tuple def get_x() -> int: """Get the acceleration measurement in the ``x`` axis, as a positive or negative integer, depending on the direction. """ def get_y() -> int: """Get the acceleration measurement in the ``y`` axis, as a positive or negative integer, depending on the direction. """ def get_z() -> int: """Get the acceleration measurement in the ``z`` axis, as a positive or negative integer, depending on the direction. """ def get_values() -> Tuple[int, int, int]: """Get the acceleration measurements in all axes at once, as a three-element tuple of integers ordered as X, Y, Z. """ def current_gesture() -> str: """Return the name of the current gesture. .. note:: MicroPython understands the following gesture names: ``"up"``, ``"down"``, ``"left"``, ``"right"``, ``"face up"``, ``"face down"``, ``"freefall"``, ``"3g"``, ``"6g"``, ``"8g"``, ``"shake"``. Gestures are always represented as strings.""" def is_gesture(name: str) -> bool: """Return True or False to indicate if the named gesture is currently active.""" def was_gesture(name: str) -> bool: """Return True or False to indicate if the named gesture was active since the last call. """ def get_gestures() -> Tuple[str, ...]: """Return a tuple of the gesture history. The most recent is listed last. Also clears the gesture history before returning. """ ================================================ FILE: typehints/microbit/microbit/compass.pyi ================================================ """This module lets you access the built-in electronic compass. Before using, the compass should be calibrated, otherwise the readings may be wrong. .. warning:: Calibrating the compass will cause your program to pause until calibration is complete. Calibration consists of a little game to draw a circle on the LED display by rotating the device. """ def calibrate() -> None: """Starts the calibration process. An instructive message will be scrolled to the user after which they will need to rotate the device in order to draw a circle on the LED display. """ def is_calibrated() -> bool: """Returns ``True`` if the compass has been successfully calibrated, and returns ``False`` otherwise. """ def clear_calibration() -> None: """Undoes the calibration, making the compass uncalibrated again.""" def get_x() -> int: """Gives the reading of the magnetic force on the ``x`` axis, as a positive or negative integer, depending on the direction of the force. """ def get_y() -> int: """Gives the reading of the magnetic force on the ``x`` axis, as a positive or negative integer, depending on the direction of the force. """ def get_z() -> int: """Gives the reading of the magnetic force on the ``x`` axis, as a positive or negative integer, depending on the direction of the force. """ def heading() -> int: """Gives the compass heading, calculated from the above readings, as an integer in the range from 0 to 360, representing the angle in degrees, clockwise, with north as 0. If the compass has not been calibrated, then this will call ``calibrate``. """ def get_field_strength() -> int: """Returns an integer indication of the magnitude of the magnetic field around the device.""" ================================================ FILE: typehints/microbit/microbit/display.pyi ================================================ """This module controls the 5×5 LED display on the front of your board. It can be used to display images, animations and even text. To continuously scroll a string across the display, and do it in the background, you can use:: import microbit microbit.display.scroll('Hello!', wait=False, loop=True) """ from . import Image from typing import overload, Iterable def get_pixel(x: int, y: int) -> int: """Return the brightness of the LED at column ``x`` and row ``y`` as an integer between 0 (off) and 9 (bright). """ def set_pixel(x: int, y: int, value: int) -> None: """Set the brightness of the LED at column ``x`` and row ``y`` to ``value``, which has to be an integer between 0 and 9. """ def clear() -> None: """Set the brightness of all LEDs to 0 (off).""" @overload def show(image: Image) -> None: """Display the ``image``.""" @overload def show(iterable: Iterable[Image, str], delay: int = 400, *, wait: bool = True, loop: bool =False, clear: bool = False) -> None: """Display images or letters from the ``iterable`` in sequence, with ``delay`` milliseconds between them. If ``wait`` is ``True``, this function will block until the animation is finished, otherwise the animation will happen in the background. If ``loop`` is ``True``, the animation will repeat forever. If ``clear`` is ``True``, the display will be cleared after the iterable has finished. Note that the ``wait``, ``loop`` and ``clear`` arguments must be specified using their keyword. .. note:: If using a generator as the ``iterable``, then take care not to allocate any memory in the generator as allocating memory in an interrupt is prohibited and will raise a ``MemoryError``. """ def scroll(string: str, delay: int = 150, *, wait: bool = True, loop: bool = False, monospace: bool = False) -> None: """Similar to ``show``, but scrolls the ``string`` horizontally instead. The ``delay`` parameter controls how fast the text is scrolling. If ``wait`` is ``True``, this function will block until the animation is finished, otherwise the animation will happen in the background. If ``loop`` is ``True``, the animation will repeat forever. If ``monospace`` is ``True``, the characters will all take up 5 pixel-columns in width, otherwise there will be exactly 1 blank pixel-column between each character as they scroll. Note that the ``wait``, ``loop`` and ``monospace`` arguments must be specified using their keyword. """ def on() -> None: """Use on() to turn on the display.""" def off() -> None: """Use off() to turn off the display (thus allowing you to re-use the GPIO pins associated with the display for other purposes). """ def is_on() -> bool: """Returns ``True`` if the display is on, otherwise returns ``False``.""" ================================================ FILE: typehints/microbit/microbit/i2c.pyi ================================================ """The ``i2c`` module lets you communicate with devices connected to your board using the I²C bus protocol. There can be multiple slave devices connected at the same time, and each one has its own unique address, that is either fixed for the device or configured on it. Your board acts as the I²C master. We use 7-bit addressing for devices because of the reasons stated `here `_. This may be different to other micro:bit related solutions. How exactly you should communicate with the devices, that is, what bytes to send and how to interpret the responses, depends on the device in question and should be described separately in that device's documentation. You should connect the device's ``SCL`` pin to micro:bit pin 19, and the device's ``SDA`` pin to micro:bit pin 20. You also must connect the device's ground to the micro:bit ground (pin ``GND``). You may need to power the device using an external power supply or the micro:bit. There are internal pull-up resistors on the I²C lines of the board, but with particularly long wires or large number of devices you may need to add additional pull-up resistors, to ensure noise-free communication. """ from . import pin19, pin20 from typing import Union from . import pin19, pin20 def init(freq: int = 100000, sda: int = pin20, scl: int = pin19) -> None: """Re-initialize peripheral with the specified clock frequency ``freq`` on the specified ``sda`` and ``scl`` pins. .. warning:: Changing the I²C pins from defaults will make the accelerometer and compass stop working, as they are connected internally to those pins. """ def read(addr: int, n: int, repeat: bool = False) -> bytes: """Read ``n`` bytes from the device with 7-bit address ``addr``. If ``repeat`` is ``True``, no stop bit will be sent. """ def write(addr: int, buf: Union[bytes, bytearray], repeat=False) -> None: """Write bytes from ``buf`` to the device with 7-bit address ``addr``. If ``repeat`` is ``True``, no stop bit will be sent. """ ================================================ FILE: typehints/microbit/microbit/spi.pyi ================================================ """The ``spi`` module lets you talk to a device connected to your board using a serial peripheral interface (SPI) bus. SPI uses a so-called master-slave architecture with a single master. You will need to specify the connections for three signals: * SCLK : Serial Clock (output from master). * MOSI : Master Output, Slave Input (output from master). * MISO : Master Input, Slave Output (output from slave). """ from . import pin13, pin14, pin15, MicroBitDigitalPin from typing import Union def init(baudrate: int = 1000000, bits: int = 8, mode: int = 0, sclk: MicroBitDigitalPin = pin13, mosi: MicroBitDigitalPin = pin15, miso: MicroBitDigitalPin = pin14) -> None: """Initialize SPI communication with the specified parameters on the specified ``pins``. Note that for correct communication, the parameters have to be the same on both communicating devices. The ``baudrate`` defines the speed of communication. The ``bits`` defines the size of bytes being transmitted. Currently only ``bits=8`` is supported. However, this may change in the future. The ``mode`` determines the combination of clock polarity and phase according to the following convention, with polarity as the high order bit and phase as the low order bit: +----------+-----------------+--------------+ | SPI Mode | Polarity (CPOL) | Phase (CPHA) | +==========+=================+==============+ | 0 | 0 | 0 | +----------+-----------------+--------------+ | 1 | 0 | 1 | +----------+-----------------+--------------+ | 2 | 1 | 0 | +----------+-----------------+--------------+ | 3 | 1 | 1 | +----------+-----------------+--------------+ Polarity (aka CPOL) 0 means that the clock is at logic value 0 when idle and goes high (logic value 1) when active; polarity 1 means the clock is at logic value 1 when idle and goes low (logic value 0) when active. Phase (aka CPHA) 0 means that data is sampled on the leading edge of the clock, and 1 means on the trailing edge (viz. https://en.wikipedia.org/wiki/Signal_edge). The ``sclk``, ``mosi`` and ``miso`` arguments specify the pins to use for each type of signal. """ def read(nbytes: int) -> bytes: """Read at most ``nbytes``. Returns what was read.""" def write(buffer: Union[bytes, bytearray]) -> None: """Write the ``buffer`` of bytes to the bus.""" def write_readinto(out: Union[bytes, bytearray], in_: bytearray) -> None: """Write the ``out`` buffer to the bus and read any response into the ``in`` buffer. The length of the buffers should be the same. The buffers can be the same object.""" ================================================ FILE: typehints/microbit/microbit/uart.pyi ================================================ """The ``uart`` module lets you talk to a device connected to your board using a serial interface. """ from . import MicroBitDigitalPin from typing import Optional, Union def init(baudrate: int = 9600, bits: int = 8, parity: int = None, stop: int = 1, *, tx: MicroBitDigitalPin = None, rx: MicroBitDigitalPin = None) -> None: """Initialize serial communication with the specified parameters on the specified ``tx`` and ``rx`` pins. Note that for correct communication, the parameters have to be the same on both communicating devices. .. warning:: Initializing the UART on external pins will cause the Python console on USB to become unaccessible, as it uses the same hardware. To bring the console back you must reinitialize the UART without passing anything for ``tx'' or ``rx'' (or passing ``None'' to these arguments). This means that calling ``uart.init(115200)'' is enough to restore the Python console. The ``baudrate`` defines the speed of communication. Common baud rates include: * 9600 * 14400 * 19200 * 28800 * 38400 * 57600 * 115200 The ``bits`` defines the size of bytes being transmitted, and the board only supports 8. The ``parity`` parameter defines how parity is checked, and it can be ``None``, ``microbit.uart.ODD`` or ``microbit.uart.EVEN``. The ``stop`` parameter tells the number of stop bits, and has to be 1 for this board. If ``tx`` and ``rx`` are not specified then the internal USB-UART TX/RX pins are used which connect to the USB serial convertor on the micro:bit, thus connecting the UART to your PC. You can specify any other pins you want by passing the desired pin objects to the ``tx`` and ``rx`` parameters. .. note:: When connecting the device, make sure you "cross" the wires -- the TX pin on your board needs to be connected with the RX pin on the device, and the RX pin -- with the TX pin on the device. Also make sure the ground pins of both devices are connected. """ def any() -> bool: """Return ``True`` if any characters waiting, else ``False``.""" def read(nbytes: int = None) -> bytes: """Read characters. If ``nbytes`` is specified then read at most that many bytes.""" def readall() -> Optional[bytes]: """Read as much data as possible. Return value: a bytes object or ``None`` on timeout. """ def readinto(buf: bytearray, nbytes: int = None) -> Optional[int]: """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. """ def readline() -> Optional[bytes]: """Read a line, ending in a newline character. Return value: the line read or ``None`` on timeout. The newline character is included in the returned bytes. """ def write(buf: Union[bytes, bytearray]) -> Optional[int]: """Write the buffer of bytes to the bus. Return value: number of bytes written or ``None`` on timeout. """ ODD: int EVEN: int ================================================ FILE: typehints/microbit/music.pyi ================================================ """ MicroPython on the BBC micro:bit comes with a powerful music and sound module. It’s very easy to generate bleeps and bloops from the device if you attach a speaker. Use crocodile clips to attach pin 0 and GND to the positive and negative inputs on the speaker - it doesn’t matter which way round they are connected to the speaker. Musical Notation An individual note is specified thus: NOTE[octave][:duration] For example, A1:4 refers to the note “A” in octave 1 that lasts for four ticks (a tick is an arbitrary length of time defined by a tempo setting function - see below). If the note name R is used then it is treated as a rest (silence). Accidentals (flats and sharps) are denoted by the b (flat - a lower case b) and # (sharp - a hash symbol). For example, Ab is A-flat and C# is C-sharp. Note names are case-insensitive. The octave and duration parameters are states that carry over to subsequent notes until re-specified. The default states are octave = 4 (containing middle C) and duration = 4 (a crotchet, given the default tempo settings - see below). For example, if 4 ticks is a crotchet, the following list is crotchet, quaver, quaver, crotchet based arpeggio: ['c1:4', 'e:2', 'g', 'c2:4'] The opening of Beethoven’s 5th Symphony would be encoded thus: ['r4:2', 'g', 'g', 'g', 'eb:8', 'r:2', 'f', 'f', 'f', 'd:8'] The definition and scope of an octave conforms to the table listed on this page about scientific pitch notation. For example, middle “C” is c4' and concert “A” (440) is 'a4'. Octaves start on the note “C”. The definition and scope of an octave conforms to the table listed on this page about scientific pitch notation. For example, middle “C” is 'c4' and concert “A” (440) is 'a4'. Octaves start on the note “C”. Built in Melodies For the purposes of education and entertainment, the module contains several example tunes that are expressed as Python lists. They can be used like this: import music music.play(music.NYAN) All the tunes are either out of copyright, composed by Nicholas H.Tollervey and released to the public domain or have an unknown composer and are covered by a fair (educational) use provision. They are: DADADADUM - the opening to Beethoven’s 5th Symphony in C minor. ENTERTAINER - the opening fragment of Scott Joplin’s Ragtime classic “The Entertainer”. PRELUDE - the opening of the first Prelude in C Major of J.S.Bach’s 48 Preludes and Fugues. ODE - the “Ode to Joy” theme from Beethoven’s 9th Symphony in D minor. NYAN - the Nyan Cat theme (http://www.nyan.cat/). The composer is unknown. This is fair use for educational porpoises (as they say in New York). RINGTONE - something that sounds like a mobile phone ringtone. To be used to indicate an incoming message. FUNK - a funky bass line for secret agents and criminal masterminds. BLUES - a boogie-woogie 12-bar blues walking bass. BIRTHDAY - “Happy Birthday to You...” for copyright status see: http://www.bbc.co.uk/news/world-us-canada-34332853 WEDDING - the bridal chorus from Wagner’s opera “Lohengrin”. FUNERAL - the “funeral march” otherwise known as Frédéric Chopin’s Piano Sonata No. 2 in B♭ minor, Op. 35. PUNCHLINE - a fun fragment that signifies a joke has been made. PYTHON - John Philip Sousa’s march “Liberty Bell” aka, the theme for “Monty Python’s Flying Circus” (after which the Python programming language is named). BADDY - silent movie era entrance of a baddy. CHASE - silent movie era chase scene. BA_DING - a short signal to indicate something has happened. WAWAWAWAA - a very sad trombone. JUMP_UP - for use in a game, indicating upward movement. JUMP_DOWN - for use in a game, indicating downward movement. POWER_UP - a fanfare to indicate an achievement unlocked. POWER_DOWN - a sad fanfare to indicate an achievement lost. Example Plays a simple tune using the Micropython music module. This example requires a speaker/buzzer/headphones connected to P0 and GND. from microbit import * import music # play Prelude in C. notes = [ 'c4:1', 'e', 'g', 'c5', 'e5', 'g4', 'c5', 'e5', 'c4', 'e', 'g', 'c5', 'e5', 'g4', 'c5', 'e5', 'c4', 'd', 'g', 'd5', 'f5', 'g4', 'd5', 'f5', 'c4', 'd', 'g', 'd5', 'f5', 'g4', 'd5', 'f5', 'b3', 'd4', 'g', 'd5', 'f5', 'g4', 'd5', 'f5', 'b3', 'd4', 'g', 'd5', 'f5', 'g4', 'd5', 'f5', 'c4', 'e', 'g', 'c5', 'e5', 'g4', 'c5', 'e5', 'c4', 'e', 'g', 'c5', 'e5', 'g4', 'c5', 'e5', 'c4', 'e', 'a', 'e5', 'a5', 'a4', 'e5', 'a5', 'c4', 'e', 'a', 'e5', 'a5', 'a4', 'e5', 'a5', 'c4', 'd', 'f#', 'a', 'd5', 'f#4', 'a', 'd5', 'c4', 'd', 'f#', 'a', 'd5', 'f#4', 'a', 'd5', 'b3', 'd4', 'g', 'd5', 'g5', 'g4', 'd5', 'g5', 'b3', 'd4', 'g', 'd5', 'g5', 'g4', 'd5', 'g5', 'b3', 'c4', 'e', 'g', 'c5', 'e4', 'g', 'c5', 'b3', 'c4', 'e', 'g', 'c5', 'e4', 'g', 'c5', 'b3', 'c4', 'e', 'g', 'c5', 'e4', 'g', 'c5', 'b3', 'c4', 'e', 'g', 'c5', 'e4', 'g', 'c5', 'a3', 'c4', 'e', 'g', 'c5', 'e4', 'g', 'c5', 'a3', 'c4', 'e', 'g', 'c5', 'e4', 'g', 'c5', 'd3', 'a', 'd4', 'f#', 'c5', 'd4', 'f#', 'c5', 'd3', 'a', 'd4', 'f#', 'c5', 'd4', 'f#', 'c5', 'g3', 'b', 'd4', 'g', 'b', 'd', 'g', 'b', 'g3', 'b3', 'd4', 'g', 'b', 'd', 'g', 'b' ] music.play(notes) """ from typing import Tuple, Union, List from . microbit import pin0, MicroBitAnalogDigitalPin DADADADUM = 0 ENTERTAINER = 1 PRELUDE = 2 ODE = 3 NYAN = 4 RINGTONE = 5 FUNK = 6 BLUES = 7 BIRTHDAY = 8 WEDDING = 9 FUNERAL = 10 PUNCHLINE = 11 PYTHON = 12 BADDY = 12 CHASE = 13 BA_DING = 14 WAWAWAWAA = 15 JUMP_UP = 16 JUMP_DOWN = 17 POWER_UP = 18 POWER_DOWN = 19 def set_tempo(ticks: int = 4, bpm: int = 120) -> None: """ Sets the approximate tempo for playback. A number of ticks (expressed as an integer) constitute a beat. Each beat is to be played at a certain frequency per minute (expressed as the more familiar BPM - beats per minute - also as an integer). Suggested default values allow the following useful behaviour: music.set_tempo() - reset the tempo to default of ticks = 4, bpm = 120 music.set_tempo(ticks=8) - change the “definition” of a beat music.set_tempo(bpm=180) - just change the tempo To work out the length of a tick in milliseconds is very simple arithmetic: 60000/bpm/ticks_per_beat . For the default values that’s 60000/120/4 = 125 milliseconds or 1 beat = 500 milliseconds. """ def get_tempo(self) -> Tuple[int, int]: """ Gets the current tempo as a tuple of integers: (ticks, bpm). """ def play(music: Union[str, List[str]], pin: MicroBitAnalogDigitalPin = pin0, wait: bool=True, loop: bool=False) -> None: """ Sets the approximate tempo for playback. A number of ticks (expressed as an integer) constitute a beat. Each beat is to be played at a certain frequency per minute (expressed as the more familiar BPM - beats per minute - also as an integer). Suggested default values allow the following useful behaviour: music.set_tempo() - reset the tempo to default of ticks = 4, bpm = 120 music.set_tempo(ticks=8) - change the “definition” of a beat music.set_tempo(bpm=180) - just change the tempo To work out the length of a tick in milliseconds is very simple arithmetic: 60000/bpm/ticks_per_beat . For the default values that’s 60000/120/4 = 125 milliseconds or 1 beat = 500 milliseconds. """ def pitch(frequency: int, len=-1, pin: MicroBitAnalogDigitalPin = pin0, wait: bool=True) -> None: """ Plays a pitch at the integer frequency given for the specified number of milliseconds. For example, if the frequency is set to 440 and the length to 1000 then we hear a standard concert A for one second. If wait is set to True, this function is blocking. If len is negative the pitch is played continuously until either the blocking call is interrupted or, in the case of a background call, a new frequency is set or stop is called (see below). """ def stop(pin: MicroBitAnalogDigitalPin = pin0) -> None: """ Stops all music playback on a given pin. """ def reset() -> None: """ Resets the state of the following attributes in the following way: ticks = 4 bpm = 120 duration = 4 octave = 4 """ ================================================ FILE: typehints/microbit/neopixel.pyi ================================================ """ The neopixel module lets you use Neopixel (WS2812) individually addressable RGB LED strips with the Microbit. Note to use the neopixel module, you need to import it separately with: import neopixel Note From our tests, the Microbit Neopixel module can drive up to around 256 Neopixels. Anything above that and you may experience weird bugs and issues. NeoPixels are fun strips of multi-coloured programmable LEDs. This module contains everything to plug them into a micro:bit and create funky displays, art and games Warning Do not use the 3v connector on the Microbit to power any more than 8 Neopixels at a time. If you wish to use more than 8 Neopixels, you must use a separate 3v-5v power supply for the Neopixel power pin. Operations Writing the colour doesn’t update the display (use show() for that). np[0] = (255, 0, 128) # first element np[-1] = (0, 255, 0) # last element np.show() # only now will the updated value be shown To read the colour of a specific pixel just reference it. print(np[0]) Using Neopixels Interact with Neopixels as if they were a list of tuples. Each tuple represents the RGB (red, green and blue) mix of colours for a specific pixel. The RGB values can range between 0 to 255. For example, initialise a strip of 8 neopixels on a strip connected to pin0 like this: import neopixel np = neopixel.NeoPixel(pin0, 8) Set pixels by indexing them (like with a Python list). For instance, to set the first pixel to full brightness red, you would use: np[0] = (255, 0, 0) Or the final pixel to purple: np[-1] = (255, 0, 255) Get the current colour value of a pixel by indexing it. For example, to print the first pixel’s RGB value use: print(np[0]) Finally, to push the new colour data to your Neopixel strip, use the .show() function: np.show() If nothing is happening, it’s probably because you’ve forgotten this final step..! Note If you’re not seeing anything change on your Neopixel strip, make sure you have show() at least somewhere otherwise your updates won’t be shown. """ from . microbit import MicroBitAnalogDigitalPin def NeoPixel(pin: MicroBitAnalogDigitalPin, n: int)-> None: """ Initialise a new strip of n number of neopixel LEDs controlled via pin pin. Each pixel is addressed by a position (starting from 0). Neopixels are given RGB (red, green, blue) values between 0-255 as a tuple. For example, (255,255,255) is white. """ def clear()->None: """ Clear all the pixels. """ def show()->None: """ Show the pixels. Must be called for any updates to become visible. """ ================================================ FILE: typehints/microbit/radio.pyi ================================================ """The ``radio`` module allows devices to work together via simple wireless networks. The radio module is conceptually very simple: * Broadcast messages are of a certain configurable length (up to 251 bytes). * Messages received are read from a queue of configurable size (the larger the queue the more RAM is used). If the queue is full, new messages are ignored. * Messages are broadcast and received on a preselected channel (numbered 0-100). * Broadcasts are at a certain level of power - more power means more range. * Messages are filtered by address (like a house number) and group (like a named recipient at the specified address). * The rate of throughput can be one of three pre-determined settings. * Send and receieve bytes to work with arbitrary data. * As a convenience for children, it's easy to send and receive messages as strings. * The default configuration is both sensible and compatible with other platforms that target the BBC micro:bit. To access this module you need to:: import radio We assume you have done this for the examples below. """ from typing import Optional RATE_250KBIT: int """Constant used to indicate a throughput of 256 Kbit a second.""" RATE_1MBIT: int """Constant used to indicate a throughput of 1 MBit a second.""" RATE_2MBIT: int """Constant used to indicate a throughput of 2 MBit a second.""" def on() -> None: """Turns the radio on. This needs to be explicitly called since the radio draws power and takes up memory that you may otherwise need. """ def off() -> None: """Turns off the radio, thus saving power and memory.""" def config(length: int = 32, queue: int = 3, channel: int = 7, power: int = 6, address: int = 0x75626974, group: int = 0, data_rate: int = RATE_1MBIT) -> None: """Configures various keyword based settings relating to the radio. The available settings and their sensible default values are listed below. The ``length`` (default=32) defines the maximum length, in bytes, of a message sent via the radio. It can be up to 251 bytes long (254 - 3 bytes for S0, LENGTH and S1 preamble). The ``queue`` (default=3) specifies the number of messages that can be stored on the incoming message queue. If there are no spaces left on the queue for incoming messages, then the incoming message is dropped. The ``channel`` (default=7) can be an integer value from 0 to 100 (inclusive) that defines an arbitrary "channel" to which the radio is tuned. Messages will be sent via this channel and only messages received via this channel will be put onto the incoming message queue. Each step is 1MHz wide, based at 2400MHz. The ``power`` (default=6) is an integer value from 0 to 7 (inclusive) to indicate the strength of signal used when broadcasting a message. The higher the value the stronger the signal, but the more power is consumed by the device. The numbering translates to positions in the following list of dBm (decibel milliwatt) values: -30, -20, -16, -12, -8, -4, 0, 4. The ``address`` (default=0x75626974) is an arbitrary name, expressed as a 32-bit address, that's used to filter incoming packets at the hardware level, keeping only those that match the address you set. The default used by other micro:bit related platforms is the default setting used here. The ``group`` (default=0) is an 8-bit value (0-255) used with the ``address`` when filtering messages. Conceptually, "address" is like a house/office address and "group" is like the person at that address to which you want to send your message. The ``data_rate`` (default=radio.RATE_1MBIT) indicates the speed at which data throughput takes place. Can be one of the following contants defined in the ``radio`` module : ``RATE_250KBIT``, ``RATE_1MBIT`` or ``RATE_2MBIT``. If ``config`` is not called then the defaults described above are assumed. """ def reset() -> None: """Reset the settings to their default values (as listed in the documentation for the ``config`` function above). """ def send_bytes(message: bytes) -> None: """Sends a message containing bytes.""" def receive_bytes() -> Optional[bytes]: """Receive the next incoming message on the message queue. Returns ``None`` if there are no pending messages. Messages are returned as bytes. """ def receive_bytes_into(buffer: bytearray) -> Optional[int]: """Receive the next incoming message on the message queue. Copies the message into ``buffer``, trimming the end of the message if necessary. Returns ``None`` if there are no pending messages, otherwise it returns the length of the message (which might be more than the length of the buffer). """ def send(message: str) -> None: """Sends a message string. This is the equivalent of ``send_bytes(bytes(message, 'utf8'))`` but with ``b'\x01\x00\x01'`` prepended to the front (to make it compatible with other platforms that target the micro:bit). """ def receive() -> Optional[str]: """Works in exactly the same way as ``receive_bytes`` but returns whatever was sent. Currently, it's equivalent to ``str(receive_bytes(), 'utf8')`` but with a check that the the first three bytes are ``b'\x01\x00\x01'`` (to make it compatible with other platforms that may target the micro:bit). It strips the prepended bytes before converting to a string. A ``ValueError`` exception is raised if conversion to string fails. """ ================================================ FILE: typehints/microbit/speech.pyi ================================================ """ Speech Warning WARNING! THIS IS ALPHA CODE. We reserve the right to change this API as development continues. The quality of the speech is not great, merely “good enough”. Given the constraints of the device you may encounter memory errors and / or unexpected extra sounds during playback. It’s early days and we’re improving the code for the speech synthesiser all the time. Bug reports and pull requests are most welcome. This module makes microbit talk, sing and make other speech like sounds provided that you connect a speaker to your board. Note This work is based upon the amazing reverse engineering efforts of Sebastian Macke based upon an old text-to-speech (TTS) program called SAM (Software Automated Mouth) originally released in 1982 for the Commodore 64. The result is a small C library that we have adopted and adapted for the micro:bit. You can find out more from his homepage. Much of the information in this document was gleaned from the original user’s manual which can be found here. The speech synthesiser can produce around 2.5 seconds worth of sound from up to 255 characters of textual input. To access this module you need to: import speech See http://microbit-micropython.readthedocs.io/en/latest/speech.html for details """ def translate(words: str) ->None: """ Given English words in the string words, return a string containing a best guess at the appropriate phonemes to pronounce. The output is generated from this text to phoneme translation table. This function should be used to generate a first approximation of phonemes that can be further hand-edited to improve accuracy, inflection and emphasis. """ def pronounce(phonemes: str, pitch: int=64, speed: int=72, mouth: int=128, throat: int=128)->None: """ Pronounce the phonemes in the string phonemes. See below for details of how to use phonemes to finely control the output of the speech synthesiser. Override the optional pitch, speed, mouth and throat settings to change the timbre (quality) of the voice. """ def say(words: str, pitch: int=64, speed: int=72, mouth: int=128, throat: int=128)->None: """ Say the English words in the string words. The result is semi-accurate for English. Override the optional pitch, speed, mouth and throat settings to change the timbre (quality) of the voice. This is a short-hand equivalent of: speech.pronounce(speech.translate(words)) """ def sing(phonemes: str, pitch: int=64, speed: int=72, mouth: int=128, throat: int=128)->None: """ Sing the phonemes contained in the string phonemes. Changing the pitch and duration of the note is described below. Override the optional pitch, speed, mouth and throat settings to change the timbre (quality) of the voice. """ ================================================ FILE: typehints/micropython/bluetooth.pyi ================================================ """ Low-level Bluetooth radio functionality. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/bluetooth.rst. This module provides an interface to a Bluetooth controller on a board. Currently this supports Bluetooth Low Energy (BLE) in Central, Peripheral, Broadcaster, and Observer roles, as well as GATT Server and Client and L2CAP connection-oriented-channels. A device may operate in multiple roles concurrently. Pairing (and bonding) is supported on some ports. This API is intended to match the low-level Bluetooth protocol and provide building-blocks for higher-level abstractions such as specific device types. .. note:: This module is still under development and its classes, functions, methods and constants are subject to change. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import overload, Any, Callable, Final from uio import AnyReadableBuf, AnyWritableBuf # noinspection SpellCheckingInspection class BLE: """ class BLE --------- """ def __init__(self): """ Returns the singleton BLE object. """ @overload def active(self) -> bool: """ Optionally changes the active state of the BLE radio, and returns the current state. The radio must be made active before using any other methods on this class. """ @overload def active(self, active: bool, /) -> None: """ Optionally changes the active state of the BLE radio, and returns the current state. The radio must be made active before using any other methods on this class. """ @overload def config(self, param: str, /) -> Any: """ Get or set configuration values of the BLE interface. To get a value the parameter name should be quoted as a string, and just one parameter is queried at a time. To set values use the keyword syntax, and one ore more parameter can be set at a time. Currently supported values are: - ``'mac'``: The current address in use, depending on the current address mode. This returns a tuple of ``(addr_type, addr)``. See :meth:`gatts_write ` for details about address type. This may only be queried while the interface is currently active. - ``'addr_mode'``: Sets the address mode. Values can be: * 0x00 - PUBLIC - Use the controller's public address. * 0x01 - RANDOM - Use a generated static address. * 0x02 - RPA - Use resolvable private addresses. * 0x03 - NRPA - Use non-resolvable private addresses. By default the interface mode will use a PUBLIC address if available, otherwise it will use a RANDOM address. - ``'gap_name'``: Get/set the GAP device name used by service 0x1800, characteristic 0x2a00. This can be set at any time and changed multiple times. - ``'rxbuf'``: Get/set the size in bytes of the internal buffer used to store incoming events. This buffer is global to the entire BLE driver and so handles incoming data for all events, including all characteristics. Increasing this allows better handling of bursty incoming data (for example scan results) and the ability to receive larger characteristic values. - ``'mtu'``: Get/set the MTU that will be used during a ATT MTU exchange. The resulting MTU will be the minimum of this and the remote device's MTU. ATT MTU exchange will not happen automatically (unless the remote device initiates it), and must be manually initiated with :meth:`gattc_exchange_mtu`. Use the ``_IRQ_MTU_EXCHANGED`` event to discover the MTU for a given connection. - ``'bond'``: Sets whether bonding will be enabled during pairing. When enabled, pairing requests will set the "bond" flag and the keys will be stored by both devices. - ``'mitm'``: Sets whether MITM-protection is required for pairing. - ``'io'``: Sets the I/O capabilities of this device. Available options are:: _IO_CAPABILITY_DISPLAY_ONLY = const(0) _IO_CAPABILITY_DISPLAY_YESNO = const(1) _IO_CAPABILITY_KEYBOARD_ONLY = const(2) _IO_CAPABILITY_NO_INPUT_OUTPUT = const(3) _IO_CAPABILITY_KEYBOARD_DISPLAY = const(4) - ``'le_secure'``: Sets whether "LE Secure" pairing is required. Default is false (i.e. allow "Legacy Pairing"). """ @overload def config(self, **kwargs) -> None: """ Get or set configuration values of the BLE interface. To get a value the parameter name should be quoted as a string, and just one parameter is queried at a time. To set values use the keyword syntax, and one ore more parameter can be set at a time. Currently supported values are: - ``'mac'``: The current address in use, depending on the current address mode. This returns a tuple of ``(addr_type, addr)``. See :meth:`gatts_write ` for details about address type. This may only be queried while the interface is currently active. - ``'addr_mode'``: Sets the address mode. Values can be: * 0x00 - PUBLIC - Use the controller's public address. * 0x01 - RANDOM - Use a generated static address. * 0x02 - RPA - Use resolvable private addresses. * 0x03 - NRPA - Use non-resolvable private addresses. By default the interface mode will use a PUBLIC address if available, otherwise it will use a RANDOM address. - ``'gap_name'``: Get/set the GAP device name used by service 0x1800, characteristic 0x2a00. This can be set at any time and changed multiple times. - ``'rxbuf'``: Get/set the size in bytes of the internal buffer used to store incoming events. This buffer is global to the entire BLE driver and so handles incoming data for all events, including all characteristics. Increasing this allows better handling of bursty incoming data (for example scan results) and the ability to receive larger characteristic values. - ``'mtu'``: Get/set the MTU that will be used during a ATT MTU exchange. The resulting MTU will be the minimum of this and the remote device's MTU. ATT MTU exchange will not happen automatically (unless the remote device initiates it), and must be manually initiated with :meth:`gattc_exchange_mtu`. Use the ``_IRQ_MTU_EXCHANGED`` event to discover the MTU for a given connection. - ``'bond'``: Sets whether bonding will be enabled during pairing. When enabled, pairing requests will set the "bond" flag and the keys will be stored by both devices. - ``'mitm'``: Sets whether MITM-protection is required for pairing. - ``'io'``: Sets the I/O capabilities of this device. Available options are:: _IO_CAPABILITY_DISPLAY_ONLY = const(0) _IO_CAPABILITY_DISPLAY_YESNO = const(1) _IO_CAPABILITY_KEYBOARD_ONLY = const(2) _IO_CAPABILITY_NO_INPUT_OUTPUT = const(3) _IO_CAPABILITY_KEYBOARD_DISPLAY = const(4) - ``'le_secure'``: Sets whether "LE Secure" pairing is required. Default is false (i.e. allow "Legacy Pairing"). """ def irq(self, handler: Callable[[int, tuple[memoryview, ...]], Any], /) -> None: """ Registers a callback for events from the BLE stack. The *handler* takes two arguments, ``event`` (which will be one of the codes below) and ``data`` (which is an event-specific tuple of values). **Note:** As an optimisation to prevent unnecessary allocations, the ``addr``, ``adv_data``, ``char_data``, ``notify_data``, and ``uuid`` entries in the tuples are read-only memoryview instances pointing to :mod:`bluetooth`'s internal ringbuffer, and are only valid during the invocation of the IRQ handler function. If your program needs to save one of these values to access after the IRQ handler has returned (e.g. by saving it in a class instance or global variable), then it needs to take a copy of the data, either by using ``bytes()`` or ``bluetooth.UUID()``, like this:: connected_addr = bytes(addr) # equivalently: adv_data, char_data, or notify_data matched_uuid = bluetooth.UUID(uuid) For example, the IRQ handler for a scan result might inspect the ``adv_data`` to decide if it's the correct device, and only then copy the address data to be used elsewhere in the program. And to print data from within the IRQ handler, ``print(bytes(addr))`` will be needed. An event handler showing all possible events:: def bt_irq(event, data): if event == _IRQ_CENTRAL_CONNECT: # A central has connected to this peripheral. conn_handle, addr_type, addr = data elif event == _IRQ_CENTRAL_DISCONNECT: # A central has disconnected from this peripheral. conn_handle, addr_type, addr = data elif event == _IRQ_GATTS_WRITE: # A client has written to this characteristic or descriptor. conn_handle, attr_handle = data elif event == _IRQ_GATTS_READ_REQUEST: # A client has issued a read. Note: this is only supported on STM32. # Return a non-zero integer to deny the read (see below), or zero (or None) # to accept the read. conn_handle, attr_handle = data elif event == _IRQ_SCAN_RESULT: # A single scan result. addr_type, addr, adv_type, rssi, adv_data = data elif event == _IRQ_SCAN_DONE: # Scan duration finished or manually stopped. pass elif event == _IRQ_PERIPHERAL_CONNECT: # A successful gap_connect(). conn_handle, addr_type, addr = data elif event == _IRQ_PERIPHERAL_DISCONNECT: # Connected peripheral has disconnected. conn_handle, addr_type, addr = data elif event == _IRQ_GATTC_SERVICE_RESULT: # Called for each service found by gattc_discover_services(). conn_handle, start_handle, end_handle, uuid = data elif event == _IRQ_GATTC_SERVICE_DONE: # Called once service discovery is complete. # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, status = data elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT: # Called for each characteristic found by gattc_discover_services(). conn_handle, def_handle, value_handle, properties, uuid = data elif event == _IRQ_GATTC_CHARACTERISTIC_DONE: # Called once service discovery is complete. # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, status = data elif event == _IRQ_GATTC_DESCRIPTOR_RESULT: # Called for each descriptor found by gattc_discover_descriptors(). conn_handle, dsc_handle, uuid = data elif event == _IRQ_GATTC_DESCRIPTOR_DONE: # Called once service discovery is complete. # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, status = data elif event == _IRQ_GATTC_READ_RESULT: # A gattc_read() has completed. conn_handle, value_handle, char_data = data elif event == _IRQ_GATTC_READ_DONE: # A gattc_read() has completed. # Note: The value_handle will be zero on btstack (but present on NimBLE). # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, value_handle, status = data elif event == _IRQ_GATTC_WRITE_DONE: # A gattc_write() has completed. # Note: The value_handle will be zero on btstack (but present on NimBLE). # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, value_handle, status = data elif event == _IRQ_GATTC_NOTIFY: # A server has sent a notify request. conn_handle, value_handle, notify_data = data elif event == _IRQ_GATTC_INDICATE: # A server has sent an indicate request. conn_handle, value_handle, notify_data = data elif event == _IRQ_GATTS_INDICATE_DONE: # A client has acknowledged the indication. # Note: Status will be zero on successful acknowledgment, implementation-specific value otherwise. conn_handle, value_handle, status = data elif event == _IRQ_MTU_EXCHANGED: # ATT MTU exchange complete (either initiated by us or the remote device). conn_handle, mtu = data elif event == _IRQ_L2CAP_ACCEPT: # A new channel has been accepted. # Return a non-zero integer to reject the connection, or zero (or None) to accept. conn_handle, cid, psm, our_mtu, peer_mtu = data elif event == _IRQ_L2CAP_CONNECT: # A new channel is now connected (either as a result of connecting or accepting). conn_handle, cid, psm, our_mtu, peer_mtu = data elif event == _IRQ_L2CAP_DISCONNECT: # Existing channel has disconnected (status is zero), or a connection attempt failed (non-zero status). conn_handle, cid, psm, status = data elif event == _IRQ_L2CAP_RECV: # New data is available on the channel. Use l2cap_recvinto to read. conn_handle, cid = data elif event == _IRQ_L2CAP_SEND_READY: # A previous l2cap_send that returned False has now completed and the channel is ready to send again. # If status is non-zero, then the transmit buffer overflowed and the application should re-send the data. conn_handle, cid, status = data elif event == _IRQ_CONNECTION_UPDATE: # The remote device has updated connection parameters. conn_handle, conn_interval, conn_latency, supervision_timeout, status = data elif event == _IRQ_ENCRYPTION_UPDATE: # The encryption state has changed (likely as a result of pairing or bonding). conn_handle, encrypted, authenticated, bonded, key_size = data elif event == _IRQ_GET_SECRET: # Return a stored secret. # If key is None, return the index'th value of this sec_type. # Otherwise return the corresponding value for this sec_type and key. sec_type, index, key = data return value elif event == _IRQ_SET_SECRET: # Save a secret to the store for this sec_type and key. sec_type, key, value = data return True elif event == _IRQ_PASSKEY_ACTION: # Respond to a passkey request during pairing. # See gap_passkey() for details. # action will be an action that is compatible with the configured "io" config. # passkey will be non-zero if action is "numeric comparison". conn_handle, action, passkey = data The event codes are:: from micropython import const _IRQ_CENTRAL_CONNECT = const(1) _IRQ_CENTRAL_DISCONNECT = const(2) _IRQ_GATTS_WRITE = const(3) _IRQ_GATTS_READ_REQUEST = const(4) _IRQ_SCAN_RESULT = const(5) _IRQ_SCAN_DONE = const(6) _IRQ_PERIPHERAL_CONNECT = const(7) _IRQ_PERIPHERAL_DISCONNECT = const(8) _IRQ_GATTC_SERVICE_RESULT = const(9) _IRQ_GATTC_SERVICE_DONE = const(10) _IRQ_GATTC_CHARACTERISTIC_RESULT = const(11) _IRQ_GATTC_CHARACTERISTIC_DONE = const(12) _IRQ_GATTC_DESCRIPTOR_RESULT = const(13) _IRQ_GATTC_DESCRIPTOR_DONE = const(14) _IRQ_GATTC_READ_RESULT = const(15) _IRQ_GATTC_READ_DONE = const(16) _IRQ_GATTC_WRITE_DONE = const(17) _IRQ_GATTC_NOTIFY = const(18) _IRQ_GATTC_INDICATE = const(19) _IRQ_GATTS_INDICATE_DONE = const(20) _IRQ_MTU_EXCHANGED = const(21) _IRQ_L2CAP_ACCEPT = const(22) _IRQ_L2CAP_CONNECT = const(23) _IRQ_L2CAP_DISCONNECT = const(24) _IRQ_L2CAP_RECV = const(25) _IRQ_L2CAP_SEND_READY = const(26) _IRQ_CONNECTION_UPDATE = const(27) _IRQ_ENCRYPTION_UPDATE = const(28) _IRQ_GET_SECRET = const(29) _IRQ_SET_SECRET = const(30) For the ``_IRQ_GATTS_READ_REQUEST`` event, the available return codes are:: _GATTS_NO_ERROR = const(0x00) _GATTS_ERROR_READ_NOT_PERMITTED = const(0x02) _GATTS_ERROR_WRITE_NOT_PERMITTED = const(0x03) _GATTS_ERROR_INSUFFICIENT_AUTHENTICATION = const(0x05) _GATTS_ERROR_INSUFFICIENT_AUTHORIZATION = const(0x08) _GATTS_ERROR_INSUFFICIENT_ENCRYPTION = const(0x0f) For the ``_IRQ_PASSKEY_ACTION`` event, the available actions are:: _PASSKEY_ACTION_NONE = const(0) _PASSKEY_ACTION_INPUT = const(2) _PASSKEY_ACTION_DISPLAY = const(3) _PASSKEY_ACTION_NUMERIC_COMPARISON = const(4) In order to save space in the firmware, these constants are not included on the :mod:`bluetooth` module. Add the ones that you need from the list above to your program. """ def gap_advertise( self, interval_us: int, adv_data: AnyReadableBuf | None = None, /, *, resp_data: AnyReadableBuf | None = None, connectable: bool = True, ) -> None: """ Starts advertising at the specified interval (in **micro**\ seconds). This interval will be rounded down to the nearest 625us. To stop advertising, set *interval_us* to ``None``. *adv_data* and *resp_data* can be any type that implements the buffer protocol (e.g. ``bytes``, ``bytearray``, ``str``). *adv_data* is included in all broadcasts, and *resp_data* is send in reply to an active scan. **Note:** if *adv_data* (or *resp_data*) is ``None``, then the data passed to the previous call to ``gap_advertise`` will be re-used. This allows a broadcaster to resume advertising with just ``gap_advertise(interval_us)``. To clear the advertising payload pass an empty ``bytes``, i.e. ``b''``. """ def gap_scan( self, duration_ms: int, interval_us: int = 1280000, window_us: int = 11250, active: bool = False, /, ) -> None: """ Run a scan operation lasting for the specified duration (in **milli**\ seconds). To scan indefinitely, set *duration_ms* to ``0``. To stop scanning, set *duration_ms* to ``None``. Use *interval_us* and *window_us* to optionally configure the duty cycle. The scanner will run for *window_us* **micro**\ seconds every *interval_us* **micro**\ seconds for a total of *duration_ms* **milli**\ seconds. The default interval and window are 1.28 seconds and 11.25 milliseconds respectively (background scanning). For each scan result the ``_IRQ_SCAN_RESULT`` event will be raised, with event data ``(addr_type, addr, adv_type, rssi, adv_data)``. ``addr_type`` values indicate public or random addresses: * 0x00 - PUBLIC * 0x01 - RANDOM (either static, RPA, or NRPA, the type is encoded in the address itself) ``adv_type`` values correspond to the Bluetooth Specification: * 0x00 - ADV_IND - connectable and scannable undirected advertising * 0x01 - ADV_DIRECT_IND - connectable directed advertising * 0x02 - ADV_SCAN_IND - scannable undirected advertising * 0x03 - ADV_NONCONN_IND - non-connectable undirected advertising * 0x04 - SCAN_RSP - scan response ``active`` can be set ``True`` if you want to receive scan responses in the results. When scanning is stopped (either due to the duration finishing or when explicitly stopped), the ``_IRQ_SCAN_DONE`` event will be raised. """ def gap_connect( self, addr_type: int, addr: bytes, scan_duration_ms: int = 2000, min_conn_interval_us: int | None = None, max_conn_interval_us: int | None = None, /, ) -> None: """ Connect to a peripheral. See :meth:`gap_scan ` for details about address types. On success, the ``_IRQ_PERIPHERAL_CONNECT`` event will be raised. The device will wait up to *scan_duration_ms* to receive an advertising payload from the device. The connection interval can be configured in **micro**\ seconds using either or both of *min_conn_interval_us* and *max_conn_interval_us*. Otherwise a default interval will be chosen, typically between 30000 and 50000 microseconds. A shorter interval will increase throughput, at the expense of power usage. Central Role ------------ A central device can connect to peripherals that it has discovered using the observer role (see :meth:`gap_scan`) or with a known address. """ def gap_disconnect(self, conn_handle: memoryview, /) -> bool: """ Disconnect the specified connection handle. This can either be a central that has connected to this device (if acting as a peripheral) or a peripheral that was previously connected to by this device (if acting as a central). On success, the ``_IRQ_PERIPHERAL_DISCONNECT`` or ``_IRQ_CENTRAL_DISCONNECT`` event will be raised. Returns ``False`` if the connection handle wasn't connected, and ``True`` otherwise. Central Role ------------ A central device can connect to peripherals that it has discovered using the observer role (see :meth:`gap_scan`) or with a known address. Peripheral Role --------------- A peripheral device is expected to send connectable advertisements (see :meth:`gap_advertise`). It will usually be acting as a GATT server, having first registered services and characteristics using :meth:`gatts_register_services`. When a central connects, the ``_IRQ_CENTRAL_CONNECT`` event will be raised. """ _Flag: Final = int _Descriptor: Final = tuple["UUID", _Flag] _Characteristic: Final = tuple["UUID", _Flag] | tuple[ "UUID", _Flag, tuple[_Descriptor, ...] ] _Service: Final = tuple["UUID", tuple[_Characteristic, ...]] def gatts_register_services( self, services_definition: tuple[_Service, ...], / ) -> tuple[tuple[memoryview, ...], ...]: """ Configures the server with the specified services, replacing any existing services. *services_definition* is a list of **services**, where each **service** is a two-element tuple containing a UUID and a list of **characteristics**. Each **characteristic** is a two-or-three-element tuple containing a UUID, a **flags** value, and optionally a list of *descriptors*. Each **descriptor** is a two-element tuple containing a UUID and a **flags** value. The **flags** are a bitwise-OR combination of the flags defined below. These set both the behaviour of the characteristic (or descriptor) as well as the security and privacy requirements. The return value is a list (one element per service) of tuples (each element is a value handle). Characteristics and descriptor handles are flattened into the same tuple, in the order that they are defined. The following example registers two services (Heart Rate, and Nordic UART):: HR_UUID = bluetooth.UUID(0x180D) HR_CHAR = (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,) HR_SERVICE = (HR_UUID, (HR_CHAR,),) UART_UUID = bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E') UART_TX = (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,) UART_RX = (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE,) UART_SERVICE = (UART_UUID, (UART_TX, UART_RX,),) SERVICES = (HR_SERVICE, UART_SERVICE,) ( (hr,), (tx, rx,), ) = bt.gatts_register_services(SERVICES) The three value handles (``hr``, ``tx``, ``rx``) can be used with :meth:`gatts_read `, :meth:`gatts_write `, :meth:`gatts_notify `, and :meth:`gatts_indicate `. **Note:** Advertising must be stopped before registering services. Available flags for characteristics and descriptors are:: from micropython import const _FLAG_BROADCAST = const(0x0001) _FLAG_READ = const(0x0002) _FLAG_WRITE_NO_RESPONSE = const(0x0004) _FLAG_WRITE = const(0x0008) _FLAG_NOTIFY = const(0x0010) _FLAG_INDICATE = const(0x0020) _FLAG_AUTHENTICATED_SIGNED_WRITE = const(0x0040) _FLAG_AUX_WRITE = const(0x0100) _FLAG_READ_ENCRYPTED = const(0x0200) _FLAG_READ_AUTHENTICATED = const(0x0400) _FLAG_READ_AUTHORIZED = const(0x0800) _FLAG_WRITE_ENCRYPTED = const(0x1000) _FLAG_WRITE_AUTHENTICATED = const(0x2000) _FLAG_WRITE_AUTHORIZED = const(0x4000) As for the IRQs above, any required constants should be added to your Python code. GATT Server ----------- A GATT server has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. These values are stored locally, and are accessed by their "value handle" which is generated during service registration. They can also be read from or written to by a remote client device. Additionally, a server can "notify" a characteristic to a connected client via a connection handle. A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more common for a peripheral device to act as the server. Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a client to a given characteristic, use :meth:`gatts_write` after registration. e.g. ``gatts_write(char_handle, bytes(100))``. """ def gatts_read(self, value_handle: memoryview, /) -> bytes: """ Reads the local value for this handle (which has either been written by :meth:`gatts_write ` or by a remote client). GATT Server ----------- A GATT server has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. These values are stored locally, and are accessed by their "value handle" which is generated during service registration. They can also be read from or written to by a remote client device. Additionally, a server can "notify" a characteristic to a connected client via a connection handle. A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more common for a peripheral device to act as the server. Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a client to a given characteristic, use :meth:`gatts_write` after registration. e.g. ``gatts_write(char_handle, bytes(100))``. """ def gatts_write( self, value_handle: memoryview, data: bytes, send_update: bool = False, / ) -> None: """ Writes the local value for this handle, which can be read by a client. If *send_update* is ``True``, then any subscribed clients will be notified (or indicated, depending on what they're subscribed to and which operations the characteristic supports) about this write. GATT Server ----------- A GATT server has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. These values are stored locally, and are accessed by their "value handle" which is generated during service registration. They can also be read from or written to by a remote client device. Additionally, a server can "notify" a characteristic to a connected client via a connection handle. A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more common for a peripheral device to act as the server. Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a client to a given characteristic, use :meth:`gatts_write` after registration. e.g. ``gatts_write(char_handle, bytes(100))``. """ def gatts_notify(self, value_handle: memoryview, data: bytes, /) -> None: """ Sends a notification request to a connected client. If *data* is not ``None``, then that value is sent to the client as part of the notification. The local value will not be modified. Otherwise, if *data* is ``None``, then the current local value (as set with :meth:`gatts_write `) will be sent. **Note:** The notification will be sent regardless of the subscription status of the client to this characteristic. GATT Server ----------- A GATT server has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. These values are stored locally, and are accessed by their "value handle" which is generated during service registration. They can also be read from or written to by a remote client device. Additionally, a server can "notify" a characteristic to a connected client via a connection handle. A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more common for a peripheral device to act as the server. Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a client to a given characteristic, use :meth:`gatts_write` after registration. e.g. ``gatts_write(char_handle, bytes(100))``. """ def gatts_indicate( self, conn_handle: memoryview, value_handle: memoryview, / ) -> None: """ Sends an indication request containing the characteristic's current value to a connected client. On acknowledgment (or failure, e.g. timeout), the ``_IRQ_GATTS_INDICATE_DONE`` event will be raised. **Note:** The indication will be sent regardless of the subscription status of the client to this characteristic. GATT Server ----------- A GATT server has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. These values are stored locally, and are accessed by their "value handle" which is generated during service registration. They can also be read from or written to by a remote client device. Additionally, a server can "notify" a characteristic to a connected client via a connection handle. A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more common for a peripheral device to act as the server. Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a client to a given characteristic, use :meth:`gatts_write` after registration. e.g. ``gatts_write(char_handle, bytes(100))``. """ def gatts_set_buffer( self, conn_handle: memoryview, len: int, append: bool = False, / ) -> None: """ Sets the internal buffer size for a value in bytes. This will limit the largest possible write that can be received. The default is 20. Setting *append* to ``True`` will make all remote writes append to, rather than replace, the current value. At most *len* bytes can be buffered in this way. When you use :meth:`gatts_read `, the value will be cleared after reading. This feature is useful when implementing something like the Nordic UART Service. GATT Server ----------- A GATT server has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. These values are stored locally, and are accessed by their "value handle" which is generated during service registration. They can also be read from or written to by a remote client device. Additionally, a server can "notify" a characteristic to a connected client via a connection handle. A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more common for a peripheral device to act as the server. Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a client to a given characteristic, use :meth:`gatts_write` after registration. e.g. ``gatts_write(char_handle, bytes(100))``. """ def gattc_discover_services( self, conn_handle: memoryview, uuid: UUID | None = None, / ) -> None: """ Query a connected server for its services. Optionally specify a service *uuid* to query for that service only. For each service discovered, the ``_IRQ_GATTC_SERVICE_RESULT`` event will be raised, followed by ``_IRQ_GATTC_SERVICE_DONE`` on completion. GATT Client ----------- A GATT client can discover and read/write characteristics on a remote GATT server. It is more common for a central role device to act as the GATT client, however it's also possible for a peripheral to act as a client in order to discover information about the central that has connected to it (e.g. to read the device name from the device information service). """ def gattc_discover_characteristics( self, conn_handle: memoryview, start_handle: int, end_handle: int, uuid: UUID | None = None, /, ) -> None: """ Query a connected server for characteristics in the specified range. Optionally specify a characteristic *uuid* to query for that characteristic only. You can use ``start_handle=1``, ``end_handle=0xffff`` to search for a characteristic in any service. For each characteristic discovered, the ``_IRQ_GATTC_CHARACTERISTIC_RESULT`` event will be raised, followed by ``_IRQ_GATTC_CHARACTERISTIC_DONE`` on completion. GATT Client ----------- A GATT client can discover and read/write characteristics on a remote GATT server. It is more common for a central role device to act as the GATT client, however it's also possible for a peripheral to act as a client in order to discover information about the central that has connected to it (e.g. to read the device name from the device information service). """ def gattc_discover_descriptors( self, conn_handle: memoryview, start_handle: int, end_handle: int, / ) -> None: """ Query a connected server for descriptors in the specified range. For each descriptor discovered, the ``_IRQ_GATTC_DESCRIPTOR_RESULT`` event will be raised, followed by ``_IRQ_GATTC_DESCRIPTOR_DONE`` on completion. GATT Client ----------- A GATT client can discover and read/write characteristics on a remote GATT server. It is more common for a central role device to act as the GATT client, however it's also possible for a peripheral to act as a client in order to discover information about the central that has connected to it (e.g. to read the device name from the device information service). """ def gattc_read(self, conn_handle: memoryview, value_handle: memoryview, /) -> None: """ Issue a remote read to a connected server for the specified characteristic or descriptor handle. When a value is available, the ``_IRQ_GATTC_READ_RESULT`` event will be raised. Additionally, the ``_IRQ_GATTC_READ_DONE`` will be raised. GATT Client ----------- A GATT client can discover and read/write characteristics on a remote GATT server. It is more common for a central role device to act as the GATT client, however it's also possible for a peripheral to act as a client in order to discover information about the central that has connected to it (e.g. to read the device name from the device information service). """ def gattc_write( self, conn_handle: memoryview, value_handle: memoryview, data: bytes, mode: int = 0, /, ) -> None: """ Issue a remote write to a connected server for the specified characteristic or descriptor handle. The argument *mode* specifies the write behaviour, with the currently supported values being: * ``mode=0`` (default) is a write-without-response: the write will be sent to the remote server but no confirmation will be returned, and no event will be raised. * ``mode=1`` is a write-with-response: the remote server is requested to send a response/acknowledgement that it received the data. If a response is received from the remote server the ``_IRQ_GATTC_WRITE_DONE`` event will be raised. GATT Client ----------- A GATT client can discover and read/write characteristics on a remote GATT server. It is more common for a central role device to act as the GATT client, however it's also possible for a peripheral to act as a client in order to discover information about the central that has connected to it (e.g. to read the device name from the device information service). """ def gattc_exchange_mtu(self, conn_handle: memoryview, /) -> None: """ Initiate MTU exchange with a connected server, using the preferred MTU set using ``BLE.config(mtu=value)``. The ``_IRQ_MTU_EXCHANGED`` event will be raised when MTU exchange completes. **Note:** MTU exchange is typically initiated by the central. When using the BlueKitchen stack in the central role, it does not support a remote peripheral initiating the MTU exchange. NimBLE works for both roles. GATT Client ----------- A GATT client can discover and read/write characteristics on a remote GATT server. It is more common for a central role device to act as the GATT client, however it's also possible for a peripheral to act as a client in order to discover information about the central that has connected to it (e.g. to read the device name from the device information service). """ def l2cap_listen(self, psm: memoryview, mtu: memoryview, /) -> None: """ Start listening for incoming L2CAP channel requests on the specified *psm* with the local MTU set to *mtu*. When a remote device initiates a connection, the ``_IRQ_L2CAP_ACCEPT`` event will be raised, which gives the listening server a chance to reject the incoming connection (by returning a non-zero integer). Once the connection is accepted, the ``_IRQ_L2CAP_CONNECT`` event will be raised, allowing the server to obtain the channel id (CID) and the local and remote MTU. **Note:** It is not currently possible to stop listening. L2CAP connection-oriented-channels ---------------------------------- This feature allows for socket-like data exchange between two BLE devices. Once the devices are connected via GAP, either device can listen for the other to connect on a numeric PSM (Protocol/Service Multiplexer). **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). Only one L2CAP channel may be active at a given time (i.e. you cannot connect while listening). Active L2CAP channels are identified by the connection handle that they were established on and a CID (channel ID). Connection-oriented channels have built-in credit-based flow control. Unlike ATT, where devices negotiate a shared MTU, both the listening and connecting devices each set an independent MTU which limits the maximum amount of outstanding data that the remote device can send before it is fully consumed in :meth:`l2cap_recvinto `. """ def l2cap_connect( self, conn_handle: memoryview, psm: memoryview, mtu: memoryview, / ) -> None: """ Connect to a listening peer on the specified *psm* with local MTU set to *mtu*. On successful connection, the the ``_IRQ_L2CAP_CONNECT`` event will be raised, allowing the client to obtain the CID and the local and remote (peer) MTU. An unsuccessful connection will raise the ``_IRQ_L2CAP_DISCONNECT`` event with a non-zero status. L2CAP connection-oriented-channels ---------------------------------- This feature allows for socket-like data exchange between two BLE devices. Once the devices are connected via GAP, either device can listen for the other to connect on a numeric PSM (Protocol/Service Multiplexer). **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). Only one L2CAP channel may be active at a given time (i.e. you cannot connect while listening). Active L2CAP channels are identified by the connection handle that they were established on and a CID (channel ID). Connection-oriented channels have built-in credit-based flow control. Unlike ATT, where devices negotiate a shared MTU, both the listening and connecting devices each set an independent MTU which limits the maximum amount of outstanding data that the remote device can send before it is fully consumed in :meth:`l2cap_recvinto `. """ def l2cap_disconnect(self, conn_handle: memoryview, cid: memoryview, /) -> None: """ Disconnect an active L2CAP channel with the specified *conn_handle* and *cid*. L2CAP connection-oriented-channels ---------------------------------- This feature allows for socket-like data exchange between two BLE devices. Once the devices are connected via GAP, either device can listen for the other to connect on a numeric PSM (Protocol/Service Multiplexer). **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). Only one L2CAP channel may be active at a given time (i.e. you cannot connect while listening). Active L2CAP channels are identified by the connection handle that they were established on and a CID (channel ID). Connection-oriented channels have built-in credit-based flow control. Unlike ATT, where devices negotiate a shared MTU, both the listening and connecting devices each set an independent MTU which limits the maximum amount of outstanding data that the remote device can send before it is fully consumed in :meth:`l2cap_recvinto `. """ def l2cap_send(self, conn_handle: memoryview, cid: memoryview, /) -> None: """ Send the specified *buf* (which must support the buffer protocol) on the L2CAP channel identified by *conn_handle* and *cid*. The specified buffer cannot be larger than the remote (peer) MTU, and no more than twice the size of the local MTU. This will return ``False`` if the channel is now "stalled", which means that :meth:`l2cap_send ` must not be called again until the ``_IRQ_L2CAP_SEND_READY`` event is received (which will happen when the remote device grants more credits, typically after it has received and processed the data). L2CAP connection-oriented-channels ---------------------------------- This feature allows for socket-like data exchange between two BLE devices. Once the devices are connected via GAP, either device can listen for the other to connect on a numeric PSM (Protocol/Service Multiplexer). **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). Only one L2CAP channel may be active at a given time (i.e. you cannot connect while listening). Active L2CAP channels are identified by the connection handle that they were established on and a CID (channel ID). Connection-oriented channels have built-in credit-based flow control. Unlike ATT, where devices negotiate a shared MTU, both the listening and connecting devices each set an independent MTU which limits the maximum amount of outstanding data that the remote device can send before it is fully consumed in :meth:`l2cap_recvinto `. """ def l2cap_recvinto( self, conn_handle: memoryview, cid: memoryview, buf: AnyWritableBuf | None, / ) -> int: """ Receive data from the specified *conn_handle* and *cid* into the provided *buf* (which must support the buffer protocol, e.g. bytearray or memoryview). Returns the number of bytes read from the channel. If *buf* is None, then returns the number of bytes available. **Note:** After receiving the ``_IRQ_L2CAP_RECV`` event, the application should continue calling :meth:`l2cap_recvinto ` until no more bytes are available in the receive buffer (typically up to the size of the remote (peer) MTU). Until the receive buffer is empty, the remote device will not be granted more channel credits and will be unable to send any more data. L2CAP connection-oriented-channels ---------------------------------- This feature allows for socket-like data exchange between two BLE devices. Once the devices are connected via GAP, either device can listen for the other to connect on a numeric PSM (Protocol/Service Multiplexer). **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). Only one L2CAP channel may be active at a given time (i.e. you cannot connect while listening). Active L2CAP channels are identified by the connection handle that they were established on and a CID (channel ID). Connection-oriented channels have built-in credit-based flow control. Unlike ATT, where devices negotiate a shared MTU, both the listening and connecting devices each set an independent MTU which limits the maximum amount of outstanding data that the remote device can send before it is fully consumed in :meth:`l2cap_recvinto `. """ def gap_pair(self, conn_handle: memoryview, /) -> None: """ Initiate pairing with the remote device. Before calling this, ensure that the ``io``, ``mitm``, ``le_secure``, and ``bond`` configuration options are set (via :meth:`config`). On successful pairing, the ``_IRQ_ENCRYPTION_UPDATE`` event will be raised. Pairing and bonding ------------------- Pairing allows a connection to be encrypted and authenticated via exchange of secrets (with optional MITM protection via passkey authentication). Bonding is the process of storing those secrets into non-volatile storage. When bonded, a device is able to resolve a resolvable private address (RPA) from another device based on the stored identity resolving key (IRK). To support bonding, an application must implement the ``_IRQ_GET_SECRET`` and ``_IRQ_SET_SECRET`` events. **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). """ def gap_passkey( self, conn_handle: memoryview, action: int, passkey: int, / ) -> None: """ Respond to a ``_IRQ_PASSKEY_ACTION`` event for the specified *conn_handle* and *action*. The *passkey* is a numeric value and will depend on on the *action* (which will depend on what I/O capability has been set): * When the *action* is ``_PASSKEY_ACTION_INPUT``, then the application should prompt the user to enter the passkey that is shown on the remote device. * When the *action* is ``_PASSKEY_ACTION_DISPLAY``, then the application should generate a random 6-digit passkey and show it to the user. * When the *action* is ``_PASSKEY_ACTION_NUMERIC_COMPARISON``, then the application should show the passkey that was provided in the ``_IRQ_PASSKEY_ACTION`` event and then respond with either ``0`` (cancel pairing), or ``1`` (accept pairing). Pairing and bonding ------------------- Pairing allows a connection to be encrypted and authenticated via exchange of secrets (with optional MITM protection via passkey authentication). Bonding is the process of storing those secrets into non-volatile storage. When bonded, a device is able to resolve a resolvable private address (RPA) from another device based on the stored identity resolving key (IRK). To support bonding, an application must implement the ``_IRQ_GET_SECRET`` and ``_IRQ_SET_SECRET`` events. **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). """ class UUID: """ class UUID ---------- """ def __init__(self, value: int | str, /): """ Creates a UUID instance with the specified **value**. The **value** can be either: - A 16-bit integer. e.g. ``0x2908``. - A 128-bit UUID string. e.g. ``'6E400001-B5A3-F393-E0A9-E50E24DCCA9E'``. """ ================================================ FILE: typehints/micropython/btree.pyi ================================================ """ simple BTree database. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/btree.rst. ===================================== .. 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 io.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() """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Any, Final, Iterable from uio import IOBase def open( stream: IOBase[bytes, Any], /, *, flags: int = 0, pagesize: int = 0, cachesize: int = 0, minkeypage: int = 0, ) -> _BTree: """ 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. """ INCL: Final[int] = ... """ A flag for `keys()`, `values()`, `items()` methods to specify that scanning should be inclusive of the end key. """ DESC: Final[int] = ... """ A flag for `keys()`, `values()`, `items()` methods to specify that scanning should be in descending direction of keys. """ class _BTree: """ """ def close(self) -> None: """ 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). """ def flush(self) -> None: """ Flush any data in cache to the underlying stream. """ def __getitem__(self, key: bytes, /) -> bytes: """ Standard dictionary methods. """ def get(self, key: bytes, default: bytes | None = None, /) -> bytes | None: """ Standard dictionary methods. """ def __setitem__(self, key: bytes, val: bytes, /) -> None: """ Standard dictionary methods. """ def __delitem__(self, key: bytes, /) -> None: """ Standard dictionary methods. """ def __contains__(self, key: bytes, /) -> bool: """ Standard dictionary methods. """ def __iter__(self) -> Iterable[bytes]: """ A BTree object can be iterated over directly (similar to a dictionary) to get access to all keys in order. """ def keys( self, start_key: bytes | None = None, end_key: bytes | None = None, flags: int = 0, /, ) -> Iterable[bytes]: """ 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. """ def values( self, start_key: bytes | None = None, end_key: bytes | None = None, flags: int = 0, /, ) -> Iterable[bytes]: """ 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. """ def items( self, start_key: bytes | None = None, end_key: bytes | None = None, flags: int = 0, /, ) -> Iterable[tuple[bytes, bytes]]: """ 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. """ ================================================ FILE: typehints/micropython/cryptolib.pyi ================================================ """ cryptographic ciphers. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/cryptolib.rst. ========================================= .. module:: cryptolib :synopsis: cryptographic ciphers """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import overload from uio import AnyReadableBuf, AnyWritableBuf # noinspection PyPep8Naming class aes: """ .. class:: aes """ @overload def __init__(self, key: AnyReadableBuf, mode: int, /): """ Initialize cipher object, suitable for encryption/decryption. Note: after initialization, cipher object can be use only either for encryption or decryption. Running decrypt() operation after encrypt() or vice versa is not supported. Parameters are: * *key* is an encryption/decryption key (bytes-like). * *mode* is: * ``1`` (or ``cryptolib.MODE_ECB`` if it exists) for Electronic Code Book (ECB). * ``2`` (or ``cryptolib.MODE_CBC`` if it exists) for Cipher Block Chaining (CBC). * ``6`` (or ``cryptolib.MODE_CTR`` if it exists) for Counter mode (CTR). * *IV* is an initialization vector for CBC mode. * For Counter mode, *IV* is the initial value for the counter. """ @overload def __init__(self, key: AnyReadableBuf, mode: int, IV: AnyReadableBuf, /): """ Initialize cipher object, suitable for encryption/decryption. Note: after initialization, cipher object can be use only either for encryption or decryption. Running decrypt() operation after encrypt() or vice versa is not supported. Parameters are: * *key* is an encryption/decryption key (bytes-like). * *mode* is: * ``1`` (or ``cryptolib.MODE_ECB`` if it exists) for Electronic Code Book (ECB). * ``2`` (or ``cryptolib.MODE_CBC`` if it exists) for Cipher Block Chaining (CBC). * ``6`` (or ``cryptolib.MODE_CTR`` if it exists) for Counter mode (CTR). * *IV* is an initialization vector for CBC mode. * For Counter mode, *IV* is the initial value for the counter. """ @overload def encrypt(self, in_buf: AnyReadableBuf, /) -> bytes: """ Encrypt *in_buf*. If no *out_buf* is given result is returned as a newly allocated `bytes` object. Otherwise, result is written into mutable buffer *out_buf*. *in_buf* and *out_buf* can also refer to the same mutable buffer, in which case data is encrypted in-place. """ @overload def encrypt(self, in_buf: AnyReadableBuf, out_buf: AnyWritableBuf, /) -> None: """ Encrypt *in_buf*. If no *out_buf* is given result is returned as a newly allocated `bytes` object. Otherwise, result is written into mutable buffer *out_buf*. *in_buf* and *out_buf* can also refer to the same mutable buffer, in which case data is encrypted in-place. """ @overload def decrypt(self, in_buf: AnyReadableBuf, /) -> bytes: """ Like `encrypt()`, but for decryption. """ @overload def decrypt(self, in_buf: AnyReadableBuf, out_buf: AnyWritableBuf, /) -> None: """ Like `encrypt()`, but for decryption. """ ================================================ FILE: typehints/micropython/framebuf.pyi ================================================ """ Frame buffer manipulation. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/framebuf.rst. This module provides a general frame buffer which can be used to create bitmap images, which can then be sent to a display. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import overload, Final from uio import AnyWritableBuf MONO_VLSB: Final[int] = ... """ 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. """ MONO_HLSB: Final[int] = ... """ 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. """ MONO_HMSB: Final[int] = ... """ 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. """ RGB565: Final[int] = ... """ Red Green Blue (16-bit, 5+6+5) color format """ GS2_HMSB: Final[int] = ... """ Grayscale (2-bit) color format """ GS4_HMSB: Final[int] = ... """ Grayscale (4-bit) color format """ GS8: Final[int] = ... """ Grayscale (8-bit) color format """ 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) """ def __init__( self, buffer: AnyWritableBuf, width: int, height: int, format: int, stride: int = ..., /, ): """ 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. """ def fill(self, c: int, /) -> None: """ Fill the entire FrameBuffer with the specified color. """ @overload def pixel(self, x: int, y: int, /) -> int: """ 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. """ @overload def pixel(self, x: int, y: int, c: int, /) -> None: """ 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. """ def hline(self, x: int, y: int, w: int, c: int, /) -> None: """ 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. """ def vline(self, x: int, y: int, h: int, c: int, /) -> None: """ 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. """ def line(self, x1: int, y1: int, x2: int, y2: int, c: int, /) -> None: """ 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. """ def rect(self, x: int, y: int, w: int, h: int, c: int, /) -> None: """ 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. """ def fill_rect(self, x: int, y: int, w: int, h: int, c: int, /) -> None: """ 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. """ def text(self, s: str, x: int, y: int, c: int = 1, /) -> None: """ 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. """ def scroll(self, xstep: int, ystep: int, /) -> None: """ Shift the contents of the FrameBuffer by the given vector. This may leave a footprint of the previous colors in the FrameBuffer. """ def blit( self, fbuf: FrameBuffer, x: int, y: int, key: int = -1, pallet: FrameBuffer | None = None, /, ) -> None: """ 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. The *palette* argument enables blitting between FrameBuffers with differing formats. Typical usage is to render a monochrome or grayscale glyph/icon to a color display. The *palette* is a FrameBuffer instance whose format is that of the current FrameBuffer. The *palette* height is one pixel and its pixel width is the number of colors in the source FrameBuffer. The *palette* for an N-bit source needs 2**N pixels; the *palette* for a monochrome source would have 2 pixels representing background and foreground colors. The application assigns a color to each pixel in the *palette*. The color of the current pixel will be that of that *palette* pixel whose x position is the color of the corresponding source pixel. """ ================================================ FILE: typehints/micropython/machine.pyi ================================================ """ functions related to the hardware. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/machine.rst. ==================================================== .. 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`. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import overload, NoReturn, Callable from typing import Sequence, ClassVar, Any, Final from uos import AbstractBlockDev from uio import AnyReadableBuf, AnyWritableBuf def reset() -> NoReturn: """ Resets the device in a manner similar to pushing the external RESET button. """ def soft_reset() -> NoReturn: """ Performs a soft reset of the interpreter, deleting all Python objects and resetting the Python heap. It tries to retain the method by which the user is connected to the MicroPython REPL (eg serial, USB, Wifi). """ def reset_cause() -> int: """ Get the reset cause. See :ref:`constants ` for the possible return values. """ def disable_irq() -> bool: """ 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. """ def enable_irq(state: bool = True, /) -> None: """ Re-enable interrupt requests. The *state* parameter should be the value that was returned from the most recent call to the `disable_irq()` function. """ @overload def freq() -> int: """ Returns the CPU frequency in hertz. On some ports this can also be used to set the CPU frequency by passing in *hz*. """ @overload def freq(hz: int, /) -> None: """ Returns the CPU frequency in hertz. On some ports this can also be used to set the CPU frequency by passing in *hz*. """ def idle() -> None: """ 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). """ def sleep() -> None: """ .. note:: This function is deprecated, use `lightsleep()` instead with no arguments. """ @overload def lightsleep() -> None: """ 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 timeout, 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. """ @overload def lightsleep(time_ms: int, /) -> None: """ 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 timeout, 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. """ @overload def deepsleep() -> NoReturn: """ 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 timeout, 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. """ @overload def deepsleep(time_ms: int, /) -> NoReturn: """ 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 timeout, 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. """ def wake_reason() -> int: """ Get the wake reason. See :ref:`constants ` for the possible return values. Availability: ESP32, WiPy. """ def unique_id() -> bytes: """ 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. """ def time_pulse_us(pin: Pin, pulse_level: int, timeout_us: int = 1_000_000, /) -> int: """ 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). """ def rng() -> int: """ Return a 24-bit software generated random number. Availability: WiPy. """ IDLE: Final[int] = ... """ IRQ wake values. """ SLEEP: Final[int] = ... """ IRQ wake values. """ DEEPSLEEP: Final[int] = ... """ IRQ wake values. """ PWRON_RESET: Final[int] = ... """ Reset causes. """ HARD_RESET: Final[int] = ... """ Reset causes. """ WDT_RESET: Final[int] = ... """ Reset causes. """ DEEPSLEEP_RESET: Final[int] = ... """ Reset causes. """ SOFT_RESET: Final[int] = ... """ Reset causes. """ WLAN_WAKE: Final[int] = ... """ Wake-up reasons. """ PIN_WAKE: Final[int] = ... """ Wake-up reasons. """ RTC_WAKE: Final[int] = ... """ Wake-up reasons. """ class Pin: """ 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 with a pull down resistor p0.init(p0.IN, p0.PULL_DOWN) # configure an irq callback p0.irq(lambda p:print(p)) """ IN: ClassVar[int] = ... """ Selects the pin mode. """ OUT: ClassVar[int] = ... """ Selects the pin mode. """ OPEN_DRAIN: ClassVar[int] = ... """ Selects the pin mode. """ ALT: ClassVar[int] = ... """ Selects the pin mode. """ ALT_OPEN_DRAIN: ClassVar[int] = ... """ Selects the pin mode. """ PULL_UP: ClassVar[int] = ... """ Selects whether there is a pull up/down resistor. Use the value ``None`` for no pull. """ PULL_DOWN: ClassVar[int] = ... """ Selects whether there is a pull up/down resistor. Use the value ``None`` for no pull. """ PULL_HOLD: ClassVar[int] = ... """ Selects whether there is a pull up/down resistor. Use the value ``None`` for no pull. """ LOW_POWER: ClassVar[int] = ... """ Selects the pin drive strength. """ MED_POWER: ClassVar[int] = ... """ Selects the pin drive strength. """ HIGH_POWER: ClassVar[int] = ... """ Selects the pin drive strength. """ IRQ_FALLING: ClassVar[int] = ... """ Selects the IRQ trigger type. """ IRQ_RISING: ClassVar[int] = ... """ Selects the IRQ trigger type. """ IRQ_LOW_LEVEL: ClassVar[int] = ... """ Selects the IRQ trigger type. """ IRQ_HIGH_LEVEL: ClassVar[int] = ... """ Selects the IRQ trigger type. """ def __init__( self, id: Any, /, mode: int = -1, pull: int = -1, *, value: Any = None, drive: int | None = None, alt: int | None = None, ): """ 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. """ def init( self, mode: int = -1, pull: int = -1, *, value: Any = None, drive: int | None = None, alt: int | None = None, ) -> None: """ 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``. """ @overload def value(self) -> int: """ 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``. """ @overload def value(self, x: Any, /) -> None: """ 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``. """ @overload def __call__(self) -> int: """ 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. """ @overload def __call__(self, x: Any, /) -> None: """ 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. """ def on(self) -> None: """ Set pin to "1" output level. """ def off(self) -> None: """ Set pin to "0" output level. """ def irq( self, /, handler: Callable[[Pin], None] | None = None, trigger: int = (IRQ_FALLING | IRQ_RISING), *, priority: int = 1, wake: int | None = None, hard: bool = False, ) -> Callable[[Pin], None] | None: """ 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`. Not all ports support this argument. This method returns a callback object. """ def low(self) -> None: """ Set pin to "0" output level. Availability: nrf, rp2, stm32 ports. """ def high(self) -> None: """ Set pin to "1" output level. Availability: nrf, rp2, stm32 ports. """ @overload def mode(self) -> int: """ Get or set the pin mode. See the constructor documentation for details of the ``mode`` argument. Availability: cc3200, stm32 ports. """ @overload def mode(self, mode: int, /) -> None: """ Get or set the pin mode. See the constructor documentation for details of the ``mode`` argument. Availability: cc3200, stm32 ports. """ @overload def pull(self) -> int: """ Get or set the pin pull state. See the constructor documentation for details of the ``pull`` argument. Availability: cc3200, stm32 ports. """ @overload def pull(self, pull: int, /) -> None: """ Get or set the pin pull state. See the constructor documentation for details of the ``pull`` argument. Availability: cc3200, stm32 ports. """ @overload def drive(self) -> int: """ Get or set the pin drive strength. See the constructor documentation for details of the ``drive`` argument. Availability: cc3200 port. """ @overload def drive(self, drive: int, /) -> None: """ Get or set the pin drive strength. See the constructor documentation for details of the ``drive`` argument. Availability: cc3200 port. """ class Signal: """ 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 use cases 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. """ @overload def __init__(self, pin_obj: Pin, invert: bool = 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). """ @overload def __init__( self, id: Pin | str, /, mode: int = -1, pull: int = -1, *, value: Any = None, drive: int | None = None, alt: int | None = None, invert: bool = 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). """ @overload def value(self) -> int: """ 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. """ @overload def value(self, x: Any, /) -> None: """ 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. """ def on(self) -> None: """ Activate signal. """ def off(self) -> None: """ Deactivate signal. """ class ADC: """ 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 """ def __init__(self, pin: int | Pin, /): """ Access the ADC associated with a source identified by *id*. This *id* may be an integer (usually specifying a channel number), a :ref:`Pin ` object, or other value supported by the underlying machine. """ def read_u16(self) -> int: """ 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. """ # noinspection PyShadowingNames class PWM: """ This class provides pulse width modulation output. Example usage:: from machine import PWM pwm = PWM(pin) # create a PWM object on a pin pwm.duty_u16(32768) # set duty to 50% # reinitialise with a period of 200us, duty of 5us pwm.init(freq=5000, duty_ns=5000) pwm.duty_ns(3000) # set pulse width to 3us pwm.deinit() """ def __init__( self, dest: Pin | int, /, *, freq: int = ..., duty_u16: int = ..., duty_ns: int = ..., ): """ Construct and return a new PWM object using the following parameters: - *dest* is the entity on which the PWM is output, which is usually a :ref:`machine.Pin ` object, but a port may allow other values, like integers. - *freq* should be an integer which sets the frequency in Hz for the PWM cycle. - *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65535``. - *duty_ns* sets the pulse width in nanoseconds. Setting *freq* may affect other PWM objects if the objects share the same underlying PWM generator (this is hardware specific). Only one of *duty_u16* and *duty_ns* should be specified at a time. """ def init(self, *, freq: int = ..., duty_u16: int = ..., duty_ns: int = ...) -> None: """ Modify settings for the PWM object. See the above constructor for details about the parameters. """ def deinit(self) -> None: """ Disable the PWM output. """ @overload def freq(self) -> int: """ Get or set the current frequency of the PWM output. With no arguments the frequency in Hz is returned. With a single *value* argument the frequency is set to that value in Hz. The method may raise a ``ValueError`` if the frequency is outside the valid range. """ @overload def freq(self, value: int, /,) -> None: """ Get or set the current frequency of the PWM output. With no arguments the frequency in Hz is returned. With a single *value* argument the frequency is set to that value in Hz. The method may raise a ``ValueError`` if the frequency is outside the valid range. """ @overload def duty_u16(self) -> int: """ Get or set the current duty cycle of the PWM output, as an unsigned 16-bit value in the range 0 to 65535 inclusive. With no arguments the duty cycle is returned. With a single *value* argument the duty cycle is set to that value, measured as the ratio ``value / 65535``. """ @overload def duty_u16(self, value: int, /,) -> None: """ Get or set the current duty cycle of the PWM output, as an unsigned 16-bit value in the range 0 to 65535 inclusive. With no arguments the duty cycle is returned. With a single *value* argument the duty cycle is set to that value, measured as the ratio ``value / 65535``. """ @overload def duty_ns(self) -> int: """ Get or set the current pulse width of the PWM output, as a value in nanoseconds. With no arguments the pulse width in nanoseconds is returned. With a single *value* argument the pulse width is set to that value. """ @overload def duty_ns(self, value: int, /,) -> None: """ Get or set the current pulse width of the PWM output, as a value in nanoseconds. With no arguments the pulse width in nanoseconds is returned. With a single *value* argument the pulse width is set to that value. """ class UART: """ 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 """ RX_ANY: ClassVar[int] = ... """ IRQ trigger sources Availability: WiPy. """ @overload def __init__( self, id: int | str, baudrate: int = 9600, bits: int = 8, parity: int | None = None, stop: int = 1, /, *, tx: Pin | None = None, rx: Pin | None = None, txbuf: int | None = None, rxbuf: int | None = None, timeout: int | None = None, timeout_char: int | None = None, invert: int | None = None, ): """ Construct a UART object of the given id. """ @overload def __init__( self, id: int | str, baudrate: int = 9600, bits: int = 8, parity: int | None = None, stop: int = 1, /, *, pins: tuple[Pin, Pin] | None = None, ): """ Construct a UART object of the given id. """ @overload def __init__( self, id: int | str, baudrate: int = 9600, bits: int = 8, parity: int | None = None, stop: int = 1, /, *, pins: tuple[Pin, Pin, Pin, Pin] | None = None, ): """ Construct a UART object of the given id. """ @overload def init( self, baudrate: int = 9600, bits: int = 8, parity: int | None = None, stop: int = 1, /, *, tx: Pin | None = None, rx: Pin | None = None, txbuf: int | None = None, rxbuf: int | None = None, timeout: int | None = None, timeout_char: int | None = None, invert: int | None = None, ) -> None: """ 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. - *rts* specifies the RTS (output) pin to use for hardware receive flow control. - *cts* specifies the CTS (input) pin to use for hardware transmit flow control. - *txbuf* specifies the length in characters of the TX buffer. - *rxbuf* specifies the length in characters of the RX buffer. - *timeout* specifies the time to wait for the first character (in ms). - *timeout_char* specifies the time to wait between characters (in ms). - *invert* specifies which lines to invert. - *flow* specifies which hardware flow control signals to use. The value is a bitmask. - ``0`` will ignore hardware flow control signals. - ``UART.RTS`` will enable receive flow control by using the RTS output pin to signal if the receive FIFO has sufficient space to accept more data. - ``UART.CTS`` will enable transmit flow control by pausing transmission when the CTS input pin signals that the receiver is running low on buffer space. - ``UART.RTS | UART.CTS`` will enable both, for full hardware flow control. 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. """ @overload def init( self, baudrate: int = 9600, bits: int = 8, parity: int | None = None, stop: int = 1, /, *, pins: tuple[Pin, Pin] | None = None, ) -> None: """ 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. - *rts* specifies the RTS (output) pin to use for hardware receive flow control. - *cts* specifies the CTS (input) pin to use for hardware transmit flow control. - *txbuf* specifies the length in characters of the TX buffer. - *rxbuf* specifies the length in characters of the RX buffer. - *timeout* specifies the time to wait for the first character (in ms). - *timeout_char* specifies the time to wait between characters (in ms). - *invert* specifies which lines to invert. - *flow* specifies which hardware flow control signals to use. The value is a bitmask. - ``0`` will ignore hardware flow control signals. - ``UART.RTS`` will enable receive flow control by using the RTS output pin to signal if the receive FIFO has sufficient space to accept more data. - ``UART.CTS`` will enable transmit flow control by pausing transmission when the CTS input pin signals that the receiver is running low on buffer space. - ``UART.RTS | UART.CTS`` will enable both, for full hardware flow control. 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. """ @overload def init( self, baudrate: int = 9600, bits: int = 8, parity: int | None = None, stop: int = 1, /, *, pins: tuple[Pin, Pin, Pin, Pin] | None = None, ) -> None: """ 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. - *rts* specifies the RTS (output) pin to use for hardware receive flow control. - *cts* specifies the CTS (input) pin to use for hardware transmit flow control. - *txbuf* specifies the length in characters of the TX buffer. - *rxbuf* specifies the length in characters of the RX buffer. - *timeout* specifies the time to wait for the first character (in ms). - *timeout_char* specifies the time to wait between characters (in ms). - *invert* specifies which lines to invert. - *flow* specifies which hardware flow control signals to use. The value is a bitmask. - ``0`` will ignore hardware flow control signals. - ``UART.RTS`` will enable receive flow control by using the RTS output pin to signal if the receive FIFO has sufficient space to accept more data. - ``UART.CTS`` will enable transmit flow control by pausing transmission when the CTS input pin signals that the receiver is running low on buffer space. - ``UART.RTS | UART.CTS`` will enable both, for full hardware flow control. 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. """ def deinit(self) -> None: """ Turn off the UART bus. """ def any(self) -> int: """ 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) """ @overload def read(self) -> bytes | None: """ Read characters. If ``nbytes`` is specified then read at most that many bytes, otherwise read as much data as possible. It may return sooner if a timeout is reached. The timeout is configurable in the constructor. Return value: a bytes object containing the bytes read in. Returns ``None`` on timeout. """ @overload def read(self, nbytes: int, /) -> bytes | None: """ Read characters. If ``nbytes`` is specified then read at most that many bytes, otherwise read as much data as possible. It may return sooner if a timeout is reached. The timeout is configurable in the constructor. Return value: a bytes object containing the bytes read in. Returns ``None`` on timeout. """ @overload def readinto(self, buf: AnyWritableBuf, /) -> int | None: """ Read bytes into the ``buf``. If ``nbytes`` is specified then read at most that many bytes. Otherwise, read at most ``len(buf)`` bytes. It may return sooner if a timeout is reached. The timeout is configurable in the constructor. Return value: number of bytes read and stored into ``buf`` or ``None`` on timeout. """ @overload def readinto(self, buf: AnyWritableBuf, nbytes: int, /) -> int | None: """ Read bytes into the ``buf``. If ``nbytes`` is specified then read at most that many bytes. Otherwise, read at most ``len(buf)`` bytes. It may return sooner if a timeout is reached. The timeout is configurable in the constructor. Return value: number of bytes read and stored into ``buf`` or ``None`` on timeout. """ def readline(self) -> bytes | None: """ Read a line, ending in a newline character. It may return sooner if a timeout is reached. The timeout is configurable in the constructor. Return value: the line read or ``None`` on timeout. """ def write(self, buf: AnyReadableBuf, /) -> int | None: """ Write the buffer of bytes to the bus. Return value: number of bytes written or ``None`` on timeout. """ def sendbreak(self) -> None: """ 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. """ def irq( self, trigger: int, priority: int = 1, handler: Callable[[UART], None] | None = None, wake: int = IDLE, /, ) -> Any: """ 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. """ class SPI: """ SPI is a synchronous serial protocol that is driven by a controller. 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, CS (Chip Select), to select a particular device on a bus with which communication takes place. Management of a CS signal should happen in user code (via machine.Pin class). Both hardware and software SPI implementations exist via the :ref:`machine.SPI ` and `machine.SoftSPI` classes. Hardware SPI uses underlying hardware support of the system to perform the reads/writes and is usually efficient and fast but may have restrictions on which pins can be used. Software SPI is implemented by bit-banging and can be used on any pin but is not as efficient. These classes have the same methods available and differ primarily in the way they are constructed. """ CONTROLLER: ClassVar[int] = ... """ for initialising the SPI bus to controller; this is only used for the WiPy """ MSB: ClassVar[int] = ... """ set the first bit to be the most significant bit """ LSB: ClassVar[int] = ... """ set the first bit to be the least significant bit """ @overload def __init__(self, id: int, /): """ 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. 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. """ @overload def __init__( self, id: int, /, baudrate: int = 1_000_000, *, polarity: int = 0, phase: int = 0, bits: int = 8, firstbit: int = MSB, sck: Pin | None = None, mosi: Pin | None = None, miso: Pin | None = None, ): """ 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. 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. """ @overload def __init__( self, id: int, /, baudrate: int = 1_000_000, *, polarity: int = 0, phase: int = 0, bits: int = 8, firstbit: int = MSB, pins: tuple[Pin, Pin, Pin] | None = None, ): """ 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. 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. """ @overload def init( self, baudrate: int = 1_000_000, *, polarity: int = 0, phase: int = 0, bits: int = 8, firstbit: int = MSB, sck: Pin | None = None, mosi: Pin | None = None, miso: Pin | None = None, ) -> None: """ 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. """ @overload def init( self, baudrate: int = 1_000_000, *, polarity: int = 0, phase: int = 0, bits: int = 8, firstbit: int = MSB, pins: tuple[Pin, Pin, Pin] | None = None, ) -> None: """ 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. """ def deinit(self) -> None: """ Turn off the SPI bus. """ def read(self, nbytes: int, write: int = 0x00, /) -> bytes: """ 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. """ def readinto(self, buf: AnyWritableBuf, write: int = 0x00, /) -> int | None: """ 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. """ def write(self, buf: AnyReadableBuf, /) -> int | None: """ Write the bytes contained in ``buf``. Returns ``None``. Note: on WiPy this function returns the number of bytes written. """ def write_readinto( self, write_buf: AnyReadableBuf, read_buf: AnyWritableBuf, / ) -> int | None: """ 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. """ # noinspection PyShadowingNames class I2C: """ 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. Both hardware and software I2C implementations exist via the :ref:`machine.I2C ` and `machine.SoftI2C` classes. Hardware I2C uses underlying hardware support of the system to perform the reads/writes and is usually efficient and fast but may have restrictions on which pins can be used. Software I2C is implemented by bit-banging and can be used on any pin but is not as efficient. These classes have the same methods available and differ primarily in the way they are constructed. 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 peripherals, returning a list of 7-bit addresses i2c.writeto(42, b'123') # write 3 bytes to peripheral with 7-bit address 42 i2c.readfrom(42, 4) # read 4 bytes from peripheral with 7-bit address 42 i2c.readfrom_mem(42, 8, 3) # read 3 bytes from memory of peripheral 42, # starting at memory-address 8 in the peripheral i2c.writeto_mem(42, 2, b'\x10') # write 1 byte to memory of peripheral 42 # starting at address 2 in the peripheral """ @overload def __init__(self, id: int, /, *, freq: int = 400_000): """ Construct and return a new I2C object using the following parameters: - *id* identifies a particular I2C peripheral. Allowed values for depend on the particular port/board - *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. Note that some ports/boards will have default values of *scl* and *sda* that can be changed in this constructor. Others will have fixed values of *scl* and *sda* that cannot be changed. """ @overload def __init__(self, id: int, /, *, scl: Pin, sda: Pin, freq: int = 400_000): """ Construct and return a new I2C object using the following parameters: - *id* identifies a particular I2C peripheral. Allowed values for depend on the particular port/board - *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. Note that some ports/boards will have default values of *scl* and *sda* that can be changed in this constructor. Others will have fixed values of *scl* and *sda* that cannot be changed. """ @overload def init(self, *, freq: int = 400_000) -> None: """ 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 """ @overload def init(self, *, scl: Pin, sda: Pin, freq: int = 400_000) -> None: """ 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 """ def deinit(self) -> None: """ Turn off the I2C bus. Availability: WiPy. """ def scan(self) -> list[int]: """ 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. """ def start(self) -> None: """ Generate a START condition on the bus (SDA transitions to low while SCL is high). Primitive I2C operations ------------------------ The following methods implement the primitive I2C controller 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 only available on the `machine.SoftI2C` class. """ def stop(self) -> None: """ Generate a STOP condition on the bus (SDA transitions to high while SCL is high). Primitive I2C operations ------------------------ The following methods implement the primitive I2C controller 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 only available on the `machine.SoftI2C` class. """ def readinto(self, buf: AnyWritableBuf, nack: bool = True, /) -> None: """ 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 peripheral assumes more bytes are going to be read in a later call). Primitive I2C operations ------------------------ The following methods implement the primitive I2C controller 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 only available on the `machine.SoftI2C` class. """ def write(self, buf: AnyReadableBuf, /) -> int: """ 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. Primitive I2C operations ------------------------ The following methods implement the primitive I2C controller 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 only available on the `machine.SoftI2C` class. """ def readfrom(self, addr: int, nbytes: int, stop: bool = True, /) -> bytes: """ Read *nbytes* from the peripheral 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. Standard bus operations ----------------------- The following methods implement the standard I2C controller read and write operations that target a given peripheral device. """ def readfrom_into( self, addr: int, buf: AnyWritableBuf, stop: bool = True, / ) -> None: """ Read into *buf* from the peripheral 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``. Standard bus operations ----------------------- The following methods implement the standard I2C controller read and write operations that target a given peripheral device. """ def writeto(self, addr: int, buf: AnyReadableBuf, stop: bool = True, /) -> int: """ Write the bytes from *buf* to the peripheral 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. Standard bus operations ----------------------- The following methods implement the standard I2C controller read and write operations that target a given peripheral device. """ def writevto( self, addr: int, vector: Sequence[AnyReadableBuf], stop: bool = True, / ) -> int: """ Write the bytes contained in *vector* to the peripheral 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. Standard bus operations ----------------------- The following methods implement the standard I2C controller read and write operations that target a given peripheral device. """ def readfrom_mem( self, addr: int, memaddr: int, nbytes: int, /, *, addrsize: int = 8 ) -> bytes: """ Read *nbytes* from the peripheral 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. 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 peripheral address and the memory address. The following methods are convenience functions to communicate with such devices. """ def readfrom_mem_into( self, addr: int, memaddr: int, buf: AnyWritableBuf, /, *, addrsize: int = 8 ) -> None: """ Read into *buf* from the peripheral 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``. 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 peripheral address and the memory address. The following methods are convenience functions to communicate with such devices. """ def writeto_mem( self, addr: int, memaddr: int, buf: AnyReadableBuf, /, *, addrsize: int = 8 ) -> None: """ Write *buf* to the peripheral 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``. 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 peripheral address and the memory address. The following methods are convenience functions to communicate with such devices. """ class I2S: """ I2S is a synchronous serial protocol used to connect digital audio devices. At the physical level, a bus consists of 3 lines: SCK, WS, SD. The I2S class supports controller operation. Peripheral operation is not supported. The I2S class is currently available as a Technical Preview. During the preview period, feedback from users is encouraged. Based on this feedback, the I2S class API and implementation may be changed. I2S objects can be created and initialized using:: from machine import I2S from machine import Pin # ESP32 sck_pin = Pin(14) # Serial clock output ws_pin = Pin(13) # Word clock output sd_pin = Pin(12) # Serial data output or # PyBoards sck_pin = Pin("Y6") # Serial clock output ws_pin = Pin("Y5") # Word clock output sd_pin = Pin("Y8") # Serial data output audio_out = I2S(2, sck=sck_pin, ws=ws_pin, sd=sd_pin, mode=I2S.TX, bits=16, format=I2S.MONO, rate=44100, ibuf=20000) audio_in = I2S(2, sck=sck_pin, ws=ws_pin, sd=sd_pin, mode=I2S.RX, bits=32, format=I2S.STEREO, rate=22050, ibuf=20000) 3 modes of operation are supported: - blocking - non-blocking - uasyncio blocking:: num_written = audio_out.write(buf) # blocks until buf emptied num_read = audio_in.readinto(buf) # blocks until buf filled non-blocking:: audio_out.irq(i2s_callback) # i2s_callback is called when buf is emptied num_written = audio_out.write(buf) # returns immediately audio_in.irq(i2s_callback) # i2s_callback is called when buf is filled num_read = audio_in.readinto(buf) # returns immediately uasyncio:: swriter = uasyncio.StreamWriter(audio_out) swriter.write(buf) await swriter.drain() sreader = uasyncio.StreamReader(audio_in) num_read = await sreader.readinto(buf) """ RX: ClassVar[int] = ... """ for initialising the I2S bus ``mode`` to receive """ TX: ClassVar[int] = ... """ for initialising the I2S bus ``mode`` to transmit """ STEREO: ClassVar[int] = ... """ for initialising the I2S bus ``format`` to stereo """ MONO: ClassVar[int] = ... """ for initialising the I2S bus ``format`` to mono """ def __init__( self, id: int, /, *, sck: Pin, ws: Pin, sd: Pin, mode: int, bits: int, format: int, rate: int, ibuf: int, ): """ Construct an I2S object of the given id: - ``id`` identifies a particular I2S bus. ``id`` is board and port specific: - PYBv1.0/v1.1: has one I2S bus with id=2. - PYBD-SFxW: has two I2S buses with id=1 and id=2. - ESP32: has two I2S buses with id=0 and id=1. Keyword-only parameters that are supported on all ports: - ``sck`` is a pin object for the serial clock line - ``ws`` is a pin object for the word select line - ``sd`` is a pin object for the serial data line - ``mode`` specifies receive or transmit - ``bits`` specifies sample size (bits), 16 or 32 - ``format`` specifies channel format, STEREO or MONO - ``rate`` specifies audio sampling rate (samples/s) - ``ibuf`` specifies internal buffer length (bytes) For all ports, DMA runs continuously in the background and allows user applications to perform other operations while sample data is transfered between the internal buffer and the I2S peripheral unit. Increasing the size of the internal buffer has the potential to increase the time that user applications can perform non-I2S operations before underflow (e.g. ``write`` method) or overflow (e.g. ``readinto`` method). """ def init( self, *, sck: Pin, ws: Pin, sd: Pin, mode: int, bits: int, format: int, rate: int, ibuf: int, ) -> None: """ see Constructor for argument descriptions """ def deinit(self) -> None: """ Deinitialize the I2S bus """ def readinto(self, buf: AnyWritableBuf, /,) -> int: """ Read audio samples into the buffer specified by ``buf``. ``buf`` must support the buffer protocol, such as bytearray or array. "buf" byte ordering is little-endian. For Stereo format, left channel sample precedes right channel sample. For Mono format, the left channel sample data is used. Returns number of bytes read """ def write(self, buf: AnyReadableBuf, /,) -> int: """ Write audio samples contained in ``buf``. ``buf`` must support the buffer protocol, such as bytearray or array. "buf" byte ordering is little-endian. For Stereo format, left channel sample precedes right channel sample. For Mono format, the sample data is written to both the right and left channels. Returns number of bytes written """ def irq(self, handler: Callable[[], None], /,) -> None: """ Set a callback. ``handler`` is called when ``buf`` is emptied (``write`` method) or becomes full (``readinto`` method). Setting a callback changes the ``write`` and ``readinto`` methods to non-blocking operation. ``handler`` is called in the context of the MicroPython scheduler. """ @staticmethod def shift(buf: AnyWritableBuf, bits: int, shift: int, /,) -> None: """ bitwise shift of all samples contained in ``buf``. ``bits`` specifies sample size in bits. ``shift`` specifies the number of bits to shift each sample. Positive for left shift, negative for right shift. Typically used for volume control. Each bit shift changes sample volume by 6dB. """ class RTC: """ The RTC is an independent clock that keeps track of the date and time. Example usage:: rtc = machine.RTC() rtc.datetime((2020, 1, 21, 2, 10, 32, 36, 0)) print(rtc.datetime()) The documentation for RTC is in a poor state; better to experiment and use `dir`! """ ALARM0: ClassVar[int] = ... """ irq trigger source The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def __init__(self, id: int = 0, /, *, datetime: tuple[int, int, int]): """ Create an RTC object. See init for parameters of initialization. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def __init__(self, id: int = 0, /, *, datetime: tuple[int, int, int, int]): """ Create an RTC object. See init for parameters of initialization. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def __init__(self, id: int = 0, /, *, datetime: tuple[int, int, int, int, int]): """ Create an RTC object. See init for parameters of initialization. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def __init__( self, id: int = 0, /, *, datetime: tuple[int, int, int, int, int, int] ): """ Create an RTC object. See init for parameters of initialization. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def __init__( self, id: int = 0, /, *, datetime: tuple[int, int, int, int, int, int, int] ): """ Create an RTC object. See init for parameters of initialization. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def __init__( self, id: int = 0, /, *, datetime: tuple[int, int, int, int, int, int, int, int] ): """ Create an RTC object. See init for parameters of initialization. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def init(self) -> None: """ Initialise the RTC. Datetime is a tuple of the form: ``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])`` The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def init(self, datetime: tuple[int, int, int], /) -> None: """ Initialise the RTC. Datetime is a tuple of the form: ``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])`` The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def init(self, datetime: tuple[int, int, int, int], /) -> None: """ Initialise the RTC. Datetime is a tuple of the form: ``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])`` The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def init(self, datetime: tuple[int, int, int, int, int], /) -> None: """ Initialise the RTC. Datetime is a tuple of the form: ``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])`` The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def init(self, datetime: tuple[int, int, int, int, int, int], /) -> None: """ Initialise the RTC. Datetime is a tuple of the form: ``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])`` The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def init(self, datetime: tuple[int, int, int, int, int, int, int], /) -> None: """ Initialise the RTC. Datetime is a tuple of the form: ``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])`` The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def init(self, datetime: tuple[int, int, int, int, int, int, int, int], /) -> None: """ Initialise the RTC. Datetime is a tuple of the form: ``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])`` The documentation for RTC is in a poor state; better to experiment and use `dir`! """ def now(self) -> tuple[int, int, int, int, int, int, int, int]: """ Get get the current datetime tuple. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ def deinit(self) -> None: """ Resets the RTC to the time of January 1, 2015 and starts running it again. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def alarm(self, id: int, time: int, /, *, repeat: bool = False) -> None: """ 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. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def alarm(self, id: int, time: tuple[int, int, int], /) -> None: """ 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. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def alarm(self, id: int, time: tuple[int, int, int, int], /) -> None: """ 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. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def alarm(self, id: int, time: tuple[int, int, int, int, int], /) -> None: """ 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. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def alarm(self, id: int, time: tuple[int, int, int, int, int, int], /) -> None: """ 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. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def alarm(self, id: int, time: tuple[int, int, int, int, int, int, int], /) -> None: """ 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. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ @overload def alarm( self, id: int, time: tuple[int, int, int, int, int, int, int, int], / ) -> None: """ 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. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ def alarm_left(self, alarm_id: int = 0, /) -> int: """ Get the number of milliseconds left before the alarm expires. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ def cancel(self, alarm_id: int = 0, /) -> None: """ Cancel a running alarm. The documentation for RTC is in a poor state; better to experiment and use `dir`! """ def irq( self, /, *, trigger: int, handler: Callable[[RTC], None] | None = None, wake: int = IDLE, ) -> None: """ 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. """ class Timer: """ 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 behaviour (which thus won't be portable to other boards). See discussion of :ref:`important constraints ` 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 ` instead of this class. """ ONE_SHOT: ClassVar[int] = ... """ Timer operating mode. """ PERIODIC: ClassVar[int] = ... """ Timer operating mode. """ @overload def __init__(self, id: int, /): """ Construct a new timer object of the given id. Id of -1 constructs a virtual timer (if supported by a board). See ``init`` for parameters of initialisation. """ @overload def __init__( self, id: int, /, *, mode: int = PERIODIC, period: int = -1, callback: Callable[[Timer], None] | None = None, ): """ Construct a new timer object of the given id. Id of -1 constructs a virtual timer (if supported by a board). See ``init`` for parameters of initialisation. """ def init( self, *, mode: int = PERIODIC, period: int = -1, callback: Callable[[Timer], None] | None = None, ) -> 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. """ def deinit(self) -> None: """ Deinitialises the timer. Stops the timer, and disables the timer peripheral. """ class WDT: """ 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, esp8266, esp32. """ def __init__(self, *, id: int = 0, timeout: int = 5000): """ Create a WDT object and start it. The timeout must be given in milliseconds. Once it is running the timeout cannot be changed and the WDT cannot be stopped either. Notes: On the esp32 the minimum timeout is 1 second. On the esp8266 a timeout cannot be specified, it is determined by the underlying system. """ def feed(self) -> None: """ 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. """ class SD: """ .. 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. `_ 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 """ def __init__( self, id: int = 0, pins: tuple[str, str, str] | tuple[Pin, Pin, Pin] = ("GP10", "GP11", "GP15"), /, ): """ Create a SD card object. See ``init()`` for parameters if initialization. """ def init( self, id: int = 0, pins: tuple[str, str, str] | tuple[Pin, Pin, Pin] = ("GP10", "GP11", "GP15"), /, ) -> None: """ Enable the SD card. In order to initialize the card, give it a 3-tuple: ``(clk_pin, cmd_pin, dat0_pin)``. """ def deinit(self) -> None: """ Disable the SD card. """ # noinspection PyShadowingNames class SDCard(AbstractBlockDev): """ 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. 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` . """ def __init__( self, slot: int = 1, width: int = 1, cd: int | str | Pin | None = None, wp: int | str | Pin | None = None, sck: int | str | Pin | None = None, miso: int | str | Pin | None = None, mosi: int | str | Pin | None = None, cs: int | str | Pin | None = None, freq: int = 20000000, /, ): """ 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:`os.AbstractBlockDev`. This allows the mounting of an SD card to be as simple as:: os.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. - *freq* selects the SD/MMC interface frequency in Hz (only supported on the ESP32). """ ================================================ FILE: typehints/micropython/micropython.pyi ================================================ """ access and control MicroPython internals. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/micropython.rst. ============================================================== .. module:: micropython :synopsis: access and control MicroPython internals """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import TypeVar, overload, Callable, Any, Final _T: Final = TypeVar("_T") _F: Final = TypeVar("_F", bound=Callable[..., Any]) def native(func: _F) -> _F: """ This causes the MicroPython compiler to emit unoptimised native CPU opcodes rather than bytecode (normal) or optimised opcodes (viper) and is an optimisation, for more information see https://docs.micropython.org/en/latest/reference/speed_python.html#the-native-code-emitter. """ def viper(func: _F) -> _F: """ This causes the MicroPython compiler to emit optimised native CPU opcodes based on special typehints rather than bytecode (normal) or unoptimised opcodes (native) and is an optimisation, for more information see https://docs.micropython.org/en/latest/reference/speed_python.html#the-viper-code-emitter. """ def const(expr: _T, /) -> _T: """ 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. """ @overload def opt_level() -> int: """ 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. """ @overload def opt_level(level: int, /) -> None: """ 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. """ def alloc_emergency_exception_buf(size: int, /) -> None: """ 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. """ @overload def mem_info() -> None: """ 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. """ @overload def mem_info(verbose: Any, /) -> None: """ 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. """ @overload def qstr_info() -> None: """ 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. """ @overload def qstr_info(verbose: bool, /) -> None: """ 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. """ def stack_use() -> int: """ 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. """ def heap_lock() -> None: """ Lock or unlock the heap. When locked no memory allocation can occur and a `MemoryError` will be raised if any heap allocation is attempted. `heap_locked()` returns a true value if the heap is currently locked. 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. Both `heap_unlock()` and `heap_locked()` return the current lock depth (after unlocking for the former) as a non-negative integer, with 0 meaning the heap is not locked. If the REPL becomes active with the heap locked then it will be forcefully unlocked. Note: `heap_locked()` is not enabled on most ports by default, requires ``MICROPY_PY_MICROPYTHON_HEAP_LOCKED``. """ def heap_unlock() -> None: """ Lock or unlock the heap. When locked no memory allocation can occur and a `MemoryError` will be raised if any heap allocation is attempted. `heap_locked()` returns a true value if the heap is currently locked. 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. Both `heap_unlock()` and `heap_locked()` return the current lock depth (after unlocking for the former) as a non-negative integer, with 0 meaning the heap is not locked. If the REPL becomes active with the heap locked then it will be forcefully unlocked. Note: `heap_locked()` is not enabled on most ports by default, requires ``MICROPY_PY_MICROPYTHON_HEAP_LOCKED``. """ def heap_locked() -> bool: """ Lock or unlock the heap. When locked no memory allocation can occur and a `MemoryError` will be raised if any heap allocation is attempted. `heap_locked()` returns a true value if the heap is currently locked. 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. Both `heap_unlock()` and `heap_locked()` return the current lock depth (after unlocking for the former) as a non-negative integer, with 0 meaning the heap is not locked. If the REPL becomes active with the heap locked then it will be forcefully unlocked. Note: `heap_locked()` is not enabled on most ports by default, requires ``MICROPY_PY_MICROPYTHON_HEAP_LOCKED``. """ def kbd_intr(chr: int) -> None: """ 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. """ def schedule(func: Callable[[_T], None], arg: _T, /) -> None: """ 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 ` 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. """ ================================================ FILE: typehints/micropython/neopixel.pyi ================================================ """ control of WS2812 / NeoPixel LEDs. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/neopixel.rst. ===================================================== .. module:: neopixel :synopsis: control of WS2812 / NeoPixel LEDs This module provides a driver for WS2818 / NeoPixel LEDs. .. note:: This module is only included by default on the ESP8266 and ESP32 ports. On STM32 / Pyboard, you can `download the module `_ and copy it to the filesystem. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Final from machine import Pin _Color: Final = tuple[int, int, int] | tuple[int, int, int, int] class NeoPixel: """ This class stores pixel data for a WS2812 LED strip connected to a pin. The application should set pixel data and then call :meth:`NeoPixel.write` when it is ready to update the strip. For example:: import neopixel # 32 LED strip connected to X8. p = machine.Pin.board.X8 n = neopixel.NeoPixel(p, 32) # Draw a red gradient. for i in range(32): n[i] = (i * 8, 0, 0) # Update the strip. n.write() """ def __init__(self, pin: Pin, n: int, /, *, bpp: int = 3, timing: int = 1): """ Construct an NeoPixel object. The parameters are: - *pin* is a machine.Pin instance. - *n* is the number of LEDs in the strip. - *bpp* is 3 for RGB LEDs, and 4 for RGBW LEDs. - *timing* is 0 for 400KHz, and 1 for 800kHz LEDs (most are 800kHz). """ def fill(self, pixel: _Color, /) -> None: """ Sets the value of all pixels to the specified *pixel* value (i.e. an RGB/RGBW tuple). """ def __len__(self) -> int: """ Returns the number of LEDs in the strip. """ def __setitem__(self, index: int, val: _Color, /) -> None: """ Set the pixel at *index* to the value, which is an RGB/RGBW tuple. """ def __getitem__(self, index: int, /) -> _Color: """ Returns the pixel at *index* as an RGB/RGBW tuple. """ def write(self) -> None: """ Writes the current pixel data to the strip. """ ================================================ FILE: typehints/micropython/network.pyi ================================================ """ network configuration. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/network.rst. https://github.com/Josverl/micropython-stubs/blob/main/stubs/micropython-v1_19_1-esp32-GENERIC/network.py **************************************** .. 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:`socket` module. For example:: # connect/ show IP config a specific network interface # see below for examples of specific drivers import network import time nic = network.Driver(...) if not nic.isconnected(): nic.connect() print("Waiting for connection...") while not nic.isconnected(): time.sleep(1) print(nic.ifconfig()) # now use socket as usual import 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() """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from abc import abstractmethod from typing import Protocol, Callable, overload, Any, ClassVar, Final import pyb @overload def country() -> str: """ Get the two-letter ISO 3166-1 Alpha-2 country code to be used for radio compliance. The default code ``"XX"`` represents the "worldwide" region. """ @overload def country(code: str) -> None: """ Set the two-letter ISO 3166-1 Alpha-2 country code to be used for radio compliance. The default code ``"XX"`` represents the "worldwide" region. """ @overload def hostname() -> str: """Get the hostname that will identify this device on the network. It will be used by all interfaces. This hostname is used for: * Sending to the DHCP server in the client request. (If using DHCP) * Broadcasting via mDNS. (If enabled) The default hostname is typically the name of the board. """ @overload def hostname(name: str) -> None: """Set the hostname that will identify this device on the network. It will be used by all interfaces. This hostname is used for: * Sending to the DHCP server in the client request. (If using DHCP) * Broadcasting via mDNS. (If enabled) A change in hostname is typically only applied during connection. For DHCP this is because the hostname is part of the DHCP client request, and the implementation of mDNS in most ports only initialises the hostname once during connection. For this reason, you must set the hostname before activating/connecting your network interfaces. The length of the hostname is limited to 32 characters. :term:`MicroPython ports ` may choose to set a lower limit for memory reasons. If the given name does not fit, a `ValueError` is raised. The default hostname is typically the name of the board. """ MODE_11B: Final[int] = ... """IEEE 802.11b""" MODE_11G: Final[int] = ... """IEEE 802.11g""" MODE_11N: Final[int] = ... """IEEE 802.11n""" STA_IF: int = 0 """station interface""" AP_IF: int = 1 """access point interface""" STAT_IDLE: int = 0 """no connection and no activity""" STAT_CONNECTING: int = 1 """connecting in progress""" STAT_WRONG_PASSWORD: int = 2 """failed due to incorrect password""" STAT_NO_AP_FOUND: int = 3 """failed because no access point replied""" STAT_CONNECT_FAIL: int = 4 """failed due to other problems""" STAT_GOT_IP: int = 5 """connection successful""" AUTH_OPEN: int = 0 AUTH_WEP:int = 1 AUTH_WPA_PSK: int = 2 AUTH_WPA2_PSK: int = 3 AUTH_WPA_WPA2_PSK: int = 4 @overload def phy_mode() -> int: """ 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. """ @overload def phy_mode(mode: int, /) -> None: """ 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. """ class AbstractNIC(Protocol): """ Common network adapter interface ================================ This section describes an (implied) abstract base class for all network interface classes implemented by :term:`MicroPython ports ` 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. """ @abstractmethod def __init__(self, id: Any = None, /, *args: Any, **kwargs: Any): """ 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`. """ @overload @abstractmethod def active(self, /) -> bool: """ 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 (behaviour of calling them on inactive interface is undefined). """ @overload @abstractmethod def active(self, is_active: bool, /) -> None: """ 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 (behaviour of calling them on inactive interface is undefined). """ @overload @abstractmethod def connect(self, key: str | None = None, /, **kwargs: Any) -> 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) """ @overload @abstractmethod def connect( self, service_id: Any, key: str | None = None, /, **kwargs: Any ) -> 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) """ @abstractmethod def disconnect(self) -> None: """ Disconnect from network. """ @abstractmethod def isconnected(self) -> bool: """ Returns ``True`` if connected to network, otherwise returns ``False``. """ @abstractmethod def scan(self, **kwargs: Any) -> list[tuple[str, ...]]: """ 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(). """ @overload @abstractmethod def status(self) -> Any: """ 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). """ @overload @abstractmethod def status(self, param: str, /) -> Any: """ 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). """ @overload @abstractmethod def ifconfig(self) -> tuple[str, str, str, str]: """ 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')) """ @overload @abstractmethod def ifconfig(self, ip_mask_gateway_dns: tuple[str, str, str, str], /) -> None: """ 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')) """ @overload @abstractmethod def config(self, param: str, /) -> Any: """ 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')) """ @overload @abstractmethod def config(self, **kwargs: Any) -> None: """ 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')) """ class WLAN: """ 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 """ def __init__(self, interface_id: int, /): """ 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. """ @overload def active(self, /) -> bool: """ 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. """ @overload def active(self, is_active: bool, /) -> None: """ 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. """ def connect( self, ssid: str | None = None, password: str | None = None, /, *, bssid: bytes | None = None, ) -> 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). """ def disconnect(self) -> None: """ Disconnect from the currently connected wireless network. """ def scan(self) -> tuple[str, bytes, int, int, int]: """ Scan for the available wireless networks. Hidden networks -- where the SSID is not broadcast -- will also be scanned if the WLAN interface allows it. 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 `binascii.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 """ @overload def status(self) -> int: """ 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'``. """ @overload def status(self, param: str, /) -> int: """ 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'``. """ def isconnected(self) -> bool: """ 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. """ @overload def ifconfig(self) -> tuple[str, str, str, str]: """ 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')) """ @overload def ifconfig(self, ip_mask_gateway_dns: tuple[str, str, str, str], /) -> None: """ 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')) """ @overload def config(self, param: str, /) -> Any: """ 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 :term:`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 reconnects Number of reconnect attempts to make (integer, 0=none, -1=unlimited) ============= =========== """ @overload def config(self, **kwargs: Any) -> None: """ 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 :term:`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 reconnects Number of reconnect attempts to make (integer, 0=none, -1=unlimited) ============= =========== """ class WLANWiPy: """ .. 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 ` 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 ... """ STA: ClassVar[int] = ... """ selects the WLAN mode """ AP: ClassVar[int] = ... """ selects the WLAN mode """ WEP: ClassVar[int] = ... """ selects the network security """ WPA: ClassVar[int] = ... """ selects the network security """ WPA2: ClassVar[int] = ... """ selects the network security """ INT_ANT: ClassVar[int] = ... """ selects the antenna type """ EXT_ANT: ClassVar[int] = ... """ selects the antenna type """ @overload def __init__(self, id: int = 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. """ @overload def __init__( self, id: int, /, *, mode: int, ssid: str, auth: tuple[str, str], channel: int, antenna: int, ): """ 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. """ def init( self, mode: int, /, *, ssid: str, auth: tuple[str, str], channel: int, antenna: int, ) -> bool: """ 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) """ def connect( self, ssid: str, /, *, auth: tuple[str, str] | None = None, bssid: bytes | None = None, timeout: int | None = None, ) -> 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. """ def scan(self) -> tuple[str, bytes, int, int | None, int]: """ 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. """ def disconnect(self) -> None: """ Disconnect from the WiFi access point. """ def isconnected(self) -> bool: """ 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. """ @overload def ifconfig(self, if_id: int = 0, /) -> tuple[str, str, str, str]: """ 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')) """ @overload def ifconfig( self, if_id: int = 0, /, *, config: str | tuple[str, str, str, str] ) -> None: """ 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')) """ @overload def mode(self) -> int: """ Get or set the WLAN mode. """ @overload def mode(self, mode: int, /) -> None: """ Get or set the WLAN mode. """ @overload def ssid(self) -> str: """ Get or set the SSID when in AP mode. """ @overload def ssid(self, ssid: str, /) -> None: """ Get or set the SSID when in AP mode. """ @overload def auth(self) -> int: """ Get or set the authentication type when in AP mode. """ @overload def auth(self, auth: int, /) -> None: """ Get or set the authentication type when in AP mode. """ @overload def channel(self) -> int: """ Get or set the channel (only applicable in AP mode). """ @overload def channel(self, channel: int, /) -> None: """ Get or set the channel (only applicable in AP mode). """ @overload def antenna(self) -> int: """ Get or set the antenna type (external or internal). """ @overload def antenna(self, antenna: int, /) -> None: """ Get or set the antenna type (external or internal). """ @overload def mac(self) -> bytes: """ Get or set a 6-byte long bytes object with the MAC address. """ @overload def mac(self, mac: bytes, /) -> None: """ Get or set a 6-byte long bytes object with the MAC address. """ def irq(self, *, handler: Callable[[], None], wake: int) -> Any: """ 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. """ class CC3K: """ 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 buses and other pins for CS, VBEN and IRQ. """ WEP: ClassVar[int] = ... """ security type to use """ WPA: ClassVar[int] = ... """ security type to use """ WPA2: ClassVar[int] = ... """ security type to use """ def __init__( self, spi: pyb.SPI, pin_cs: pyb.Pin, pin_en: pyb.Pin, pin_irq: pyb.Pin, / ): """ 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 ` which is the SPI bus that the CC3000 is connected to (the MOSI, MISO and CLK pins). - *pin_cs* is a :ref:`Pin object ` which is connected to the CC3000 CS pin. - *pin_en* is a :ref:`Pin object ` which is connected to the CC3000 VBEN pin. - *pin_irq* is a :ref:`Pin object ` 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) """ def connect( self, ssid: str, key: str | None = None, /, *, security: int = WPA2, bssid: bytes | None = None, ) -> None: """ Connect to a WiFi access point using the given SSID, and other security parameters. """ def disconnect(self) -> None: """ Disconnect from the WiFi access point. """ def isconnected(self) -> bool: """ Returns True if connected to a WiFi access point and has a valid IP address, False otherwise. """ def ifconfig(self) -> tuple[str, str, str, str, str, str, str]: """ Returns a 7-tuple with (ip, subnet mask, gateway, DNS server, DHCP server, MAC address, SSID). """ def patch_version(self) -> str: """ Return the version of the patch program (firmware) on the CC3000. """ def patch_program(self, cmd: str, /) -> None: """ Upload the current firmware to the CC3000. You must pass 'pgm' as the first argument in order for the upload to proceed. """ class WIZNET5K: """ 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 buses and other pins for nSS and nRESET. """ def __init__(self, spi: pyb.SPI, pin_cs: pyb.Pin, pin_rst: pyb.Pin, /): """ 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 ` which is the SPI bus that the WIZnet5x00 is connected to (the MOSI, MISO and SCLK pins). - *pin_cs* is a :ref:`Pin object ` which is connected to the WIZnet5x00 nSS pin. - *pin_rst* is a :ref:`Pin object ` 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) """ def isconnected(self) -> bool: """ Returns ``True`` if the physical Ethernet link is connected and up. Returns ``False`` otherwise. """ @overload def ifconfig(self) -> tuple[str, str, str, str]: """ 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')) """ @overload def ifconfig(self, config: tuple[str, str, str, str], /): """ 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')) """ def regs(self) -> Any: """ Dump the WIZnet5x00 registers. Useful for debugging. """ ================================================ FILE: typehints/micropython/ubluetooth.pyi ================================================ """ Low-level Bluetooth radio functionality. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/bluetooth.rst. This module provides an interface to a Bluetooth controller on a board. Currently this supports Bluetooth Low Energy (BLE) in Central, Peripheral, Broadcaster, and Observer roles, as well as GATT Server and Client and L2CAP connection-oriented-channels. A device may operate in multiple roles concurrently. Pairing (and bonding) is supported on some ports. This API is intended to match the low-level Bluetooth protocol and provide building-blocks for higher-level abstractions such as specific device types. .. note:: This module is still under development and its classes, functions, methods and constants are subject to change. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import overload, Any, Callable, Final from uio import AnyReadableBuf, AnyWritableBuf # noinspection SpellCheckingInspection class BLE: """ class BLE --------- """ def __init__(self): """ Returns the singleton BLE object. """ @overload def active(self) -> bool: """ Optionally changes the active state of the BLE radio, and returns the current state. The radio must be made active before using any other methods on this class. """ @overload def active(self, active: bool, /) -> None: """ Optionally changes the active state of the BLE radio, and returns the current state. The radio must be made active before using any other methods on this class. """ @overload def config(self, param: str, /) -> Any: """ Get or set configuration values of the BLE interface. To get a value the parameter name should be quoted as a string, and just one parameter is queried at a time. To set values use the keyword syntax, and one ore more parameter can be set at a time. Currently supported values are: - ``'mac'``: The current address in use, depending on the current address mode. This returns a tuple of ``(addr_type, addr)``. See :meth:`gatts_write ` for details about address type. This may only be queried while the interface is currently active. - ``'addr_mode'``: Sets the address mode. Values can be: * 0x00 - PUBLIC - Use the controller's public address. * 0x01 - RANDOM - Use a generated static address. * 0x02 - RPA - Use resolvable private addresses. * 0x03 - NRPA - Use non-resolvable private addresses. By default the interface mode will use a PUBLIC address if available, otherwise it will use a RANDOM address. - ``'gap_name'``: Get/set the GAP device name used by service 0x1800, characteristic 0x2a00. This can be set at any time and changed multiple times. - ``'rxbuf'``: Get/set the size in bytes of the internal buffer used to store incoming events. This buffer is global to the entire BLE driver and so handles incoming data for all events, including all characteristics. Increasing this allows better handling of bursty incoming data (for example scan results) and the ability to receive larger characteristic values. - ``'mtu'``: Get/set the MTU that will be used during a ATT MTU exchange. The resulting MTU will be the minimum of this and the remote device's MTU. ATT MTU exchange will not happen automatically (unless the remote device initiates it), and must be manually initiated with :meth:`gattc_exchange_mtu`. Use the ``_IRQ_MTU_EXCHANGED`` event to discover the MTU for a given connection. - ``'bond'``: Sets whether bonding will be enabled during pairing. When enabled, pairing requests will set the "bond" flag and the keys will be stored by both devices. - ``'mitm'``: Sets whether MITM-protection is required for pairing. - ``'io'``: Sets the I/O capabilities of this device. Available options are:: _IO_CAPABILITY_DISPLAY_ONLY = const(0) _IO_CAPABILITY_DISPLAY_YESNO = const(1) _IO_CAPABILITY_KEYBOARD_ONLY = const(2) _IO_CAPABILITY_NO_INPUT_OUTPUT = const(3) _IO_CAPABILITY_KEYBOARD_DISPLAY = const(4) - ``'le_secure'``: Sets whether "LE Secure" pairing is required. Default is false (i.e. allow "Legacy Pairing"). """ @overload def config(self, **kwargs) -> None: """ Get or set configuration values of the BLE interface. To get a value the parameter name should be quoted as a string, and just one parameter is queried at a time. To set values use the keyword syntax, and one ore more parameter can be set at a time. Currently supported values are: - ``'mac'``: The current address in use, depending on the current address mode. This returns a tuple of ``(addr_type, addr)``. See :meth:`gatts_write ` for details about address type. This may only be queried while the interface is currently active. - ``'addr_mode'``: Sets the address mode. Values can be: * 0x00 - PUBLIC - Use the controller's public address. * 0x01 - RANDOM - Use a generated static address. * 0x02 - RPA - Use resolvable private addresses. * 0x03 - NRPA - Use non-resolvable private addresses. By default the interface mode will use a PUBLIC address if available, otherwise it will use a RANDOM address. - ``'gap_name'``: Get/set the GAP device name used by service 0x1800, characteristic 0x2a00. This can be set at any time and changed multiple times. - ``'rxbuf'``: Get/set the size in bytes of the internal buffer used to store incoming events. This buffer is global to the entire BLE driver and so handles incoming data for all events, including all characteristics. Increasing this allows better handling of bursty incoming data (for example scan results) and the ability to receive larger characteristic values. - ``'mtu'``: Get/set the MTU that will be used during a ATT MTU exchange. The resulting MTU will be the minimum of this and the remote device's MTU. ATT MTU exchange will not happen automatically (unless the remote device initiates it), and must be manually initiated with :meth:`gattc_exchange_mtu`. Use the ``_IRQ_MTU_EXCHANGED`` event to discover the MTU for a given connection. - ``'bond'``: Sets whether bonding will be enabled during pairing. When enabled, pairing requests will set the "bond" flag and the keys will be stored by both devices. - ``'mitm'``: Sets whether MITM-protection is required for pairing. - ``'io'``: Sets the I/O capabilities of this device. Available options are:: _IO_CAPABILITY_DISPLAY_ONLY = const(0) _IO_CAPABILITY_DISPLAY_YESNO = const(1) _IO_CAPABILITY_KEYBOARD_ONLY = const(2) _IO_CAPABILITY_NO_INPUT_OUTPUT = const(3) _IO_CAPABILITY_KEYBOARD_DISPLAY = const(4) - ``'le_secure'``: Sets whether "LE Secure" pairing is required. Default is false (i.e. allow "Legacy Pairing"). """ def irq(self, handler: Callable[[int, tuple[memoryview, ...]], Any], /) -> None: """ Registers a callback for events from the BLE stack. The *handler* takes two arguments, ``event`` (which will be one of the codes below) and ``data`` (which is an event-specific tuple of values). **Note:** As an optimisation to prevent unnecessary allocations, the ``addr``, ``adv_data``, ``char_data``, ``notify_data``, and ``uuid`` entries in the tuples are read-only memoryview instances pointing to :mod:`bluetooth`'s internal ringbuffer, and are only valid during the invocation of the IRQ handler function. If your program needs to save one of these values to access after the IRQ handler has returned (e.g. by saving it in a class instance or global variable), then it needs to take a copy of the data, either by using ``bytes()`` or ``bluetooth.UUID()``, like this:: connected_addr = bytes(addr) # equivalently: adv_data, char_data, or notify_data matched_uuid = bluetooth.UUID(uuid) For example, the IRQ handler for a scan result might inspect the ``adv_data`` to decide if it's the correct device, and only then copy the address data to be used elsewhere in the program. And to print data from within the IRQ handler, ``print(bytes(addr))`` will be needed. An event handler showing all possible events:: def bt_irq(event, data): if event == _IRQ_CENTRAL_CONNECT: # A central has connected to this peripheral. conn_handle, addr_type, addr = data elif event == _IRQ_CENTRAL_DISCONNECT: # A central has disconnected from this peripheral. conn_handle, addr_type, addr = data elif event == _IRQ_GATTS_WRITE: # A client has written to this characteristic or descriptor. conn_handle, attr_handle = data elif event == _IRQ_GATTS_READ_REQUEST: # A client has issued a read. Note: this is only supported on STM32. # Return a non-zero integer to deny the read (see below), or zero (or None) # to accept the read. conn_handle, attr_handle = data elif event == _IRQ_SCAN_RESULT: # A single scan result. addr_type, addr, adv_type, rssi, adv_data = data elif event == _IRQ_SCAN_DONE: # Scan duration finished or manually stopped. pass elif event == _IRQ_PERIPHERAL_CONNECT: # A successful gap_connect(). conn_handle, addr_type, addr = data elif event == _IRQ_PERIPHERAL_DISCONNECT: # Connected peripheral has disconnected. conn_handle, addr_type, addr = data elif event == _IRQ_GATTC_SERVICE_RESULT: # Called for each service found by gattc_discover_services(). conn_handle, start_handle, end_handle, uuid = data elif event == _IRQ_GATTC_SERVICE_DONE: # Called once service discovery is complete. # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, status = data elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT: # Called for each characteristic found by gattc_discover_services(). conn_handle, def_handle, value_handle, properties, uuid = data elif event == _IRQ_GATTC_CHARACTERISTIC_DONE: # Called once service discovery is complete. # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, status = data elif event == _IRQ_GATTC_DESCRIPTOR_RESULT: # Called for each descriptor found by gattc_discover_descriptors(). conn_handle, dsc_handle, uuid = data elif event == _IRQ_GATTC_DESCRIPTOR_DONE: # Called once service discovery is complete. # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, status = data elif event == _IRQ_GATTC_READ_RESULT: # A gattc_read() has completed. conn_handle, value_handle, char_data = data elif event == _IRQ_GATTC_READ_DONE: # A gattc_read() has completed. # Note: The value_handle will be zero on btstack (but present on NimBLE). # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, value_handle, status = data elif event == _IRQ_GATTC_WRITE_DONE: # A gattc_write() has completed. # Note: The value_handle will be zero on btstack (but present on NimBLE). # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, value_handle, status = data elif event == _IRQ_GATTC_NOTIFY: # A server has sent a notify request. conn_handle, value_handle, notify_data = data elif event == _IRQ_GATTC_INDICATE: # A server has sent an indicate request. conn_handle, value_handle, notify_data = data elif event == _IRQ_GATTS_INDICATE_DONE: # A client has acknowledged the indication. # Note: Status will be zero on successful acknowledgment, implementation-specific value otherwise. conn_handle, value_handle, status = data elif event == _IRQ_MTU_EXCHANGED: # ATT MTU exchange complete (either initiated by us or the remote device). conn_handle, mtu = data elif event == _IRQ_L2CAP_ACCEPT: # A new channel has been accepted. # Return a non-zero integer to reject the connection, or zero (or None) to accept. conn_handle, cid, psm, our_mtu, peer_mtu = data elif event == _IRQ_L2CAP_CONNECT: # A new channel is now connected (either as a result of connecting or accepting). conn_handle, cid, psm, our_mtu, peer_mtu = data elif event == _IRQ_L2CAP_DISCONNECT: # Existing channel has disconnected (status is zero), or a connection attempt failed (non-zero status). conn_handle, cid, psm, status = data elif event == _IRQ_L2CAP_RECV: # New data is available on the channel. Use l2cap_recvinto to read. conn_handle, cid = data elif event == _IRQ_L2CAP_SEND_READY: # A previous l2cap_send that returned False has now completed and the channel is ready to send again. # If status is non-zero, then the transmit buffer overflowed and the application should re-send the data. conn_handle, cid, status = data elif event == _IRQ_CONNECTION_UPDATE: # The remote device has updated connection parameters. conn_handle, conn_interval, conn_latency, supervision_timeout, status = data elif event == _IRQ_ENCRYPTION_UPDATE: # The encryption state has changed (likely as a result of pairing or bonding). conn_handle, encrypted, authenticated, bonded, key_size = data elif event == _IRQ_GET_SECRET: # Return a stored secret. # If key is None, return the index'th value of this sec_type. # Otherwise return the corresponding value for this sec_type and key. sec_type, index, key = data return value elif event == _IRQ_SET_SECRET: # Save a secret to the store for this sec_type and key. sec_type, key, value = data return True elif event == _IRQ_PASSKEY_ACTION: # Respond to a passkey request during pairing. # See gap_passkey() for details. # action will be an action that is compatible with the configured "io" config. # passkey will be non-zero if action is "numeric comparison". conn_handle, action, passkey = data The event codes are:: from micropython import const _IRQ_CENTRAL_CONNECT = const(1) _IRQ_CENTRAL_DISCONNECT = const(2) _IRQ_GATTS_WRITE = const(3) _IRQ_GATTS_READ_REQUEST = const(4) _IRQ_SCAN_RESULT = const(5) _IRQ_SCAN_DONE = const(6) _IRQ_PERIPHERAL_CONNECT = const(7) _IRQ_PERIPHERAL_DISCONNECT = const(8) _IRQ_GATTC_SERVICE_RESULT = const(9) _IRQ_GATTC_SERVICE_DONE = const(10) _IRQ_GATTC_CHARACTERISTIC_RESULT = const(11) _IRQ_GATTC_CHARACTERISTIC_DONE = const(12) _IRQ_GATTC_DESCRIPTOR_RESULT = const(13) _IRQ_GATTC_DESCRIPTOR_DONE = const(14) _IRQ_GATTC_READ_RESULT = const(15) _IRQ_GATTC_READ_DONE = const(16) _IRQ_GATTC_WRITE_DONE = const(17) _IRQ_GATTC_NOTIFY = const(18) _IRQ_GATTC_INDICATE = const(19) _IRQ_GATTS_INDICATE_DONE = const(20) _IRQ_MTU_EXCHANGED = const(21) _IRQ_L2CAP_ACCEPT = const(22) _IRQ_L2CAP_CONNECT = const(23) _IRQ_L2CAP_DISCONNECT = const(24) _IRQ_L2CAP_RECV = const(25) _IRQ_L2CAP_SEND_READY = const(26) _IRQ_CONNECTION_UPDATE = const(27) _IRQ_ENCRYPTION_UPDATE = const(28) _IRQ_GET_SECRET = const(29) _IRQ_SET_SECRET = const(30) For the ``_IRQ_GATTS_READ_REQUEST`` event, the available return codes are:: _GATTS_NO_ERROR = const(0x00) _GATTS_ERROR_READ_NOT_PERMITTED = const(0x02) _GATTS_ERROR_WRITE_NOT_PERMITTED = const(0x03) _GATTS_ERROR_INSUFFICIENT_AUTHENTICATION = const(0x05) _GATTS_ERROR_INSUFFICIENT_AUTHORIZATION = const(0x08) _GATTS_ERROR_INSUFFICIENT_ENCRYPTION = const(0x0f) For the ``_IRQ_PASSKEY_ACTION`` event, the available actions are:: _PASSKEY_ACTION_NONE = const(0) _PASSKEY_ACTION_INPUT = const(2) _PASSKEY_ACTION_DISPLAY = const(3) _PASSKEY_ACTION_NUMERIC_COMPARISON = const(4) In order to save space in the firmware, these constants are not included on the :mod:`bluetooth` module. Add the ones that you need from the list above to your program. """ def gap_advertise( self, interval_us: int, adv_data: AnyReadableBuf | None = None, /, *, resp_data: AnyReadableBuf | None = None, connectable: bool = True, ) -> None: """ Starts advertising at the specified interval (in **micro**\ seconds). This interval will be rounded down to the nearest 625us. To stop advertising, set *interval_us* to ``None``. *adv_data* and *resp_data* can be any type that implements the buffer protocol (e.g. ``bytes``, ``bytearray``, ``str``). *adv_data* is included in all broadcasts, and *resp_data* is send in reply to an active scan. **Note:** if *adv_data* (or *resp_data*) is ``None``, then the data passed to the previous call to ``gap_advertise`` will be re-used. This allows a broadcaster to resume advertising with just ``gap_advertise(interval_us)``. To clear the advertising payload pass an empty ``bytes``, i.e. ``b''``. """ def gap_scan( self, duration_ms: int, interval_us: int = 1280000, window_us: int = 11250, active: bool = False, /, ) -> None: """ Run a scan operation lasting for the specified duration (in **milli**\ seconds). To scan indefinitely, set *duration_ms* to ``0``. To stop scanning, set *duration_ms* to ``None``. Use *interval_us* and *window_us* to optionally configure the duty cycle. The scanner will run for *window_us* **micro**\ seconds every *interval_us* **micro**\ seconds for a total of *duration_ms* **milli**\ seconds. The default interval and window are 1.28 seconds and 11.25 milliseconds respectively (background scanning). For each scan result the ``_IRQ_SCAN_RESULT`` event will be raised, with event data ``(addr_type, addr, adv_type, rssi, adv_data)``. ``addr_type`` values indicate public or random addresses: * 0x00 - PUBLIC * 0x01 - RANDOM (either static, RPA, or NRPA, the type is encoded in the address itself) ``adv_type`` values correspond to the Bluetooth Specification: * 0x00 - ADV_IND - connectable and scannable undirected advertising * 0x01 - ADV_DIRECT_IND - connectable directed advertising * 0x02 - ADV_SCAN_IND - scannable undirected advertising * 0x03 - ADV_NONCONN_IND - non-connectable undirected advertising * 0x04 - SCAN_RSP - scan response ``active`` can be set ``True`` if you want to receive scan responses in the results. When scanning is stopped (either due to the duration finishing or when explicitly stopped), the ``_IRQ_SCAN_DONE`` event will be raised. """ def gap_connect( self, addr_type: int, addr: bytes, scan_duration_ms: int = 2000, min_conn_interval_us: int | None = None, max_conn_interval_us: int | None = None, /, ) -> None: """ Connect to a peripheral. See :meth:`gap_scan ` for details about address types. On success, the ``_IRQ_PERIPHERAL_CONNECT`` event will be raised. The device will wait up to *scan_duration_ms* to receive an advertising payload from the device. The connection interval can be configured in **micro**\ seconds using either or both of *min_conn_interval_us* and *max_conn_interval_us*. Otherwise a default interval will be chosen, typically between 30000 and 50000 microseconds. A shorter interval will increase throughput, at the expense of power usage. Central Role ------------ A central device can connect to peripherals that it has discovered using the observer role (see :meth:`gap_scan`) or with a known address. """ def gap_disconnect(self, conn_handle: memoryview, /) -> bool: """ Disconnect the specified connection handle. This can either be a central that has connected to this device (if acting as a peripheral) or a peripheral that was previously connected to by this device (if acting as a central). On success, the ``_IRQ_PERIPHERAL_DISCONNECT`` or ``_IRQ_CENTRAL_DISCONNECT`` event will be raised. Returns ``False`` if the connection handle wasn't connected, and ``True`` otherwise. Central Role ------------ A central device can connect to peripherals that it has discovered using the observer role (see :meth:`gap_scan`) or with a known address. Peripheral Role --------------- A peripheral device is expected to send connectable advertisements (see :meth:`gap_advertise`). It will usually be acting as a GATT server, having first registered services and characteristics using :meth:`gatts_register_services`. When a central connects, the ``_IRQ_CENTRAL_CONNECT`` event will be raised. """ _Flag: Final = int _Descriptor: Final = tuple["UUID", _Flag] _Characteristic: Final = tuple["UUID", _Flag] | tuple[ "UUID", _Flag, tuple[_Descriptor, ...] ] _Service: Final = tuple["UUID", tuple[_Characteristic, ...]] def gatts_register_services( self, services_definition: tuple[_Service, ...], / ) -> tuple[tuple[memoryview, ...], ...]: """ Configures the server with the specified services, replacing any existing services. *services_definition* is a list of **services**, where each **service** is a two-element tuple containing a UUID and a list of **characteristics**. Each **characteristic** is a two-or-three-element tuple containing a UUID, a **flags** value, and optionally a list of *descriptors*. Each **descriptor** is a two-element tuple containing a UUID and a **flags** value. The **flags** are a bitwise-OR combination of the flags defined below. These set both the behaviour of the characteristic (or descriptor) as well as the security and privacy requirements. The return value is a list (one element per service) of tuples (each element is a value handle). Characteristics and descriptor handles are flattened into the same tuple, in the order that they are defined. The following example registers two services (Heart Rate, and Nordic UART):: HR_UUID = bluetooth.UUID(0x180D) HR_CHAR = (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,) HR_SERVICE = (HR_UUID, (HR_CHAR,),) UART_UUID = bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E') UART_TX = (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,) UART_RX = (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE,) UART_SERVICE = (UART_UUID, (UART_TX, UART_RX,),) SERVICES = (HR_SERVICE, UART_SERVICE,) ( (hr,), (tx, rx,), ) = bt.gatts_register_services(SERVICES) The three value handles (``hr``, ``tx``, ``rx``) can be used with :meth:`gatts_read `, :meth:`gatts_write `, :meth:`gatts_notify `, and :meth:`gatts_indicate `. **Note:** Advertising must be stopped before registering services. Available flags for characteristics and descriptors are:: from micropython import const _FLAG_BROADCAST = const(0x0001) _FLAG_READ = const(0x0002) _FLAG_WRITE_NO_RESPONSE = const(0x0004) _FLAG_WRITE = const(0x0008) _FLAG_NOTIFY = const(0x0010) _FLAG_INDICATE = const(0x0020) _FLAG_AUTHENTICATED_SIGNED_WRITE = const(0x0040) _FLAG_AUX_WRITE = const(0x0100) _FLAG_READ_ENCRYPTED = const(0x0200) _FLAG_READ_AUTHENTICATED = const(0x0400) _FLAG_READ_AUTHORIZED = const(0x0800) _FLAG_WRITE_ENCRYPTED = const(0x1000) _FLAG_WRITE_AUTHENTICATED = const(0x2000) _FLAG_WRITE_AUTHORIZED = const(0x4000) As for the IRQs above, any required constants should be added to your Python code. GATT Server ----------- A GATT server has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. These values are stored locally, and are accessed by their "value handle" which is generated during service registration. They can also be read from or written to by a remote client device. Additionally, a server can "notify" a characteristic to a connected client via a connection handle. A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more common for a peripheral device to act as the server. Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a client to a given characteristic, use :meth:`gatts_write` after registration. e.g. ``gatts_write(char_handle, bytes(100))``. """ def gatts_read(self, value_handle: memoryview, /) -> bytes: """ Reads the local value for this handle (which has either been written by :meth:`gatts_write ` or by a remote client). GATT Server ----------- A GATT server has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. These values are stored locally, and are accessed by their "value handle" which is generated during service registration. They can also be read from or written to by a remote client device. Additionally, a server can "notify" a characteristic to a connected client via a connection handle. A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more common for a peripheral device to act as the server. Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a client to a given characteristic, use :meth:`gatts_write` after registration. e.g. ``gatts_write(char_handle, bytes(100))``. """ def gatts_write( self, value_handle: memoryview, data: bytes, send_update: bool = False, / ) -> None: """ Writes the local value for this handle, which can be read by a client. If *send_update* is ``True``, then any subscribed clients will be notified (or indicated, depending on what they're subscribed to and which operations the characteristic supports) about this write. GATT Server ----------- A GATT server has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. These values are stored locally, and are accessed by their "value handle" which is generated during service registration. They can also be read from or written to by a remote client device. Additionally, a server can "notify" a characteristic to a connected client via a connection handle. A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more common for a peripheral device to act as the server. Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a client to a given characteristic, use :meth:`gatts_write` after registration. e.g. ``gatts_write(char_handle, bytes(100))``. """ def gatts_notify(self, value_handle: memoryview, data: bytes, /) -> None: """ Sends a notification request to a connected client. If *data* is not ``None``, then that value is sent to the client as part of the notification. The local value will not be modified. Otherwise, if *data* is ``None``, then the current local value (as set with :meth:`gatts_write `) will be sent. **Note:** The notification will be sent regardless of the subscription status of the client to this characteristic. GATT Server ----------- A GATT server has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. These values are stored locally, and are accessed by their "value handle" which is generated during service registration. They can also be read from or written to by a remote client device. Additionally, a server can "notify" a characteristic to a connected client via a connection handle. A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more common for a peripheral device to act as the server. Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a client to a given characteristic, use :meth:`gatts_write` after registration. e.g. ``gatts_write(char_handle, bytes(100))``. """ def gatts_indicate( self, conn_handle: memoryview, value_handle: memoryview, / ) -> None: """ Sends an indication request containing the characteristic's current value to a connected client. On acknowledgment (or failure, e.g. timeout), the ``_IRQ_GATTS_INDICATE_DONE`` event will be raised. **Note:** The indication will be sent regardless of the subscription status of the client to this characteristic. GATT Server ----------- A GATT server has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. These values are stored locally, and are accessed by their "value handle" which is generated during service registration. They can also be read from or written to by a remote client device. Additionally, a server can "notify" a characteristic to a connected client via a connection handle. A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more common for a peripheral device to act as the server. Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a client to a given characteristic, use :meth:`gatts_write` after registration. e.g. ``gatts_write(char_handle, bytes(100))``. """ def gatts_set_buffer( self, conn_handle: memoryview, len: int, append: bool = False, / ) -> None: """ Sets the internal buffer size for a value in bytes. This will limit the largest possible write that can be received. The default is 20. Setting *append* to ``True`` will make all remote writes append to, rather than replace, the current value. At most *len* bytes can be buffered in this way. When you use :meth:`gatts_read `, the value will be cleared after reading. This feature is useful when implementing something like the Nordic UART Service. GATT Server ----------- A GATT server has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. These values are stored locally, and are accessed by their "value handle" which is generated during service registration. They can also be read from or written to by a remote client device. Additionally, a server can "notify" a characteristic to a connected client via a connection handle. A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more common for a peripheral device to act as the server. Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a client to a given characteristic, use :meth:`gatts_write` after registration. e.g. ``gatts_write(char_handle, bytes(100))``. """ def gattc_discover_services( self, conn_handle: memoryview, uuid: UUID | None = None, / ) -> None: """ Query a connected server for its services. Optionally specify a service *uuid* to query for that service only. For each service discovered, the ``_IRQ_GATTC_SERVICE_RESULT`` event will be raised, followed by ``_IRQ_GATTC_SERVICE_DONE`` on completion. GATT Client ----------- A GATT client can discover and read/write characteristics on a remote GATT server. It is more common for a central role device to act as the GATT client, however it's also possible for a peripheral to act as a client in order to discover information about the central that has connected to it (e.g. to read the device name from the device information service). """ def gattc_discover_characteristics( self, conn_handle: memoryview, start_handle: int, end_handle: int, uuid: UUID | None = None, /, ) -> None: """ Query a connected server for characteristics in the specified range. Optionally specify a characteristic *uuid* to query for that characteristic only. You can use ``start_handle=1``, ``end_handle=0xffff`` to search for a characteristic in any service. For each characteristic discovered, the ``_IRQ_GATTC_CHARACTERISTIC_RESULT`` event will be raised, followed by ``_IRQ_GATTC_CHARACTERISTIC_DONE`` on completion. GATT Client ----------- A GATT client can discover and read/write characteristics on a remote GATT server. It is more common for a central role device to act as the GATT client, however it's also possible for a peripheral to act as a client in order to discover information about the central that has connected to it (e.g. to read the device name from the device information service). """ def gattc_discover_descriptors( self, conn_handle: memoryview, start_handle: int, end_handle: int, / ) -> None: """ Query a connected server for descriptors in the specified range. For each descriptor discovered, the ``_IRQ_GATTC_DESCRIPTOR_RESULT`` event will be raised, followed by ``_IRQ_GATTC_DESCRIPTOR_DONE`` on completion. GATT Client ----------- A GATT client can discover and read/write characteristics on a remote GATT server. It is more common for a central role device to act as the GATT client, however it's also possible for a peripheral to act as a client in order to discover information about the central that has connected to it (e.g. to read the device name from the device information service). """ def gattc_read(self, conn_handle: memoryview, value_handle: memoryview, /) -> None: """ Issue a remote read to a connected server for the specified characteristic or descriptor handle. When a value is available, the ``_IRQ_GATTC_READ_RESULT`` event will be raised. Additionally, the ``_IRQ_GATTC_READ_DONE`` will be raised. GATT Client ----------- A GATT client can discover and read/write characteristics on a remote GATT server. It is more common for a central role device to act as the GATT client, however it's also possible for a peripheral to act as a client in order to discover information about the central that has connected to it (e.g. to read the device name from the device information service). """ def gattc_write( self, conn_handle: memoryview, value_handle: memoryview, data: bytes, mode: int = 0, /, ) -> None: """ Issue a remote write to a connected server for the specified characteristic or descriptor handle. The argument *mode* specifies the write behaviour, with the currently supported values being: * ``mode=0`` (default) is a write-without-response: the write will be sent to the remote server but no confirmation will be returned, and no event will be raised. * ``mode=1`` is a write-with-response: the remote server is requested to send a response/acknowledgement that it received the data. If a response is received from the remote server the ``_IRQ_GATTC_WRITE_DONE`` event will be raised. GATT Client ----------- A GATT client can discover and read/write characteristics on a remote GATT server. It is more common for a central role device to act as the GATT client, however it's also possible for a peripheral to act as a client in order to discover information about the central that has connected to it (e.g. to read the device name from the device information service). """ def gattc_exchange_mtu(self, conn_handle: memoryview, /) -> None: """ Initiate MTU exchange with a connected server, using the preferred MTU set using ``BLE.config(mtu=value)``. The ``_IRQ_MTU_EXCHANGED`` event will be raised when MTU exchange completes. **Note:** MTU exchange is typically initiated by the central. When using the BlueKitchen stack in the central role, it does not support a remote peripheral initiating the MTU exchange. NimBLE works for both roles. GATT Client ----------- A GATT client can discover and read/write characteristics on a remote GATT server. It is more common for a central role device to act as the GATT client, however it's also possible for a peripheral to act as a client in order to discover information about the central that has connected to it (e.g. to read the device name from the device information service). """ def l2cap_listen(self, psm: memoryview, mtu: memoryview, /) -> None: """ Start listening for incoming L2CAP channel requests on the specified *psm* with the local MTU set to *mtu*. When a remote device initiates a connection, the ``_IRQ_L2CAP_ACCEPT`` event will be raised, which gives the listening server a chance to reject the incoming connection (by returning a non-zero integer). Once the connection is accepted, the ``_IRQ_L2CAP_CONNECT`` event will be raised, allowing the server to obtain the channel id (CID) and the local and remote MTU. **Note:** It is not currently possible to stop listening. L2CAP connection-oriented-channels ---------------------------------- This feature allows for socket-like data exchange between two BLE devices. Once the devices are connected via GAP, either device can listen for the other to connect on a numeric PSM (Protocol/Service Multiplexer). **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). Only one L2CAP channel may be active at a given time (i.e. you cannot connect while listening). Active L2CAP channels are identified by the connection handle that they were established on and a CID (channel ID). Connection-oriented channels have built-in credit-based flow control. Unlike ATT, where devices negotiate a shared MTU, both the listening and connecting devices each set an independent MTU which limits the maximum amount of outstanding data that the remote device can send before it is fully consumed in :meth:`l2cap_recvinto `. """ def l2cap_connect( self, conn_handle: memoryview, psm: memoryview, mtu: memoryview, / ) -> None: """ Connect to a listening peer on the specified *psm* with local MTU set to *mtu*. On successful connection, the the ``_IRQ_L2CAP_CONNECT`` event will be raised, allowing the client to obtain the CID and the local and remote (peer) MTU. An unsuccessful connection will raise the ``_IRQ_L2CAP_DISCONNECT`` event with a non-zero status. L2CAP connection-oriented-channels ---------------------------------- This feature allows for socket-like data exchange between two BLE devices. Once the devices are connected via GAP, either device can listen for the other to connect on a numeric PSM (Protocol/Service Multiplexer). **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). Only one L2CAP channel may be active at a given time (i.e. you cannot connect while listening). Active L2CAP channels are identified by the connection handle that they were established on and a CID (channel ID). Connection-oriented channels have built-in credit-based flow control. Unlike ATT, where devices negotiate a shared MTU, both the listening and connecting devices each set an independent MTU which limits the maximum amount of outstanding data that the remote device can send before it is fully consumed in :meth:`l2cap_recvinto `. """ def l2cap_disconnect(self, conn_handle: memoryview, cid: memoryview, /) -> None: """ Disconnect an active L2CAP channel with the specified *conn_handle* and *cid*. L2CAP connection-oriented-channels ---------------------------------- This feature allows for socket-like data exchange between two BLE devices. Once the devices are connected via GAP, either device can listen for the other to connect on a numeric PSM (Protocol/Service Multiplexer). **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). Only one L2CAP channel may be active at a given time (i.e. you cannot connect while listening). Active L2CAP channels are identified by the connection handle that they were established on and a CID (channel ID). Connection-oriented channels have built-in credit-based flow control. Unlike ATT, where devices negotiate a shared MTU, both the listening and connecting devices each set an independent MTU which limits the maximum amount of outstanding data that the remote device can send before it is fully consumed in :meth:`l2cap_recvinto `. """ def l2cap_send(self, conn_handle: memoryview, cid: memoryview, /) -> None: """ Send the specified *buf* (which must support the buffer protocol) on the L2CAP channel identified by *conn_handle* and *cid*. The specified buffer cannot be larger than the remote (peer) MTU, and no more than twice the size of the local MTU. This will return ``False`` if the channel is now "stalled", which means that :meth:`l2cap_send ` must not be called again until the ``_IRQ_L2CAP_SEND_READY`` event is received (which will happen when the remote device grants more credits, typically after it has received and processed the data). L2CAP connection-oriented-channels ---------------------------------- This feature allows for socket-like data exchange between two BLE devices. Once the devices are connected via GAP, either device can listen for the other to connect on a numeric PSM (Protocol/Service Multiplexer). **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). Only one L2CAP channel may be active at a given time (i.e. you cannot connect while listening). Active L2CAP channels are identified by the connection handle that they were established on and a CID (channel ID). Connection-oriented channels have built-in credit-based flow control. Unlike ATT, where devices negotiate a shared MTU, both the listening and connecting devices each set an independent MTU which limits the maximum amount of outstanding data that the remote device can send before it is fully consumed in :meth:`l2cap_recvinto `. """ def l2cap_recvinto( self, conn_handle: memoryview, cid: memoryview, buf: AnyWritableBuf | None, / ) -> int: """ Receive data from the specified *conn_handle* and *cid* into the provided *buf* (which must support the buffer protocol, e.g. bytearray or memoryview). Returns the number of bytes read from the channel. If *buf* is None, then returns the number of bytes available. **Note:** After receiving the ``_IRQ_L2CAP_RECV`` event, the application should continue calling :meth:`l2cap_recvinto ` until no more bytes are available in the receive buffer (typically up to the size of the remote (peer) MTU). Until the receive buffer is empty, the remote device will not be granted more channel credits and will be unable to send any more data. L2CAP connection-oriented-channels ---------------------------------- This feature allows for socket-like data exchange between two BLE devices. Once the devices are connected via GAP, either device can listen for the other to connect on a numeric PSM (Protocol/Service Multiplexer). **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). Only one L2CAP channel may be active at a given time (i.e. you cannot connect while listening). Active L2CAP channels are identified by the connection handle that they were established on and a CID (channel ID). Connection-oriented channels have built-in credit-based flow control. Unlike ATT, where devices negotiate a shared MTU, both the listening and connecting devices each set an independent MTU which limits the maximum amount of outstanding data that the remote device can send before it is fully consumed in :meth:`l2cap_recvinto `. """ def gap_pair(self, conn_handle: memoryview, /) -> None: """ Initiate pairing with the remote device. Before calling this, ensure that the ``io``, ``mitm``, ``le_secure``, and ``bond`` configuration options are set (via :meth:`config`). On successful pairing, the ``_IRQ_ENCRYPTION_UPDATE`` event will be raised. Pairing and bonding ------------------- Pairing allows a connection to be encrypted and authenticated via exchange of secrets (with optional MITM protection via passkey authentication). Bonding is the process of storing those secrets into non-volatile storage. When bonded, a device is able to resolve a resolvable private address (RPA) from another device based on the stored identity resolving key (IRK). To support bonding, an application must implement the ``_IRQ_GET_SECRET`` and ``_IRQ_SET_SECRET`` events. **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). """ def gap_passkey( self, conn_handle: memoryview, action: int, passkey: int, / ) -> None: """ Respond to a ``_IRQ_PASSKEY_ACTION`` event for the specified *conn_handle* and *action*. The *passkey* is a numeric value and will depend on on the *action* (which will depend on what I/O capability has been set): * When the *action* is ``_PASSKEY_ACTION_INPUT``, then the application should prompt the user to enter the passkey that is shown on the remote device. * When the *action* is ``_PASSKEY_ACTION_DISPLAY``, then the application should generate a random 6-digit passkey and show it to the user. * When the *action* is ``_PASSKEY_ACTION_NUMERIC_COMPARISON``, then the application should show the passkey that was provided in the ``_IRQ_PASSKEY_ACTION`` event and then respond with either ``0`` (cancel pairing), or ``1`` (accept pairing). Pairing and bonding ------------------- Pairing allows a connection to be encrypted and authenticated via exchange of secrets (with optional MITM protection via passkey authentication). Bonding is the process of storing those secrets into non-volatile storage. When bonded, a device is able to resolve a resolvable private address (RPA) from another device based on the stored identity resolving key (IRK). To support bonding, an application must implement the ``_IRQ_GET_SECRET`` and ``_IRQ_SET_SECRET`` events. **Note:** This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32). """ class UUID: """ class UUID ---------- """ def __init__(self, value: int | str, /): """ Creates a UUID instance with the specified **value**. The **value** can be either: - A 16-bit integer. e.g. ``0x2908``. - A 128-bit UUID string. e.g. ``'6E400001-B5A3-F393-E0A9-E50E24DCCA9E'``. """ ================================================ FILE: typehints/micropython/ucryptolib.pyi ================================================ """ cryptographic ciphers. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/cryptolib.rst. ========================================= .. module:: cryptolib :synopsis: cryptographic ciphers """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import overload from uio import AnyReadableBuf, AnyWritableBuf # noinspection PyPep8Naming class aes: """ .. class:: aes """ @overload def __init__(self, key: AnyReadableBuf, mode: int, /): """ Initialize cipher object, suitable for encryption/decryption. Note: after initialization, cipher object can be use only either for encryption or decryption. Running decrypt() operation after encrypt() or vice versa is not supported. Parameters are: * *key* is an encryption/decryption key (bytes-like). * *mode* is: * ``1`` (or ``cryptolib.MODE_ECB`` if it exists) for Electronic Code Book (ECB). * ``2`` (or ``cryptolib.MODE_CBC`` if it exists) for Cipher Block Chaining (CBC). * ``6`` (or ``cryptolib.MODE_CTR`` if it exists) for Counter mode (CTR). * *IV* is an initialization vector for CBC mode. * For Counter mode, *IV* is the initial value for the counter. """ @overload def __init__(self, key: AnyReadableBuf, mode: int, IV: AnyReadableBuf, /): """ Initialize cipher object, suitable for encryption/decryption. Note: after initialization, cipher object can be use only either for encryption or decryption. Running decrypt() operation after encrypt() or vice versa is not supported. Parameters are: * *key* is an encryption/decryption key (bytes-like). * *mode* is: * ``1`` (or ``cryptolib.MODE_ECB`` if it exists) for Electronic Code Book (ECB). * ``2`` (or ``cryptolib.MODE_CBC`` if it exists) for Cipher Block Chaining (CBC). * ``6`` (or ``cryptolib.MODE_CTR`` if it exists) for Counter mode (CTR). * *IV* is an initialization vector for CBC mode. * For Counter mode, *IV* is the initial value for the counter. """ @overload def encrypt(self, in_buf: AnyReadableBuf, /) -> bytes: """ Encrypt *in_buf*. If no *out_buf* is given result is returned as a newly allocated `bytes` object. Otherwise, result is written into mutable buffer *out_buf*. *in_buf* and *out_buf* can also refer to the same mutable buffer, in which case data is encrypted in-place. """ @overload def encrypt(self, in_buf: AnyReadableBuf, out_buf: AnyWritableBuf, /) -> None: """ Encrypt *in_buf*. If no *out_buf* is given result is returned as a newly allocated `bytes` object. Otherwise, result is written into mutable buffer *out_buf*. *in_buf* and *out_buf* can also refer to the same mutable buffer, in which case data is encrypted in-place. """ @overload def decrypt(self, in_buf: AnyReadableBuf, /) -> bytes: """ Like `encrypt()`, but for decryption. """ @overload def decrypt(self, in_buf: AnyReadableBuf, out_buf: AnyWritableBuf, /) -> None: """ Like `encrypt()`, but for decryption. """ ================================================ FILE: typehints/micropython/uctypes.pyi ================================================ """ access binary data in a structured way. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/uctypes.rst. ======================================================== .. module:: uctypes :synopsis: access binary data in a structured way This module implements "foreign data interface" for MicroPython. The idea behind it is similar to CPython's ``ctypes`` modules, but the actual API is different, streamlined and optimized for small size. The basic idea of the module is to define data structure layout with about the same power as the C language allows, and then access it using familiar dot-syntax to reference sub-fields. .. warning:: ``uctypes`` module allows access to arbitrary memory addresses of the machine (including I/O and control registers). Uncareful usage of it may lead to crashes, data loss, and even hardware malfunction. .. seealso:: Module :mod:`struct` Standard Python way to access binary data structures (doesn't scale well to large and complex structures). Usage examples:: import uctypes # Example 1: Subset of ELF file header # https://wikipedia.org/wiki/Executable_and_Linkable_Format#File_header ELF_HEADER = { "EI_MAG": (0x0 | uctypes.ARRAY, 4 | uctypes.UINT8), "EI_DATA": 0x5 | uctypes.UINT8, "e_machine": 0x12 | uctypes.UINT16, } # "f" is an ELF file opened in binary mode buf = f.read(uctypes.sizeof(ELF_HEADER, uctypes.LITTLE_ENDIAN)) header = uctypes.struct(uctypes.addressof(buf), ELF_HEADER, uctypes.LITTLE_ENDIAN) assert header.EI_MAG == b"\x7fELF" assert header.EI_DATA == 1, "Oops, wrong endianness. Could retry with uctypes.BIG_ENDIAN." print("machine:", hex(header.e_machine)) # Example 2: In-memory data structure, with pointers COORD = { "x": 0 | uctypes.FLOAT32, "y": 4 | uctypes.FLOAT32, } STRUCT1 = { "data1": 0 | uctypes.UINT8, "data2": 4 | uctypes.UINT32, "ptr": (8 | uctypes.PTR, COORD), } # Suppose you have address of a structure of type STRUCT1 in "addr" # uctypes.NATIVE is optional (used by default) struct1 = uctypes.struct(addr, STRUCT1, uctypes.NATIVE) print("x:", struct1.ptr[0].x) # Example 3: Access to CPU registers. Subset of STM32F4xx WWDG block WWDG_LAYOUT = { "WWDG_CR": (0, { # BFUINT32 here means size of the WWDG_CR register "WDGA": 7 << uctypes.BF_POS | 1 << uctypes.BF_LEN | uctypes.BFUINT32, "T": 0 << uctypes.BF_POS | 7 << uctypes.BF_LEN | uctypes.BFUINT32, }), "WWDG_CFR": (4, { "EWI": 9 << uctypes.BF_POS | 1 << uctypes.BF_LEN | uctypes.BFUINT32, "WDGTB": 7 << uctypes.BF_POS | 2 << uctypes.BF_LEN | uctypes.BFUINT32, "W": 0 << uctypes.BF_POS | 7 << uctypes.BF_LEN | uctypes.BFUINT32, }), } WWDG = uctypes.struct(0x40002c00, WWDG_LAYOUT) WWDG.WWDG_CFR.WDGTB = 0b10 WWDG.WWDG_CR.WDGA = 1 print("Current counter:", WWDG.WWDG_CR.T) Defining structure layout ------------------------- Structure layout is defined by a "descriptor" - a Python dictionary which encodes field names as keys and other properties required to access them as associated values:: { "field1": , "field2": , ... } Currently, ``uctypes`` requires explicit specification of offsets for each field. Offset are given in bytes from the structure start. Following are encoding examples for various field types: * Scalar types:: "field_name": offset | uctypes.UINT32 in other words, the value is a scalar type identifier ORed with a field offset (in bytes) from the start of the structure. * Recursive structures:: "sub": (offset, { "b0": 0 | uctypes.UINT8, "b1": 1 | uctypes.UINT8, }) i.e. value is a 2-tuple, first element of which is an offset, and second is a structure descriptor dictionary (note: offsets in recursive descriptors are relative to the structure it defines). Of course, recursive structures can be specified not just by a literal dictionary, but by referring to a structure descriptor dictionary (defined earlier) by name. * Arrays of primitive types:: "arr": (offset | uctypes.ARRAY, size | uctypes.UINT8), i.e. value is a 2-tuple, first element of which is ARRAY flag ORed with offset, and second is scalar element type ORed number of elements in the array. * Arrays of aggregate types:: "arr2": (offset | uctypes.ARRAY, size, {"b": 0 | uctypes.UINT8}), i.e. value is a 3-tuple, first element of which is ARRAY flag ORed with offset, second is a number of elements in the array, and third is a descriptor of element type. * Pointer to a primitive type:: "ptr": (offset | uctypes.PTR, uctypes.UINT8), i.e. value is a 2-tuple, first element of which is PTR flag ORed with offset, and second is a scalar element type. * Pointer to an aggregate type:: "ptr2": (offset | uctypes.PTR, {"b": 0 | uctypes.UINT8}), i.e. value is a 2-tuple, first element of which is PTR flag ORed with offset, second is a descriptor of type pointed to. * Bitfields:: "bitf0": offset | uctypes.BFUINT16 | lsbit << uctypes.BF_POS | bitsize << uctypes.BF_LEN, i.e. value is a type of scalar value containing given bitfield (typenames are similar to scalar types, but prefixes with ``BF``), ORed with offset for scalar value containing the bitfield, and further ORed with values for bit position and bit length of the bitfield within the scalar value, shifted by BF_POS and BF_LEN bits, respectively. A bitfield position is counted from the least significant bit of the scalar (having position of 0), and is the number of right-most bit of a field (in other words, it's a number of bits a scalar needs to be shifted right to extract the bitfield). In the example above, first a UINT16 value will be extracted at offset 0 (this detail may be important when accessing hardware registers, where particular access size and alignment are required), and then bitfield whose rightmost bit is *lsbit* bit of this UINT16, and length is *bitsize* bits, will be extracted. For example, if *lsbit* is 0 and *bitsize* is 8, then effectively it will access least-significant byte of UINT16. Note that bitfield operations are independent of target byte endianness, in particular, example above will access least-significant byte of UINT16 in both little- and big-endian structures. But it depends on the least significant bit being numbered 0. Some targets may use different numbering in their native ABI, but ``uctypes`` always uses the normalized numbering described above. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Final from uio import AnyReadableBuf _ScalarProperty: Final = int _RecursiveProperty: Final = tuple[int, "_property"] _ArrayProperty: Final = tuple[int, int] _ArrayOfAggregateProperty: Final = tuple[int, int, "_property"] _PointerToAPrimitiveProperty: Final = tuple[int, int] _PointerToAaAggregateProperty: Final = tuple[int, "_property"] _BitfieldProperty: Final = int _property: Final = _ScalarProperty | _RecursiveProperty | _ArrayProperty | _ArrayOfAggregateProperty | _PointerToAPrimitiveProperty | _PointerToAaAggregateProperty | _BitfieldProperty _descriptor: Final = tuple[str, _property] LITTLE_ENDIAN: Final[int] = ... """ Layout type for a little-endian packed structure. (Packed means that every field occupies exactly as many bytes as defined in the descriptor, i.e. the alignment is 1). """ BIG_ENDIAN: Final[int] = ... """ Layout type for a big-endian packed structure. """ NATIVE: Final[int] = ... """ Layout type for a native structure - with data endianness and alignment conforming to the ABI of the system on which MicroPython runs. """ # noinspection PyShadowingNames def sizeof(struct: struct | _descriptor, layout_type: int = NATIVE, /) -> int: """ Return size of data structure in bytes. The *struct* argument can be either a structure class or a specific instantiated structure object (or its aggregate field). """ def addressof(obj: AnyReadableBuf, /) -> int: """ Return address of an object. Argument should be bytes, bytearray or other object supporting buffer protocol (and address of this buffer is what actually returned). """ def bytes_at(addr: int, size: int, /) -> bytes: """ Capture memory at the given address and size as bytes object. As bytes object is immutable, memory is actually duplicated and copied into bytes object, so if memory contents change later, created object retains original value. """ def bytearray_at(addr: int, size: int, /) -> bytearray: """ Capture memory at the given address and size as bytearray object. Unlike bytes_at() function above, memory is captured by reference, so it can be both written too, and you will access current value at the given memory address. """ UINT8: Final[int] = ... """ Integer types for structure descriptors. Constants for 8, 16, 32, and 64 bit types are provided, both signed and unsigned. """ INT8: Final[int] = ... """ Integer types for structure descriptors. Constants for 8, 16, 32, and 64 bit types are provided, both signed and unsigned. """ UINT16: Final[int] = ... """ Integer types for structure descriptors. Constants for 8, 16, 32, and 64 bit types are provided, both signed and unsigned. """ INT16: Final[int] = ... """ Integer types for structure descriptors. Constants for 8, 16, 32, and 64 bit types are provided, both signed and unsigned. """ UINT32: Final[int] = ... """ Integer types for structure descriptors. Constants for 8, 16, 32, and 64 bit types are provided, both signed and unsigned. """ INT32: Final[int] = ... """ Integer types for structure descriptors. Constants for 8, 16, 32, and 64 bit types are provided, both signed and unsigned. """ UINT64: Final[int] = ... """ Integer types for structure descriptors. Constants for 8, 16, 32, and 64 bit types are provided, both signed and unsigned. """ INT64: Final[int] = ... """ Integer types for structure descriptors. Constants for 8, 16, 32, and 64 bit types are provided, both signed and unsigned. """ FLOAT32: Final[int] = ... """ Floating-point types for structure descriptors. """ FLOAT64: Final[int] = ... """ Floating-point types for structure descriptors. """ VOID: Final[int] = ... """ ``VOID`` is an alias for ``UINT8``, and is provided to conveniently define C's void pointers: ``(uctypes.PTR, uctypes.VOID)``. """ PTR: Final[int] = ... """ Type constants for pointers and arrays. Note that there is no explicit constant for structures, it's implicit: an aggregate type without ``PTR`` or ``ARRAY`` flags is a structure. """ ARRAY: Final[int] = ... """ Type constants for pointers and arrays. Note that there is no explicit constant for structures, it's implicit: an aggregate type without ``PTR`` or ``ARRAY`` flags is a structure. """ # noinspection PyPep8Naming class struct: """ Module contents --------------- """ def __init__( self, addr: int, descriptor: _descriptor, layout_type: int = NATIVE, / ): """ Instantiate a "foreign data structure" object based on structure address in memory, descriptor (encoded as a dictionary), and layout type (see below). """ ================================================ FILE: typehints/pyboard/lcd160cr.pyi ================================================ """ control of LCD160CR display. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/lcd160cr.rst. =============================================== .. 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 `_ (100KiB PDF) * `LCD160CRv1.0 schematics `_ (1.6MiB PDF) """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import overload, Any, Final from pyb import Pin, I2C, SPI from uio import AnyReadableBuf, AnyWritableBuf PORTRAIT: Final[str] = ... """ Orientations of the display, used by :meth:`LCD160CR.set_orient`. """ LANDSCAPE: Final[str] = ... """ Orientations of the display, used by :meth:`LCD160CR.set_orient`. """ PORTRAIT_UPSIDEDOWN: Final[str] = ... """ Orientations of the display, used by :meth:`LCD160CR.set_orient`. """ LANDSCAPE_UPSIDEDOWN: Final[str] = ... """ Orientations of the display, used by :meth:`LCD160CR.set_orient`. """ STARTUP_DECO_NONE: Final[int] = ... """ Types of start-up decoration, can be OR'ed together, used by :meth:`LCD160CR.set_startup_deco`. """ STARTUP_DECO_MLOGO: Final[int] = ... """ Types of start-up decoration, can be OR'ed together, used by :meth:`LCD160CR.set_startup_deco`. """ STARTUP_DECO_INFO: Final[int] = ... """ Types of start-up decoration, can be OR'ed together, used by :meth:`LCD160CR.set_startup_deco`. """ 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()) """ w: Final[int] = ... """ 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. """ h: Final[int] = ... """ 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. """ @overload def __init__(self, connect: str, /): """ 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 `_ for how the display can be connected to the pyboard. """ @overload def __init__(self, *, pwr: Pin, i2c: I2C, spi: SPI, i2c_addr: int = 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 `_ for how the display can be connected to the pyboard. """ @staticmethod def rgb(r: int, g: int, b: int, /) -> int: """ 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 def clip_line(data: Any, w: int, h: int, /) -> int: """ Clip the given line data. This is for internal use. """ def set_power(self, on: bool, /) -> None: """ 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. """ def set_orient(self, orient: str, /) -> None: """ Set the orientation of the display. The *orient* parameter can be one of `PORTRAIT`, `LANDSCAPE`, `PORTRAIT_UPSIDEDOWN`, `LANDSCAPE_UPSIDEDOWN`. """ def set_brightness(self, value: int, /) -> None: """ Set the brightness of the display, between 0 and 31. """ def set_i2c_addr(self, addr: int, /) -> None: """ Set the I2C address of the display. The *addr* value must have the lower 2 bits cleared. """ def set_uart_baudrate(self, baudrate: int, /) -> None: """ Set the baudrate of the UART interface. """ def set_startup_deco(self, value: bool | str, /) -> None: """ 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`. """ def save_to_flash(self) -> None: """ Save the following parameters to flash so they persist on restart and power up: initial decoration, orientation, brightness, UART baud rate, I2C address. """ def set_pixel(self, x: int, y: int, c: int, /) -> None: """ Set the specified pixel to the given color. The color should be a 16-bit integer and can be created by :meth:`LCD160CR.rgb`. """ def get_pixel(self, x: int, y: int, /) -> int: """ Get the 16-bit value of the specified pixel. """ def get_line(self, x: int, y: int, buf: AnyWritableBuf, /) -> None: """ 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)*. """ def screen_dump( self, buf: AnyWritableBuf, x: int = 0, y: int = 0, w: int | None = None, h: int | None = None, /, ) -> 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. """ def screen_load(self, buf: AnyReadableBuf, /) -> None: """ Load the entire screen from the given buffer. """ def set_pos(self, x: int, y: int, /) -> None: """ Set the position for text output using :meth:`LCD160CR.write`. The position is the upper-left corner of the text. """ def set_text_color(self, fg: int, bg: int, /) -> None: """ Set the foreground and background color of the text. """ def set_font( self, font: int, scale: int = 0, bold: int = 0, trans: int = 0, scroll: int = 0, /, ) -> None: """ 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. """ def write(self, s: str, /) -> None: """ 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. """ def set_pen(self, line: int, fill: int, /) -> None: """ Set the line and fill color for primitive shapes. """ def erase(self) -> None: """ Erase the entire display to the pen fill color. """ def dot(self, x: int, y: int, /) -> None: """ Draw a single pixel at the given location using the pen line color. """ def rect(self, x: int, y: int, w: int, h: int, /) -> None: """ 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. """ def rect_outline(self, x: int, y: int, w: int, h: int, /) -> None: """ 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. """ def rect_interior(self, x: int, y: int, w: int, h: int, /) -> None: """ 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. """ def line(self, x1: int, y1: int, x2: int, y2: int, /) -> None: """ Draw a line between the given coordinates using the pen line color. """ def dot_no_clip(self, x: int, y: int, /) -> None: """ 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. """ def rect_no_clip(self, x: int, y: int, w: int, h: int, /) -> None: """ 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. """ def rect_outline_no_clip(self, x: int, y: int, w: int, h: int, /) -> None: """ 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. """ def rect_interior_no_clip(self, x: int, y: int, w: int, h: int, /) -> None: """ 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. """ def line_no_clip(self, x1: int, y1: int, x2: int, y2: int, /) -> None: """ 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. """ def poly_dot(self, data: AnyReadableBuf, /) -> None: """ 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). """ def poly_line(self, data: AnyReadableBuf, /) -> None: """ Similar to :meth:`LCD160CR.poly_dot` but draws lines between the dots. """ def touch_config( self, calib: bool = False, save: bool = False, irq: bool | None = None, / ) -> 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. """ def is_touched(self) -> bool: """ Returns a boolean: ``True`` if there is currently a touch force on the screen, ``False`` otherwise. """ def get_touch(self) -> tuple[int, int, int]: """ 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. """ def set_spi_win(self, x: int, y: int, w: int, h: int, /) -> None: """ Set the window that SPI data is written to. """ def fast_spi(self, flush: bool = True, /) -> SPI: """ 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. """ def show_framebuf(self, buf: AnyReadableBuf, /) -> None: """ 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 `_ 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. """ def set_scroll(self, on: bool, /) -> None: """ Turn scrolling on or off. This controls globally whether any window regions will scroll. """ def set_scroll_win( self, win: int, x: int = -1, y: int = 0, w: int = 0, h: int = 0, vec: int = 0, pat: int = 0, fill: int = 0x07E0, color: int = 0, /, ) -> None: """ 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. """ def set_scroll_win_param(self, win: int, param: int, value: int, /) -> None: """ 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. """ def set_scroll_buf(self, s: str, /) -> None: """ Set the string for scrolling in window 8. The parameter *s* must be a string with length 32 or less. """ def jpeg(self, buf: AnyReadableBuf, /) -> None: """ 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`. """ def jpeg_start(self, total_len: int, /) -> None: """ 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. """ def jpeg_data(self, buf: AnyReadableBuf, /) -> None: """ 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. """ def feed_wdt(self) -> None: """ 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. """ def reset(self) -> None: """ Reset the display. """ ================================================ FILE: typehints/pyboard/pyb.pyi ================================================ """ functions related to the board. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/pyb.rst. ============================================= 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. 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. 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. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from abc import ABC, abstractmethod from typing import NoReturn, overload, Sequence, runtime_checkable, Protocol from typing import Callable, Dict, Any, ClassVar, Final from uarray import array from uio import AnyReadableBuf, AnyWritableBuf from uos import AbstractBlockDev @runtime_checkable class _OldAbstractReadOnlyBlockDev(Protocol): """ A `Protocol` (structurally typed) with the defs needed by `mount` argument `device` for read-only devices. """ __slots__ = () @abstractmethod def readblocks(self, blocknum: int, buf: bytearray, /) -> None: ... @abstractmethod def count(self) -> int: ... @runtime_checkable class _OldAbstractBlockDev(_OldAbstractReadOnlyBlockDev, Protocol): """ A `Protocol` (structurally typed) with the defs needed by `mount` argument `device` for read-write devices. """ __slots__ = () @abstractmethod def writeblocks(self, blocknum: int, buf: bytes | bytearray, /) -> None: ... @abstractmethod def sync(self) -> None: ... hid_mouse: Final[tuple[int, int, int, int, bytes]] = ... """ Mouse human interface device (hid), see `hid` argument of `usb_mode`. """ hid_keyboard: Final[tuple[int, int, int, int, bytes]] = ... """ Keyboard human interface device (hid), see `hid` argument of `usb_mode`. """ @overload def country() -> str: """Return the current ISO 3166-1, Alpha-2, country code, eg US, GB, DE, AU.""" @overload def country(alpha_2_code: str) -> None: """Set the ISO 3166-1, Alpha-2, country code, eg US, GB, DE, AU.""" def delay(ms: int, /) -> None: """ Delay for the given number of milliseconds. """ def udelay(us: int, /) -> None: """ Delay for the given number of microseconds. """ def millis() -> int: """ Returns the number of milliseconds since the board was last reset. The result is always a MicroPython smallint (31-bit signed number), so after 2^30 milliseconds (about 12.4 days) this will start to return negative numbers. Note that if :meth:`pyb.stop()` is issued the hardware counter supporting this function will pause for the duration of the "sleeping" state. This will affect the outcome of :meth:`pyb.elapsed_millis()`. """ def micros() -> int: """ Returns the number of microseconds since the board was last reset. The result is always a MicroPython smallint (31-bit signed number), so after 2^30 microseconds (about 17.8 minutes) this will start to return negative numbers. Note that if :meth:`pyb.stop()` is issued the hardware counter supporting this function will pause for the duration of the "sleeping" state. This will affect the outcome of :meth:`pyb.elapsed_micros()`. """ def elapsed_millis(start: int, /) -> int: """ Returns the number of milliseconds which have elapsed since ``start``. This function takes care of counter wrap, and always returns a positive number. This means it can be used to measure periods up to about 12.4 days. Example:: start = pyb.millis() while pyb.elapsed_millis(start) < 1000: # Perform some operation """ def elapsed_micros(start: int, /) -> int: """ Returns the number of microseconds which have elapsed since ``start``. This function takes care of counter wrap, and always returns a positive number. This means it can be used to measure periods up to about 17.8 minutes. Example:: start = pyb.micros() while pyb.elapsed_micros(start) < 1000: # Perform some operation pass """ def hard_reset() -> NoReturn: """ Resets the pyboard in a manner similar to pushing the external RESET button. """ def bootloader() -> NoReturn: """ Activate the bootloader without BOOT\* pins. """ def fault_debug(value: bool = False) -> None: """ Enable or disable hard-fault debugging. A hard-fault is when there is a fatal error in the underlying system, like an invalid memory access. If the *value* argument is ``False`` then the board will automatically reset if there is a hard fault. If *value* is ``True`` then, when the board has a hard fault, it will print the registers and the stack trace, and then cycle the LEDs indefinitely. The default value is disabled, i.e. to automatically reset. """ def disable_irq() -> bool: """ Disable interrupt requests. Returns the previous IRQ state: ``False``/``True`` for disabled/enabled IRQs respectively. This return value can be passed to enable_irq to restore the IRQ to its original state. """ def enable_irq(state: bool = True, /) -> None: """ Enable interrupt requests. If ``state`` is ``True`` (the default value) then IRQs are enabled. If ``state`` is ``False`` then IRQs are disabled. The most common use of this function is to pass it the value returned by ``disable_irq`` to exit a critical section. """ @overload def freq() -> tuple[int, int, int, int]: """ If given no arguments, returns a tuple of clock frequencies: (sysclk, hclk, pclk1, pclk2). These correspond to: - sysclk: frequency of the CPU - hclk: frequency of the AHB bus, core memory and DMA - pclk1: frequency of the APB1 bus - pclk2: frequency of the APB2 bus If given any arguments then the function sets the frequency of the CPU, and the buses if additional arguments are given. Frequencies are given in Hz. Eg freq(120000000) sets sysclk (the CPU frequency) to 120MHz. Note that not all values are supported and the largest supported frequency not greater than the given value will be selected. Supported sysclk frequencies are (in MHz): 8, 16, 24, 30, 32, 36, 40, 42, 48, 54, 56, 60, 64, 72, 84, 96, 108, 120, 144, 168. The maximum frequency of hclk is 168MHz, of pclk1 is 42MHz, and of pclk2 is 84MHz. Be sure not to set frequencies above these values. The hclk, pclk1 and pclk2 frequencies are derived from the sysclk frequency using a prescaler (divider). Supported prescalers for hclk are: 1, 2, 4, 8, 16, 64, 128, 256, 512. Supported prescalers for pclk1 and pclk2 are: 1, 2, 4, 8. A prescaler will be chosen to best match the requested frequency. A sysclk frequency of 8MHz uses the HSE (external crystal) directly and 16MHz uses the HSI (internal oscillator) directly. The higher frequencies use the HSE to drive the PLL (phase locked loop), and then use the output of the PLL. Note that if you change the frequency while the USB is enabled then the USB may become unreliable. It is best to change the frequency in boot.py, before the USB peripheral is started. Also note that sysclk frequencies below 36MHz do not allow the USB to function correctly. """ @overload def freq(sysclk: int, /) -> None: """ If given no arguments, returns a tuple of clock frequencies: (sysclk, hclk, pclk1, pclk2). These correspond to: - sysclk: frequency of the CPU - hclk: frequency of the AHB bus, core memory and DMA - pclk1: frequency of the APB1 bus - pclk2: frequency of the APB2 bus If given any arguments then the function sets the frequency of the CPU, and the buses if additional arguments are given. Frequencies are given in Hz. Eg freq(120000000) sets sysclk (the CPU frequency) to 120MHz. Note that not all values are supported and the largest supported frequency not greater than the given value will be selected. Supported sysclk frequencies are (in MHz): 8, 16, 24, 30, 32, 36, 40, 42, 48, 54, 56, 60, 64, 72, 84, 96, 108, 120, 144, 168. The maximum frequency of hclk is 168MHz, of pclk1 is 42MHz, and of pclk2 is 84MHz. Be sure not to set frequencies above these values. The hclk, pclk1 and pclk2 frequencies are derived from the sysclk frequency using a prescaler (divider). Supported prescalers for hclk are: 1, 2, 4, 8, 16, 64, 128, 256, 512. Supported prescalers for pclk1 and pclk2 are: 1, 2, 4, 8. A prescaler will be chosen to best match the requested frequency. A sysclk frequency of 8MHz uses the HSE (external crystal) directly and 16MHz uses the HSI (internal oscillator) directly. The higher frequencies use the HSE to drive the PLL (phase locked loop), and then use the output of the PLL. Note that if you change the frequency while the USB is enabled then the USB may become unreliable. It is best to change the frequency in boot.py, before the USB peripheral is started. Also note that sysclk frequencies below 36MHz do not allow the USB to function correctly. """ @overload def freq(sysclk: int, hclk: int, /) -> None: """ If given no arguments, returns a tuple of clock frequencies: (sysclk, hclk, pclk1, pclk2). These correspond to: - sysclk: frequency of the CPU - hclk: frequency of the AHB bus, core memory and DMA - pclk1: frequency of the APB1 bus - pclk2: frequency of the APB2 bus If given any arguments then the function sets the frequency of the CPU, and the buses if additional arguments are given. Frequencies are given in Hz. Eg freq(120000000) sets sysclk (the CPU frequency) to 120MHz. Note that not all values are supported and the largest supported frequency not greater than the given value will be selected. Supported sysclk frequencies are (in MHz): 8, 16, 24, 30, 32, 36, 40, 42, 48, 54, 56, 60, 64, 72, 84, 96, 108, 120, 144, 168. The maximum frequency of hclk is 168MHz, of pclk1 is 42MHz, and of pclk2 is 84MHz. Be sure not to set frequencies above these values. The hclk, pclk1 and pclk2 frequencies are derived from the sysclk frequency using a prescaler (divider). Supported prescalers for hclk are: 1, 2, 4, 8, 16, 64, 128, 256, 512. Supported prescalers for pclk1 and pclk2 are: 1, 2, 4, 8. A prescaler will be chosen to best match the requested frequency. A sysclk frequency of 8MHz uses the HSE (external crystal) directly and 16MHz uses the HSI (internal oscillator) directly. The higher frequencies use the HSE to drive the PLL (phase locked loop), and then use the output of the PLL. Note that if you change the frequency while the USB is enabled then the USB may become unreliable. It is best to change the frequency in boot.py, before the USB peripheral is started. Also note that sysclk frequencies below 36MHz do not allow the USB to function correctly. """ @overload def freq(sysclk: int, hclk: int, pclk1: int, /) -> None: """ If given no arguments, returns a tuple of clock frequencies: (sysclk, hclk, pclk1, pclk2). These correspond to: - sysclk: frequency of the CPU - hclk: frequency of the AHB bus, core memory and DMA - pclk1: frequency of the APB1 bus - pclk2: frequency of the APB2 bus If given any arguments then the function sets the frequency of the CPU, and the buses if additional arguments are given. Frequencies are given in Hz. Eg freq(120000000) sets sysclk (the CPU frequency) to 120MHz. Note that not all values are supported and the largest supported frequency not greater than the given value will be selected. Supported sysclk frequencies are (in MHz): 8, 16, 24, 30, 32, 36, 40, 42, 48, 54, 56, 60, 64, 72, 84, 96, 108, 120, 144, 168. The maximum frequency of hclk is 168MHz, of pclk1 is 42MHz, and of pclk2 is 84MHz. Be sure not to set frequencies above these values. The hclk, pclk1 and pclk2 frequencies are derived from the sysclk frequency using a prescaler (divider). Supported prescalers for hclk are: 1, 2, 4, 8, 16, 64, 128, 256, 512. Supported prescalers for pclk1 and pclk2 are: 1, 2, 4, 8. A prescaler will be chosen to best match the requested frequency. A sysclk frequency of 8MHz uses the HSE (external crystal) directly and 16MHz uses the HSI (internal oscillator) directly. The higher frequencies use the HSE to drive the PLL (phase locked loop), and then use the output of the PLL. Note that if you change the frequency while the USB is enabled then the USB may become unreliable. It is best to change the frequency in boot.py, before the USB peripheral is started. Also note that sysclk frequencies below 36MHz do not allow the USB to function correctly. """ @overload def freq(sysclk: int, hclk: int, pclk1: int, pclk2: int, /) -> None: """ If given no arguments, returns a tuple of clock frequencies: (sysclk, hclk, pclk1, pclk2). These correspond to: - sysclk: frequency of the CPU - hclk: frequency of the AHB bus, core memory and DMA - pclk1: frequency of the APB1 bus - pclk2: frequency of the APB2 bus If given any arguments then the function sets the frequency of the CPU, and the buses if additional arguments are given. Frequencies are given in Hz. Eg freq(120000000) sets sysclk (the CPU frequency) to 120MHz. Note that not all values are supported and the largest supported frequency not greater than the given value will be selected. Supported sysclk frequencies are (in MHz): 8, 16, 24, 30, 32, 36, 40, 42, 48, 54, 56, 60, 64, 72, 84, 96, 108, 120, 144, 168. The maximum frequency of hclk is 168MHz, of pclk1 is 42MHz, and of pclk2 is 84MHz. Be sure not to set frequencies above these values. The hclk, pclk1 and pclk2 frequencies are derived from the sysclk frequency using a prescaler (divider). Supported prescalers for hclk are: 1, 2, 4, 8, 16, 64, 128, 256, 512. Supported prescalers for pclk1 and pclk2 are: 1, 2, 4, 8. A prescaler will be chosen to best match the requested frequency. A sysclk frequency of 8MHz uses the HSE (external crystal) directly and 16MHz uses the HSI (internal oscillator) directly. The higher frequencies use the HSE to drive the PLL (phase locked loop), and then use the output of the PLL. Note that if you change the frequency while the USB is enabled then the USB may become unreliable. It is best to change the frequency in boot.py, before the USB peripheral is started. Also note that sysclk frequencies below 36MHz do not allow the USB to function correctly. """ def wfi() -> None: """ Wait for an internal or external interrupt. This executes a ``wfi`` instruction which reduces power consumption of the MCU until any interrupt occurs (be it internal or external), at which point execution continues. Note that the system-tick interrupt occurs once every millisecond (1000Hz) so this function will block for at most 1ms. """ def stop() -> None: """ Put the pyboard in a "sleeping" state. This reduces power consumption to less than 500 uA. To wake from this sleep state requires an external interrupt or a real-time-clock event. Upon waking execution continues where it left off. See :meth:`rtc.wakeup` to configure a real-time-clock wakeup event. """ def standby() -> None: """ Put the pyboard into a "deep sleep" state. This reduces power consumption to less than 50 uA. To wake from this sleep state requires a real-time-clock event, or an external interrupt on X1 (PA0=WKUP) or X18 (PC13=TAMP1). Upon waking the system undergoes a hard reset. See :meth:`rtc.wakeup` to configure a real-time-clock wakeup event. """ def have_cdc() -> bool: """ Return True if USB is connected as a serial device, False otherwise. .. note:: This function is deprecated. Use pyb.USB_VCP().isconnected() instead. """ @overload def hid(data: tuple[int, int, int, int], /) -> None: """ Takes a 4-tuple (or list) and sends it to the USB host (the PC) to signal a HID mouse-motion event. .. note:: This function is deprecated. Use :meth:`pyb.USB_HID.send()` instead. """ @overload def hid(data: Sequence[int], /) -> None: """ Takes a 4-tuple (or list) and sends it to the USB host (the PC) to signal a HID mouse-motion event. .. note:: This function is deprecated. Use :meth:`pyb.USB_HID.send()` instead. """ @overload def info() -> None: """ Print out lots of information about the board. """ @overload def info(dump_alloc_table: bytes, /) -> None: """ Print out lots of information about the board. """ def main(filename: str, /) -> None: """ Set the filename of the main script to run after boot.py is finished. If this function is not called then the default file main.py will be executed. It only makes sense to call this function from within boot.py. """ @overload def mount( device: _OldAbstractReadOnlyBlockDev, mountpoint: str, /, *, readonly: bool = False, mkfs: bool = False, ) -> None: """ .. note:: This function is deprecated. Mounting and unmounting devices should be performed by :meth:`os.mount` and :meth:`os.umount` instead. Mount a block device and make it available as part of the filesystem. ``device`` must be an object that provides the block protocol. (The following is also deprecated. See :class:`os.AbstractBlockDev` for the correct way to create a block device.) - ``readblocks(self, blocknum, buf)`` - ``writeblocks(self, blocknum, buf)`` (optional) - ``count(self)`` - ``sync(self)`` (optional) ``readblocks`` and ``writeblocks`` should copy data between ``buf`` and the block device, starting from block number ``blocknum`` on the device. ``buf`` will be a bytearray with length a multiple of 512. If ``writeblocks`` is not defined then the device is mounted read-only. The return value of these two functions is ignored. ``count`` should return the number of blocks available on the device. ``sync``, if implemented, should sync the data on the device. The parameter ``mountpoint`` is the location in the root of the filesystem to mount the device. It must begin with a forward-slash. If ``readonly`` is ``True``, then the device is mounted read-only, otherwise it is mounted read-write. If ``mkfs`` is ``True``, then a new filesystem is created if one does not already exist. """ @overload def mount( device: _OldAbstractBlockDev, mountpoint: str, /, *, readonly: bool = False, mkfs: bool = False, ) -> None: """ .. note:: This function is deprecated. Mounting and unmounting devices should be performed by :meth:`os.mount` and :meth:`os.umount` instead. Mount a block device and make it available as part of the filesystem. ``device`` must be an object that provides the block protocol. (The following is also deprecated. See :class:`os.AbstractBlockDev` for the correct way to create a block device.) - ``readblocks(self, blocknum, buf)`` - ``writeblocks(self, blocknum, buf)`` (optional) - ``count(self)`` - ``sync(self)`` (optional) ``readblocks`` and ``writeblocks`` should copy data between ``buf`` and the block device, starting from block number ``blocknum`` on the device. ``buf`` will be a bytearray with length a multiple of 512. If ``writeblocks`` is not defined then the device is mounted read-only. The return value of these two functions is ignored. ``count`` should return the number of blocks available on the device. ``sync``, if implemented, should sync the data on the device. The parameter ``mountpoint`` is the location in the root of the filesystem to mount the device. It must begin with a forward-slash. If ``readonly`` is ``True``, then the device is mounted read-only, otherwise it is mounted read-write. If ``mkfs`` is ``True``, then a new filesystem is created if one does not already exist. """ @overload def repl_uart() -> UART | None: """ Get or set the UART object where the REPL is repeated on. """ @overload def repl_uart(uart: UART, /) -> None: """ Get or set the UART object where the REPL is repeated on. """ def rng() -> int: """ Return a 30-bit hardware generated random number. """ def sync() -> None: """ Sync all file systems. """ def unique_id() -> bytes: """ Returns a string of 12 bytes (96 bits), which is the unique ID of the MCU. """ # noinspection PyShadowingNames @overload def usb_mode() -> str: """ If called with no arguments, return the current USB mode as a string. If called with *modestr* provided, attempts to configure the USB mode. The following values of *modestr* are understood: - ``None``: disables USB - ``'VCP'``: enable with VCP (Virtual COM Port) interface - ``'MSC'``: enable with MSC (mass storage device class) interface - ``'VCP+MSC'``: enable with VCP and MSC - ``'VCP+HID'``: enable with VCP and HID (human interface device) - ``'VCP+MSC+HID'``: enabled with VCP, MSC and HID (only available on PYBD boards) For backwards compatibility, ``'CDC'`` is understood to mean ``'VCP'`` (and similarly for ``'CDC+MSC'`` and ``'CDC+HID'``). The *port* parameter should be an integer (0, 1, ...) and selects which USB port to use if the board supports multiple ports. A value of -1 uses the default or automatically selected port. The *vid* and *pid* parameters allow you to specify the VID (vendor id) and PID (product id). A *pid* value of -1 will select a PID based on the value of *modestr*. If enabling MSC mode, the *msc* parameter can be used to specify a list of SCSI LUNs to expose on the mass storage interface. For example ``msc=(pyb.Flash(), pyb.SDCard())``. If enabling HID mode, you may also specify the HID details by passing the *hid* keyword parameter. It takes a tuple of (subclass, protocol, max packet length, polling interval, report descriptor). By default it will set appropriate values for a USB mouse. There is also a ``pyb.hid_keyboard`` constant, which is an appropriate tuple for a USB keyboard. The *high_speed* parameter, when set to ``True``, enables USB HS mode if it is supported by the hardware. """ # noinspection PyShadowingNames @overload def usb_mode( modestr: str, /, *, port: int = -1, vid: int = 0xF055, pid: int = -1, msc: Sequence[AbstractBlockDev] = (), hid: tuple[int, int, int, int, bytes] = hid_mouse, high_speed: bool = False, ) -> None: """ If called with no arguments, return the current USB mode as a string. If called with *modestr* provided, attempts to configure the USB mode. The following values of *modestr* are understood: - ``None``: disables USB - ``'VCP'``: enable with VCP (Virtual COM Port) interface - ``'MSC'``: enable with MSC (mass storage device class) interface - ``'VCP+MSC'``: enable with VCP and MSC - ``'VCP+HID'``: enable with VCP and HID (human interface device) - ``'VCP+MSC+HID'``: enabled with VCP, MSC and HID (only available on PYBD boards) For backwards compatibility, ``'CDC'`` is understood to mean ``'VCP'`` (and similarly for ``'CDC+MSC'`` and ``'CDC+HID'``). The *port* parameter should be an integer (0, 1, ...) and selects which USB port to use if the board supports multiple ports. A value of -1 uses the default or automatically selected port. The *vid* and *pid* parameters allow you to specify the VID (vendor id) and PID (product id). A *pid* value of -1 will select a PID based on the value of *modestr*. If enabling MSC mode, the *msc* parameter can be used to specify a list of SCSI LUNs to expose on the mass storage interface. For example ``msc=(pyb.Flash(), pyb.SDCard())``. If enabling HID mode, you may also specify the HID details by passing the *hid* keyword parameter. It takes a tuple of (subclass, protocol, max packet length, polling interval, report descriptor). By default it will set appropriate values for a USB mouse. There is also a ``pyb.hid_keyboard`` constant, which is an appropriate tuple for a USB keyboard. The *high_speed* parameter, when set to ``True``, enables USB HS mode if it is supported by the hardware. """ class Accel: """ 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. """ def __init__(self): """ Create and return an accelerometer object. """ def filtered_xyz(self) -> tuple[int, int, int]: """ 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. """ def tilt(self) -> int: """ Get the tilt register. """ def x(self) -> int: """ Get the x-axis value. """ def y(self) -> int: """ Get the y-axis value. """ def z(self) -> int: """ Get the z-axis value. """ class ADC: """ 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 """ def __init__(self, pin: int | Pin, /): """ Create an ADC object associated with the given pin. This allows you to then read analog values on that pin. """ def read(self) -> int: """ Read the value on the analog pin and return it. The returned value will be between 0 and 4095. """ def read_timed(self, buf: AnyWritableBuf, timer: Timer | int, /) -> None: """ 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. """ @staticmethod def read_timed_multi( adcs: tuple[ADC, ...], bufs: tuple[AnyWritableBuf, ...], timer: Timer, / ) -> bool: """ 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. """ class ADCAll: """ 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() """ def __init__(self, resolution: int, mask: int = 0xFFFFFFFF, /): """ Create a multi-channel ADC instance. ``resolution`` is the number of bits for all the ADCs (even those not enabled); one of: 14, 12, 10, or 8 bits. To avoid unwanted activation of analog inputs (channel 0..15) a second parameter, ``mask``, 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. """ def read_channel(self, channel: int, /) -> int: """ Read the given channel. """ def read_core_temp(self) -> float: """ Read MCU temperature (centigrade). """ def read_core_vbat(self) -> float: """ Read MCU VBAT (volts). """ def read_core_vref(self) -> float: """ Read MCU VREF (volts). """ def read_vref(self) -> float: """ Read MCU supply voltage (volts). """ class CAN: """ 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 """ NORMAL: ClassVar[int] = ... """ The mode of the CAN bus used in :meth:`~CAN.init()`. """ LOOPBACK: ClassVar[int] = ... """ The mode of the CAN bus used in :meth:`~CAN.init()`. """ SILENT: ClassVar[int] = ... """ The mode of the CAN bus used in :meth:`~CAN.init()`. """ SILENT_LOOPBACK: ClassVar[int] = ... """ The mode of the CAN bus used in :meth:`~CAN.init()`. """ STOPPED: ClassVar[int] = ... """ Possible states of the CAN controller returned from :meth:`~CAN.state()`. """ ERROR_ACTIVE: ClassVar[int] = ... """ Possible states of the CAN controller returned from :meth:`~CAN.state()`. """ ERROR_WARNING: ClassVar[int] = ... """ Possible states of the CAN controller returned from :meth:`~CAN.state()`. """ ERROR_PASSIVE: ClassVar[int] = ... """ Possible states of the CAN controller returned from :meth:`~CAN.state()`. """ BUS_OFF: ClassVar[int] = ... """ Possible states of the CAN controller returned from :meth:`~CAN.state()`. """ LIST16: ClassVar[int] = ... """ The operation mode of a filter used in :meth:`~CAN.setfilter()`. """ MASK16: ClassVar[int] = ... """ The operation mode of a filter used in :meth:`~CAN.setfilter()`. """ LIST32: ClassVar[int] = ... """ The operation mode of a filter used in :meth:`~CAN.setfilter()`. """ MASK32: ClassVar[int] = ... """ The operation mode of a filter used in :meth:`~CAN.setfilter()`. """ def __init__( self, bus: int | str, mode: int, /, extframe: bool = False, prescaler: int = 100, *, sjw: int = 1, bs1: int = 6, bs2: int = 8, auto_restart: bool = False, ): """ 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 buses are: - ``CAN(1)`` is on ``YA``: ``(RX, TX) = (Y3, Y4) = (PB8, PB9)`` - ``CAN(2)`` is on ``YB``: ``(RX, TX) = (Y5, Y6) = (PB12, PB13)`` """ @staticmethod def initfilterbanks(nr: int, /) -> None: """ 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. """ def init( self, mode: int, /, extframe: bool = False, prescaler: int = 100, *, sjw: int = 1, bs1: int = 6, bs2: int = 8, auto_restart: bool = False, baudrate: int = 0, sample_point: int = 75, ) -> None: """ 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 - *baudrate* if a baudrate other than 0 is provided, this function will try to automatically calculate a CAN bit-timing (overriding *prescaler*, *bs1* and *bs2*) that satisfies both the baudrate and the desired *sample_point*. - *sample_point* given in a percentage of the bit time, the *sample_point* specifies the position of the last bit sample with respect to the whole bit time. The default *sample_point* is 75%. 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. """ def deinit(self) -> None: """ Turn off the CAN bus. """ def restart(self) -> None: """ 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. """ def state(self) -> int: """ 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). """ @overload def info(self) -> list[int]: """ 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 """ @overload def info(self, list: list[int], /) -> list[int]: """ 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 """ @overload def setfilter( self, bank: int, mode: int, fifo: int, params: Sequence[int], / ) -> None: """ 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 | +-----------+----------------------+ """ @overload def setfilter( self, bank: int, mode: int, fifo: int, params: Sequence[int], /, *, rtr: Sequence[bool], ) -> None: """ 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 | +-----------+----------------------+ """ def clearfilter(self, bank: int, /) -> None: """ Clear and disables a filter bank: - *bank* is the filter bank that is to be cleared. """ def any(self, fifo: int, /) -> bool: """ Return ``True`` if any message waiting on the FIFO, else ``False``. """ @overload def recv( self, fifo: int, /, *, timeout: int = 5000 ) -> tuple[int, bool, int, memoryview]: """ 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) """ @overload def recv( self, fifo: int, list: None, /, *, timeout: int = 5000 ) -> tuple[int, bool, int, memoryview]: """ 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) """ @overload def recv( self, fifo: int, list: list[int | bool | memoryview], /, *, timeout: int = 5000 ) -> None: """ 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) """ def send( self, data: int | AnyWritableBuf, id: int, /, *, timeout: int = 0, rtr: bool = False, ) -> None: """ 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``. """ def rxcallback(self, fifo: int, fun: Callable[[CAN], None], /) -> None: """ 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) """ # noinspection PyShadowingNames class DAC: """ 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) """ NORMAL: ClassVar[int] = ... """ Normal mode (output buffer once) for `mode` argument of `write_timed`. """ CIRCULAR: ClassVar[int] = ... """ Circular mode (output buffer continuously) for `mode` argument of `write_timed`. """ def __init__( self, port: int | Pin, /, bits: int = 8, *, buffering: bool | None = 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. """ def init(self, bits: int = 8, *, buffering: bool | None = None) -> 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. """ def deinit(self) -> None: """ De-initialise the DAC making its pin available for other uses. """ def noise(self, freq: int, /) -> None: """ Generate a pseudo-random noise signal. A new random sample is written to the DAC output at the given frequency. """ def triangle(self, freq: int, /) -> None: """ 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. """ def write(self, value: int, /) -> None: """ 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. """ def write_timed( self, data: AnyWritableBuf, freq: int | Timer, /, *, mode: int = NORMAL ) -> None: """ 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) """ class ExtInt: """ 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. """ IRQ_FALLING: ClassVar[int] = ... """ interrupt on a falling edge """ IRQ_RISING: ClassVar[int] = ... """ interrupt on a rising edge """ IRQ_RISING_FALLING: ClassVar[int] = ... """ interrupt on a rising or falling edge """ def __init__( self, pin: int | str | Pin, mode: int, pull: int, callback: Callable[[int], None], ): """ 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. """ @staticmethod def regs() -> None: """ Dump the values of the EXTI registers. """ def disable(self) -> None: """ Disable the interrupt associated with the ExtInt object. This could be useful for debouncing. """ def enable(self) -> None: """ Enable a disabled interrupt. """ def line(self) -> int: """ Return the line number that the pin is mapped to. """ def swint(self) -> None: """ Trigger the callback from software. """ class Flash(AbstractBlockDev): """ 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 ` or implement a low-level storage system for your application. """ @overload def __init__(self): """ 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. """ @overload def __init__(self, *, start: int = -1, len: int = -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). """ def readblocks(self, blocknum: int, buf: bytes, offset: int = 0, /) -> None: """ These methods implement the simple and :ref:`extended ` block protocol defined by :class:`os.AbstractBlockDev`. """ def writeblocks(self, blocknum: int, buf: bytes, offset: int = 0, /) -> None: """ These methods implement the simple and :ref:`extended ` block protocol defined by :class:`os.AbstractBlockDev`. """ def ioctl(self, op: int, arg: int) -> int | None: """ These methods implement the simple and :ref:`extended ` block protocol defined by :class:`os.AbstractBlockDev`. """ class I2C: """ 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.CONTROLLER) # create and init as a controller i2c.init(I2C.CONTROLLER, baudrate=20000) # init as a controller i2c.init(I2C.PERIPHERAL, addr=0x42) # init as a peripheral with given address i2c.deinit() # turn off the I2C unit 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 controller must specify the recipient's address:: i2c.init(I2C.CONTROLLER) i2c.send('123', 0x42) # send 3 bytes to peripheral with address 0x42 i2c.send(b'456', addr=0x42) # keyword for address Master also has other methods:: i2c.is_ready(0x42) # check if peripheral 0x42 is ready i2c.scan() # scan for peripherals on the bus, returning # a list of valid addresses i2c.mem_read(3, 0x42, 2) # read 3 bytes from memory of peripheral 0x42, # starting at address 2 in the peripheral i2c.mem_write('abc', 0x42, 2, timeout=1000) # write 'abc' (3 bytes) to memory of peripheral 0x42 # starting at address 2 in the peripheral, timeout after 1 second """ CONTROLLER: ClassVar[int] = ... """ for initialising the bus to controller mode """ PERIPHERAL: ClassVar[int] = ... """ for initialising the bus to peripheral mode """ def __init__( self, bus: int | str, mode: str, /, *, addr: int = 0x12, baudrate: int = 400_000, gencall: bool = False, dma: bool = False, ): """ 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 buses 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. """ def deinit(self) -> None: """ Turn off the I2C bus. """ def init( self, bus: int | str, mode: str, /, *, addr: int = 0x12, baudrate: int = 400_000, gencall: bool = False, dma: bool = False, ) -> None: """ Initialise the I2C bus with the given parameters: - ``mode`` must be either ``I2C.CONTROLLER`` or ``I2C.PERIPHERAL`` - ``addr`` is the 7-bit address (only sensible for a peripheral) - ``baudrate`` is the SCL clock rate (only sensible for a controller) - ``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) """ def is_ready(self, addr: int, /) -> bool: """ Check if an I2C device responds to the given address. Only valid when in controller mode. """ @overload def mem_read( self, data: int, addr: int, memaddr: int, /, *, timeout: int = 5000, addr_size: int = 8, ) -> bytes: """ 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 controller mode. """ @overload def mem_read( self, data: AnyWritableBuf, addr: int, memaddr: int, /, *, timeout: int = 5000, addr_size: int = 8, ) -> AnyWritableBuf: """ 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 controller mode. """ def mem_write( self, data: int | AnyWritableBuf, addr: int, memaddr: int, /, *, timeout: int = 5000, addr_size: int = 8, ) -> None: """ 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 controller mode. """ @overload def recv(self, recv: int, addr: int = 0x00, /, *, timeout: int = 5000,) -> bytes: """ 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 controller 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``. """ @overload def recv( self, recv: AnyWritableBuf, addr: int = 0x00, /, *, timeout: int = 5000, ) -> AnyWritableBuf: """ 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 controller 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``. """ def send(self, addr: int = 0x00, /, *, timeout: int = 5000,) -> None: """ 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 controller mode) - ``timeout`` is the timeout in milliseconds to wait for the send Return value: ``None``. """ def scan(self) -> list[int]: """ Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond. Only valid when in controller mode. """ class LCD: """ 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 """ def __init__(self, skin_position: str, /): """ 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. """ def command(self, inst_data: int, buf: bytes, /) -> None: """ 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. """ def contrast(self, value: int, /) -> None: """ Set the contrast of the LCD. Valid values are between 0 and 47. """ def fill(self, colour: int, /) -> None: """ 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. """ def get(self, x: int, y: int, /) -> int: """ Get the pixel at the position ``(x, y)``. Returns 0 or 1. This method reads from the visible buffer. """ def light(self, value: bool | int, /) -> None: """ Turn the backlight on/off. True or 1 turns it on, False or 0 turns it off. """ def pixel(self, x: int, y: int, colour: int, /) -> None: """ 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. """ def show(self) -> None: """ Show the hidden buffer on the screen. """ def text(self, str: str, x: int, y: int, colour: int, /) -> None: """ 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. """ def write(self, str: str, /) -> None: """ Write the string ``str`` to the screen. It will appear immediately. """ class LED: """ The LED object controls an individual LED (Light Emitting Diode). """ def __init__(self, id: int, /): """ Create an LED object associated with the given LED: - ``id`` is the LED number, 1-4. """ @overload def intensity(self) -> int: """ 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. """ @overload def intensity(self, value: int, /) -> None: """ 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. """ def off(self) -> None: """ Turn the LED off. """ def on(self) -> None: """ Turn the LED on, to maximum intensity. """ def toggle(self) -> None: """ 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. """ # noinspection PyNestedDecorators class Pin: """ 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. """ AF1_TIM1: ClassVar[PinAF] = ... """ Alternate def_ 1, timer 1. """ AF1_TIM2: ClassVar[PinAF] = ... """ Alternate def_ 1, timer 2. """ AF2_TIM3: ClassVar[PinAF] = ... """ Alternate def_ 2, timer 3. """ AF2_TIM4: ClassVar[PinAF] = ... """ Alternate def_ 2, timer 4. """ AF2_TIM5: ClassVar[PinAF] = ... """ Alternate def_ 2, timer 5. """ AF3_TIM10: ClassVar[PinAF] = ... """ Alternate def_ 3, timer 10. """ AF3_TIM11: ClassVar[PinAF] = ... """ Alternate def_ 3, timer 11. """ AF3_TIM8: ClassVar[PinAF] = ... """ Alternate def_ 3, timer 8. """ AF3_TIM9: ClassVar[PinAF] = ... """ Alternate def_ 3, timer 9. """ AF4_I2C1: ClassVar[PinAF] = ... """ Alternate def_ 4, I2C 1. """ AF4_I2C2: ClassVar[PinAF] = ... """ Alternate def_ 4, I2C 2. """ AF5_SPI1: ClassVar[PinAF] = ... """ Alternate def_ 5, SPI 1. """ AF5_SPI2: ClassVar[PinAF] = ... """ Alternate def_ 5, SPI 2. """ AF7_USART1: ClassVar[PinAF] = ... """ Alternate def_ 7, USART 1. """ AF7_USART2: ClassVar[PinAF] = ... """ Alternate def_ 7, USART 2. """ AF7_USART3: ClassVar[PinAF] = ... """ Alternate def_ 7, USART 3. """ AF8_UART4: ClassVar[PinAF] = ... """ Alternate def_ 8, USART 4. """ AF8_USART6: ClassVar[PinAF] = ... """ Alternate def_ 8, USART 6. """ AF9_CAN1: ClassVar[PinAF] = ... """ Alternate def_ 9, CAN 1. """ AF9_CAN2: ClassVar[PinAF] = ... """ Alternate def_ 9, CAN 2. """ AF9_TIM12: ClassVar[PinAF] = ... """ Alternate def_ 9, timer 12. """ AF9_TIM13: ClassVar[PinAF] = ... """ Alternate def_ 9, timer 13. """ AF9_TIM14: ClassVar[PinAF] = ... """ Alternate def_ 9, timer 14. """ ALT: ClassVar[int] = ... """ Initialise the pin to alternate-def_ mode with a push-pull drive (same as `AF_PP`). """ ALT_OPEN_DRAIN: ClassVar[int] = ... """ Initialise the pin to alternate-def_ mode with an open-drain drive (same as `AF_OD`). """ IRQ_FALLING: ClassVar[int] = ... """ Initialise the pin to generate an interrupt on a falling edge. """ IRQ_RISING: ClassVar[int] = ... """ Initialise the pin to generate an interrupt on a rising edge. """ OPEN_DRAIN: ClassVar[int] = ... """ Initialise the pin to output mode with an open-drain drive (same as `OUT_OD`). """ # noinspection PyPep8Naming class board: """ The board pins (board nomenclature, e.g. `X1`) that are bought out onto pads on a PyBoard. """ LED_BLUE: ClassVar[Pin] = ... """ The blue LED. """ LED_GREEN: ClassVar[Pin] = ... """ The green LED. """ LED_RED: ClassVar[Pin] = ... """ The red LED. """ LED_YELLOW: ClassVar[Pin] = ... """ The yellow LED. """ MMA_AVDD: ClassVar[Pin] = ... """ Accelerometer (MMA7660) analogue power (AVDD) pin. """ MMA_INT: ClassVar[Pin] = ... """ Accelerometer (MMA7660) interrupt (\INT) pin. """ SD: ClassVar[Pin] = ... """ SD card present switch (0 for card inserted, 1 for no card) (same as SD_SW). """ SD_CK: ClassVar[Pin] = ... """ SD card clock. """ SD_CMD: ClassVar[Pin] = ... """ SD card command. """ SD_D0: ClassVar[Pin] = ... """ SD card serial data 0. """ SD_D1: ClassVar[Pin] = ... """ SD card serial data 1. """ SD_D2: ClassVar[Pin] = ... """ SD card serial data 2. """ SD_D3: ClassVar[Pin] = ... """ SD card serial data 3. """ SD_SW: ClassVar[Pin] = ... """ SD card present switch (0 for card inserted, 1 for no card) (same as SD). """ SW: ClassVar[Pin] = ... """ Usr switch (0 = pressed, 1 = not pressed). """ USB_DM: ClassVar[Pin] = ... """ USB data -. """ USB_DP: ClassVar[Pin] = ... """ USB data +. """ USB_ID: ClassVar[Pin] = ... """ USB OTG (on-the-go) ID. """ USB_VBUS: ClassVar[Pin] = ... """ USB VBUS (power) monitoring pin. """ X1: ClassVar[Pin] = ... """ X1 pin. """ X10: ClassVar[Pin] = ... """ X10 pin. """ X11: ClassVar[Pin] = ... """ X11 pin. """ X12: ClassVar[Pin] = ... """ X12 pin. """ X17: ClassVar[Pin] = ... """ X17 pin. """ X18: ClassVar[Pin] = ... """ X18 pin. """ X19: ClassVar[Pin] = ... """ X19 pin. """ X2: ClassVar[Pin] = ... """ X2 pin. """ X20: ClassVar[Pin] = ... """ X20 pin. """ X21: ClassVar[Pin] = ... """ X21 pin. """ X22: ClassVar[Pin] = ... """ X22 pin. """ X3: ClassVar[Pin] = ... """ X3 pin. """ X4: ClassVar[Pin] = ... """ X4 pin. """ X5: ClassVar[Pin] = ... """ X5 pin. """ X6: ClassVar[Pin] = ... """ X6 pin. """ X7: ClassVar[Pin] = ... """ X7 pin. """ X8: ClassVar[Pin] = ... """ X8 pin. """ X9: ClassVar[Pin] = ... """ X9 pin. """ Y1: ClassVar[Pin] = ... """ Y1 pin. """ Y10: ClassVar[Pin] = ... """ Y10 pin. """ Y11: ClassVar[Pin] = ... """ Y11 pin. """ Y12: ClassVar[Pin] = ... """ Y12 pin. """ Y2: ClassVar[Pin] = ... """ Y2 pin. """ Y3: ClassVar[Pin] = ... """ Y3 pin. """ Y4: ClassVar[Pin] = ... """ Y4 pin. """ Y5: ClassVar[Pin] = ... """ Y5 pin. """ Y6: ClassVar[Pin] = ... """ Y6 pin. """ Y7: ClassVar[Pin] = ... """ Y7 pin. """ Y8: ClassVar[Pin] = ... """ Y8 pin. """ Y9: ClassVar[Pin] = ... """ Y9 pin. """ # noinspection PyPep8Naming class cpu: """ The CPU pins (CPU nomenclature, e.g. `A0`) that are bought out onto pads on a PyBoard. """ A0: ClassVar[Pin] = ... """ A0 pin. """ A1: ClassVar[Pin] = ... """ A1 pin. """ A10: ClassVar[Pin] = ... """ A10 pin. """ A11: ClassVar[Pin] = ... """ A11 pin. """ A12: ClassVar[Pin] = ... """ A12 pin. """ A13: ClassVar[Pin] = ... """ A13 pin. """ A14: ClassVar[Pin] = ... """ A14 pin. """ A15: ClassVar[Pin] = ... """ A15 pin. """ A2: ClassVar[Pin] = ... """ A2 pin. """ A3: ClassVar[Pin] = ... """ A3 pin. """ A4: ClassVar[Pin] = ... """ A4 pin. """ A5: ClassVar[Pin] = ... """ A5 pin. """ A6: ClassVar[Pin] = ... """ A6 pin. """ A7: ClassVar[Pin] = ... """ A7 pin. """ A8: ClassVar[Pin] = ... """ A8 pin. """ A9: ClassVar[Pin] = ... """ A9 pin. """ B0: ClassVar[Pin] = ... """ B0 pin. """ B1: ClassVar[Pin] = ... """ B1 pin. """ B10: ClassVar[Pin] = ... """ B10 pin. """ B11: ClassVar[Pin] = ... """ B11 pin. """ B12: ClassVar[Pin] = ... """ B12 pin. """ B13: ClassVar[Pin] = ... """ B13 pin. """ B14: ClassVar[Pin] = ... """ B14 pin. """ B15: ClassVar[Pin] = ... """ B15 pin. """ B2: ClassVar[Pin] = ... """ B2 pin. """ B3: ClassVar[Pin] = ... """ B3 pin. """ B4: ClassVar[Pin] = ... """ B4 pin. """ B5: ClassVar[Pin] = ... """ B5 pin. """ B6: ClassVar[Pin] = ... """ B6 pin. """ B7: ClassVar[Pin] = ... """ B7 pin. """ B8: ClassVar[Pin] = ... """ B8 pin. """ B9: ClassVar[Pin] = ... """ B9 pin. """ C0: ClassVar[Pin] = ... """ C0 pin. """ C1: ClassVar[Pin] = ... """ C1 pin. """ C10: ClassVar[Pin] = ... """ C10 pin. """ C11: ClassVar[Pin] = ... """ C11 pin. """ C12: ClassVar[Pin] = ... """ C12 pin. """ C13: ClassVar[Pin] = ... """ C13 pin. """ C2: ClassVar[Pin] = ... """ C2 pin. """ C3: ClassVar[Pin] = ... """ C3 pin. """ C4: ClassVar[Pin] = ... """ C4 pin. """ C5: ClassVar[Pin] = ... """ C5 pin. """ C6: ClassVar[Pin] = ... """ C6 pin. """ C7: ClassVar[Pin] = ... """ C7 pin. """ C8: ClassVar[Pin] = ... """ C8 pin. """ C9: ClassVar[Pin] = ... """ C9 pin. """ D2: ClassVar[Pin] = ... """ D2 pin. """ AF_OD: ClassVar[int] = ... """ initialise the pin to alternate-function mode with an open-drain drive """ AF_PP: ClassVar[int] = ... """ initialise the pin to alternate-function mode with a push-pull drive """ ANALOG: ClassVar[int] = ... """ initialise the pin to analog mode """ IN: ClassVar[int] = ... """ initialise the pin to input mode """ OUT_OD: ClassVar[int] = ... """ initialise the pin to output mode with an open-drain drive """ OUT_PP: ClassVar[int] = ... """ initialise the pin to output mode with a push-pull drive """ PULL_DOWN: ClassVar[int] = ... """ enable the pull-down resistor on the pin """ PULL_NONE: ClassVar[int] = ... """ don't enable any pull up or down resistors on the pin """ PULL_UP: ClassVar[int] = ... """ enable the pull-up resistor on the pin """ def __init__( self, id: Pin | str, /, mode: int = IN, pull: int = PULL_NONE, *, value: Any = None, alt: str | int = -1, ): """ 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`. """ @overload @staticmethod def debug() -> bool: """ Get or set the debugging state (``True`` or ``False`` for on or off). """ @overload @staticmethod def debug(state: bool, /) -> None: """ Get or set the debugging state (``True`` or ``False`` for on or off). """ @overload @staticmethod def dict() -> Dict[str, Pin]: """ Get or set the pin mapper dictionary. """ @overload @staticmethod def dict(dict: Dict[str, Pin], /) -> None: """ Get or set the pin mapper dictionary. """ @overload @staticmethod def mapper() -> Callable[[str], Pin]: """ Get or set the pin mapper function. """ @overload @staticmethod def mapper(fun: Callable[[str], Pin], /) -> None: """ Get or set the pin mapper function. """ def init( self, mode: int = IN, pull: int = PULL_NONE, *, value: Any = None, alt: str | int = -1, ) -> None: """ 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. - *value* if not None will set the port output value before enabling the pin. - *alt* can be used when mode is ``Pin.AF_PP`` or ``Pin.AF_OD`` to set the index or name of one of the alternate functions associated with a pin. This arg was previously called *af* which can still be used if needed. Returns: ``None``. """ @overload def value(self) -> int: """ 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. """ @overload def value(self, value: Any, /) -> None: """ 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. """ def __str__(self) -> str: """ Return a string describing the pin object. """ def af(self) -> int: """ 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. """ def af_list(self) -> list[PinAF]: """ Returns an array of alternate functions available for this pin. """ def gpio(self) -> int: """ Returns the base address of the GPIO block associated with this pin. """ def mode(self) -> int: """ 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. """ def name(self) -> str: """ Get the pin name. """ def names(self) -> list[str]: """ Returns the cpu and board names for this pin. """ def pin(self) -> int: """ Get the pin number. """ def port(self) -> int: """ Get the pin port. """ def pull(self) -> int: """ 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. """ class PinAF(ABC): """ 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) """ __slots__ = () @abstractmethod def __str__(self) -> str: """ Return a string describing the alternate function. """ @abstractmethod def index(self) -> int: """ Return the alternate function index. """ @abstractmethod def name(self) -> str: """ Return the name of the alternate function. """ @abstractmethod def reg(self) -> int: """ 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 """ class RTC: """ The RTC is an 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()) """ def __init__(self): """ Create an RTC object. """ def datetime( self, datetimetuple: tuple[int, int, int, int, int, int, int, int], / ) -> None: """ 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 """ def wakeup( self, timeout: int, callback: Callable[[RTC], None] | None = None, / ) -> 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. """ def info(self) -> int: """ 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 """ @overload def calibration(self) -> int: """ 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 """ @overload def calibration(self, cal: int, /) -> None: """ 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 """ class Servo: """ 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. """ def __init__(self, id: int, /): """ Create a servo object. ``id`` is 1-4, and corresponds to pins X1 through X4. """ @overload def angle(self) -> int: """ 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. """ @overload def angle(self, angle: int, time: int = 0, /) -> None: """ 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. """ @overload def speed(self) -> int: """ 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. """ @overload def speed(self, speed: int, time: int = 0, /) -> None: """ 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. """ @overload def speed(self) -> int: """ 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. """ @overload def speed(self, value: int, /) -> None: """ 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. """ @overload def calibration(self) -> tuple[int, int, int, int, int]: """ 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. """ @overload def calibration(self, pulse_min: int, pulse_max: int, pulse_centre: int, /) -> None: """ 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. """ @overload def calibration( self, pulse_min: int, pulse_max: int, pulse_centre: int, pulse_angle_90: int, pulse_speed_100: int, /, ) -> None: """ 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. """ class SPI: """ SPI is a serial protocol that is driven by a controller. 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.CONTROLLER, baudrate=600000, polarity=1, phase=0, crc=0x7) Only required parameter is mode, SPI.CONTROLLER or SPI.PERIPHERAL. 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 """ CONTROLLER: ClassVar[int] = ... """ for initialising the SPI bus to controller or peripheral mode """ PERIPHERAL: ClassVar[int] = ... """ for initialising the SPI bus to controller or peripheral mode """ LSB: ClassVar[int] = ... """ set the first bit to be the least or most significant bit """ MSB: ClassVar[int] = ... """ set the first bit to be the least or most significant bit """ @overload def __init__(self, bus: int, /): """ 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 buses 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. """ @overload def __init__( self, bus: int, /, mode: int = CONTROLLER, baudrate: int = 328125, *, polarity: int = 1, phase: int = 0, bits: int = 8, firstbit: int = MSB, ti: bool = False, crc: int | None = None, ): """ 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 buses 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. """ @overload def __init__( self, bus: int, /, mode: int = CONTROLLER, *, prescaler: int = 256, polarity: int = 1, phase: int = 0, bits: int = 8, firstbit: int = MSB, ti: bool = False, crc: int | None = None, ): """ 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 buses 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. """ def deinit(self) -> None: """ Turn off the SPI bus. """ @overload def init( self, mode: int = CONTROLLER, baudrate: int = 328125, *, polarity: int = 1, phase: int = 0, bits: int = 8, firstbit: int = MSB, ti: bool = False, crc: int | None = None, ): """ Initialise the SPI bus with the given parameters: - ``mode`` must be either ``SPI.CONTROLLER`` or ``SPI.PERIPHERAL``. - ``baudrate`` is the SCK clock rate (only sensible for a controller). - ``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``. - ``ti`` True indicates Texas Instruments, as opposed to Motorola, signal conventions. - ``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. """ @overload def init( self, mode: int = CONTROLLER, *, prescaler: int = 256, polarity: int = 1, phase: int = 0, bits: int = 8, firstbit: int = MSB, ti: bool = False, crc: int | None = None, ): """ Initialise the SPI bus with the given parameters: - ``mode`` must be either ``SPI.CONTROLLER`` or ``SPI.PERIPHERAL``. - ``baudrate`` is the SCK clock rate (only sensible for a controller). - ``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``. - ``ti`` True indicates Texas Instruments, as opposed to Motorola, signal conventions. - ``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. """ def recv( self, recv: int | AnyWritableBuf, /, *, timeout: int = 5000 ) -> AnyWritableBuf: """ 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``. """ def send( self, send: int | AnyWritableBuf | bytes, /, *, timeout: int = 5000 ) -> None: """ 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``. """ def send_recv( self, send: int | bytearray | array | bytes, recv: AnyWritableBuf | None = None, /, *, timeout: int = 5000, ) -> AnyWritableBuf: """ 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. """ class Switch: """ 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()) """ def __init__(self): """ Create and return a switch object. """ def __call__(self) -> bool: """ Call switch object directly to get its state: ``True`` if pressed down, ``False`` otherwise. """ def value(self) -> bool: """ Get the switch state. Returns ``True`` if pressed down, otherwise ``False``. """ def callback(self, fun: Callable[[], None] | None) -> None: """ Register the given function to be called when the switch is pressed down. If ``fun`` is ``None``, then it disables the callback. """ # noinspection PyShadowingNames,PyUnresolvedReferences class Timer: """ 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. """ UP: ClassVar[int] = ... """ configures the timer to count from 0 to ARR (default). """ DOWN: ClassVar[int] = ... """ configures the timer to count from ARR down to 0. """ CENTER: ClassVar[int] = ... """ configures the timer to count from 0 to ARR and then back down to 0. """ PWM: ClassVar[int] = ... """ configure the timer in PWM mode (active high). """ PWM_INVERTED: ClassVar[int] = ... """ configure the timer in PWM mode (active low). """ OC_TIMING: ClassVar[int] = ... """ indicates that no pin is driven. """ OC_ACTIVE: ClassVar[int] = ... """ the pin will be made active when a compare match occurs (active is determined by polarity). """ OC_INACTIVE: ClassVar[int] = ... """ the pin will be made inactive when a compare match occurs. """ OC_TOGGLE: ClassVar[int] = ... """ the pin will be toggled when an compare match occurs. """ OC_FORCED_ACTIVE: ClassVar[int] = ... """ the pin is forced active (compare match is ignored). """ OC_FORCED_INACTIVE: ClassVar[int] = ... """ the pin is forced inactive (compare match is ignored). """ IC: ClassVar[int] = ... """ configure the timer in Input Capture mode. """ ENC_A: ClassVar[int] = ... """ configure the timer in Encoder mode. The counter only changes when CH1 changes. """ ENC_B: ClassVar[int] = ... """ configure the timer in Encoder mode. The counter only changes when CH2 changes. """ ENC_AB: ClassVar[int] = ... """ configure the timer in Encoder mode. The counter changes when CH1 or CH2 changes. """ HIGH: ClassVar[int] = ... """ output is active high. """ LOW: ClassVar[int] = ... """ output is active low. """ RISING: ClassVar[int] = ... """ captures on rising edge. """ FALLING: ClassVar[int] = ... """ captures on falling edge. """ BOTH: ClassVar[int] = ... """ captures on both edges. """ @overload def __init__(self, id: int, /): """ 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. """ @overload def __init__( self, id: int, /, *, freq: int, mode: int = UP, div: int = 1, callback: Callable[[Timer], None] | None = None, deadtime: int = 0, ): """ 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. """ @overload def __init__( self, id: int, /, *, prescaler: int, period: int, mode: int = UP, div: int = 1, callback: Callable[[Timer], None] | None = None, deadtime: int = 0, ): """ 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. """ @overload def init( self, *, freq: int, mode: int = UP, div: int = 1, callback: Callable[[Timer], None] | None = None, deadtime: int = 0, ) -> None: """ 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. """ @overload def init( self, *, prescaler: int, period: int, mode: int = UP, div: int = 1, callback: Callable[[Timer], None] | None = None, deadtime: int = 0, ) -> None: """ 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. """ def deinit(self) -> None: """ 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. """ def callback(self, fun: Callable[[Timer], None] | None, /) -> None: """ 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. """ @overload def channel(self, channel: int, /) -> "TimerChannel" | None: """ 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) """ @overload def channel( self, channel: int, /, mode: int, *, callback: Callable[[Timer], None] | None = None, pin: Pin | None = None, pulse_width: int, ) -> "TimerChannel": """ 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) """ @overload def channel( self, channel: int, /, mode: int, *, callback: Callable[[Timer], None] | None = None, pin: Pin | None = None, pulse_width_percent: int | float, ) -> "TimerChannel": """ 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) """ @overload def channel( self, channel: int, /, mode: int, *, callback: Callable[[Timer], None] | None = None, pin: Pin | None = None, compare: int, polarity: int, ) -> "TimerChannel": """ 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) """ @overload def channel( self, channel: int, /, mode: int, *, callback: Callable[[Timer], None] | None = None, pin: Pin | None = None, polarity: int, ) -> "TimerChannel": """ 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) """ @overload def channel( self, channel: int, /, mode: int, *, callback: Callable[[Timer], None] | None = None, pin: Pin | None = None, ) -> "TimerChannel": """ 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) """ @overload def counter(self) -> int: """ Get or set the timer counter. """ @overload def counter(self, value: int, /) -> None: """ Get or set the timer counter. """ @overload def freq(self) -> int: """ Get or set the frequency for the timer (changes prescaler and period if set). """ @overload def freq(self, value: int, /) -> None: """ Get or set the frequency for the timer (changes prescaler and period if set). """ @overload def period(self) -> int: """ Get or set the period of the timer. """ @overload def period(self, value: int, /) -> None: """ Get or set the period of the timer. """ @overload def prescaler(self) -> int: """ Get or set the prescaler for the timer. """ @overload def prescaler(self, value: int, /) -> None: """ Get or set the prescaler for the timer. """ def source_freq(self) -> int: """ Get the frequency of the source of the timer. """ class TimerChannel(ABC): """ Timer channels are used to generate/capture a signal using a timer. TimerChannel objects are created using the Timer.channel() method. """ @abstractmethod def callback(self, fun: Callable[[Timer], None] | None, /) -> None: """ 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. """ @overload @abstractmethod def capture(self) -> int: """ 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. """ @overload @abstractmethod def capture(self, value: int, /) -> None: """ 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. """ @overload @abstractmethod def compare(self) -> int: """ 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. """ @overload @abstractmethod def compare(self, value: int, /) -> None: """ 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. """ @overload @abstractmethod def pulse_width(self) -> int: """ 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% """ @overload @abstractmethod def pulse_width(self, value: int, /) -> None: """ 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% """ @overload @abstractmethod def pulse_width_percent(self) -> float: """ 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%. """ @overload @abstractmethod def pulse_width_percent(self, value: int | float, /) -> None: """ 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%. """ # noinspection PyShadowingNames class UART: """ 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``. """ RTS: ClassVar[int] = ... """ to select the flow control type. """ CTS: ClassVar[int] = ... """ to select the flow control type. """ @overload def __init__(self, bus: int | str, /): """ Construct a UART object on the given bus. For Pyboard ``bus`` can be 1-4, 6, 'XA', 'XB', 'YA', or 'YB'. For Pyboard Lite ``bus`` can be 1, 2, 6, 'XB', or 'YA'. For Pyboard D ``bus`` can be 1-4, 'XA', '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 buses on Pyboard 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: - ``UART(1)`` is on ``XB``: ``(TX, RX) = (X9, X10) = (PB6, PB7)`` - ``UART(6)`` is on ``YA``: ``(TX, RX) = (Y1, Y2) = (PC6, PC7)`` - ``UART(2)`` is on: ``(TX, RX) = (X1, X2) = (PA2, PA3)`` The Pyboard D supports UART(1), UART(2), UART(3) and UART(4) only, pins are: - ``UART(4)`` is on ``XA``: ``(TX, RX) = (X1, X2) = (PA0, PA1)`` - ``UART(1)`` is on ``YA``: ``(TX, RX) = (Y1, Y2) = (PA9, PA10)`` - ``UART(3)`` is on ``YB``: ``(TX, RX) = (Y9, Y10) = (PB10, PB11)`` - ``UART(2)`` is on: ``(TX, RX) = (X3, X4) = (PA2, PA3)`` *Note:* Pyboard D has ``UART(1)`` on ``YA``, unlike Pyboard and Pyboard Lite that both have ``UART(1)`` on ``XB`` and ``UART(6)`` on ``YA``. """ @overload def __init__( self, bus: int | str, baudrate: int, /, bits: int = 8, parity: int | None = None, stop: int = 1, *, timeout: int = 0, flow: int = 0, timeout_char: int = 0, read_buf_len: int = 64, ): """ Construct a UART object on the given bus. For Pyboard ``bus`` can be 1-4, 6, 'XA', 'XB', 'YA', or 'YB'. For Pyboard Lite ``bus`` can be 1, 2, 6, 'XB', or 'YA'. For Pyboard D ``bus`` can be 1-4, 'XA', '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 buses on Pyboard 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: - ``UART(1)`` is on ``XB``: ``(TX, RX) = (X9, X10) = (PB6, PB7)`` - ``UART(6)`` is on ``YA``: ``(TX, RX) = (Y1, Y2) = (PC6, PC7)`` - ``UART(2)`` is on: ``(TX, RX) = (X1, X2) = (PA2, PA3)`` The Pyboard D supports UART(1), UART(2), UART(3) and UART(4) only, pins are: - ``UART(4)`` is on ``XA``: ``(TX, RX) = (X1, X2) = (PA0, PA1)`` - ``UART(1)`` is on ``YA``: ``(TX, RX) = (Y1, Y2) = (PA9, PA10)`` - ``UART(3)`` is on ``YB``: ``(TX, RX) = (Y9, Y10) = (PB10, PB11)`` - ``UART(2)`` is on: ``(TX, RX) = (X3, X4) = (PA2, PA3)`` *Note:* Pyboard D has ``UART(1)`` on ``YA``, unlike Pyboard and Pyboard Lite that both have ``UART(1)`` on ``XB`` and ``UART(6)`` on ``YA``. """ def init( self, baudrate: int, /, bits: int = 8, parity: int | None = None, stop: int = 1, *, timeout: int = 0, flow: int = 0, timeout_char: int = 0, read_buf_len: int = 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 ` 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. """ def deinit(self) -> None: """ Turn off the UART bus. """ def any(self) -> int: """ Returns the number of bytes waiting (may be 0). """ @overload def read(self) -> bytes | None: """ 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. """ @overload def read(self, nbytes: int, /) -> bytes | None: """ 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. """ def readchar(self) -> int: """ Receive a single character on the bus. Return value: The character read, as an integer. Returns -1 on timeout. """ @overload def readinto(self, buf: AnyWritableBuf, /) -> int | None: """ 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. """ @overload def readinto(self, buf: AnyWritableBuf, nbytes: int, /) -> int | None: """ 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. """ def readline(self) -> str | None: """ 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. """ def write(self, buf: AnyWritableBuf, /) -> int | None: """ 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``. """ def writechar(self, char: int, /) -> None: """ 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. """ def sendbreak(self) -> None: """ Send a break condition on the bus. This drives the bus low for a duration of 13 bits. Return value: ``None``. """ # noinspection PyPep8Naming class USB_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. """ def __init__(self): """ Create a new USB_HID object. """ @overload def recv(self, data: int, /, *, timeout: int = 5000) -> bytes: """ 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. """ @overload def recv(self, data: AnyWritableBuf, /, *, timeout: int = 5000) -> int: """ 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. """ def send(self, data: Sequence[int]) -> None: """ Send data over the USB HID interface: - ``data`` is the data to send (a tuple/list of integers, or a bytearray). """ # noinspection PyPep8Naming class USB_VCP: """ The USB_VCP class allows creation of a `stream`-like object representing the USB virtual comm port. It can be used to read and write data over USB to the connected host. """ RTS: ClassVar[int] = ... """ to select the flow control type. .. data:: USB_VCP.IRQ_RX IRQ trigger values for :meth:`USB_VCP.irq`. """ CTS: ClassVar[int] = ... """ to select the flow control type. .. data:: USB_VCP.IRQ_RX IRQ trigger values for :meth:`USB_VCP.irq`. """ def __init__(self, id: int = 0, /): """ Create a new USB_VCP object. The *id* argument specifies which USB VCP port to use. """ def init(self, *, flow: int = -1) -> int: """ Configure the USB VCP port. If the *flow* argument is not -1 then the value sets the flow control, which can be a bitwise-or of ``USB_VCP.RTS`` and ``USB_VCP.CTS``. RTS is used to control read behaviour and CTS, to control write behaviour. """ def setinterrupt(self, chr: int, /) -> None: """ Set the character which interrupts running Python code. This is set to 3 (CTRL-C) by default, and when a CTRL-C character is received over the USB VCP port, a KeyboardInterrupt exception is raised. Set to -1 to disable this interrupt feature. This is useful when you want to send raw bytes over the USB VCP port. """ def isconnected(self) -> bool: """ Return ``True`` if USB is connected as a serial device, else ``False``. """ def any(self) -> bool: """ Return ``True`` if any characters waiting, else ``False``. """ def close(self) -> None: """ This method does nothing. It exists so the USB_VCP object can act as a file. """ @overload def read(self) -> bytes | None: """ Read at most ``nbytes`` from the serial device and return them as a bytes object. If ``nbytes`` is not specified then the method reads all available bytes from the serial device. USB_VCP `stream` implicitly works in non-blocking mode, so if no pending data available, this method will return immediately with ``None`` value. """ @overload def read(self, nbytes, /) -> bytes | None: """ Read at most ``nbytes`` from the serial device and return them as a bytes object. If ``nbytes`` is not specified then the method reads all available bytes from the serial device. USB_VCP `stream` implicitly works in non-blocking mode, so if no pending data available, this method will return immediately with ``None`` value. """ @overload def readinto(self, buf: AnyWritableBuf, /) -> int | None: """ Read bytes from the serial device and store them into ``buf``, which should be a buffer-like object. At most ``len(buf)`` bytes are read. If ``maxlen`` is given and then at most ``min(maxlen, len(buf))`` bytes are read. Returns the number of bytes read and stored into ``buf`` or ``None`` if no pending data available. """ @overload def readinto(self, buf: AnyWritableBuf, maxlen: int, /) -> int | None: """ Read bytes from the serial device and store them into ``buf``, which should be a buffer-like object. At most ``len(buf)`` bytes are read. If ``maxlen`` is given and then at most ``min(maxlen, len(buf))`` bytes are read. Returns the number of bytes read and stored into ``buf`` or ``None`` if no pending data available. """ def readline(self) -> bytes | None: """ Read a whole line from the serial device. Returns a bytes object containing the data, including the trailing newline character or ``None`` if no pending data available. """ def readlines(self) -> list[bytes] | None: """ Read as much data as possible from the serial device, breaking it into lines. Returns a list of bytes objects, each object being one of the lines. Each line will include the newline character. """ def write(self, buf: AnyReadableBuf, /) -> int: """ Write the bytes from ``buf`` to the serial device. Returns the number of bytes written. """ @overload def recv(self, data: int, /, *, timeout: int = 5000) -> bytes | None: """ 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. """ @overload def recv(self, data: AnyWritableBuf, /, *, timeout: int = 5000) -> int | None: """ 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. """ def send(self, buf: AnyWritableBuf | bytes | int, /, *, timeout: int = 5000) -> int: """ Send data over the USB VCP: - ``data`` 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: number of bytes sent. """ ================================================ FILE: typehints/pyboard/stm.pyi ================================================ """ functionality specific to STM32 MCUs. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/stm.rst. =================================================== .. module:: stm :synopsis: functionality specific to STM32 MCUs This module provides functionality specific to STM32 microcontrollers, including direct access to peripheral registers. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Final # noinspection PyPep8Naming class mem: """ Memory objects that can be used in combination with the peripheral register constants to read and write registers of the MCU hardware peripherals, as well as all other areas of address space. Cannot make an instance of this class, but pre-made instances: `mem8`, `mem16`, and `mem32` are available for 8, 16, and 32 bit access respectively. """ def __getitem__(self, loc: int, /) -> int: """ Get the contents of the given memory location using subscript notation e.g., `mem8[0]`. Returns 8 bits for mem8`, 16 bits for `mem16`, and 32 bits for `mem32`, in all cases as a single `int`. Location doesn't overflow, it is truncated. Can be used in combination with the peripheral register constants to read registers of the MCU hardware peripherals, as well as all other areas of address space. """ def __setitem__(self, loc: int, value: int, /) -> None: """ Set the contents of the given memory location to the given value using subscript notation e.g., `mem8[0] = 195`. Sets 8 bits for `mem8`, 16 bits for `mem16`, and 32 bits for `mem32`, from the given `int` value. Location doesn't overflow, it is truncated. Can be used in combination with the peripheral register constants to write registers of the MCU hardware peripherals, as well as all other areas of address space. """ mem8: Final[mem] = ... """ Read/write 8 bits of memory. """ mem16: Final[mem] = ... """ Read/write 16 bits of memory. """ mem32: Final[mem] = ... """ Read/write 32 bits of memory. """ GPIOA: Final[int] = ... """ Base address of the GPIOA peripheral. The module defines constants for registers which are generated from CMSIS header files, and the constants available depend on the microcontroller series that is being compiled for. Examples of some constants include: address of that peripheral. Constants that have a prefix which is the name of a peripheral, like ``GPIO_BSRR``, are relative offsets of the register. Accessing peripheral registers requires adding the absolute base address of the peripheral and the relative register offset. For example ``GPIOA + GPIO_BSRR`` is the full, absolute address of the ``GPIOA->BSRR`` register. Example use: .. code-block:: python3 # set PA2 high stm.mem32[stm.GPIOA + stm.GPIO_BSRR] = 1 << 2 # read PA3 value = (stm.mem32[stm.GPIOA + stm.GPIO_IDR] >> 3) & 1 """ GPIOB: Final[int] = ... """ Base address of the GPIOB peripheral. The module defines constants for registers which are generated from CMSIS header files, and the constants available depend on the microcontroller series that is being compiled for. Examples of some constants include: address of that peripheral. Constants that have a prefix which is the name of a peripheral, like ``GPIO_BSRR``, are relative offsets of the register. Accessing peripheral registers requires adding the absolute base address of the peripheral and the relative register offset. For example ``GPIOA + GPIO_BSRR`` is the full, absolute address of the ``GPIOA->BSRR`` register. Example use: .. code-block:: python3 # set PA2 high stm.mem32[stm.GPIOA + stm.GPIO_BSRR] = 1 << 2 # read PA3 value = (stm.mem32[stm.GPIOA + stm.GPIO_IDR] >> 3) & 1 """ GPIO_BSRR: Final[int] = ... """ Offset of the GPIO bit set/reset register. The module defines constants for registers which are generated from CMSIS header files, and the constants available depend on the microcontroller series that is being compiled for. Examples of some constants include: address of that peripheral. Constants that have a prefix which is the name of a peripheral, like ``GPIO_BSRR``, are relative offsets of the register. Accessing peripheral registers requires adding the absolute base address of the peripheral and the relative register offset. For example ``GPIOA + GPIO_BSRR`` is the full, absolute address of the ``GPIOA->BSRR`` register. Example use: .. code-block:: python3 # set PA2 high stm.mem32[stm.GPIOA + stm.GPIO_BSRR] = 1 << 2 # read PA3 value = (stm.mem32[stm.GPIOA + stm.GPIO_IDR] >> 3) & 1 """ GPIO_IDR: Final[int] = ... """ Offset of the GPIO input data register. The module defines constants for registers which are generated from CMSIS header files, and the constants available depend on the microcontroller series that is being compiled for. Examples of some constants include: address of that peripheral. Constants that have a prefix which is the name of a peripheral, like ``GPIO_BSRR``, are relative offsets of the register. Accessing peripheral registers requires adding the absolute base address of the peripheral and the relative register offset. For example ``GPIOA + GPIO_BSRR`` is the full, absolute address of the ``GPIOA->BSRR`` register. Example use: .. code-block:: python3 # set PA2 high stm.mem32[stm.GPIOA + stm.GPIO_BSRR] = 1 << 2 # read PA3 value = (stm.mem32[stm.GPIOA + stm.GPIO_IDR] >> 3) & 1 """ GPIO_ODR: Final[int] = ... """ Offset of the GPIO output data register. Constants that are named after a peripheral, like ``GPIOA``, are the absolute The module defines constants for registers which are generated from CMSIS header files, and the constants available depend on the microcontroller series that is being compiled for. Examples of some constants include: address of that peripheral. Constants that have a prefix which is the name of a peripheral, like ``GPIO_BSRR``, are relative offsets of the register. Accessing peripheral registers requires adding the absolute base address of the peripheral and the relative register offset. For example ``GPIOA + GPIO_BSRR`` is the full, absolute address of the ``GPIOA->BSRR`` register. Example use: .. code-block:: python3 # set PA2 high stm.mem32[stm.GPIOA + stm.GPIO_BSRR] = 1 << 2 # read PA3 value = (stm.mem32[stm.GPIOA + stm.GPIO_IDR] >> 3) & 1 """ def rfcore_status() -> int: """ Returns the status of the second CPU as an integer (the first word of device info table). These functions are available on STM32WBxx microcontrollers, and interact with the second CPU, the RF core. """ def rfcore_fw_version(id: int, /) -> tuple[int, int, int, int, int]: """ Get the version of the firmware running on the second CPU. Pass in 0 for *id* to get the FUS version, and 1 to get the WS version. Returns a 5-tuple with the full version number. These functions are available on STM32WBxx microcontrollers, and interact with the second CPU, the RF core. """ def rfcore_sys_hci(ogf: int, ocf: int, data: int, timeout_ms: int = 0, /) -> bytes: """ Execute a HCI command on the SYS channel. The execution is synchronous. Returns a bytes object with the result of the SYS command. These functions are available on STM32WBxx microcontrollers, and interact with the second CPU, the RF core. """ ================================================ FILE: typehints/rpi_pico/rp2.pyi ================================================ """ Raspberry Pi Pico specific micropython support. These methods are not fully documented and this is a best effort to produce the interface """ from typing import Optional, Callable from machine import Pin class Flash: """ Low level access to flash device """ def ioctl(self): pass def readblocks(self): pass def writeblocks(self): pass class irq: """ IRQ definition """ def flags(self) -> int: """ IRQ flags """ def trigger(self): """ Trigger IRQ """ class PIO: IN_LOW: int = 0 IN_HIGH: int = 1 OUT_LOW: int = 2 OUT_HIGH: int = 3 SHIFT_LEFT: int = 0 SHIFT_RIGHT: int = 1 IRQ_SM0: int = 256 IRQ_SM1: int = 512 IRQ_SM2: int = 1024 IRQ_SM3: int = 2048 def __init__(self, num: int): pass def irq(self, callback: Optional[Callable[["PIO"], None]]) -> irq: pass class StateMachine: """ Instantiate a state machine with a program. """ def __init__(self, num: int, prog: list, freq: int = None, set_base: Pin = None) -> None: pass def active(self) -> bool: """ This state machine is active """ def init(self, prog: list): """ Initialise and start a PIO program """ def irq(self) -> PIO.irq: pass def put(self, data: bytes): """ Send data to PIO program """ class PIOASMError(Exception): pass def asm_pio(**kwargs) -> list: """ Assemble a PIO program """ ================================================ FILE: typehints/stdlib/_thread.pyi ================================================ """ multithreading support. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/_thread.rst. ======================================== .. 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. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver ================================================ FILE: typehints/stdlib/array.pyi ================================================ """ efficient arrays of numeric data. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/array.rst. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import ( overload, Sequence, Any, MutableSequence, Generic, Text, TypeVar, Final, ) _T: Final = TypeVar("_T", int, float, Text) # noinspection PyPep8Naming class array(MutableSequence[_T], Generic[_T]): """ |see_cpython_module| :mod:`python:array`. Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``, ``L``, ``q``, ``Q``, ``f``, ``d`` (the latter 2 depending on the floating-point support). +-----------+--------------------+-------------------+-----------------------+ | Type code | C Type | Python Type | Minimum size in bytes | +===========+====================+===================+=======================+ | ``'b'`` | signed char | int | 1 | +-----------+--------------------+-------------------+-----------------------+ | ``'B'`` | unsigned char | int | 1 | +-----------+--------------------+-------------------+-----------------------+ | ``'h'`` | signed short | int | 2 | +-----------+--------------------+-------------------+-----------------------+ | ``'H'`` | unsigned short | int | 2 | +-----------+--------------------+-------------------+-----------------------+ | ``'i'`` | signed int | int | 2 | +-----------+--------------------+-------------------+-----------------------+ | ``'I'`` | unsigned int | int | 2 | +-----------+--------------------+-------------------+-----------------------+ | ``'l'`` | signed long | int | 4 | +-----------+--------------------+-------------------+-----------------------+ | ``'L'`` | unsigned long | int | 4 | +-----------+--------------------+-------------------+-----------------------+ | ``'q'`` | signed long long | int | 8 | +-----------+--------------------+-------------------+-----------------------+ | ``'Q'`` | unsigned long long | int | 8 | +-----------+--------------------+-------------------+-----------------------+ | ``'f'`` | float | float | 4 | +-----------+--------------------+-------------------+-----------------------+ | ``'d'`` | double | float | 8 | +-----------+--------------------+-------------------+-----------------------+ """ def __init__(self, typecode: str, iterable: Sequence[Any] = ..., /): """ Create array with elements of given type. Initial contents of the array are given by *iterable*. If it is not provided, an empty array is created. """ def append(self, val: Any, /) -> None: """ Append new element *val* to the end of array, growing it. """ def extend(self, iterable: Sequence[Any], /) -> None: """ Append new elements as contained in *iterable* to the end of array, growing it. """ def decode(self, encoding: str = "utf-8", errors: str = "strict") -> str: """ Deprecated *do not use*, likely to be removed in future! Note: ``decode`` is only meant to be present for ``bytearray``, but for efficiency of code-size reasons ``bytearray`` is implemented with the same code as the other array type-codes and hence ``decode`` is on all ``array``s at present. """ @overload def __delitem__(self, i: int) -> None: """``array`` object does **not** support item deletion.""" @overload def __delitem__(self, sl: slice) -> None: """``array`` object does **not** support item deletion.""" def insert(self, index: int, value: _T) -> None: """``array`` object does **not** support item insertion.""" @overload def __getitem__(self, index: int) -> _T: """ Indexed read of ``self``; called as ``a[index]``, where ``a`` is an ``array``. Returns the value at the given ``index``. Negative indices count from end and ``IndexError``is thrown if the index out of range. **Note:** ``__getitem__`` cannot be called directly (``a.__getitem__(index)`` fails) and is not present in ``__dict__``, however ``a[index]`` does work. """ @overload def __getitem__(self, sl: slice) -> array[_T]: """ Slice read of ``self``; called as ``a[sl]``, where ``a`` is an ``array``. Returns an ``array`` of values for the given slice. Negative slice indices count from end and ``IndexError``is thrown if any of the slice indices are out of range. **Note:** ``__getitem__`` cannot be called directly (``a.__getitem__(sl)`` fails) and is not present in ``__dict__``, however ``a[sl]`` does work. """ @overload def __setitem__(self, index: int, value: _T) -> None: """ Indexed write into ``self``; called as ``a[index] = value`` where ``a`` is an ``array``, ``index`` is an ``int``, and ``value`` is the same type as ``a``'s content. Negative indices count from end and ``IndexError``is thrown if the index out of range. **Note:** ``__setitem__`` cannot be called directly (``a.__setitem__(index, value)`` fails) and is not present in ``__dict__``, however ``a[index] = value`` does work. """ @overload def __setitem__(self, sl: slice, values: array[_T]) -> None: """ Indexed write into ``self``; called as ``a[sl] = values``, where ``a`` is an ``array``, ``sl`` is an ``slice``, and ``values`` is the same type as ``a``. Negative indices count from end and ``IndexError``is thrown if any of the slice indices are out of range. **Note:** ``__setitem__`` cannot be called directly (``a.__setitem__(index, value)`` fails) and is not present in ``__dict__``, however ``a[index] = value`` does work. """ def __len__(self) -> int: """ Returns the number of items in ``self``; called as ``len(a)``, where ``a`` is an ``array``. **Note:** ``__len__`` cannot be called directly (``a.__len__()`` fails) and the method is not present in ``__dict__``, however ``len(a)`` does work. """ def __add__(self, other: array[_T]) -> array[_T]: """ Return a new ``array`` that is the concatenation of ``self`` with ``other``; called as ``a + other`` (where ``a`` and ``other`` are both ``array``s). **Note:** ``__add__`` cannot be called directly (``a.__add__(other)`` fails) and is not present in ``__dict__``, however ``a + other`` does work. """ def __iadd__(self, other: array[_T]) -> None: """ Concatenates ``self`` with ``other`` in-place; called as ``a += other``, where ``a`` and ``other`` are both ``array``s. Equivalent to ``extend(other)``. **Note:** ``__iadd__`` cannot be called directly (``a.__iadd__(other)`` fails) and is not present in ``__dict__``, however ``a += other`` does work. """ def __repr__(self) -> str: """ Returns the string representation of ``self``; called as ``str(a)`` or ``repr(a)```, where ``a`` is an ``array``. Returns the string 'array(, [])', where ```` is the type code letter for ``self`` and ```` is a comma separated list of the elements of ``self``. **Note:** ``__repr__`` cannot be called directly (``a.__repr__()`` fails) and is not present in ``__dict__``, however ``str(a)`` and ``repr(a)`` both work. """ ================================================ FILE: typehints/stdlib/binascii.pyi ================================================ """ binary/ASCII conversions. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/binascii.rst. =========================================== .. module:: binascii :synopsis: binary/ASCII conversions |see_cpython_module| :mod:`python:binascii`. This module implements conversions between binary data and various encodings of it in ASCII form (in both directions). """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver def hexlify(data: bytes, sep: str | bytes = ..., /) -> bytes: """ Convert the bytes in the *data* object to a hexadecimal representation. Returns a bytes object. If the additional argument *sep* is supplied it is used as a separator between hexadecimal values. """ def unhexlify(data: str | bytes, /) -> bytes: """ Convert hexadecimal data to binary representation. Returns bytes string. (i.e. inverse of hexlify) """ def a2b_base64(data: str | bytes, /) -> bytes: """ Decode base64-encoded data, ignoring invalid characters in the input. Conforms to `RFC 2045 s.6.8 `_. Returns a bytes object. """ def b2a_base64(data: bytes, /) -> bytes: """ Encode binary data in base64 format, as in `RFC 3548 `_. Returns the encoded data followed by a newline character, as a bytes object. """ ================================================ FILE: typehints/stdlib/cmath.pyi ================================================ """ mathematical functions for complex numbers. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/cmath.rst. ========================================================== .. 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. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import SupportsComplex, SupportsFloat, Final _C: Final = SupportsFloat | SupportsComplex def cos(z: _C, /) -> complex: """ Return the cosine of ``z``. """ def exp(z: _C, /) -> complex: """ Return the exponential of ``z``. """ def log(z: _C, /) -> complex: """ Return the natural logarithm of ``z``. The branch cut is along the negative real axis. """ def log10(z: _C, /) -> complex: """ Return the base-10 logarithm of ``z``. The branch cut is along the negative real axis. """ def phase(z: _C, /) -> float: """ Returns the phase of the number ``z``, in the range (-pi, +pi]. """ def polar(z: _C, /) -> tuple[float, float]: """ Returns, as a tuple, the polar form of ``z``. """ def rect(r: float, phi: float, /) -> complex: """ Returns the complex number with modulus ``r`` and phase ``phi``. """ def sin(z: _C, /) -> complex: """ Return the sine of ``z``. """ def sqrt(z: _C, /) -> complex: """ Return the square-root of ``z``. """ e: Final[float] = ... """ base of the natural logarithm """ pi: Final[float] = ... """ the ratio of a circle's circumference to its diameter """ ================================================ FILE: typehints/stdlib/collections.pyi ================================================ """ collection and container types. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/collections.rst. ==================================================== .. module:: collections :synopsis: collection and container types |see_cpython_module| :mod:`python:collections`. This module implements advanced collection and container types to hold/accumulate various objects. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import overload, Any, Type, Iterable, TypeVar, Generic, Mapping, Dict, Final _KT: Final = TypeVar("_KT") _VT: Final = TypeVar("_VT") def namedtuple(name: str, fields: str | Iterable[str]) -> Type[tuple[Any, ...]]: """ This is factory function to create a new namedtuple type with a specific name and set of fields. A namedtuple is a subclass of tuple which allows to access its fields not just by numeric index, but also with an attribute access syntax using symbolic field names. Fields is a sequence of strings specifying field names. For compatibility with CPython it can also be a a string with space-separated field named (but this is less efficient). Example of use:: from collections import namedtuple MyTuple = namedtuple("MyTuple", ("id", "name")) t1 = MyTuple(1, "foo") t2 = MyTuple(2, "bar") print(t1.name) assert t2.name == t2[1] """ # noinspection PyPep8Naming class deque: """ Minimal implementation of a deque that implements a FIFO buffer. """ def __init__(self, iterable: tuple[Any], maxlen: int, flags: int = 0, /): """ Deques (double-ended queues) are a list-like container that support O(1) appends and pops from either side of the deque. New deques are created using the following arguments: - *iterable* must be the empty tuple, and the new deque is created empty. - *maxlen* must be specified and the deque will be bounded to this maximum length. Once the deque is full, any new items added will discard items from the opposite end. - The optional *flags* can be 1 to check for overflow when adding items. """ def __bool__(self) -> bool: """ Returns true if the `deque` isn't empty. **Note:** The method isn't listed by ``dir(deque)`` and can't be called directly, however ``bool(deque)`` and automatic conversion work! """ def __len__(self) -> int: """ Returns the number of items in the `deque`. **Note:** The method isn't listed by ``dir(deque)`` and can't be called directly, however ``len(deque)`` works! """ def append(self, x: Any, /) -> None: """ Add *x* to the right side of the deque. Raises IndexError if overflow checking is enabled and there is no more room left. """ def popleft(self) -> Any: """ Remove and return an item from the left side of the deque. Raises IndexError if no items are present. """ class OrderedDict(Dict[_KT, _VT], Generic[_KT, _VT]): """ W h e n o r d e r e d d i c t i s i t e r a t e d o v e r , k e y s / i t e m s a r e r e t u r n e d i n t h e o r d e r t h e y w e r e a d d e d . """ @overload def __init__(self): """ ``dict`` type subclass which remembers and preserves the order of keys added. When ordered dict is iterated over, keys/items are returned in the order they were added:: from collections import OrderedDict # To make benefit of ordered keys, OrderedDict should be initialized # from sequence of (key, value) pairs. d = OrderedDict([("z", 1), ("a", 2)]) # More items can be added as usual d["w"] = 5 d["b"] = 3 for k, v in d.items(): print(k, v) Output:: z 1 a 2 w 5 b 3 """ @overload def __init__(self, **kwargs: _VT): """ ``dict`` type subclass which remembers and preserves the order of keys added. When ordered dict is iterated over, keys/items are returned in the order they were added:: from collections import OrderedDict # To make benefit of ordered keys, OrderedDict should be initialized # from sequence of (key, value) pairs. d = OrderedDict([("z", 1), ("a", 2)]) # More items can be added as usual d["w"] = 5 d["b"] = 3 for k, v in d.items(): print(k, v) Output:: z 1 a 2 w 5 b 3 """ @overload def __init__(self, map: Mapping[_KT, _VT], **kwargs: _VT): """ ``dict`` type subclass which remembers and preserves the order of keys added. When ordered dict is iterated over, keys/items are returned in the order they were added:: from collections import OrderedDict # To make benefit of ordered keys, OrderedDict should be initialized # from sequence of (key, value) pairs. d = OrderedDict([("z", 1), ("a", 2)]) # More items can be added as usual d["w"] = 5 d["b"] = 3 for k, v in d.items(): print(k, v) Output:: z 1 a 2 w 5 b 3 """ ================================================ FILE: typehints/stdlib/errno.pyi ================================================ """ system error codes. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/errno.rst. ================================== .. module:: errno :synopsis: system error codes |see_cpython_module| :mod:`python:errno`. This module provides access to symbolic error codes for `OSError` exception. A particular inventory of codes depends on :term:`MicroPython port`. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Final, Dict EEXIST: Final[int] = ... """ Error codes, based on ANSI C/POSIX standard. All error codes start with "E". As mentioned above, inventory of the codes depends on :term:`MicroPython port`. Errors are usually accessible as ``exc.errno`` where ``exc`` is an instance of `OSError`. Usage example:: try: os.mkdir("my_dir") except OSError as exc: if exc.errno == errno.EEXIST: print("Directory already exists") """ EAGAIN: Final[int] = ... """ Error codes, based on ANSI C/POSIX standard. All error codes start with "E". As mentioned above, inventory of the codes depends on :term:`MicroPython port`. Errors are usually accessible as ``exc.errno`` where ``exc`` is an instance of `OSError`. Usage example:: try: os.mkdir("my_dir") except OSError as exc: if exc.errno == errno.EEXIST: print("Directory already exists") """ errorcode: Final[Dict[int, str]] = ... """ Dictionary mapping numeric error codes to strings with symbolic error code (see above):: >>> print(errno.errorcode[errno.EEXIST]) EEXIST """ ================================================ FILE: typehints/stdlib/gc.pyi ================================================ """ control the garbage collector. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/gc.rst. ========================================== .. module:: gc :synopsis: control the garbage collector |see_cpython_module| :mod:`python:gc`. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import overload def enable() -> None: """ Enable automatic garbage collection. """ def disable() -> None: """ Disable automatic garbage collection. Heap memory can still be allocated, and garbage collection can still be initiated manually using :meth:`gc.collect`. """ def collect() -> None: """ Run a garbage collection. """ def mem_alloc() -> int: """ Return the number of bytes of heap RAM that are allocated. .. admonition:: Difference to CPython :class: attention This function is MicroPython extension. """ def mem_free() -> int: """ 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. """ @overload def threshold() -> int: """ 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. """ @overload def threshold(amount: int) -> None: """ 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. """ ================================================ FILE: typehints/stdlib/hashlib.pyi ================================================ """ hashing algorithms. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/hashlib.rst. ==================================== .. module:: hashlib :synopsis: hashing algorithms |see_cpython_module| :mod:`python:hashlib`. This module implements binary data hashing algorithms. The exact inventory of available algorithms depends on a board. Among the algorithms which may be implemented: * SHA256 - The current generation, modern hashing algorithm (of SHA2 series). It is suitable for cryptographically-secure purposes. Included in the MicroPython core and any board is recommended to provide this, unless it has particular code size constraints. * SHA1 - A previous generation algorithm. Not recommended for new usages, but SHA1 is a part of number of Internet standards and existing applications, so boards targeting network connectivity and interoperability will try to provide this. * MD5 - A legacy algorithm, not considered cryptographically secure. Only selected boards, targeting interoperability with legacy applications, will offer this. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from abc import ABC from typing import overload from uio import AnyReadableBuf # noinspection PyPep8Naming class sha256("_Hash"): """ The current generation, modern hashing algorithm (of SHA2 series). It is suitable for cryptographically-secure purposes. Included in the MicroPython core and any board is recommended to provide this, unless it has particular code size constraints. """ @overload def __init__(self): """ Create an SHA256 hasher object and optionally feed ``data`` into it. """ @overload def __init__(self, data: AnyReadableBuf): """ Create an SHA256 hasher object and optionally feed ``data`` into it. """ # noinspection PyPep8Naming class sha1("_Hash"): """ A previous generation algorithm. Not recommended for new usages, but SHA1 is a part of number of Internet standards and existing applications, so boards targeting network connectivity and interoperability will try to provide this. """ @overload def __init__(self): """ Create an SHA1 hasher object and optionally feed ``data`` into it. """ @overload def __init__(self, data: AnyReadableBuf): """ Create an SHA1 hasher object and optionally feed ``data`` into it. """ # noinspection PyPep8Naming class md5("_Hash"): """ A legacy algorithm, not considered cryptographically secure. Only selected boards, targeting interoperability with legacy applications, will offer this. """ def __init__(self, data: AnyReadableBuf = ..., /): """ Create an MD5 hasher object and optionally feed ``data`` into it. """ class _Hash(ABC): """ Abstract base class for hashing algorithms that defines methods available in all algorithms. """ def update(self, data: AnyReadableBuf, /) -> None: """ Feed more binary data into hash. """ def digest(self) -> bytes: """ Return hash for all data passed through hash, as a bytes object. After this method is called, more data cannot be fed into the hash any longer. """ def hexdigest(self) -> str: """ This method is NOT implemented. Use ``binascii.hexlify(hash.digest())`` to achieve a similar effect. """ ================================================ FILE: typehints/stdlib/heapq.pyi ================================================ """ heap queue algorithm. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/heapq.rst. ==================================== .. module:: heapq :synopsis: heap queue algorithm |see_cpython_module| :mod:`python:heapq`. This module implements the `min heap queue algorithm `_. A heap queue is essentially a list that has its elements stored in such a way that the first item of the list is always the smallest. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import TypeVar, Any, Final _T: Final = TypeVar("_T") def heappush(heap: list[_T], item: _T, /) -> None: """ Push the ``item`` onto the ``heap``. """ def heappop(heap: list[_T], /) -> _T: """ Pop the first item from the ``heap``, and return it. Raise ``IndexError`` if ``heap`` is empty. The returned item will be the smallest item in the ``heap``. """ def heapify(x: list[Any], /) -> None: """ Convert the list ``x`` into a heap. This is an in-place operation. """ ================================================ FILE: typehints/stdlib/io.pyi ================================================ """ input/output streams. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/io.rst. ================================= .. module:: io :synopsis: input/output streams |see_cpython_module| :mod:`python:io`. This module contains additional types of `stream` (file-like) objects and helper functions. Conceptual hierarchy -------------------- .. admonition:: Difference to CPython :class: attention Conceptual hierarchy of stream base classes is simplified in MicroPython, as described in this section. (Abstract) base stream classes, which serve as a foundation for behaviour of all the concrete classes, adhere to few dichotomies (pair-wise classifications) in CPython. In MicroPython, they are somewhat simplified and made implicit to achieve higher efficiencies and save resources. An important dichotomy in CPython is unbuffered vs buffered streams. In MicroPython, all streams are currently unbuffered. This is because all modern OSes, and even many RTOSes and filesystem drivers already perform buffering on their side. Adding another layer of buffering is counter- productive (an issue known as "bufferbloat") and takes precious memory. Note that there still cases where buffering may be useful, so we may introduce optional buffering support at a later time. But in CPython, another important dichotomy is tied with "bufferedness" - it's whether a stream may incur short read/writes or not. A short read is when a user asks e.g. 10 bytes from a stream, but gets less, similarly for writes. In CPython, unbuffered streams are automatically short operation susceptible, while buffered are guarantee against them. The no short read/writes is an important trait, as it allows to develop more concise and efficient programs - something which is highly desirable for MicroPython. So, while MicroPython doesn't support buffered streams, it still provides for no-short-operations streams. Whether there will be short operations or not depends on each particular class' needs, but developers are strongly advised to favour no-short-operations behaviour for the reasons stated above. For example, MicroPython sockets are guaranteed to avoid short read/writes. Actually, at this time, there is no example of a short-operations stream class in the core, and one would be a port-specific class, where such a need is governed by hardware peculiarities. The no-short-operations behaviour gets tricky in case of non-blocking streams, blocking vs non-blocking behaviour being another CPython dichotomy, fully supported by MicroPython. Non-blocking streams never wait for data either to arrive or be written - they read/write whatever possible, or signal lack of data (or ability to write data). Clearly, this conflicts with "no-short-operations" policy, and indeed, a case of non-blocking buffered (and this no-short-ops) streams is convoluted in CPython - in some places, such combination is prohibited, in some it's undefined or just not documented, in some cases it raises verbose exceptions. The matter is much simpler in MicroPython: non-blocking stream are important for efficient asynchronous operations, so this property prevails on the "no-short-ops" one. So, while blocking streams will avoid short reads/writes whenever possible (the only case to get a short read is if end of file is reached, or in case of error (but errors don't return short data, but raise exceptions)), non-blocking streams may produce short data to avoid blocking the operation. The final dichotomy is binary vs text streams. MicroPython of course supports these, but while in CPython text streams are inherently buffered, they aren't in MicroPython. (Indeed, that's one of the cases for which we may introduce buffering support.) Note that for efficiency, MicroPython doesn't provide abstract base classes corresponding to the hierarchy above, and it's not possible to implement, or subclass, a stream class in pure Python. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from types import TracebackType from typing import TypeVar, Final, Protocol, runtime_checkable, Literal from typing import AnyStr, overload, Type from uarray import array _T: Final = TypeVar("_T") _OpenTextModeUpdating: Final = Literal[ "r+", "+r", "rt+", "r+t", "+rt", "tr+", "t+r", "+tr", "w+", "+w", "wt+", "w+t", "+wt", "tw+", "t+w", "+tw", "a+", "+a", "at+", "a+t", "+at", "ta+", "t+a", "+ta", "x+", "+x", "xt+", "x+t", "+xt", "tx+", "t+x", "+tx", ] _OpenTextModeWriting: Final = Literal["w", "wt", "tw", "a", "at", "ta", "x", "xt", "tx"] _OpenTextModeReading: Final = Literal[ "r", "rt", "tr", "U", "rU", "Ur", "rtU", "rUt", "Urt", "trU", "tUr", "Utr" ] _OpenTextMode: Final = _OpenTextModeUpdating | _OpenTextModeWriting | _OpenTextModeReading _OpenBinaryModeUpdating: Final = Literal[ "rb+", "r+b", "+rb", "br+", "b+r", "+br", "wb+", "w+b", "+wb", "bw+", "b+w", "+bw", "ab+", "a+b", "+ab", "ba+", "b+a", "+ba", "xb+", "x+b", "+xb", "bx+", "b+x", "+bx", ] _OpenBinaryModeWriting: Final = Literal["wb", "bw", "ab", "ba", "xb", "bx"] _OpenBinaryModeReading: Final = Literal[ "rb", "br", "rbU", "rUb", "Urb", "brU", "bUr", "Ubr" ] _OpenBinaryMode: Final = _OpenBinaryModeUpdating | _OpenBinaryModeReading | _OpenBinaryModeWriting AnyStr_co: Final = TypeVar("AnyStr_co", str, bytes, covariant=True) @runtime_checkable class PathLike(Protocol[AnyStr_co]): def __fspath__(self) -> AnyStr_co: ... StrOrBytesPath: Final = str | bytes | PathLike[str] | PathLike[bytes] _OpenFile: Final = StrOrBytesPath | int AnyReadableBuf: Final = TypeVar("AnyReadableBuf", bytearray, array, memoryview, bytes) """ Type that allows bytearray, array, memoryview, or bytes, but only one of these and not a mixture in a single declaration. """ AnyWritableBuf: Final = TypeVar("AnyWritableBuf", bytearray, array, memoryview) """ Type that allows bytearray, array, or memoryview, but only one of these and not a mixture in a single declaration. """ _Self: Final = TypeVar("_Self") # The type that extends `IOBase`. @runtime_checkable class IOBase(Protocol[AnyStr, _Self]): """A `Protocol` (structurally typed) for an IOStream.""" __slots__ = () def __enter__(self) -> _Self: """ Called on entry to a `with` block. The `with` statement will bind this method’s return value to the target(s) specified in the `as` clause of the statement, if any. """ def __exit__( self, exc_type: Type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None, ) -> bool | None: """ Called on exit of a `with` block. The parameters describe the exception that caused the context to be exited. If the context was exited without an exception, all three arguments will be `None`. If an exception is supplied, and the method wishes to suppress the exception (i.e., prevent it from being propagated), it should return a true value. Otherwise, the exception will be processed normally upon exit from this method. *Note* that `__exit__()` methods should not re-raise the passed-in exception; this is the caller’s responsibility. """ def __next__(self) -> AnyStr: """ Next string. """ def __iter__(self) -> _Self: """ Start new iteration. """ def close(self) -> None: """ Flushes the write buffers and closes the IO stream; best not called directly, use a `with` block instead. Calling `f.close()` without using a `with` block might result in content not being completely written to the disk, even if the program exits successfully. A closed file cannot be read or written any more. Any operation which requires that the file be open will raise a `ValueError` after the file has been closed. Calling `f.close()` more than once is allowed. """ def flush(self) -> None: """ Flushes the write buffers of the IO stream. `flush()` does not necessarily write the file’s data to disk. Use `f.flush()` followed by `os.sync()` to ensure this behavior. This method does nothing for read-only and non-blocking streams. """ def read(self, size: int | None = -1) -> AnyStr | None: """ Read up to `size` bytes from the object and return them as a `str` (text file) or `bytes` (binary file). As a convenience, if `size` is unspecified or -1, all bytes until EOF are returned. Otherwise, only one system call is ever made. Fewer than `size` bytes may be returned if the operating system call returns fewer than `size` bytes. If 0 bytes are returned, and `size` was not 0, this indicates end of file. If `self` is in non-blocking mode and no bytes are available, `None` is returned. """ def readinto(self, b: AnyWritableBuf) -> int | None: """ Read bytes into a pre-allocated, writable bytes-like object b, and return the number of bytes read. For example, b might be a bytearray. If `self` is in non-blocking mode and no bytes are available, `None` is returned. """ def readline(self, size: int = -1) -> AnyStr: """ Read and return, as a `str` (text file) or `bytes` (binary file), one line from the stream. If size is specified, at most size bytes will be read. The line terminator is always `b' '` for binary files; for text files, the newline argument to `open()` can be used to select the line terminator(s) recognized. """ def readlines(self, hint: int | None = -1) -> list[AnyStr]: """ Read and return a list of lines, as a `list[str]` (text file) or `list[bytes]` (binary file), from the stream. `hint` can be specified to control the number of lines read: no more lines will be read if the total size (in bytes/characters) of all lines so far exceeds `hint`. `hint` values of 0 or less, as well as `None`, are treated as no hint. The line terminator is always `b' '` for binary files; for text files, the newline argument to `open()` can be used to select the line terminator(s) recognized. *Note* that it’s already possible to iterate on file objects using `for line in file: ...` without calling `file.readlines()`. """ def write(self, b: AnyReadableBuf) -> int | None: """ Write the given bytes-like object, `b`, to the underlying raw stream, and return the number of bytes written. This can be less than the length of `b` in bytes, depending on specifics of the underlying raw stream, and especially if it is in non-blocking mode. `None` is returned if the raw stream is set not to block and no single byte could be readily written to it. The caller may release or mutate `b` after this method returns, so the implementation only access `b` during the method call. """ def seek(self, offset: int, whence: int = 0) -> int: """ Change the stream position to the given byte `offset`. `offset` is interpreted relative to the position indicated by `whence`. The default value for whence is 0. Values for whence are: * 0 – start of the stream (the default); offset should be zero or positive. * 1 – current stream position; offset may be negative. * 2 – end of the stream; offset is usually negative. Returns the new absolute position. """ def tell(self) -> int: """ Return the current stream position. """ @overload def open(name: _OpenFile, /, **kwargs) -> "TextIOWrapper": """ Open a file. Builtin ``open()`` function is aliased to this function. All ports (which provide access to file system) are required to support *mode* parameter, but support for other arguments vary by port. """ @overload def open(name: _OpenFile, mode: _OpenTextMode = ..., /, **kwargs) -> "TextIOWrapper": """ Open a file. Builtin ``open()`` function is aliased to this function. All ports (which provide access to file system) are required to support *mode* parameter, but support for other arguments vary by port. """ @overload def open(name: _OpenFile, mode: _OpenBinaryMode = ..., /, **kwargs) -> "FileIO": """ Open a file. Builtin ``open()`` function is aliased to this function. All ports (which provide access to file system) are required to support *mode* parameter, but support for other arguments vary by port. """ class FileIO(IOBase[bytes, "FileIO"]): """ Bytes stream from a file. """ def __init__(self, name: _OpenFile, mode: str = ..., /, **kwargs): """ This is type of a file open in binary mode, e.g. using ``open(name, "rb")``. You should not instantiate this class directly. """ class TextIOWrapper(IOBase[str, "TextIOWrapper"]): """ Str stream from a file. """ def __init__(self, name: _OpenFile, mode: str = ..., /, **kwargs): """ This is type of a file open in text mode, e.g. using ``open(name, "rt")``. You should not instantiate this class directly. """ class StringIO(IOBase[str, "StringIO"]): """ Str stream from a str (wrapper). """ @overload def __init__(self, string: str = "", /): """ In-memory file-like object for input/output. `StringIO` is used for text-mode I/O (similar to a normal file opened with "t" modifier). Initial contents can be specified with `string` parameter. `alloc_size` constructor creates an empty `StringIO` object, pre-allocated to hold up to `alloc_size` number of bytes. That means that writing that amount of bytes won't lead to reallocation of the buffer, and thus won't hit out-of-memory situation or lead to memory fragmentation. This constructor is a MicroPython extension and is recommended for usage only in special cases and in system-level libraries, not for end-user applications. .. admonition:: Difference to CPython :class: attention This constructor is a MicroPython extension. """ @overload def __init__(self, alloc_size: int, /): """ In-memory file-like object for input/output. `StringIO` is used for text-mode I/O (similar to a normal file opened with "t" modifier). Initial contents can be specified with `string` parameter. `alloc_size` constructor creates an empty `StringIO` object, pre-allocated to hold up to `alloc_size` number of bytes. That means that writing that amount of bytes won't lead to reallocation of the buffer, and thus won't hit out-of-memory situation or lead to memory fragmentation. This constructor is a MicroPython extension and is recommended for usage only in special cases and in system-level libraries, not for end-user applications. .. admonition:: Difference to CPython :class: attention This constructor is a MicroPython extension. """ def getvalue(self) -> str: """Get the current contents of the underlying buffer which holds data.""" class BytesIO(IOBase[bytes, "BytesIO"]): """ Bytes stream from a bytes array (wrapper). """ @overload def __init__(self, string: bytes = "", /): """ In-memory file-like objects for input/output. `StringIO` is used for text-mode I/O (similar to a normal file opened with "t" modifier). `BytesIO` is used for binary-mode I/O (similar to a normal file opened with "b" modifier). Initial contents of file-like objects can be specified with *string* parameter (should be normal string for `StringIO` or bytes object for `BytesIO`). All the usual file methods like ``read()``, ``write()``, ``seek()``, ``flush()``, ``close()`` are available on these objects, and additionally, a following method: `alloc_size` constructor creates an empty `BytesIO` object, pre-allocated to hold up to `alloc_size` number of bytes. That means that writing that amount of bytes won't lead to reallocation of the buffer, and thus won't hit out-of-memory situation or lead to memory fragmentation. This constructor is a MicroPython extension and is recommended for usage only in special cases and in system-level libraries, not for end-user applications. .. admonition:: Difference to CPython :class: attention This constructor is a MicroPython extension. """ @overload def __init__(self, alloc_size: int, /): """ In-memory file-like objects for input/output. `StringIO` is used for text-mode I/O (similar to a normal file opened with "t" modifier). `BytesIO` is used for binary-mode I/O (similar to a normal file opened with "b" modifier). Initial contents of file-like objects can be specified with *string* parameter (should be normal string for `StringIO` or bytes object for `BytesIO`). All the usual file methods like ``read()``, ``write()``, ``seek()``, ``flush()``, ``close()`` are available on these objects, and additionally, a following method: `alloc_size` constructor creates an empty `BytesIO` object, pre-allocated to hold up to `alloc_size` number of bytes. That means that writing that amount of bytes won't lead to reallocation of the buffer, and thus won't hit out-of-memory situation or lead to memory fragmentation. This constructor is a MicroPython extension and is recommended for usage only in special cases and in system-level libraries, not for end-user applications. .. admonition:: Difference to CPython :class: attention This constructor is a MicroPython extension. """ def getvalue(self) -> bytes: """ Get the current contents of the underlying buffer which holds data. """ ================================================ FILE: typehints/stdlib/json.pyi ================================================ """ JSON encoding and decoding. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/json.rst. ========================================= .. module:: json :synopsis: JSON encoding and decoding |see_cpython_module| :mod:`python:json`. This modules allows to convert between Python objects and the JSON data format. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Any, AnyStr from uio import IOBase def dump( obj: Any, stream: IOBase[str, Any], separators: tuple[str, str] | None = None, / ) -> None: """ Serialise *obj* to a JSON string, writing it to the given *stream*. If specified, separators should be an ``(item_separator, key_separator)`` tuple. The default is ``(', ', ': ')``. To get the most compact JSON representation, you should specify ``(',', ':')`` to eliminate whitespace. """ def dumps(obj: Any, separators: tuple[str, str] | None = None) -> str: """ Return *obj* represented as a JSON string. The arguments have the same meaning as in `dump`. """ def load(stream: IOBase[str, Any]) -> Any: """ Parse the given *stream*, interpreting it as a JSON string and deserialising the data to a Python object. The resulting object is returned. Parsing continues until end-of-file is encountered. A :exc:`ValueError` is raised if the data in *stream* is not correctly formed. """ def loads(str: AnyStr) -> Any: """ Parse the JSON *str* and return an object. Raises :exc:`ValueError` if the string is not correctly formed. """ ================================================ FILE: typehints/stdlib/math.pyi ================================================ """ mathematical functions. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/math.rst. ===================================== .. 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. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import SupportsFloat, Final def acos(x: SupportsFloat, /) -> float: """ Return the inverse cosine of ``x``. """ def acosh(x: SupportsFloat, /) -> float: """ Return the inverse hyperbolic cosine of ``x``. """ def asin(x: SupportsFloat, /) -> float: """ Return the inverse sine of ``x``. """ def asinh(x: SupportsFloat, /) -> float: """ Return the inverse hyperbolic sine of ``x``. """ def atan(x: SupportsFloat, /) -> float: """ Return the inverse tangent of ``x``. """ def atan2(y: SupportsFloat, x: SupportsFloat, /) -> float: """ Return the principal value of the inverse tangent of ``y/x``. """ def atanh(x: SupportsFloat, /) -> float: """ Return the inverse hyperbolic tangent of ``x``. """ def ceil(x: SupportsFloat, /) -> int: """ Return an integer, being ``x`` rounded towards positive infinity. """ def copysign(x: SupportsFloat, y: SupportsFloat, /) -> float: """ Return ``x`` with the sign of ``y``. """ def cos(x: SupportsFloat, /) -> float: """ Return the cosine of ``x``. """ def cosh(x: SupportsFloat, /) -> float: """ Return the hyperbolic cosine of ``x``. """ def degrees(x: SupportsFloat, /) -> float: """ Return radians ``x`` converted to degrees. """ def erf(x: SupportsFloat, /) -> float: """ Return the error function of ``x``. """ def erfc(x: SupportsFloat, /) -> float: """ Return the complementary error function of ``x``. """ def exp(x: SupportsFloat, /) -> float: """ Return the exponential of ``x``. """ def expm1(x: SupportsFloat, /) -> float: """ Return ``exp(x) - 1``. """ def fabs(x: SupportsFloat, /) -> float: """ Return the absolute value of ``x``. """ def floor(x: SupportsFloat, /) -> int: """ Return an integer, being ``x`` rounded towards negative infinity. """ def fmod(x: SupportsFloat, y: SupportsFloat, /) -> float: """ Return the remainder of ``x/y``. """ def frexp(x: SupportsFloat, /) -> tuple[float, int]: """ 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. """ def gamma(x: SupportsFloat, /) -> float: """ Return the gamma function of ``x``. """ def isfinite(x: SupportsFloat, /) -> bool: """ Return ``True`` if ``x`` is finite. """ def isinf(x: SupportsFloat, /) -> bool: """ Return ``True`` if ``x`` is infinite. """ def isnan(x: SupportsFloat, /) -> bool: """ Return ``True`` if ``x`` is not-a-number """ # noinspection PyShadowingNames def ldexp(x: SupportsFloat, exp: int, /) -> float: """ Return ``x * (2**exp)``. """ def lgamma(x: SupportsFloat, /) -> float: """ Return the natural logarithm of the gamma function of ``x``. """ def log(x: SupportsFloat, /) -> float: """ Return the natural logarithm of ``x``. """ def log10(x: SupportsFloat, /) -> float: """ Return the base-10 logarithm of ``x``. """ def log2(x: SupportsFloat, /) -> float: """ Return the base-2 logarithm of ``x``. """ def modf(x: SupportsFloat, /) -> tuple[float, float]: """ Return a tuple of two floats, being the fractional and integral parts of ``x``. Both return values have the same sign as ``x``. """ def pow(x: SupportsFloat, y: SupportsFloat, /) -> float: """ Returns ``x`` to the power of ``y``. """ def radians(x: SupportsFloat, /) -> float: """ Return degrees ``x`` converted to radians. """ def sin(x: SupportsFloat, /) -> float: """ Return the sine of ``x``. """ def sinh(x: SupportsFloat, /) -> float: """ Return the hyperbolic sine of ``x``. """ def sqrt(x: SupportsFloat, /) -> float: """ Return the square root of ``x``. """ def tan(x: SupportsFloat, /) -> float: """ Return the tangent of ``x``. """ def tanh(x: SupportsFloat, /) -> float: """ Return the hyperbolic tangent of ``x``. """ def trunc(x: SupportsFloat, /) -> float: """ Return an integer, being ``x`` rounded towards 0. """ e: Final[float] = ... """ base of the natural logarithm """ pi: Final[float] = ... """ the ratio of a circle's circumference to its diameter """ ================================================ FILE: typehints/stdlib/os.pyi ================================================ """ basic "operating system" services. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/os.rst. ============================================== .. module:: os :synopsis: basic "operating system" services |see_cpython_module| :mod:`python:os`. The ``os`` module contains functions for filesystem access and mounting, terminal redirection and duplication, and the ``uname`` and ``urandom`` functions. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from abc import abstractmethod from typing import Final, TypeVar, runtime_checkable, Protocol, overload, Literal from uio import IOBase _StrOrBytesT: Final = TypeVar("_StrOrBytesT", str, bytes) class _PathLike(Protocol[_StrOrBytesT]): @abstractmethod def __fspath__(self) -> _StrOrBytesT: """Return the file system path representation of the object, preferably as a `str`.""" _AnyPath: Final = str | bytes | _PathLike[str] | _PathLike[bytes] _FdOrAnyPath: Final = int | _AnyPath def uname() -> tuple[str, str, str, str, str]: """ Return a tuple (possibly a named tuple) containing information about the underlying machine and/or its operating system. The tuple has five fields in the following order, each of them being a string: * ``sysname`` -- the name of the underlying system * ``nodename`` -- the network name (can be the same as ``sysname``) * ``release`` -- the version of the underlying system * ``version`` -- the MicroPython version and build date * ``machine`` -- an identifier for the underlying hardware (eg board, CPU) """ def urandom(n: int, /) -> bytes: """ Return a bytes object with *n* random bytes. Whenever possible, it is generated by the hardware random number generator. """ def chdir(path: _FdOrAnyPath, /) -> None: """ Change current directory. """ def getcwd() -> str: """ Get the current directory. """ @overload def ilistdir() -> list[tuple[str, int, int] | tuple[str, int, int, int]]: """ This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is listing. With no argument it lists the current directory, otherwise it lists the directory given by *dir*. The tuples have the form *(name, type, inode[, size])*: - *name* is a string (or bytes if *dir* is a bytes object) and is the name of the entry; - *type* is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files; - *inode* is an integer corresponding to the inode of the file, and may be 0 for filesystems that don't have such a notion. - Some platforms may return a 4-tuple that includes the entry's *size*. For file entries, *size* is an integer representing the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries. """ @overload def ilistdir(dir: int, /) -> list[tuple[str, int, int] | tuple[str, int, int, int]]: """ This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is listing. With no argument it lists the current directory, otherwise it lists the directory given by *dir*. The tuples have the form *(name, type, inode[, size])*: - *name* is a string (or bytes if *dir* is a bytes object) and is the name of the entry; - *type* is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files; - *inode* is an integer corresponding to the inode of the file, and may be 0 for filesystems that don't have such a notion. - Some platforms may return a 4-tuple that includes the entry's *size*. For file entries, *size* is an integer representing the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries. """ @overload def ilistdir(dir: str, /) -> list[tuple[str, int, int] | tuple[str, int, int, int]]: """ This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is listing. With no argument it lists the current directory, otherwise it lists the directory given by *dir*. The tuples have the form *(name, type, inode[, size])*: - *name* is a string (or bytes if *dir* is a bytes object) and is the name of the entry; - *type* is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files; - *inode* is an integer corresponding to the inode of the file, and may be 0 for filesystems that don't have such a notion. - Some platforms may return a 4-tuple that includes the entry's *size*. For file entries, *size* is an integer representing the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries. """ @overload def ilistdir( dir: bytes, / ) -> list[tuple[bytes, int, int] | tuple[bytes, int, int, int]]: """ This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is listing. With no argument it lists the current directory, otherwise it lists the directory given by *dir*. The tuples have the form *(name, type, inode[, size])*: - *name* is a string (or bytes if *dir* is a bytes object) and is the name of the entry; - *type* is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files; - *inode* is an integer corresponding to the inode of the file, and may be 0 for filesystems that don't have such a notion. - Some platforms may return a 4-tuple that includes the entry's *size*. For file entries, *size* is an integer representing the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries. """ @overload def ilistdir( dir: _PathLike[str], / ) -> list[tuple[str, int, int] | tuple[str, int, int, int]]: """ This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is listing. With no argument it lists the current directory, otherwise it lists the directory given by *dir*. The tuples have the form *(name, type, inode[, size])*: - *name* is a string (or bytes if *dir* is a bytes object) and is the name of the entry; - *type* is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files; - *inode* is an integer corresponding to the inode of the file, and may be 0 for filesystems that don't have such a notion. - Some platforms may return a 4-tuple that includes the entry's *size*. For file entries, *size* is an integer representing the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries. """ @overload def ilistdir( dir: _PathLike[bytes], / ) -> list[tuple[bytes, int, int] | tuple[bytes, int, int, int]]: """ This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is listing. With no argument it lists the current directory, otherwise it lists the directory given by *dir*. The tuples have the form *(name, type, inode[, size])*: - *name* is a string (or bytes if *dir* is a bytes object) and is the name of the entry; - *type* is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files; - *inode* is an integer corresponding to the inode of the file, and may be 0 for filesystems that don't have such a notion. - Some platforms may return a 4-tuple that includes the entry's *size*. For file entries, *size* is an integer representing the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries. """ @overload def listdir() -> list[str]: """ With no argument, list the current directory. Otherwise list the given directory. """ @overload def listdir(dir: int, /) -> list[str]: """ With no argument, list the current directory. Otherwise list the given directory. """ @overload def listdir(dir: str, /) -> list[str]: """ With no argument, list the current directory. Otherwise list the given directory. """ @overload def listdir(dir: bytes, /) -> list[bytes]: """ With no argument, list the current directory. Otherwise list the given directory. """ @overload def listdir(dir: _PathLike[str], /) -> list[str]: """ With no argument, list the current directory. Otherwise list the given directory. """ @overload def listdir(dir: _PathLike[bytes], /) -> list[bytes]: """ With no argument, list the current directory. Otherwise list the given directory. """ def mkdir(path: _AnyPath, /) -> None: """ Create a new directory. """ def remove(path: _AnyPath, /) -> None: """ Remove a file. """ def rmdir(path: _AnyPath, /) -> None: """ Remove a directory. """ def rename(old_path: _AnyPath, new_path: _AnyPath, /) -> None: """ Rename a file. """ def stat( path: _FdOrAnyPath, / ) -> tuple[int, int, int, int, int, int, int, int, int, int]: """ Get the status of a file or directory. """ def statvfs( path: _FdOrAnyPath, / ) -> tuple[int, int, int, int, int, int, int, int, int, int]: """ Get the status of a fileystem. Returns a tuple with the filesystem information in the following order: * ``f_bsize`` -- file system block size * ``f_frsize`` -- fragment size * ``f_blocks`` -- size of fs in f_frsize units * ``f_bfree`` -- number of free blocks * ``f_bavail`` -- number of free blocks for unprivileged users * ``f_files`` -- number of inodes * ``f_ffree`` -- number of free inodes * ``f_favail`` -- number of free inodes for unprivileged users * ``f_flag`` -- mount flags * ``f_namemax`` -- maximum filename length Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail`` and the ``f_flags`` parameter may return ``0`` as they can be unavailable in a port-specific implementation. """ def sync() -> None: """ Sync all filesystems. """ def dupterm(stream_object: IOBase | None, index: int = 0, /) -> IOBase | None: """ Duplicate or switch the MicroPython terminal (the REPL) on the given `stream`-like object. The *stream_object* argument must be a native stream object, or derive from ``io.IOBase`` and implement the ``readinto()`` and ``write()`` methods. The stream should be in non-blocking mode and ``readinto()`` should return ``None`` if there is no data available for reading. After calling this function all terminal output is repeated on this stream, and any input that is available on the stream is passed on to the terminal input. The *index* parameter should be a non-negative integer and specifies which duplication slot is set. A given port may implement more than one slot (slot 0 will always be available) and in that case terminal input and output is duplicated on all the slots that are set. If ``None`` is passed as the *stream_object* then duplication is cancelled on the slot given by *index*. The function returns the previous stream-like object in the given slot. """ def mount( fsobj: "AbstractBlockDev", mount_point: str, /, *, readonly: bool = False ) -> IOBase | None: """ Mount the filesystem object *fsobj* at the location in the VFS given by the *mount_point* string. *fsobj* can be a a VFS object that has a ``mount()`` method, or a block device. If it's a block device then the filesystem type is automatically detected (an exception is raised if no filesystem was recognised). *mount_point* may be ``'/'`` to mount *fsobj* at the root, or ``'/'`` to mount it at a subdirectory under the root. If *readonly* is ``True`` then the filesystem is mounted read-only. During the mount process the method ``mount()`` is called on the filesystem object. Will raise ``OSError(EPERM)`` if *mount_point* is already mounted. Filesystem mounting ------------------- Some ports provide a Virtual Filesystem (VFS) and the ability to mount multiple "real" filesystems within this VFS. Filesystem objects can be mounted at either the root of the VFS, or at a subdirectory that lives in the root. This allows dynamic and flexible configuration of the filesystem that is seen by Python programs. Ports that have this functionality provide the :func:`mount` and :func:`umount` functions, and possibly various filesystem implementations represented by VFS classes. """ def umount(mount_point: str, /) -> None: """ Unmount a filesystem. *mount_point* can be a string naming the mount location, or a previously-mounted filesystem object. During the unmount process the method ``umount()`` is called on the filesystem object. Will raise ``OSError(EINVAL)`` if *mount_point* is not found. """ class VfsFat("AbstractBlockDev"): """ """ def __init__(self, block_dev: "AbstractBlockDev", /): """ Create a filesystem object that uses the FAT filesystem format. Storage of the FAT filesystem is provided by *block_dev*. Objects created by this constructor can be mounted using :func:`mount`. """ @staticmethod def mkfs(block_dev: "AbstractBlockDev", /) -> None: """ Build a FAT filesystem on *block_dev*. """ class VfsLfs1("AbstractBlockDev"): """ """ def __init__( self, block_dev: "AbstractBlockDev", readsize: int = 32, progsize: int = 32, lookahead: int = 32, /, ): """ Create a filesystem object that uses the `littlefs v1 filesystem format`_. Storage of the littlefs filesystem is provided by *block_dev*, which must support the :ref:`extended interface `. Objects created by this constructor can be mounted using :func:`mount`. See :ref:`filesystem` for more information. """ @staticmethod def mkfs( block_dev: "AbstractBlockDev", readsize: int = 32, progsize: int = 32, lookahead: int = 32, /, ) -> None: """ Build a Lfs1 filesystem on *block_dev*. .. note:: There are reports of littlefs v1 failing in certain situations, for details see `littlefs issue 347`_. """ class VfsLfs2("AbstractBlockDev"): """ """ def __init__( self, block_dev: "AbstractBlockDev", readsize: int = 32, progsize: int = 32, lookahead: int = 32, mtime: bool = True, /, ): """ Create a filesystem object that uses the `littlefs v2 filesystem format`_. Storage of the littlefs filesystem is provided by *block_dev*, which must support the :ref:`extended interface `. Objects created by this constructor can be mounted using :func:`mount`. The *mtime* argument enables modification timestamps for files, stored using littlefs attributes. This option can be disabled or enabled differently each mount time and timestamps will only be added or updated if *mtime* is enabled, otherwise the timestamps will remain untouched. Littlefs v2 filesystems without timestamps will work without reformatting and timestamps will be added transparently to existing files once they are opened for writing. When *mtime* is enabled `os.stat` on files without timestamps will return 0 for the timestamp. See :ref:`filesystem` for more information. """ @staticmethod def mkfs( block_dev: "AbstractBlockDev", readsize: int = 32, progsize: int = 32, lookahead: int = 32, mtime: bool = True, /, ) -> None: """ Build a Lfs2 filesystem on *block_dev*. .. note:: There are reports of littlefs v2 failing in certain situations, for details see `littlefs issue 295`_. """ @runtime_checkable class AbstractBlockDev(Protocol): """ Block devices ------------- A block device is an object which implements the block protocol. This enables a device to support MicroPython filesystems. The physical hardware is represented by a user defined class. The :class:`AbstractBlockDev` class is a template for the design of such a class: MicroPython does not actually provide that class, but an actual block device class must implement the methods described below. A concrete implementation of this class will usually allow access to the memory-like functionality of a piece of hardware (like flash memory). A block device can be formatted to any supported filesystem and mounted using ``os`` methods. See :ref:`filesystem` for example implementations of block devices using the two variants of the block protocol described below. .. _block-device-interface: Simple and extended interface ............................. There are two compatible signatures for the ``readblocks`` and ``writeblocks`` methods (see below), in order to support a variety of use cases. A given block device may implement one form or the other, or both at the same time. The second form (with the offset parameter) is referred to as the "extended interface". Some filesystems (such as littlefs) that require more control over write operations, for example writing to sub-block regions without erasing, may require that the block device supports the extended interface. """ def __init__(self): """ Construct a block device object. The parameters to the constructor are dependent on the specific block device. """ @overload def readblocks(self, block_num: int, buf: bytearray, /) -> None: """ The first form reads aligned, multiples of blocks. Starting at the block given by the index *block_num*, read blocks from the device into *buf* (an array of bytes). The number of blocks to read is given by the length of *buf*, which will be a multiple of the block size. The second form allows reading at arbitrary locations within a block, and arbitrary lengths. Starting at block index *block_num*, and byte offset within that block of *offset*, read bytes from the device into *buf* (an array of bytes). The number of bytes to read is given by the length of *buf*. """ @overload def readblocks(self, block_num: int, buf: bytearray, offset: int, /) -> None: """ The first form reads aligned, multiples of blocks. Starting at the block given by the index *block_num*, read blocks from the device into *buf* (an array of bytes). The number of blocks to read is given by the length of *buf*, which will be a multiple of the block size. The second form allows reading at arbitrary locations within a block, and arbitrary lengths. Starting at block index *block_num*, and byte offset within that block of *offset*, read bytes from the device into *buf* (an array of bytes). The number of bytes to read is given by the length of *buf*. """ @overload def writeblocks(self, block_num: int, buf: bytes | bytearray, /) -> None: """ The first form writes aligned, multiples of blocks, and requires that the blocks that are written to be first erased (if necessary) by this method. Starting at the block given by the index *block_num*, write blocks from *buf* (an array of bytes) to the device. The number of blocks to write is given by the length of *buf*, which will be a multiple of the block size. The second form allows writing at arbitrary locations within a block, and arbitrary lengths. Only the bytes being written should be changed, and the caller of this method must ensure that the relevant blocks are erased via a prior ``ioctl`` call. Starting at block index *block_num*, and byte offset within that block of *offset*, write bytes from *buf* (an array of bytes) to the device. The number of bytes to write is given by the length of *buf*. Note that implementations must never implicitly erase blocks if the offset argument is specified, even if it is zero. """ @overload def writeblocks( self, block_num: int, buf: bytes | bytearray, offset: int, / ) -> None: """ The first form writes aligned, multiples of blocks, and requires that the blocks that are written to be first erased (if necessary) by this method. Starting at the block given by the index *block_num*, write blocks from *buf* (an array of bytes) to the device. The number of blocks to write is given by the length of *buf*, which will be a multiple of the block size. The second form allows writing at arbitrary locations within a block, and arbitrary lengths. Only the bytes being written should be changed, and the caller of this method must ensure that the relevant blocks are erased via a prior ``ioctl`` call. Starting at block index *block_num*, and byte offset within that block of *offset*, write bytes from *buf* (an array of bytes) to the device. The number of bytes to write is given by the length of *buf*. Note that implementations must never implicitly erase blocks if the offset argument is specified, even if it is zero. """ @overload def ioctl(self, op: int, arg: int) -> int | None: """ Control the block device and query its parameters. The operation to perform is given by *op* which is one of the following integers: - 1 -- initialise the device (*arg* is unused) - 2 -- shutdown the device (*arg* is unused) - 3 -- sync the device (*arg* is unused) - 4 -- get a count of the number of blocks, should return an integer (*arg* is unused) - 5 -- get the number of bytes in a block, should return an integer, or ``None`` in which case the default value of 512 is used (*arg* is unused) - 6 -- erase a block, *arg* is the block number to erase As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs ``ioctl(6, ...)`` must also be intercepted. The need for others is hardware dependent. Prior to any call to ``writeblocks(block, ...)`` littlefs issues ``ioctl(6, block)``. This enables a device driver to erase the block prior to a write if the hardware requires it. Alternatively a driver might intercept ``ioctl(6, block)`` and return 0 (success). In this case the driver assumes responsibility for detecting the need for erasure. Unless otherwise stated ``ioctl(op, arg)`` can return ``None``. Consequently an implementation can ignore unused values of ``op``. Where ``op`` is intercepted, the return value for operations 4 and 5 are as detailed above. Other operations should return 0 on success and non-zero for failure, with the value returned being an ``OSError`` errno code. """ @overload def ioctl(self, op: Literal[4, 5], arg: int) -> int: """ Control the block device and query its parameters. The operation to perform is given by *op* which is one of the following integers: - 1 -- initialise the device (*arg* is unused) - 2 -- shutdown the device (*arg* is unused) - 3 -- sync the device (*arg* is unused) - 4 -- get a count of the number of blocks, should return an integer (*arg* is unused) - 5 -- get the number of bytes in a block, should return an integer, or ``None`` in which case the default value of 512 is used (*arg* is unused) - 6 -- erase a block, *arg* is the block number to erase As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs ``ioctl(6, ...)`` must also be intercepted. The need for others is hardware dependent. Prior to any call to ``writeblocks(block, ...)`` littlefs issues ``ioctl(6, block)``. This enables a device driver to erase the block prior to a write if the hardware requires it. Alternatively a driver might intercept ``ioctl(6, block)`` and return 0 (success). In this case the driver assumes responsibility for detecting the need for erasure. Unless otherwise stated ``ioctl(op, arg)`` can return ``None``. Consequently an implementation can ignore unused values of ``op``. Where ``op`` is intercepted, the return value for operations 4 and 5 are as detailed above. Other operations should return 0 on success and non-zero for failure, with the value returned being an ``OSError`` errno code. """ @overload def ioctl(self, op: Literal[1, 2, 3, 6], arg: int) -> int | None: """ Control the block device and query its parameters. The operation to perform is given by *op* which is one of the following integers: - 1 -- initialise the device (*arg* is unused) - 2 -- shutdown the device (*arg* is unused) - 3 -- sync the device (*arg* is unused) - 4 -- get a count of the number of blocks, should return an integer (*arg* is unused) - 5 -- get the number of bytes in a block, should return an integer, or ``None`` in which case the default value of 512 is used (*arg* is unused) - 6 -- erase a block, *arg* is the block number to erase As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs ``ioctl(6, ...)`` must also be intercepted. The need for others is hardware dependent. Prior to any call to ``writeblocks(block, ...)`` littlefs issues ``ioctl(6, block)``. This enables a device driver to erase the block prior to a write if the hardware requires it. Alternatively a driver might intercept ``ioctl(6, block)`` and return 0 (success). In this case the driver assumes responsibility for detecting the need for erasure. Unless otherwise stated ``ioctl(op, arg)`` can return ``None``. Consequently an implementation can ignore unused values of ``op``. Where ``op`` is intercepted, the return value for operations 4 and 5 are as detailed above. Other operations should return 0 on success and non-zero for failure, with the value returned being an ``OSError`` errno code. """ ================================================ FILE: typehints/stdlib/re.pyi ================================================ """ regular expressions. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/re.rst. ======================================= .. module:: re :synopsis: regular expressions |see_cpython_module| :mod:`python:re`. This module implements regular expression operations. Regular expression syntax supported is a subset of CPython ``re`` module (and actually is a subset of POSIX extended regular expressions). Supported operators and special sequences are: ``.`` Match any character. ``[...]`` Match set of characters. Individual characters and ranges are supported, including negated sets (e.g. ``[^a-c]``). ``^`` Match the start of the string. ``$`` Match the end of the string. ``?`` Match zero or one of the previous sub-pattern. ``*`` Match zero or more of the previous sub-pattern. ``+`` Match one or more of the previous sub-pattern. ``??`` Non-greedy version of ``?``, match zero or one, with the preference for zero. ``*?`` Non-greedy version of ``*``, match zero or more, with the preference for the shortest match. ``+?`` Non-greedy version of ``+``, match one or more, with the preference for the shortest match. ``|`` Match either the left-hand side or the right-hand side sub-patterns of this operator. ``(...)`` Grouping. Each group is capturing (a substring it captures can be accessed with `match.group()` method). ``\d`` Matches digit. Equivalent to ``[0-9]``. ``\D`` Matches non-digit. Equivalent to ``[^0-9]``. ``\s`` Matches whitespace. Equivalent to ``[ \t-\r]``. ``\S`` Matches non-whitespace. Equivalent to ``[^ \t-\r]``. ``\w`` Matches "word characters" (ASCII only). Equivalent to ``[A-Za-z0-9_]``. ``\W`` Matches non "word characters" (ASCII only). Equivalent to ``[^A-Za-z0-9_]``. ``\`` Escape character. Any other character following the backslash, except for those listed above, is taken literally. For example, ``\*`` is equivalent to literal ``*`` (not treated as the ``*`` operator). Note that ``\r``, ``\n``, etc. are not handled specially, and will be equivalent to literal letters ``r``, ``n``, etc. Due to this, it's not recommended to use raw Python strings (``r""``) for regular expressions. For example, ``r"\r\n"`` when used as the regular expression is equivalent to ``"rn"``. To match CR character followed by LF, use ``"\r\n"``. **NOT SUPPORTED**: * counted repetitions (``{m,n}``) * named groups (``(?P...)``) * non-capturing groups (``(?:...)``) * more advanced assertions (``\b``, ``\B``) * special character escapes like ``\r``, ``\n`` - use Python's own escaping instead * etc. Example:: import re # As re doesn't support escapes itself, use of r"" strings is not # recommended. regex = re.compile("[\r\n]") regex.split("line1\rline2\nline3\r\n") # Result: # ['line1', 'line2', 'line3', '', ''] """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import AnyStr, Callable, Generic, Final, Any _StrLike: Final = str | bytes def compile(regex_str: _StrLike, flags: int = ..., /) -> "ure": """ Compile regular expression, return `regex ` object. """ def match(regex_str: _StrLike, string: AnyStr, /) -> "Match[AnyStr]": """ Compile *regex_str* and match against *string*. Match always happens from starting position in a string. """ def search(regex_str: _StrLike, string: AnyStr, /) -> "Match[AnyStr]": """ Compile *regex_str* and search it in a *string*. Unlike `match`, this will search string for first position which matches regex (which still may be 0 if regex is anchored). """ def sub( regex_str: _StrLike, replace: AnyStr | Callable[["Match[AnyStr]"], AnyStr], string: AnyStr, count: int = 0, flags: int = 0, /, ) -> AnyStr: """ Compile *regex_str* and search for it in *string*, replacing all matches with *replace*, and returning the new string. *replace* can be a string or a function. If it is a string then escape sequences of the form ``\`` and ``\g`` can be used to expand to the corresponding group (or an empty string for unmatched groups). If *replace* is a function then it must take a single argument (the match) and should return a replacement string. If *count* is specified and non-zero then substitution will stop after this many substitutions are made. The *flags* argument is ignored. Note: availability of this function depends on :term:`MicroPython port`. """ DEBUG: Final[int] = ... """ Flag value, display debug information about compiled expression. (Availability depends on :term:`MicroPython port`.) """ # noinspection PyPep8Naming class ure: """ Compiled regular expression. Instances of this class are created using `re.compile()`. """ def match(self, string: AnyStr, /) -> "Match[AnyStr]": """ Similar to the module-level functions :meth:`match`, :meth:`search` and :meth:`sub`. Using methods is (much) more efficient if the same regex is applied to multiple strings. """ def search(self, string: AnyStr, /) -> "Match[AnyStr]": """ Similar to the module-level functions :meth:`match`, :meth:`search` and :meth:`sub`. Using methods is (much) more efficient if the same regex is applied to multiple strings. """ def sub( self, replace: AnyStr | Callable[["Match[AnyStr]"], AnyStr], string: AnyStr, count: int = 0, flags: int = 0, /, ) -> AnyStr: """ Similar to the module-level functions :meth:`match`, :meth:`search` and :meth:`sub`. Using methods is (much) more efficient if the same regex is applied to multiple strings. """ def split(self, string: AnyStr, max_split: int = -1, /) -> list[AnyStr]: """ Split a *string* using regex. If *max_split* is given, it specifies maximum number of splits to perform. Returns list of strings (there may be up to *max_split+1* elements if it's specified). """ class Match(Generic[AnyStr]): """ Match objects as returned by `match()` and `search()` methods, and passed to the replacement function in `sub()`. The name, `Match`, used for typing is not the same as the runtime name, `match` (note lowercase `m`). The reason for this difference is that the runtime uses `match` as both a class name and as a method name and this is not possible within code written entirely in Python and therefore not possible within typing code. """ def group(self, index: int, /) -> AnyStr: """ Return matching (sub)string. *index* is 0 for entire match, 1 and above for each capturing group. Only numeric groups are supported. """ def groups(self) -> tuple[AnyStr | Any, ...]: """ Return a tuple containing all the substrings of the groups of the match. Note: availability of this method depends on :term:`MicroPython port`. """ def start(self, index: int = ..., /) -> int: """ Return the index in the original string of the start or end of the substring group that was matched. *index* defaults to the entire group, otherwise it will select a group. Note: availability of these methods depends on :term:`MicroPython port`. """ def end(self, index: int = ..., /) -> int: """ Return the index in the original string of the start or end of the substring group that was matched. *index* defaults to the entire group, otherwise it will select a group. Note: availability of these methods depends on :term:`MicroPython port`. """ def span(self, index: int = ..., /) -> tuple[int, int]: """ Returns the 2-tuple ``(match.start(index), match.end(index))``. Note: availability of this method depends on :term:`MicroPython port`. """ ================================================ FILE: typehints/stdlib/select.pyi ================================================ """ wait for events on a set of streams. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/select.rst. ==================================================== .. module:: select :synopsis: wait for events on a set of streams |see_cpython_module| :mod:`python:select`. This module provides functions to efficiently wait for events on multiple `streams ` (select streams which are ready for operations). """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Iterable, Any, Final, Iterator from uio import IOBase POLLIN: Final[int] = ... """Data available for reading.""" POLLOUT: Final[int] = ... """More data can be written.""" POLLHUP: Final[int] = ... """Socket is no longer connected.""" POLLERR: Final[int] = ... """Socket got an asynchronous error.""" def poll() -> "Poll": """ Create an instance of the Poll class. """ def select( rlist: Iterable[Any], wlist: Iterable[Any], xlist: Iterable[Any], timeout: int = -1, /, ) -> list[tuple[Any, int, Any, ...]]: """ Wait for activity on a set of objects. This function is provided by some MicroPython ports for compatibility and is not efficient. Usage of :class:`Poll` is recommended instead. """ class Poll: """ The name, `Poll`, used for typing is not the same as the runtime name, `poll` (note lowercase `p`). The reason for this difference is that the runtime uses `poll` as both a class name and as a method name and this is not possible within code written entirely in Python and therefore not possible within typing code. """ def register(self, obj: IOBase, eventmask: int = POLLIN | POLLOUT, /) -> None: """ Register `stream` *obj* for polling. *eventmask* is logical OR of: * ``select.POLLIN`` - data available for reading * ``select.POLLOUT`` - more data can be written Note that flags like ``select.POLLHUP`` and ``select.POLLERR`` are *not* valid as input eventmask (these are unsolicited events which will be returned from `poll()` regardless of whether they are asked for). This semantics is per POSIX. *eventmask* defaults to ``select.POLLIN | select.POLLOUT``. It is OK to call this function multiple times for the same *obj*. Successive calls will update *obj*'s eventmask to the value of *eventmask* (i.e. will behave as `modify()`). """ def unregister(self, obj: IOBase, /) -> None: """ Unregister *obj* from polling. """ def modify(self, obj: IOBase, eventmask: int, /) -> None: """ Modify the *eventmask* for *obj*. If *obj* is not registered, `OSError` is raised with error of ENOENT. """ def poll(self, timeout: int = -1, /) -> list[tuple[Any, int, Any, ...]]: """ Wait for at least one of the registered objects to become ready or have an exceptional condition, with optional timeout in milliseconds (if *timeout* arg is not specified or -1, there is no timeout). Returns list of (``obj``, ``event``, ...) tuples. There may be other elements in tuple, depending on a platform and version, so don't assume that its size is 2. The ``event`` element specifies which events happened with a stream and is a combination of ``select.POLL*`` constants described above. Note that flags ``select.POLLHUP`` and ``select.POLLERR`` can be returned at any time (even if were not asked for), and must be acted on accordingly (the corresponding stream unregistered from poll and likely closed), because otherwise all further invocations of `poll()` may return immediately with these flags set for this stream again. In case of timeout, an empty list is returned. .. admonition:: Difference to CPython :class: attention Tuples returned may contain more than 2 elements as described above. """ def ipoll( self, timeout: int = -1, flags: int = 0, / ) -> Iterator[tuple[Any, int, Any, ...]]: """ Like :meth:`poll.poll`, but instead returns an iterator which yields a `callee-owned tuple`. This function provides an efficient, allocation-free way to poll on streams. If *flags* is 1, one-shot behaviour for events is employed: streams for which events happened will have their event masks automatically reset (equivalent to ``poll.modify(obj, 0)``), so new events for such a stream won't be processed until new mask is set with `poll.modify()`. This behaviour is useful for asynchronous I/O schedulers. .. admonition:: Difference to CPython :class: attention This function is a MicroPython extension. """ ================================================ FILE: typehints/stdlib/socket.pyi ================================================ """ socket. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/socket.rst. ****************************** .. module:: socket :synopsis: socket module |see_cpython_module| :mod:`python:socket`. This module provides access to the BSD socket interface. .. admonition:: Difference to CPython :class: attention For efficiency and consistency, socket objects in MicroPython implement a `stream` (file-like) interface directly. In CPython, you need to convert a socket to a file-like object using `makefile()` method. This method is still supported by MicroPython (but is a no-op), so where compatibility with CPython matters, be sure to use it. Socket address format(s) ------------------------ The native socket address format of the ``socket`` module is an opaque data type returned by `getaddrinfo` function, which must be used to resolve textual address (including numeric addresses):: sockaddr = socket.getaddrinfo('www.micropython.org', 80)[0][-1] # You must use getaddrinfo() even for numeric addresses sockaddr = socket.getaddrinfo('127.0.0.1', 80)[0][-1] # Now you can use that address sock.connect(addr) Using `getaddrinfo` is the most efficient (both in terms of memory and processing power) and portable way to work with addresses. However, ``socket`` module (note the difference with native MicroPython ``socket`` module described here) provides CPython-compatible way to specify addresses using tuples, as described below. Note that depending on a :term:`MicroPython port`, ``socket`` module can be builtin or need to be installed from `micropython-lib` (as in the case of :term:`MicroPython Unix port`), and some ports still accept only numeric addresses in the tuple format, and require to use `getaddrinfo` function to resolve domain names. Summing up: * Always use `getaddrinfo` when writing portable applications. * Tuple addresses described below can be used as a shortcut for quick hacks and interactive use, if your port supports them. Tuple address format for ``socket`` module: * IPv4: *(ipv4_address, port)*, where *ipv4_address* is a string with dot-notation numeric IPv4 address, e.g. ``"8.8.8.8"``, and *port* is and integer port number in the range 1-65535. Note the domain names are not accepted as *ipv4_address*, they should be resolved first using `socket.getaddrinfo()`. * IPv6: *(ipv6_address, port, flowinfo, scopeid)*, where *ipv6_address* is a string with colon-notation numeric IPv6 address, e.g. ``"2001:db8::1"``, and *port* is an integer port number in the range 1-65535. *flowinfo* must be 0. *scopeid* is the interface scope identifier for link-local addresses. Note the domain names are not accepted as *ipv6_address*, they should be resolved first using `socket.getaddrinfo()`. Availability of IPv6 support depends on a :term:`MicroPython port`. .. exception:: socket.error MicroPython does NOT have this exception. .. admonition:: Difference to CPython :class: attention CPython used to have a ``socket.error`` exception which is now deprecated, and is an alias of `OSError`. In MicroPython, use `OSError` directly. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Final, Any, Literal, overload from uio import AnyReadableBuf, AnyWritableBuf _Address: Final = tuple[str, int] | tuple[str, int, int, int] | str def socket( af: int = "AF_INET", type: int = "SOCK_STREAM", proto: int = "IPPROTO_TCP", /, ) -> "Socket": """ Create a new socket using the given address family, socket type and protocol number. Note that specifying *proto* in most cases is not required (and not recommended, as some MicroPython ports may omit ``IPPROTO_*`` constants). Instead, *type* argument will select needed protocol automatically:: # Create STREAM TCP socket socket(AF_INET, SOCK_STREAM) # Create DGRAM UDP socket socket(AF_INET, SOCK_DGRAM) """ def getaddrinfo( host: str, port: int, af: int = 0, type: int = 0, proto: int = 0, flags: int = 0, /, ) -> list[tuple[int, int, int, str, tuple[str, int] | tuple[str, int, int, int]]]: """ Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. Arguments *af*, *type*, and *proto* (which have the same meaning as for the `socket()` function) can be used to filter which kind of addresses are returned. If a parameter is not specified or zero, all combinations of addresses can be returned (requiring filtering on the user side). The resulting list of 5-tuples has the following structure:: (family, type, proto, canonname, sockaddr) The following example shows how to connect to a given url:: s = socket.socket() # This assumes that if "type" is not specified, an address for # SOCK_STREAM will be returned, which may be not true s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][-1]) Recommended use of filtering params:: s = socket.socket() # Guaranteed to return an address which can be connect'ed to for # stream operation. s.connect(socket.getaddrinfo('www.micropython.org', 80, 0, SOCK_STREAM)[0][-1]) .. admonition:: Difference to CPython :class: attention CPython raises a ``socket.gaierror`` exception (`OSError` subclass) in case of error in this function. MicroPython doesn't have ``socket.gaierror`` and raises OSError directly. Note that error numbers of `getaddrinfo()` form a separate namespace and may not match error numbers from the :mod:`errno` module. To distinguish `getaddrinfo()` errors, they are represented by negative numbers, whereas standard system errors are positive numbers (error numbers are accessible using ``e.args[0]`` property from an exception object). The use of negative values is a provisional detail which may change in the future. """ def inet_ntop(af: int, bin_addr: bytes, /) -> str: """ Convert a binary network address *bin_addr* of the given address family *af* to a textual representation:: >>> socket.inet_ntop(socket.AF_INET, b"\x7f\0\0\1") '127.0.0.1' """ def inet_pton(af: int, txt_addr: str, /) -> bytes: """ Convert a textual network address *txt_addr* of the given address family *af* to a binary representation:: >>> socket.inet_pton(socket.AF_INET, "1.2.3.4") b'\x01\x02\x03\x04' """ AF_INET: Final[int] = ... """ Address family types. Availability depends on a particular :term:`MicroPython port`. """ AF_INET6: Final[int] = ... """ Address family types. Availability depends on a particular :term:`MicroPython port`. """ SOCK_STREAM: Final[int] = ... """ Socket types. """ SOCK_DGRAM: Final[int] = ... """ Socket types. """ IPPROTO_UDP: Final[int] = ... """ IP protocol numbers. Availability depends on a particular :term:`MicroPython port`. Note that you don't need to specify these in a call to `socket.socket()`, because `SOCK_STREAM` socket type automatically selects `IPPROTO_TCP`, and `SOCK_DGRAM` - `IPPROTO_UDP`. Thus, the only real use of these constants is as an argument to `setsockopt()`. """ IPPROTO_TCP: Final[int] = ... """ IP protocol numbers. Availability depends on a particular :term:`MicroPython port`. Note that you don't need to specify these in a call to `socket.socket()`, because `SOCK_STREAM` socket type automatically selects `IPPROTO_TCP`, and `SOCK_DGRAM` - `IPPROTO_UDP`. Thus, the only real use of these constants is as an argument to `setsockopt()`. """ SOL_SOCKET: Final[int] = ... """ Socket option levels (an argument to `setsockopt()`). The exact inventory depends on a :term:`MicroPython port`. """ SO_REUSEADDR: Final[int] = ... """ Socket options (an argument to `setsockopt()`). The exact inventory depends on a :term:`MicroPython port`. """ IPPROTO_SEC: Final[int] = ... """ Special protocol value to create SSL-compatible socket. Constants specific to WiPy: """ class Socket: """ A unix like socket, for more information see module ``socket``'s description. The name, `Socket`, used for typing is not the same as the runtime name, `socket` (note lowercase `s`). The reason for this difference is that the runtime uses `socket` as both a class name and as a method name and this is not possible within code written entirely in Python and therefore not possible within typing code. """ def close(self) -> None: """ Mark the socket closed and release all resources. Once that happens, all future operations on the socket object will fail. The remote end will receive EOF indication if supported by protocol. Sockets are automatically closed when they are garbage-collected, but it is recommended to `close()` them explicitly as soon you finished working with them. """ def bind(self, address: _Address | bytes, /) -> None: """ Bind the socket to *address*. The socket must not already be bound. """ def listen(self, backlog: int = ..., /) -> None: """ Enable a server to accept connections. If *backlog* is specified, it must be at least 0 (if it's lower, it will be set to 0); and specifies the number of unaccepted connections that the system will allow before refusing new connections. If not specified, a default reasonable value is chosen. """ def accept(self) -> None: """ Accept a connection. The socket must be bound to an address and listening for connections. The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection. """ def connect(self, address: _Address | bytes, /) -> None: """ Connect to a remote socket at *address*. """ def send(self, bytes: AnyReadableBuf, /) -> int: """ Send data to the socket. The socket must be connected to a remote socket. Returns number of bytes sent, which may be smaller than the length of data ("short write"). """ def sendall(self, bytes: AnyReadableBuf, /) -> None: """ Send all data to the socket. The socket must be connected to a remote socket. Unlike `send()`, this method will try to send all of data, by sending data chunk by chunk consecutively. The behaviour of this method on non-blocking sockets is undefined. Due to this, on MicroPython, it's recommended to use `write()` method instead, which has the same "no short writes" policy for blocking sockets, and will return number of bytes sent on non-blocking sockets. """ def recv(self, bufsize: int, /) -> bytes: """ Receive data from the socket. The return value is a bytes object representing the data received. The maximum amount of data to be received at once is specified by bufsize. """ def sendto(self, bytes: AnyReadableBuf, address: _Address, /) -> int: """ Send data to the socket. The socket should not be connected to a remote socket, since the destination socket is specified by *address*. """ def recvfrom(self, bufsize: int, /) -> tuple[bytes, Any]: """ Receive data from the socket. The return value is a pair *(bytes, address)* where *bytes* is a bytes object representing the data received and *address* is the address of the socket sending the data. """ def setsockopt( self, level: int, optname: int, value: AnyReadableBuf | int, / ) -> None: """ Set the value of the given socket option. The needed symbolic constants are defined in the socket module (SO_* etc.). The *value* can be an integer or a bytes-like object representing a buffer. """ def settimeout(self, value: float | None, /) -> None: """ **Note**: Not every port supports this method, see below. Set a timeout on blocking socket operations. The value argument can be a nonnegative floating point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations will raise an `OSError` exception if the timeout period value has elapsed before the operation has completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket is put in blocking mode. Not every :term:`MicroPython port` supports this method. A more portable and generic solution is to use `select.poll` object. This allows to wait on multiple objects at the same time (and not just on sockets, but on generic `stream` objects which support polling). Example:: # Instead of: s.settimeout(1.0) # time in seconds s.read(10) # may timeout # Use: poller = select.poll() poller.register(s, select.POLLIN) res = poller.poll(1000) # time in milliseconds if not res: # s is still not ready for input, i.e. operation timed out .. admonition:: Difference to CPython :class: attention CPython raises a ``socket.timeout`` exception in case of timeout, which is an `OSError` subclass. MicroPython raises an OSError directly instead. If you use ``except OSError:`` to catch the exception, your code will work both in MicroPython and CPython. """ def setblocking(self, value: bool, /) -> None: """ Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking, else to blocking mode. This method is a shorthand for certain `settimeout()` calls: * ``sock.setblocking(True)`` is equivalent to ``sock.settimeout(None)`` * ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0)`` """ @overload def makefile( self, mode: Literal["rb", "wb", "rwb"] = "rb", buffering: int = 0, / ) -> Socket: """ Return a file object associated with the socket. The exact returned type depends on the arguments given to makefile(). The support is limited to binary modes only ('rb', 'wb', and 'rwb'). CPython's arguments: *encoding*, *errors* and *newline* are not supported. .. admonition:: Difference to CPython :class: attention As MicroPython doesn't support buffered streams, values of *buffering* parameter is ignored and treated as if it was 0 (unbuffered). .. admonition:: Difference to CPython :class: attention Closing the file object returned by makefile() WILL close the original socket as well. """ @overload def makefile(self, mode: str, buffering: int = 0, /) -> Socket: """ Return a file object associated with the socket. The exact returned type depends on the arguments given to makefile(). The support is limited to binary modes only ('rb', 'wb', and 'rwb'). CPython's arguments: *encoding*, *errors* and *newline* are not supported. .. admonition:: Difference to CPython :class: attention As MicroPython doesn't support buffered streams, values of *buffering* parameter is ignored and treated as if it was 0 (unbuffered). .. admonition:: Difference to CPython :class: attention Closing the file object returned by makefile() WILL close the original socket as well. """ @overload def read(self) -> bytes: """ Read up to size bytes from the socket. Return a bytes object. If *size* is not given, it reads all data available from the socket until EOF; as such the method will not return until the socket is closed. This function tries to read as much data as requested (no "short reads"). This may be not possible with non-blocking socket though, and then less data will be returned. """ @overload def read(self, size: int, /) -> bytes: """ Read up to size bytes from the socket. Return a bytes object. If *size* is not given, it reads all data available from the socket until EOF; as such the method will not return until the socket is closed. This function tries to read as much data as requested (no "short reads"). This may be not possible with non-blocking socket though, and then less data will be returned. """ @overload def readinto(self, buf: AnyWritableBuf, /) -> int | None: """ Read bytes into the *buf*. If *nbytes* is specified then read at most that many bytes. Otherwise, read at most *len(buf)* bytes. Just as `read()`, this method follows "no short reads" policy. Return value: number of bytes read and stored into *buf*. """ @overload def readinto(self, buf: AnyWritableBuf, nbytes: int, /) -> int | None: """ Read bytes into the *buf*. If *nbytes* is specified then read at most that many bytes. Otherwise, read at most *len(buf)* bytes. Just as `read()`, this method follows "no short reads" policy. Return value: number of bytes read and stored into *buf*. """ def readline(self) -> bytes: """ Read a line, ending in a newline character. Return value: the line read. """ def write(self, buf: AnyReadableBuf, /) -> int | None: """ Write the buffer of bytes to the socket. This function will try to write all data to a socket (no "short writes"). This may be not possible with a non-blocking socket though, and returned value will be less than the length of *buf*. Return value: number of bytes written. """ ================================================ FILE: typehints/stdlib/ssl.pyi ================================================ """ TLS/SSL wrapper for socket objects. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/ssl.rst. |see_cpython_module| :mod:`python:ssl`. This module provides access to Transport Layer Security (previously and widely known as “Secure Sockets Layer”) encryption and peer authentication facilities for network sockets, both client-side and server-side. .. admonition:: Difference to CPython :class: attention The CPython version of ``ssl`` uses ``SSLError``. This exception does NOT exist. Instead its base class, OSError, is used. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Final from uio import StrOrBytesPath from usocket import Socket def wrap_socket( sock: Socket, server_side: bool = False, keyfile: StrOrBytesPath | None = None, certfile: StrOrBytesPath | None = None, cert_reqs: int = "CERT_NONE", ca_certs: str | None = None, do_handshake: bool = True, /, ) -> Socket: """ Takes a `stream` *sock* (usually socket.socket instance of ``SOCK_STREAM`` type), and returns an instance of ssl.SSLSocket, which wraps the underlying stream in an SSL context. Returned object has the usual `stream` interface methods like ``read()``, ``write()``, etc. A server-side SSL socket should be created from a normal socket returned from :meth:`~socket.socket.accept()` on a non-SSL listening server socket. - *do_handshake* determines whether the handshake is done as part of the ``wrap_socket`` or whether it is deferred to be done as part of the initial reads or writes (there is no ``do_handshake`` method as in CPython). For blocking sockets doing the handshake immediately is standard. For non-blocking sockets (i.e. when the *sock* passed into ``wrap_socket`` is in non-blocking mode) the handshake should generally be deferred because otherwise ``wrap_socket`` blocks until it completes. Note that in AXTLS the handshake can be deferred until the first read or write but it then blocks until completion. Depending on the underlying module implementation in a particular :term:`MicroPython port`, some or all keyword arguments above may be not supported. """ CERT_NONE: Final[int] = ... """ Supported values for *cert_reqs* parameter. """ CERT_OPTIONAL: Final[int] = ... """ Supported values for *cert_reqs* parameter. """ CERT_REQUIRED: Final[int] = ... """ Supported values for *cert_reqs* parameter. """ ================================================ FILE: typehints/stdlib/struct.pyi ================================================ """ pack and unpack primitive data types. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/struct.rst. ===================================================== .. module:: struct :synopsis: pack and unpack primitive data types |see_cpython_module| :mod:`python:struct`. Supported size/byte order prefixes: ``@``, ``<``, ``>``, ``!``. Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``, ``L``, ``q``, ``Q``, ``s``, ``P``, ``f``, ``d`` (the latter 2 depending on the floating-point support). .. admonition:: Difference to CPython :class: attention Whitespace is not supported in format strings. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Any from uio import AnyReadableBuf, AnyWritableBuf def calcsize(fmt: str | bytes, /,) -> int: """ Return the number of bytes needed to store the given *fmt*. """ def pack(fmt: str | bytes, /, *v: Any) -> bytes: """ Pack the values *v1*, *v2*, ... according to the format string *fmt*. The return value is a bytes object encoding the values. """ def pack_into( fmt: str | bytes, buffer: AnyWritableBuf, offset: int, /, *v: Any ) -> None: """ Pack the values *v1*, *v2*, ... according to the format string *fmt* into a *buffer* starting at *offset*. *offset* may be negative to count from the end of *buffer*. """ def unpack(fmt: str | bytes, data: AnyReadableBuf, /) -> tuple[Any, ...]: """ Unpack from the *data* according to the format string *fmt*. The return value is a tuple of the unpacked values. """ def unpack_from( fmt: str | bytes, data: AnyReadableBuf, offset: int = 0, / ) -> tuple[Any, ...]: """ Unpack from the *data* starting at *offset* according to the format string *fmt*. *offset* may be negative to count from the end of *buffer*. The return value is a tuple of the unpacked values. """ ================================================ FILE: typehints/stdlib/sys.pyi ================================================ """ system specific functions. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/sys.rst. ======================================= .. module:: sys :synopsis: system specific functions |see_cpython_module| :mod:`python:sys`. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Callable, Final, Literal, NoReturn from uio import IOBase class Implementation(tuple[str, tuple[int, int, int], int]): name: str version: tuple[int, int, int] mpy: int class ModuleType: __class__: str __name__: str def exit(retval: object = 0, /) -> NoReturn: """ Terminate current program with a given exit code. Underlyingly, this function raise as `SystemExit` exception. If an argument is given, its value given as an argument to `SystemExit`. """ def atexit(func: Callable[[], None] | None, /) -> Callable[[], None] | None: """ Register *func* to be called upon termination. *func* must be a callable that takes no arguments, or ``None`` to disable the call. The ``atexit`` function will return the previous value set by this function, which is initially ``None``. .. admonition:: Difference to CPython :class: attention This function is a MicroPython extension intended to provide similar functionality to the :mod:`atexit` module in CPython. """ def print_exception(exc: BaseException, file: IOBase[str] = "stdout", /) -> None: """ Print exception with a traceback to a file-like object *file* (or `sys.stdout` by default). .. admonition:: Difference to CPython :class: attention This is simplified version of a function which appears in the ``traceback`` module in CPython. Unlike ``traceback.print_exception()``, this function takes just exception value instead of exception type, exception value, and traceback object; *file* argument should be positional; further arguments are not supported. CPython-compatible ``traceback`` module can be found in `micropython-lib`. """ argv: Final[list[str]] = ... """ A mutable list of arguments the current program was started with. """ byteorder: Final[Literal["little", "big"]] = ... """ The byte order of the system (``"little"`` or ``"big"``). """ implementation: Final[Implementation] = ... """ Object with information about the current Python implementation. For MicroPython, it has following attributes: * *name* - string "micropython" * *version* - tuple (major, minor, micro), e.g. (1, 7, 0) This object is the recommended way to distinguish MicroPython from other Python implementations (note that it still may not exist in the very minimal ports). .. admonition:: Difference to CPython :class: attention CPython mandates more attributes for this object, but the actual useful bare minimum is implemented in MicroPython. """ maxsize: Final[int] = ... """ Maximum value which a native integer type can hold on the current platform, or maximum value representable by MicroPython integer type, if it's smaller than platform max value (that is the case for MicroPython ports without long int support). This attribute is useful for detecting "bitness" of a platform (32-bit vs 64-bit, etc.). It's recommended to not compare this attribute to some value directly, but instead count number of bits in it:: bits = 0 v = sys.maxsize while v: bits += 1 v >>= 1 if bits > 32: # 64-bit (or more) platform ... else: # 32-bit (or less) platform # Note that on 32-bit platform, value of bits may be less than 32 # (e.g. 31) due to peculiarities described above, so use "> 16", # "> 32", "> 64" style of comparisons. """ modules: Final[dict[str, ModuleType]] = ... """ Dictionary of loaded modules. On some ports, it may not include builtin modules. """ path: Final[list[str]] = ... """ A mutable list of directories to search for imported modules. """ platform: Final[str] = ... """ The platform that MicroPython is running on. For OS/RTOS ports, this is usually an identifier of the OS, e.g. ``"linux"``. For baremetal ports it is an identifier of a board, e.g. ``"pyboard"`` for the original MicroPython reference board. It thus can be used to distinguish one board from another. If you need to check whether your program runs on MicroPython (vs other Python implementation), use `sys.implementation` instead. """ stderr: Final[IOBase[str]] = ... """ Standard error `stream`. """ stdin: Final[IOBase[str]] = ... """ Standard input `stream`. """ stdout: Final[IOBase[str]] = ... """ Standard output `stream`. """ version: Final[str] = ... """ Python language version that this implementation conforms to, as a string. """ version_info: Final[tuple[int, int, int]] = ... """ Python language version that this implementation conforms to, as a tuple of ints. .. admonition:: Difference to CPython :class: attention Only the first three version numbers (major, minor, micro) are supported and they can be referenced only by index, not by name. """ ================================================ FILE: typehints/stdlib/time.pyi ================================================ """ time related functions. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/time.rst. ===================================== .. module:: time :synopsis: time related functions |see_cpython_module| :mod:`python:time`. The ``time`` module provides functions for getting the current time and date, measuring time intervals, and for delays. **Time Epoch**: Unix port uses standard for POSIX systems epoch of 1970-01-01 00:00:00 UTC. However, embedded ports use epoch of 2000-01-01 00:00:00 UTC. **Maintaining actual calendar date/time**: This requires a Real Time Clock (RTC). On systems with underlying OS (including some RTOS), an RTC may be implicit. Setting and maintaining actual calendar time is responsibility of OS/RTOS and is done outside of MicroPython, it just uses OS API to query date/time. On baremetal ports however system time depends on ``machine.RTC()`` object. The current calendar time may be set using ``machine.RTC().datetime(tuple)`` function, and maintained by following means: * By a backup battery (which may be an additional, optional component for a particular board). * Using networked time protocol (requires setup by a port/user). * Set manually by a user on each power-up (many boards then maintain RTC time across hard resets, though some may require setting it again in such case). If actual calendar time is not maintained with a system/MicroPython RTC, functions below which require reference to current absolute time may behave not as expected. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Final, TypeVar class _TicksMs: ... class _TicksUs: ... class _TicksCPU: ... _Ticks: Final = TypeVar("_Ticks", _TicksMs, _TicksUs, _TicksCPU, int) def gmtime(secs: int | None = None, /) -> tuple[int, int, int, int, int, int, int, int]: """ Convert the time *secs* expressed in seconds since the Epoch (see above) into an 8-tuple which contains: ``(year, month, mday, hour, minute, second, weekday, yearday)`` If *secs* is not provided or None, then the current time from the RTC is used. The `gmtime()` function returns a date-time tuple in UTC, and `localtime()` returns a date-time tuple in local time. The format of the entries in the 8-tuple are: * year includes the century (for example 2014). * month is 1-12 * mday is 1-31 * hour is 0-23 * minute is 0-59 * second is 0-59 * weekday is 0-6 for Mon-Sun * yearday is 1-366 """ def localtime( secs: int | None = None, / ) -> tuple[int, int, int, int, int, int, int, int]: """ Convert the time *secs* expressed in seconds since the Epoch (see above) into an 8-tuple which contains: ``(year, month, mday, hour, minute, second, weekday, yearday)`` If *secs* is not provided or None, then the current time from the RTC is used. The `gmtime()` function returns a date-time tuple in UTC, and `localtime()` returns a date-time tuple in local time. The format of the entries in the 8-tuple are: * year includes the century (for example 2014). * month is 1-12 * mday is 1-31 * hour is 0-23 * minute is 0-59 * second is 0-59 * weekday is 0-6 for Mon-Sun * yearday is 1-366 """ def mktime(local_time: tuple[int, int, int, int, int, int, int, int], /) -> int: """ This is inverse function of localtime. It's argument is a full 8-tuple which expresses a time as per localtime. It returns an integer which is the number of seconds since Jan 1, 2000. """ def sleep(seconds: float, /) -> None: """ Sleep for the given number of seconds. Some boards may accept *seconds* as a floating-point number to sleep for a fractional number of seconds. Note that other boards may not accept a floating-point argument, for compatibility with them use `sleep_ms()` and `sleep_us()` functions. """ def sleep_ms(ms: int, /) -> None: """ Delay for given number of milliseconds, should be positive or 0. This function will delay for at least the given number of milliseconds, but may take longer than that if other processing must take place, for example interrupt handlers or other threads. Passing in 0 for *ms* will still allow this other processing to occur. Use `sleep_us()` for more precise delays. """ def sleep_us(us: int, /) -> None: """ Delay for given number of microseconds, should be positive or 0. This function attempts to provide an accurate delay of at least *us* microseconds, but it may take longer if the system has other higher priority processing to perform. """ def ticks_ms() -> _TicksMs: """ Returns an increasing millisecond counter with an arbitrary reference point, that wraps around after some value. The wrap-around value is not explicitly exposed, but we will refer to it as *TICKS_MAX* to simplify discussion. Period of the values is *TICKS_PERIOD = TICKS_MAX + 1*. *TICKS_PERIOD* is guaranteed to be a power of two, but otherwise may differ from port to port. The same period value is used for all of `ticks_ms()`, `ticks_us()`, `ticks_cpu()` functions (for simplicity). Thus, these functions will return a value in range [*0* .. *TICKS_MAX*], inclusive, total *TICKS_PERIOD* values. Note that only non-negative values are used. For the most part, you should treat values returned by these functions as opaque. The only operations available for them are `ticks_diff()` and `ticks_add()` functions described below. Note: Performing standard mathematical operations (+, -) or relational operators (<, <=, >, >=) directly on these value will lead to invalid result. Performing mathematical operations and then passing their results as arguments to `ticks_diff()` or `ticks_add()` will also lead to invalid results from the latter functions. """ def ticks_us() -> _TicksUs: """ Just like `ticks_ms()` above, but in microseconds. """ def ticks_cpu() -> _TicksCPU: """ Similar to `ticks_ms()` and `ticks_us()`, but with the highest possible resolution in the system. This is usually CPU clocks, and that's why the function is named that way. But it doesn't have to be a CPU clock, some other timing source available in a system (e.g. high-resolution timer) can be used instead. The exact timing unit (resolution) of this function is not specified on ``time`` module level, but documentation for a specific port may provide more specific information. This function is intended for very fine benchmarking or very tight real-time loops. Avoid using it in portable code. Availability: Not every port implements this function. """ def ticks_add(ticks: _Ticks, delta: int, /) -> _Ticks: """ Offset ticks value by a given number, which can be either positive or negative. Given a *ticks* value, this function allows to calculate ticks value *delta* ticks before or after it, following modular-arithmetic definition of tick values (see `ticks_ms()` above). *ticks* parameter must be a direct result of call to `ticks_ms()`, `ticks_us()`, or `ticks_cpu()` functions (or from previous call to `ticks_add()`). However, *delta* can be an arbitrary integer number or numeric expression. `ticks_add()` is useful for calculating deadlines for events/tasks. (Note: you must use `ticks_diff()` function to work with deadlines.) Examples:: # Find out what ticks value there was 100ms ago print(ticks_add(time.ticks_ms(), -100)) # Calculate deadline for operation and test for it deadline = ticks_add(time.ticks_ms(), 200) while ticks_diff(deadline, time.ticks_ms()) > 0: do_a_little_of_something() # Find out TICKS_MAX used by this port print(ticks_add(0, -1)) """ def ticks_diff(ticks1: _Ticks, ticks2: _Ticks, /) -> int: """ Measure ticks difference between values returned from `ticks_ms()`, `ticks_us()`, or `ticks_cpu()` functions, as a signed value which may wrap around. The argument order is the same as for subtraction operator, ``ticks_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``. However, values returned by `ticks_ms()`, etc. functions may wrap around, so directly using subtraction on them will produce incorrect result. That is why `ticks_diff()` is needed, it implements modular (or more specifically, ring) arithmetics to produce correct result even for wrap-around values (as long as they not too distant inbetween, see below). The function returns **signed** value in the range [*-TICKS_PERIOD/2* .. *TICKS_PERIOD/2-1*] (that's a typical range definition for two's-complement signed binary integers). If the result is negative, it means that *ticks1* occurred earlier in time than *ticks2*. Otherwise, it means that *ticks1* occurred after *ticks2*. This holds **only** if *ticks1* and *ticks2* are apart from each other for no more than *TICKS_PERIOD/2-1* ticks. If that does not hold, incorrect result will be returned. Specifically, if two tick values are apart for *TICKS_PERIOD/2-1* ticks, that value will be returned by the function. However, if *TICKS_PERIOD/2* of real-time ticks has passed between them, the function will return *-TICKS_PERIOD/2* instead, i.e. result value will wrap around to the negative range of possible values. Informal rationale of the constraints above: Suppose you are locked in a room with no means to monitor passing of time except a standard 12-notch clock. Then if you look at dial-plate now, and don't look again for another 13 hours (e.g., if you fall for a long sleep), then once you finally look again, it may seem to you that only 1 hour has passed. To avoid this mistake, just look at the clock regularly. Your application should do the same. "Too long sleep" metaphor also maps directly to application behaviour: don't let your application run any single task for too long. Run tasks in steps, and do time-keeping inbetween. `ticks_diff()` is designed to accommodate various usage patterns, among them: * Polling with timeout. In this case, the order of events is known, and you will deal only with positive results of `ticks_diff()`:: # Wait for GPIO pin to be asserted, but at most 500us start = time.ticks_us() while pin.value() == 0: if time.ticks_diff(time.ticks_us(), start) > 500: raise TimeoutError * Scheduling events. In this case, `ticks_diff()` result may be negative if an event is overdue:: # This code snippet is not optimized now = time.ticks_ms() scheduled_time = task.scheduled_time() if ticks_diff(scheduled_time, now) > 0: print("Too early, let's nap") sleep_ms(ticks_diff(scheduled_time, now)) task.run() elif ticks_diff(scheduled_time, now) == 0: print("Right at time!") task.run() elif ticks_diff(scheduled_time, now) < 0: print("Oops, running late, tell task to run faster!") task.run(run_faster=true) Note: Do not pass `time()` values to `ticks_diff()`, you should use normal mathematical operations on them. But note that `time()` may (and will) also overflow. This is known as https://en.wikipedia.org/wiki/Year_2038_problem . """ def time() -> int: """ Returns the number of seconds, as an integer, since the Epoch, assuming that underlying RTC is set and maintained as described above. If an RTC is not set, this function returns number of seconds since a port-specific reference point in time (for embedded boards without a battery-backed RTC, usually since power up or reset). If you want to develop portable MicroPython application, you should not rely on this function to provide higher than second precision. If you need higher precision, absolute timestamps, use `time_ns()`. If relative times are acceptable then use the `ticks_ms()` and `ticks_us()` functions. If you need calendar time, `gmtime()` or `localtime()` without an argument is a better choice. .. admonition:: Difference to CPython :class: attention In CPython, this function returns number of seconds since Unix epoch, 1970-01-01 00:00 UTC, as a floating-point, usually having microsecond precision. With MicroPython, only Unix port uses the same Epoch, and if floating-point precision allows, returns sub-second precision. Embedded hardware usually doesn't have floating-point precision to represent both long time ranges and subsecond precision, so they use integer value with second precision. Some embedded hardware also lacks battery-powered RTC, so returns number of seconds since last power-up or from other relative, hardware-specific point (e.g. reset). """ def time_ns() -> int: """ Similar to `time()` but returns nanoseconds since the Epoch, as an integer (usually a big integer, so will allocate on the heap). """ ================================================ FILE: typehints/stdlib/uarray.pyi ================================================ """ efficient arrays of numeric data. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/array.rst. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import ( overload, Sequence, Any, MutableSequence, Generic, Text, TypeVar, Final, ) _T: Final = TypeVar("_T", int, float, Text) # noinspection PyPep8Naming class array(MutableSequence[_T], Generic[_T]): """ |see_cpython_module| :mod:`python:array`. Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``, ``L``, ``q``, ``Q``, ``f``, ``d`` (the latter 2 depending on the floating-point support). +-----------+--------------------+-------------------+-----------------------+ | Type code | C Type | Python Type | Minimum size in bytes | +===========+====================+===================+=======================+ | ``'b'`` | signed char | int | 1 | +-----------+--------------------+-------------------+-----------------------+ | ``'B'`` | unsigned char | int | 1 | +-----------+--------------------+-------------------+-----------------------+ | ``'h'`` | signed short | int | 2 | +-----------+--------------------+-------------------+-----------------------+ | ``'H'`` | unsigned short | int | 2 | +-----------+--------------------+-------------------+-----------------------+ | ``'i'`` | signed int | int | 2 | +-----------+--------------------+-------------------+-----------------------+ | ``'I'`` | unsigned int | int | 2 | +-----------+--------------------+-------------------+-----------------------+ | ``'l'`` | signed long | int | 4 | +-----------+--------------------+-------------------+-----------------------+ | ``'L'`` | unsigned long | int | 4 | +-----------+--------------------+-------------------+-----------------------+ | ``'q'`` | signed long long | int | 8 | +-----------+--------------------+-------------------+-----------------------+ | ``'Q'`` | unsigned long long | int | 8 | +-----------+--------------------+-------------------+-----------------------+ | ``'f'`` | float | float | 4 | +-----------+--------------------+-------------------+-----------------------+ | ``'d'`` | double | float | 8 | +-----------+--------------------+-------------------+-----------------------+ """ def __init__(self, typecode: str, iterable: Sequence[Any] = ..., /): """ Create array with elements of given type. Initial contents of the array are given by *iterable*. If it is not provided, an empty array is created. """ def append(self, val: Any, /) -> None: """ Append new element *val* to the end of array, growing it. """ def extend(self, iterable: Sequence[Any], /) -> None: """ Append new elements as contained in *iterable* to the end of array, growing it. """ def decode(self, encoding: str = "utf-8", errors: str = "strict") -> str: """ Deprecated *do not use*, likely to be removed in future! Note: ``decode`` is only meant to be present for ``bytearray``, but for efficiency of code-size reasons ``bytearray`` is implemented with the same code as the other array type-codes and hence ``decode`` is on all ``array``s at present. """ @overload def __delitem__(self, i: int) -> None: """``array`` object does **not** support item deletion.""" @overload def __delitem__(self, sl: slice) -> None: """``array`` object does **not** support item deletion.""" def insert(self, index: int, value: _T) -> None: """``array`` object does **not** support item insertion.""" @overload def __getitem__(self, index: int) -> _T: """ Indexed read of ``self``; called as ``a[index]``, where ``a`` is an ``array``. Returns the value at the given ``index``. Negative indices count from end and ``IndexError``is thrown if the index out of range. **Note:** ``__getitem__`` cannot be called directly (``a.__getitem__(index)`` fails) and is not present in ``__dict__``, however ``a[index]`` does work. """ @overload def __getitem__(self, sl: slice) -> array[_T]: """ Slice read of ``self``; called as ``a[sl]``, where ``a`` is an ``array``. Returns an ``array`` of values for the given slice. Negative slice indices count from end and ``IndexError``is thrown if any of the slice indices are out of range. **Note:** ``__getitem__`` cannot be called directly (``a.__getitem__(sl)`` fails) and is not present in ``__dict__``, however ``a[sl]`` does work. """ @overload def __setitem__(self, index: int, value: _T) -> None: """ Indexed write into ``self``; called as ``a[index] = value`` where ``a`` is an ``array``, ``index`` is an ``int``, and ``value`` is the same type as ``a``'s content. Negative indices count from end and ``IndexError``is thrown if the index out of range. **Note:** ``__setitem__`` cannot be called directly (``a.__setitem__(index, value)`` fails) and is not present in ``__dict__``, however ``a[index] = value`` does work. """ @overload def __setitem__(self, sl: slice, values: array[_T]) -> None: """ Indexed write into ``self``; called as ``a[sl] = values``, where ``a`` is an ``array``, ``sl`` is an ``slice``, and ``values`` is the same type as ``a``. Negative indices count from end and ``IndexError``is thrown if any of the slice indices are out of range. **Note:** ``__setitem__`` cannot be called directly (``a.__setitem__(index, value)`` fails) and is not present in ``__dict__``, however ``a[index] = value`` does work. """ def __len__(self) -> int: """ Returns the number of items in ``self``; called as ``len(a)``, where ``a`` is an ``array``. **Note:** ``__len__`` cannot be called directly (``a.__len__()`` fails) and the method is not present in ``__dict__``, however ``len(a)`` does work. """ def __add__(self, other: array[_T]) -> array[_T]: """ Return a new ``array`` that is the concatenation of ``self`` with ``other``; called as ``a + other`` (where ``a`` and ``other`` are both ``array``s). **Note:** ``__add__`` cannot be called directly (``a.__add__(other)`` fails) and is not present in ``__dict__``, however ``a + other`` does work. """ def __iadd__(self, other: array[_T]) -> None: """ Concatenates ``self`` with ``other`` in-place; called as ``a += other``, where ``a`` and ``other`` are both ``array``s. Equivalent to ``extend(other)``. **Note:** ``__iadd__`` cannot be called directly (``a.__iadd__(other)`` fails) and is not present in ``__dict__``, however ``a += other`` does work. """ def __repr__(self) -> str: """ Returns the string representation of ``self``; called as ``str(a)`` or ``repr(a)```, where ``a`` is an ``array``. Returns the string 'array(, [])', where ```` is the type code letter for ``self`` and ```` is a comma separated list of the elements of ``self``. **Note:** ``__repr__`` cannot be called directly (``a.__repr__()`` fails) and is not present in ``__dict__``, however ``str(a)`` and ``repr(a)`` both work. """ ================================================ FILE: typehints/stdlib/uasyncio.pyi ================================================ """ asynchronous I/O scheduler for writing concurrent code. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/uasyncio.rst. |see_cpython_module| `asyncio `_ Example:: import uasyncio async def blink(led, period_ms): while True: led.on() await uasyncio.sleep_ms(5) led.off() await uasyncio.sleep_ms(period_ms) async def main(led1, led2): uasyncio.create_task(blink(led1, 700)) uasyncio.create_task(blink(led2, 400)) await uasyncio.sleep_ms(10_000) # Running on a pyboard from pyb import LED uasyncio.run(main(LED(1), LED(2))) # Running on a generic board from machine import Pin uasyncio.run(main(Pin(1), Pin(2))) """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from abc import ABC from typing import Awaitable, TypeVar, Callable from typing import Coroutine, Any, Dict, Iterable, Generic, Final from uio import AnyReadableBuf _T: Final = TypeVar("_T") # `Coroutine` `_T` is covariant and `Awaitable` `_T` is invariant. _C: Final = Coroutine[Any, None, _T] | Awaitable[_T] def create_task(coro: _C, /) -> Task[_T]: """ Create a new task from the given coroutine and schedule it to run. Returns the corresponding `Task` object. """ def current_task() -> Task[Any] | None: """ Return the `Task` object associated with the currently running task. """ def run(coro: _C, /) -> _T: """ Create a new task from the given coroutine and run it until it completes. Returns the value returned by *coro*. """ def sleep(t: float) -> Awaitable[None]: """ Sleep for *t* seconds (can be a float). This is a coroutine. """ def sleep_ms(t: int, /) -> Awaitable[None]: """ Sleep for *t* milliseconds. This is a coroutine, and a MicroPython extension. """ def wait_for(awaitable: Awaitable[_T], timeout: float, /) -> Awaitable[_T]: """ Wait for the *awaitable* to complete, but cancel it if it takes longer that *timeout* seconds. If *awaitable* is not a task then a task will be created from it. If a timeout occurs, it cancels the task and raises ``asyncio.TimeoutError``: this should be trapped by the caller. Returns the return value of *awaitable*. This is a coroutine. """ def wait_for_ms(awaitable: Awaitable[_T], timeout: int, /) -> Awaitable[_T]: """ Similar to `wait_for` but *timeout* is an integer in milliseconds. This is a coroutine, and a MicroPython extension. """ def gather( *awaitable: Awaitable[Any], return_exceptions: bool = False ) -> Awaitable[list[Any]]: """ Run all *awaitables* concurrently. Any *awaitables* that are not tasks are promoted to tasks. Returns a list of return values of all *awaitables*. This is a coroutine. """ StreamReader = "Stream" StreamWriter = "Stream" def open_connection( host: str | None, port: str | int | None, /, ) -> Awaitable[tuple[StreamReader, StreamWriter]]: """ Open a TCP connection to the given *host* and *port*. The *host* address will be resolved using `socket.getaddrinfo`, which is currently a blocking call. Returns a pair of streams: a reader and a writer stream. Will raise a socket-specific ``OSError`` if the host could not be resolved or if the connection could not be made. This is a coroutine. """ def start_server( callback: Callable[[StreamReader, StreamWriter], None], host: str | None, port: str | int | None, backlog: int = 5, /, ) -> Awaitable[Server]: """ Start a TCP server on the given *host* and *port*. The *callback* will be called with incoming, accepted connections, and be passed 2 arguments: reader and writer streams for the connection. Returns a `Server` object. This is a coroutine. """ def get_event_loop() -> Loop: """ Return the event loop used to schedule and run tasks. See `Loop`. """ def new_event_loop() -> Loop: """ Reset the event loop and return it. Note: since MicroPython only has a single event loop this function just resets the loop's state, it does not create a new one. """ class Task(Awaitable[_T], Iterable[_T], Generic[_T], ABC): """ class Task ---------- """ def __init__(self): """ This object wraps a coroutine into a running task. Tasks can be waited on using ``await task``, which will wait for the task to complete and return the return value of the task. Tasks should not be created directly, rather use `create_task` to create them. """ def cancel(self) -> None: """ Cancel the task by injecting a ``CancelledError`` into it. The task may or may not ignore this exception. """ class Event: """ class Event ----------- """ def __init__(self): """ Create a new event which can be used to synchronise tasks. Events start in the cleared state. """ def is_set(self) -> bool: """ Returns ``True`` if the event is set, ``False`` otherwise. """ def set(self) -> None: """ Set the event. Any tasks waiting on the event will be scheduled to run. Note: This must be called from within a task. It is not safe to call this from an IRQ, scheduler callback, or other thread. See `ThreadSafeFlag`. """ def clear(self) -> None: """ Clear the event. """ def wait(self) -> Awaitable[Any]: """ Wait for the event to be set. If the event is already set then it returns immediately. This is a coroutine. """ class ThreadSafeFlag: """ class ThreadSafeFlag -------------------- """ def __init__(self): """ Create a new flag which can be used to synchronise a task with code running outside the asyncio loop, such as other threads, IRQs, or scheduler callbacks. Flags start in the cleared state. """ def set(self) -> None: """ Set the flag. If there is a task waiting on the event, it will be scheduled to run. """ def wait(self) -> Awaitable[None]: """ Wait for the flag to be set. If the flag is already set then it returns immediately. A flag may only be waited on by a single task at a time. This is a coroutine. """ class Lock(Awaitable[None], ABC): """ class Lock ---------- """ def __init__(self): """ Create a new lock which can be used to coordinate tasks. Locks start in the unlocked state. In addition to the methods below, locks can be used in an ``async with`` statement. """ def locked(self) -> bool: """ Returns ``True`` if the lock is locked, otherwise ``False``. """ def acquire(self) -> Awaitable[None]: """ Wait for the lock to be in the unlocked state and then lock it in an atomic way. Only one task can acquire the lock at any one time. This is a coroutine. """ def release(self) -> None: """ Release the lock. If any tasks are waiting on the lock then the next one in the queue is scheduled to run and the lock remains locked. Otherwise, no tasks are waiting an the lock becomes unlocked. """ class Stream: """ """ def __init__(self): """ This represents a TCP stream connection. To minimise code this class implements both a reader and a writer, and both ``StreamReader`` and ``StreamWriter`` alias to this class. """ def get_extra_info(self, v: str, /) -> str: """ Get extra information about the stream, given by *v*. The valid values for *v* are: ``peername``. """ def close(self) -> None: """ Close the stream. """ def wait_close(self) -> Awaitable[None]: """ Wait for the stream to close. This is a coroutine. """ def read(self, n: int, /) -> Awaitable[bytes]: """ Read up to *n* bytes and return them. This is a coroutine. """ def readline(self) -> Awaitable[bytes]: """ Read a line and return it. This is a coroutine. """ def write(self, buf: AnyReadableBuf, /) -> None: """ Accumulated *buf* to the output buffer. The data is only flushed when `Stream.drain` is called. It is recommended to call `Stream.drain` immediately after calling this function. """ def drain(self) -> Awaitable[None]: """ Drain (write) all buffered output data out to the stream. This is a coroutine. """ class Server: """ """ def __init__(self): """ This represents the server class returned from `start_server`. It can be used in an ``async with`` statement to close the server upon exit. """ def close(self) -> None: """ Close the server. """ def wait_close(self) -> Awaitable[None]: """ Wait for the server to close. This is a coroutine. """ class Loop: """ """ def __init__(self): """ This represents the object which schedules and runs tasks. It cannot be created, use `get_event_loop` instead. """ def create_task(self, coro: _C, /) -> Task[_T]: """ Create a task from the given *coro* and return the new `Task` object. """ def run_forever(self) -> None: """ Run the event loop until `stop()` is called. """ def run_until_complete(self, awaitable: Awaitable[_T], /) -> None: """ Run the given *awaitable* until it completes. If *awaitable* is not a task then it will be promoted to one. """ def stop(self) -> None: """ Stop the event loop. """ def close(self) -> None: """ Close the event loop. """ def set_exception_handler( self, handler: Callable[[Loop, Dict[str, Any]], None] | None, / ) -> None: """ Set the exception handler to call when a Task raises an exception that is not caught. The *handler* should accept two arguments: ``(loop, context)``. """ def get_exception_handler(self) -> Callable[[Loop, Dict[str, Any]], None] | None: """ Get the current exception handler. Returns the handler, or ``None`` if no custom handler is set. """ def default_exception_handler(self, context: Dict[str, Any], /) -> None: """ The default exception handler that is called. """ def call_exception_handler(self, context: Dict[str, Any], /) -> None: """ Call the current exception handler. The argument *context* is passed through and is a dictionary containing keys: ``'message'``, ``'exception'``, ``'future'``. """ ================================================ FILE: typehints/stdlib/ubinascii.pyi ================================================ """ binary/ASCII conversions. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/binascii.rst. =========================================== .. module:: binascii :synopsis: binary/ASCII conversions |see_cpython_module| :mod:`python:binascii`. This module implements conversions between binary data and various encodings of it in ASCII form (in both directions). """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver def hexlify(data: bytes, sep: str | bytes = ..., /) -> bytes: """ Convert the bytes in the *data* object to a hexadecimal representation. Returns a bytes object. If the additional argument *sep* is supplied it is used as a separator between hexadecimal values. """ def unhexlify(data: str | bytes, /) -> bytes: """ Convert hexadecimal data to binary representation. Returns bytes string. (i.e. inverse of hexlify) """ def a2b_base64(data: str | bytes, /) -> bytes: """ Decode base64-encoded data, ignoring invalid characters in the input. Conforms to `RFC 2045 s.6.8 `_. Returns a bytes object. """ def b2a_base64(data: bytes, /) -> bytes: """ Encode binary data in base64 format, as in `RFC 3548 `_. Returns the encoded data followed by a newline character, as a bytes object. """ ================================================ FILE: typehints/stdlib/ucollections.pyi ================================================ """ collection and container types. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/collections.rst. ==================================================== .. module:: collections :synopsis: collection and container types |see_cpython_module| :mod:`python:collections`. This module implements advanced collection and container types to hold/accumulate various objects. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import overload, Any, Type, Iterable, TypeVar, Generic, Mapping, Dict, Final _KT: Final = TypeVar("_KT") _VT: Final = TypeVar("_VT") def namedtuple(name: str, fields: str | Iterable[str]) -> Type[tuple[Any, ...]]: """ This is factory function to create a new namedtuple type with a specific name and set of fields. A namedtuple is a subclass of tuple which allows to access its fields not just by numeric index, but also with an attribute access syntax using symbolic field names. Fields is a sequence of strings specifying field names. For compatibility with CPython it can also be a a string with space-separated field named (but this is less efficient). Example of use:: from collections import namedtuple MyTuple = namedtuple("MyTuple", ("id", "name")) t1 = MyTuple(1, "foo") t2 = MyTuple(2, "bar") print(t1.name) assert t2.name == t2[1] """ # noinspection PyPep8Naming class deque: """ Minimal implementation of a deque that implements a FIFO buffer. """ def __init__(self, iterable: tuple[Any], maxlen: int, flags: int = 0, /): """ Deques (double-ended queues) are a list-like container that support O(1) appends and pops from either side of the deque. New deques are created using the following arguments: - *iterable* must be the empty tuple, and the new deque is created empty. - *maxlen* must be specified and the deque will be bounded to this maximum length. Once the deque is full, any new items added will discard items from the opposite end. - The optional *flags* can be 1 to check for overflow when adding items. """ def __bool__(self) -> bool: """ Returns true if the `deque` isn't empty. **Note:** The method isn't listed by ``dir(deque)`` and can't be called directly, however ``bool(deque)`` and automatic conversion work! """ def __len__(self) -> int: """ Returns the number of items in the `deque`. **Note:** The method isn't listed by ``dir(deque)`` and can't be called directly, however ``len(deque)`` works! """ def append(self, x: Any, /) -> None: """ Add *x* to the right side of the deque. Raises IndexError if overflow checking is enabled and there is no more room left. """ def popleft(self) -> Any: """ Remove and return an item from the left side of the deque. Raises IndexError if no items are present. """ class OrderedDict(Dict[_KT, _VT], Generic[_KT, _VT]): """ W h e n o r d e r e d d i c t i s i t e r a t e d o v e r , k e y s / i t e m s a r e r e t u r n e d i n t h e o r d e r t h e y w e r e a d d e d . """ @overload def __init__(self): """ ``dict`` type subclass which remembers and preserves the order of keys added. When ordered dict is iterated over, keys/items are returned in the order they were added:: from collections import OrderedDict # To make benefit of ordered keys, OrderedDict should be initialized # from sequence of (key, value) pairs. d = OrderedDict([("z", 1), ("a", 2)]) # More items can be added as usual d["w"] = 5 d["b"] = 3 for k, v in d.items(): print(k, v) Output:: z 1 a 2 w 5 b 3 """ @overload def __init__(self, **kwargs: _VT): """ ``dict`` type subclass which remembers and preserves the order of keys added. When ordered dict is iterated over, keys/items are returned in the order they were added:: from collections import OrderedDict # To make benefit of ordered keys, OrderedDict should be initialized # from sequence of (key, value) pairs. d = OrderedDict([("z", 1), ("a", 2)]) # More items can be added as usual d["w"] = 5 d["b"] = 3 for k, v in d.items(): print(k, v) Output:: z 1 a 2 w 5 b 3 """ @overload def __init__(self, map: Mapping[_KT, _VT], **kwargs: _VT): """ ``dict`` type subclass which remembers and preserves the order of keys added. When ordered dict is iterated over, keys/items are returned in the order they were added:: from collections import OrderedDict # To make benefit of ordered keys, OrderedDict should be initialized # from sequence of (key, value) pairs. d = OrderedDict([("z", 1), ("a", 2)]) # More items can be added as usual d["w"] = 5 d["b"] = 3 for k, v in d.items(): print(k, v) Output:: z 1 a 2 w 5 b 3 """ ================================================ FILE: typehints/stdlib/uerrno.pyi ================================================ """ system error codes. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/errno.rst. ================================== .. module:: errno :synopsis: system error codes |see_cpython_module| :mod:`python:errno`. This module provides access to symbolic error codes for `OSError` exception. A particular inventory of codes depends on :term:`MicroPython port`. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Final, Dict EEXIST: Final[int] = ... """ Error codes, based on ANSI C/POSIX standard. All error codes start with "E". As mentioned above, inventory of the codes depends on :term:`MicroPython port`. Errors are usually accessible as ``exc.errno`` where ``exc`` is an instance of `OSError`. Usage example:: try: os.mkdir("my_dir") except OSError as exc: if exc.errno == errno.EEXIST: print("Directory already exists") """ EAGAIN: Final[int] = ... """ Error codes, based on ANSI C/POSIX standard. All error codes start with "E". As mentioned above, inventory of the codes depends on :term:`MicroPython port`. Errors are usually accessible as ``exc.errno`` where ``exc`` is an instance of `OSError`. Usage example:: try: os.mkdir("my_dir") except OSError as exc: if exc.errno == errno.EEXIST: print("Directory already exists") """ errorcode: Final[Dict[int, str]] = ... """ Dictionary mapping numeric error codes to strings with symbolic error code (see above):: >>> print(errno.errorcode[errno.EEXIST]) EEXIST """ ================================================ FILE: typehints/stdlib/uhashlib.pyi ================================================ """ hashing algorithms. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/hashlib.rst. ==================================== .. module:: hashlib :synopsis: hashing algorithms |see_cpython_module| :mod:`python:hashlib`. This module implements binary data hashing algorithms. The exact inventory of available algorithms depends on a board. Among the algorithms which may be implemented: * SHA256 - The current generation, modern hashing algorithm (of SHA2 series). It is suitable for cryptographically-secure purposes. Included in the MicroPython core and any board is recommended to provide this, unless it has particular code size constraints. * SHA1 - A previous generation algorithm. Not recommended for new usages, but SHA1 is a part of number of Internet standards and existing applications, so boards targeting network connectivity and interoperability will try to provide this. * MD5 - A legacy algorithm, not considered cryptographically secure. Only selected boards, targeting interoperability with legacy applications, will offer this. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from abc import ABC from typing import overload from uio import AnyReadableBuf # noinspection PyPep8Naming class sha256("_Hash"): """ The current generation, modern hashing algorithm (of SHA2 series). It is suitable for cryptographically-secure purposes. Included in the MicroPython core and any board is recommended to provide this, unless it has particular code size constraints. """ @overload def __init__(self): """ Create an SHA256 hasher object and optionally feed ``data`` into it. """ @overload def __init__(self, data: AnyReadableBuf): """ Create an SHA256 hasher object and optionally feed ``data`` into it. """ # noinspection PyPep8Naming class sha1("_Hash"): """ A previous generation algorithm. Not recommended for new usages, but SHA1 is a part of number of Internet standards and existing applications, so boards targeting network connectivity and interoperability will try to provide this. """ @overload def __init__(self): """ Create an SHA1 hasher object and optionally feed ``data`` into it. """ @overload def __init__(self, data: AnyReadableBuf): """ Create an SHA1 hasher object and optionally feed ``data`` into it. """ # noinspection PyPep8Naming class md5("_Hash"): """ A legacy algorithm, not considered cryptographically secure. Only selected boards, targeting interoperability with legacy applications, will offer this. """ def __init__(self, data: AnyReadableBuf = ..., /): """ Create an MD5 hasher object and optionally feed ``data`` into it. """ class _Hash(ABC): """ Abstract base class for hashing algorithms that defines methods available in all algorithms. """ def update(self, data: AnyReadableBuf, /) -> None: """ Feed more binary data into hash. """ def digest(self) -> bytes: """ Return hash for all data passed through hash, as a bytes object. After this method is called, more data cannot be fed into the hash any longer. """ def hexdigest(self) -> str: """ This method is NOT implemented. Use ``binascii.hexlify(hash.digest())`` to achieve a similar effect. """ ================================================ FILE: typehints/stdlib/uheapq.pyi ================================================ """ heap queue algorithm. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/heapq.rst. ==================================== .. module:: heapq :synopsis: heap queue algorithm |see_cpython_module| :mod:`python:heapq`. This module implements the `min heap queue algorithm `_. A heap queue is essentially a list that has its elements stored in such a way that the first item of the list is always the smallest. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import TypeVar, Any, Final _T: Final = TypeVar("_T") def heappush(heap: list[_T], item: _T, /) -> None: """ Push the ``item`` onto the ``heap``. """ def heappop(heap: list[_T], /) -> _T: """ Pop the first item from the ``heap``, and return it. Raise ``IndexError`` if ``heap`` is empty. The returned item will be the smallest item in the ``heap``. """ def heapify(x: list[Any], /) -> None: """ Convert the list ``x`` into a heap. This is an in-place operation. """ ================================================ FILE: typehints/stdlib/uio.pyi ================================================ """ input/output streams. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/io.rst. ================================= .. module:: io :synopsis: input/output streams |see_cpython_module| :mod:`python:io`. This module contains additional types of `stream` (file-like) objects and helper functions. Conceptual hierarchy -------------------- .. admonition:: Difference to CPython :class: attention Conceptual hierarchy of stream base classes is simplified in MicroPython, as described in this section. (Abstract) base stream classes, which serve as a foundation for behaviour of all the concrete classes, adhere to few dichotomies (pair-wise classifications) in CPython. In MicroPython, they are somewhat simplified and made implicit to achieve higher efficiencies and save resources. An important dichotomy in CPython is unbuffered vs buffered streams. In MicroPython, all streams are currently unbuffered. This is because all modern OSes, and even many RTOSes and filesystem drivers already perform buffering on their side. Adding another layer of buffering is counter- productive (an issue known as "bufferbloat") and takes precious memory. Note that there still cases where buffering may be useful, so we may introduce optional buffering support at a later time. But in CPython, another important dichotomy is tied with "bufferedness" - it's whether a stream may incur short read/writes or not. A short read is when a user asks e.g. 10 bytes from a stream, but gets less, similarly for writes. In CPython, unbuffered streams are automatically short operation susceptible, while buffered are guarantee against them. The no short read/writes is an important trait, as it allows to develop more concise and efficient programs - something which is highly desirable for MicroPython. So, while MicroPython doesn't support buffered streams, it still provides for no-short-operations streams. Whether there will be short operations or not depends on each particular class' needs, but developers are strongly advised to favour no-short-operations behaviour for the reasons stated above. For example, MicroPython sockets are guaranteed to avoid short read/writes. Actually, at this time, there is no example of a short-operations stream class in the core, and one would be a port-specific class, where such a need is governed by hardware peculiarities. The no-short-operations behaviour gets tricky in case of non-blocking streams, blocking vs non-blocking behaviour being another CPython dichotomy, fully supported by MicroPython. Non-blocking streams never wait for data either to arrive or be written - they read/write whatever possible, or signal lack of data (or ability to write data). Clearly, this conflicts with "no-short-operations" policy, and indeed, a case of non-blocking buffered (and this no-short-ops) streams is convoluted in CPython - in some places, such combination is prohibited, in some it's undefined or just not documented, in some cases it raises verbose exceptions. The matter is much simpler in MicroPython: non-blocking stream are important for efficient asynchronous operations, so this property prevails on the "no-short-ops" one. So, while blocking streams will avoid short reads/writes whenever possible (the only case to get a short read is if end of file is reached, or in case of error (but errors don't return short data, but raise exceptions)), non-blocking streams may produce short data to avoid blocking the operation. The final dichotomy is binary vs text streams. MicroPython of course supports these, but while in CPython text streams are inherently buffered, they aren't in MicroPython. (Indeed, that's one of the cases for which we may introduce buffering support.) Note that for efficiency, MicroPython doesn't provide abstract base classes corresponding to the hierarchy above, and it's not possible to implement, or subclass, a stream class in pure Python. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from types import TracebackType from typing import TypeVar, Final, Protocol, runtime_checkable, Literal from typing import AnyStr, overload, Type from uarray import array _T: Final = TypeVar("_T") _OpenTextModeUpdating: Final = Literal[ "r+", "+r", "rt+", "r+t", "+rt", "tr+", "t+r", "+tr", "w+", "+w", "wt+", "w+t", "+wt", "tw+", "t+w", "+tw", "a+", "+a", "at+", "a+t", "+at", "ta+", "t+a", "+ta", "x+", "+x", "xt+", "x+t", "+xt", "tx+", "t+x", "+tx", ] _OpenTextModeWriting: Final = Literal["w", "wt", "tw", "a", "at", "ta", "x", "xt", "tx"] _OpenTextModeReading: Final = Literal[ "r", "rt", "tr", "U", "rU", "Ur", "rtU", "rUt", "Urt", "trU", "tUr", "Utr" ] _OpenTextMode: Final = _OpenTextModeUpdating | _OpenTextModeWriting | _OpenTextModeReading _OpenBinaryModeUpdating: Final = Literal[ "rb+", "r+b", "+rb", "br+", "b+r", "+br", "wb+", "w+b", "+wb", "bw+", "b+w", "+bw", "ab+", "a+b", "+ab", "ba+", "b+a", "+ba", "xb+", "x+b", "+xb", "bx+", "b+x", "+bx", ] _OpenBinaryModeWriting: Final = Literal["wb", "bw", "ab", "ba", "xb", "bx"] _OpenBinaryModeReading: Final = Literal[ "rb", "br", "rbU", "rUb", "Urb", "brU", "bUr", "Ubr" ] _OpenBinaryMode: Final = _OpenBinaryModeUpdating | _OpenBinaryModeReading | _OpenBinaryModeWriting AnyStr_co: Final = TypeVar("AnyStr_co", str, bytes, covariant=True) @runtime_checkable class PathLike(Protocol[AnyStr_co]): def __fspath__(self) -> AnyStr_co: ... StrOrBytesPath: Final = str | bytes | PathLike[str] | PathLike[bytes] _OpenFile: Final = StrOrBytesPath | int AnyReadableBuf: Final = TypeVar("AnyReadableBuf", bytearray, array, memoryview, bytes) """ Type that allows bytearray, array, memoryview, or bytes, but only one of these and not a mixture in a single declaration. """ AnyWritableBuf: Final = TypeVar("AnyWritableBuf", bytearray, array, memoryview) """ Type that allows bytearray, array, or memoryview, but only one of these and not a mixture in a single declaration. """ _Self: Final = TypeVar("_Self") # The type that extends `IOBase`. @runtime_checkable class IOBase(Protocol[AnyStr, _Self]): """A `Protocol` (structurally typed) for an IOStream.""" __slots__ = () def __enter__(self) -> _Self: """ Called on entry to a `with` block. The `with` statement will bind this method’s return value to the target(s) specified in the `as` clause of the statement, if any. """ def __exit__( self, exc_type: Type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None, ) -> bool | None: """ Called on exit of a `with` block. The parameters describe the exception that caused the context to be exited. If the context was exited without an exception, all three arguments will be `None`. If an exception is supplied, and the method wishes to suppress the exception (i.e., prevent it from being propagated), it should return a true value. Otherwise, the exception will be processed normally upon exit from this method. *Note* that `__exit__()` methods should not re-raise the passed-in exception; this is the caller’s responsibility. """ def __next__(self) -> AnyStr: """ Next string. """ def __iter__(self) -> _Self: """ Start new iteration. """ def close(self) -> None: """ Flushes the write buffers and closes the IO stream; best not called directly, use a `with` block instead. Calling `f.close()` without using a `with` block might result in content not being completely written to the disk, even if the program exits successfully. A closed file cannot be read or written any more. Any operation which requires that the file be open will raise a `ValueError` after the file has been closed. Calling `f.close()` more than once is allowed. """ def flush(self) -> None: """ Flushes the write buffers of the IO stream. `flush()` does not necessarily write the file’s data to disk. Use `f.flush()` followed by `os.sync()` to ensure this behavior. This method does nothing for read-only and non-blocking streams. """ def read(self, size: int | None = -1) -> AnyStr | None: """ Read up to `size` bytes from the object and return them as a `str` (text file) or `bytes` (binary file). As a convenience, if `size` is unspecified or -1, all bytes until EOF are returned. Otherwise, only one system call is ever made. Fewer than `size` bytes may be returned if the operating system call returns fewer than `size` bytes. If 0 bytes are returned, and `size` was not 0, this indicates end of file. If `self` is in non-blocking mode and no bytes are available, `None` is returned. """ def readinto(self, b: AnyWritableBuf) -> int | None: """ Read bytes into a pre-allocated, writable bytes-like object b, and return the number of bytes read. For example, b might be a bytearray. If `self` is in non-blocking mode and no bytes are available, `None` is returned. """ def readline(self, size: int = -1) -> AnyStr: """ Read and return, as a `str` (text file) or `bytes` (binary file), one line from the stream. If size is specified, at most size bytes will be read. The line terminator is always `b' '` for binary files; for text files, the newline argument to `open()` can be used to select the line terminator(s) recognized. """ def readlines(self, hint: int | None = -1) -> list[AnyStr]: """ Read and return a list of lines, as a `list[str]` (text file) or `list[bytes]` (binary file), from the stream. `hint` can be specified to control the number of lines read: no more lines will be read if the total size (in bytes/characters) of all lines so far exceeds `hint`. `hint` values of 0 or less, as well as `None`, are treated as no hint. The line terminator is always `b' '` for binary files; for text files, the newline argument to `open()` can be used to select the line terminator(s) recognized. *Note* that it’s already possible to iterate on file objects using `for line in file: ...` without calling `file.readlines()`. """ def write(self, b: AnyReadableBuf) -> int | None: """ Write the given bytes-like object, `b`, to the underlying raw stream, and return the number of bytes written. This can be less than the length of `b` in bytes, depending on specifics of the underlying raw stream, and especially if it is in non-blocking mode. `None` is returned if the raw stream is set not to block and no single byte could be readily written to it. The caller may release or mutate `b` after this method returns, so the implementation only access `b` during the method call. """ def seek(self, offset: int, whence: int = 0) -> int: """ Change the stream position to the given byte `offset`. `offset` is interpreted relative to the position indicated by `whence`. The default value for whence is 0. Values for whence are: * 0 – start of the stream (the default); offset should be zero or positive. * 1 – current stream position; offset may be negative. * 2 – end of the stream; offset is usually negative. Returns the new absolute position. """ def tell(self) -> int: """ Return the current stream position. """ @overload def open(name: _OpenFile, /, **kwargs) -> "TextIOWrapper": """ Open a file. Builtin ``open()`` function is aliased to this function. All ports (which provide access to file system) are required to support *mode* parameter, but support for other arguments vary by port. """ @overload def open(name: _OpenFile, mode: _OpenTextMode = ..., /, **kwargs) -> "TextIOWrapper": """ Open a file. Builtin ``open()`` function is aliased to this function. All ports (which provide access to file system) are required to support *mode* parameter, but support for other arguments vary by port. """ @overload def open(name: _OpenFile, mode: _OpenBinaryMode = ..., /, **kwargs) -> "FileIO": """ Open a file. Builtin ``open()`` function is aliased to this function. All ports (which provide access to file system) are required to support *mode* parameter, but support for other arguments vary by port. """ class FileIO(IOBase[bytes, "FileIO"]): """ Bytes stream from a file. """ def __init__(self, name: _OpenFile, mode: str = ..., /, **kwargs): """ This is type of a file open in binary mode, e.g. using ``open(name, "rb")``. You should not instantiate this class directly. """ class TextIOWrapper(IOBase[str, "TextIOWrapper"]): """ Str stream from a file. """ def __init__(self, name: _OpenFile, mode: str = ..., /, **kwargs): """ This is type of a file open in text mode, e.g. using ``open(name, "rt")``. You should not instantiate this class directly. """ class StringIO(IOBase[str, "StringIO"]): """ Str stream from a str (wrapper). """ @overload def __init__(self, string: str = "", /): """ In-memory file-like object for input/output. `StringIO` is used for text-mode I/O (similar to a normal file opened with "t" modifier). Initial contents can be specified with `string` parameter. `alloc_size` constructor creates an empty `StringIO` object, pre-allocated to hold up to `alloc_size` number of bytes. That means that writing that amount of bytes won't lead to reallocation of the buffer, and thus won't hit out-of-memory situation or lead to memory fragmentation. This constructor is a MicroPython extension and is recommended for usage only in special cases and in system-level libraries, not for end-user applications. .. admonition:: Difference to CPython :class: attention This constructor is a MicroPython extension. """ @overload def __init__(self, alloc_size: int, /): """ In-memory file-like object for input/output. `StringIO` is used for text-mode I/O (similar to a normal file opened with "t" modifier). Initial contents can be specified with `string` parameter. `alloc_size` constructor creates an empty `StringIO` object, pre-allocated to hold up to `alloc_size` number of bytes. That means that writing that amount of bytes won't lead to reallocation of the buffer, and thus won't hit out-of-memory situation or lead to memory fragmentation. This constructor is a MicroPython extension and is recommended for usage only in special cases and in system-level libraries, not for end-user applications. .. admonition:: Difference to CPython :class: attention This constructor is a MicroPython extension. """ def getvalue(self) -> str: """Get the current contents of the underlying buffer which holds data.""" class BytesIO(IOBase[bytes, "BytesIO"]): """ Bytes stream from a bytes array (wrapper). """ @overload def __init__(self, string: bytes = "", /): """ In-memory file-like objects for input/output. `StringIO` is used for text-mode I/O (similar to a normal file opened with "t" modifier). `BytesIO` is used for binary-mode I/O (similar to a normal file opened with "b" modifier). Initial contents of file-like objects can be specified with *string* parameter (should be normal string for `StringIO` or bytes object for `BytesIO`). All the usual file methods like ``read()``, ``write()``, ``seek()``, ``flush()``, ``close()`` are available on these objects, and additionally, a following method: `alloc_size` constructor creates an empty `BytesIO` object, pre-allocated to hold up to `alloc_size` number of bytes. That means that writing that amount of bytes won't lead to reallocation of the buffer, and thus won't hit out-of-memory situation or lead to memory fragmentation. This constructor is a MicroPython extension and is recommended for usage only in special cases and in system-level libraries, not for end-user applications. .. admonition:: Difference to CPython :class: attention This constructor is a MicroPython extension. """ @overload def __init__(self, alloc_size: int, /): """ In-memory file-like objects for input/output. `StringIO` is used for text-mode I/O (similar to a normal file opened with "t" modifier). `BytesIO` is used for binary-mode I/O (similar to a normal file opened with "b" modifier). Initial contents of file-like objects can be specified with *string* parameter (should be normal string for `StringIO` or bytes object for `BytesIO`). All the usual file methods like ``read()``, ``write()``, ``seek()``, ``flush()``, ``close()`` are available on these objects, and additionally, a following method: `alloc_size` constructor creates an empty `BytesIO` object, pre-allocated to hold up to `alloc_size` number of bytes. That means that writing that amount of bytes won't lead to reallocation of the buffer, and thus won't hit out-of-memory situation or lead to memory fragmentation. This constructor is a MicroPython extension and is recommended for usage only in special cases and in system-level libraries, not for end-user applications. .. admonition:: Difference to CPython :class: attention This constructor is a MicroPython extension. """ def getvalue(self) -> bytes: """ Get the current contents of the underlying buffer which holds data. """ ================================================ FILE: typehints/stdlib/ujson.pyi ================================================ """ JSON encoding and decoding. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/json.rst. ========================================= .. module:: json :synopsis: JSON encoding and decoding |see_cpython_module| :mod:`python:json`. This modules allows to convert between Python objects and the JSON data format. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Any, AnyStr from uio import IOBase def dump( obj: Any, stream: IOBase[str, Any], separators: tuple[str, str] | None = None, / ) -> None: """ Serialise *obj* to a JSON string, writing it to the given *stream*. If specified, separators should be an ``(item_separator, key_separator)`` tuple. The default is ``(', ', ': ')``. To get the most compact JSON representation, you should specify ``(',', ':')`` to eliminate whitespace. """ def dumps(obj: Any, separators: tuple[str, str] | None = None) -> str: """ Return *obj* represented as a JSON string. The arguments have the same meaning as in `dump`. """ def load(stream: IOBase[str, Any]) -> Any: """ Parse the given *stream*, interpreting it as a JSON string and deserialising the data to a Python object. The resulting object is returned. Parsing continues until end-of-file is encountered. A :exc:`ValueError` is raised if the data in *stream* is not correctly formed. """ def loads(str: AnyStr) -> Any: """ Parse the JSON *str* and return an object. Raises :exc:`ValueError` if the string is not correctly formed. """ ================================================ FILE: typehints/stdlib/uos.pyi ================================================ """ basic "operating system" services. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/os.rst. ============================================== .. module:: os :synopsis: basic "operating system" services |see_cpython_module| :mod:`python:os`. The ``os`` module contains functions for filesystem access and mounting, terminal redirection and duplication, and the ``uname`` and ``urandom`` functions. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from abc import abstractmethod from typing import Final, TypeVar, runtime_checkable, Protocol, overload, Literal from uio import IOBase _StrOrBytesT: Final = TypeVar("_StrOrBytesT", str, bytes) class _PathLike(Protocol[_StrOrBytesT]): @abstractmethod def __fspath__(self) -> _StrOrBytesT: """Return the file system path representation of the object, preferably as a `str`.""" _AnyPath: Final = str | bytes | _PathLike[str] | _PathLike[bytes] _FdOrAnyPath: Final = int | _AnyPath def uname() -> tuple[str, str, str, str, str]: """ Return a tuple (possibly a named tuple) containing information about the underlying machine and/or its operating system. The tuple has five fields in the following order, each of them being a string: * ``sysname`` -- the name of the underlying system * ``nodename`` -- the network name (can be the same as ``sysname``) * ``release`` -- the version of the underlying system * ``version`` -- the MicroPython version and build date * ``machine`` -- an identifier for the underlying hardware (eg board, CPU) """ def urandom(n: int, /) -> bytes: """ Return a bytes object with *n* random bytes. Whenever possible, it is generated by the hardware random number generator. """ def chdir(path: _FdOrAnyPath, /) -> None: """ Change current directory. """ def getcwd() -> str: """ Get the current directory. """ @overload def ilistdir() -> list[tuple[str, int, int] | tuple[str, int, int, int]]: """ This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is listing. With no argument it lists the current directory, otherwise it lists the directory given by *dir*. The tuples have the form *(name, type, inode[, size])*: - *name* is a string (or bytes if *dir* is a bytes object) and is the name of the entry; - *type* is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files; - *inode* is an integer corresponding to the inode of the file, and may be 0 for filesystems that don't have such a notion. - Some platforms may return a 4-tuple that includes the entry's *size*. For file entries, *size* is an integer representing the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries. """ @overload def ilistdir(dir: int, /) -> list[tuple[str, int, int] | tuple[str, int, int, int]]: """ This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is listing. With no argument it lists the current directory, otherwise it lists the directory given by *dir*. The tuples have the form *(name, type, inode[, size])*: - *name* is a string (or bytes if *dir* is a bytes object) and is the name of the entry; - *type* is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files; - *inode* is an integer corresponding to the inode of the file, and may be 0 for filesystems that don't have such a notion. - Some platforms may return a 4-tuple that includes the entry's *size*. For file entries, *size* is an integer representing the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries. """ @overload def ilistdir(dir: str, /) -> list[tuple[str, int, int] | tuple[str, int, int, int]]: """ This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is listing. With no argument it lists the current directory, otherwise it lists the directory given by *dir*. The tuples have the form *(name, type, inode[, size])*: - *name* is a string (or bytes if *dir* is a bytes object) and is the name of the entry; - *type* is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files; - *inode* is an integer corresponding to the inode of the file, and may be 0 for filesystems that don't have such a notion. - Some platforms may return a 4-tuple that includes the entry's *size*. For file entries, *size* is an integer representing the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries. """ @overload def ilistdir( dir: bytes, / ) -> list[tuple[bytes, int, int] | tuple[bytes, int, int, int]]: """ This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is listing. With no argument it lists the current directory, otherwise it lists the directory given by *dir*. The tuples have the form *(name, type, inode[, size])*: - *name* is a string (or bytes if *dir* is a bytes object) and is the name of the entry; - *type* is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files; - *inode* is an integer corresponding to the inode of the file, and may be 0 for filesystems that don't have such a notion. - Some platforms may return a 4-tuple that includes the entry's *size*. For file entries, *size* is an integer representing the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries. """ @overload def ilistdir( dir: _PathLike[str], / ) -> list[tuple[str, int, int] | tuple[str, int, int, int]]: """ This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is listing. With no argument it lists the current directory, otherwise it lists the directory given by *dir*. The tuples have the form *(name, type, inode[, size])*: - *name* is a string (or bytes if *dir* is a bytes object) and is the name of the entry; - *type* is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files; - *inode* is an integer corresponding to the inode of the file, and may be 0 for filesystems that don't have such a notion. - Some platforms may return a 4-tuple that includes the entry's *size*. For file entries, *size* is an integer representing the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries. """ @overload def ilistdir( dir: _PathLike[bytes], / ) -> list[tuple[bytes, int, int] | tuple[bytes, int, int, int]]: """ This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is listing. With no argument it lists the current directory, otherwise it lists the directory given by *dir*. The tuples have the form *(name, type, inode[, size])*: - *name* is a string (or bytes if *dir* is a bytes object) and is the name of the entry; - *type* is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files; - *inode* is an integer corresponding to the inode of the file, and may be 0 for filesystems that don't have such a notion. - Some platforms may return a 4-tuple that includes the entry's *size*. For file entries, *size* is an integer representing the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries. """ @overload def listdir() -> list[str]: """ With no argument, list the current directory. Otherwise list the given directory. """ @overload def listdir(dir: int, /) -> list[str]: """ With no argument, list the current directory. Otherwise list the given directory. """ @overload def listdir(dir: str, /) -> list[str]: """ With no argument, list the current directory. Otherwise list the given directory. """ @overload def listdir(dir: bytes, /) -> list[bytes]: """ With no argument, list the current directory. Otherwise list the given directory. """ @overload def listdir(dir: _PathLike[str], /) -> list[str]: """ With no argument, list the current directory. Otherwise list the given directory. """ @overload def listdir(dir: _PathLike[bytes], /) -> list[bytes]: """ With no argument, list the current directory. Otherwise list the given directory. """ def mkdir(path: _AnyPath, /) -> None: """ Create a new directory. """ def remove(path: _AnyPath, /) -> None: """ Remove a file. """ def rmdir(path: _AnyPath, /) -> None: """ Remove a directory. """ def rename(old_path: _AnyPath, new_path: _AnyPath, /) -> None: """ Rename a file. """ def stat( path: _FdOrAnyPath, / ) -> tuple[int, int, int, int, int, int, int, int, int, int]: """ Get the status of a file or directory. """ def statvfs( path: _FdOrAnyPath, / ) -> tuple[int, int, int, int, int, int, int, int, int, int]: """ Get the status of a fileystem. Returns a tuple with the filesystem information in the following order: * ``f_bsize`` -- file system block size * ``f_frsize`` -- fragment size * ``f_blocks`` -- size of fs in f_frsize units * ``f_bfree`` -- number of free blocks * ``f_bavail`` -- number of free blocks for unprivileged users * ``f_files`` -- number of inodes * ``f_ffree`` -- number of free inodes * ``f_favail`` -- number of free inodes for unprivileged users * ``f_flag`` -- mount flags * ``f_namemax`` -- maximum filename length Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail`` and the ``f_flags`` parameter may return ``0`` as they can be unavailable in a port-specific implementation. """ def sync() -> None: """ Sync all filesystems. """ def dupterm(stream_object: IOBase | None, index: int = 0, /) -> IOBase | None: """ Duplicate or switch the MicroPython terminal (the REPL) on the given `stream`-like object. The *stream_object* argument must be a native stream object, or derive from ``io.IOBase`` and implement the ``readinto()`` and ``write()`` methods. The stream should be in non-blocking mode and ``readinto()`` should return ``None`` if there is no data available for reading. After calling this function all terminal output is repeated on this stream, and any input that is available on the stream is passed on to the terminal input. The *index* parameter should be a non-negative integer and specifies which duplication slot is set. A given port may implement more than one slot (slot 0 will always be available) and in that case terminal input and output is duplicated on all the slots that are set. If ``None`` is passed as the *stream_object* then duplication is cancelled on the slot given by *index*. The function returns the previous stream-like object in the given slot. """ def mount( fsobj: "AbstractBlockDev", mount_point: str, /, *, readonly: bool = False ) -> IOBase | None: """ Mount the filesystem object *fsobj* at the location in the VFS given by the *mount_point* string. *fsobj* can be a a VFS object that has a ``mount()`` method, or a block device. If it's a block device then the filesystem type is automatically detected (an exception is raised if no filesystem was recognised). *mount_point* may be ``'/'`` to mount *fsobj* at the root, or ``'/'`` to mount it at a subdirectory under the root. If *readonly* is ``True`` then the filesystem is mounted read-only. During the mount process the method ``mount()`` is called on the filesystem object. Will raise ``OSError(EPERM)`` if *mount_point* is already mounted. Filesystem mounting ------------------- Some ports provide a Virtual Filesystem (VFS) and the ability to mount multiple "real" filesystems within this VFS. Filesystem objects can be mounted at either the root of the VFS, or at a subdirectory that lives in the root. This allows dynamic and flexible configuration of the filesystem that is seen by Python programs. Ports that have this functionality provide the :func:`mount` and :func:`umount` functions, and possibly various filesystem implementations represented by VFS classes. """ def umount(mount_point: str, /) -> None: """ Unmount a filesystem. *mount_point* can be a string naming the mount location, or a previously-mounted filesystem object. During the unmount process the method ``umount()`` is called on the filesystem object. Will raise ``OSError(EINVAL)`` if *mount_point* is not found. """ class VfsFat("AbstractBlockDev"): """ """ def __init__(self, block_dev: "AbstractBlockDev", /): """ Create a filesystem object that uses the FAT filesystem format. Storage of the FAT filesystem is provided by *block_dev*. Objects created by this constructor can be mounted using :func:`mount`. """ @staticmethod def mkfs(block_dev: "AbstractBlockDev", /) -> None: """ Build a FAT filesystem on *block_dev*. """ class VfsLfs1("AbstractBlockDev"): """ """ def __init__( self, block_dev: "AbstractBlockDev", readsize: int = 32, progsize: int = 32, lookahead: int = 32, /, ): """ Create a filesystem object that uses the `littlefs v1 filesystem format`_. Storage of the littlefs filesystem is provided by *block_dev*, which must support the :ref:`extended interface `. Objects created by this constructor can be mounted using :func:`mount`. See :ref:`filesystem` for more information. """ @staticmethod def mkfs( block_dev: "AbstractBlockDev", readsize: int = 32, progsize: int = 32, lookahead: int = 32, /, ) -> None: """ Build a Lfs1 filesystem on *block_dev*. .. note:: There are reports of littlefs v1 failing in certain situations, for details see `littlefs issue 347`_. """ class VfsLfs2("AbstractBlockDev"): """ """ def __init__( self, block_dev: "AbstractBlockDev", readsize: int = 32, progsize: int = 32, lookahead: int = 32, mtime: bool = True, /, ): """ Create a filesystem object that uses the `littlefs v2 filesystem format`_. Storage of the littlefs filesystem is provided by *block_dev*, which must support the :ref:`extended interface `. Objects created by this constructor can be mounted using :func:`mount`. The *mtime* argument enables modification timestamps for files, stored using littlefs attributes. This option can be disabled or enabled differently each mount time and timestamps will only be added or updated if *mtime* is enabled, otherwise the timestamps will remain untouched. Littlefs v2 filesystems without timestamps will work without reformatting and timestamps will be added transparently to existing files once they are opened for writing. When *mtime* is enabled `os.stat` on files without timestamps will return 0 for the timestamp. See :ref:`filesystem` for more information. """ @staticmethod def mkfs( block_dev: "AbstractBlockDev", readsize: int = 32, progsize: int = 32, lookahead: int = 32, mtime: bool = True, /, ) -> None: """ Build a Lfs2 filesystem on *block_dev*. .. note:: There are reports of littlefs v2 failing in certain situations, for details see `littlefs issue 295`_. """ @runtime_checkable class AbstractBlockDev(Protocol): """ Block devices ------------- A block device is an object which implements the block protocol. This enables a device to support MicroPython filesystems. The physical hardware is represented by a user defined class. The :class:`AbstractBlockDev` class is a template for the design of such a class: MicroPython does not actually provide that class, but an actual block device class must implement the methods described below. A concrete implementation of this class will usually allow access to the memory-like functionality of a piece of hardware (like flash memory). A block device can be formatted to any supported filesystem and mounted using ``os`` methods. See :ref:`filesystem` for example implementations of block devices using the two variants of the block protocol described below. .. _block-device-interface: Simple and extended interface ............................. There are two compatible signatures for the ``readblocks`` and ``writeblocks`` methods (see below), in order to support a variety of use cases. A given block device may implement one form or the other, or both at the same time. The second form (with the offset parameter) is referred to as the "extended interface". Some filesystems (such as littlefs) that require more control over write operations, for example writing to sub-block regions without erasing, may require that the block device supports the extended interface. """ def __init__(self): """ Construct a block device object. The parameters to the constructor are dependent on the specific block device. """ @overload def readblocks(self, block_num: int, buf: bytearray, /) -> None: """ The first form reads aligned, multiples of blocks. Starting at the block given by the index *block_num*, read blocks from the device into *buf* (an array of bytes). The number of blocks to read is given by the length of *buf*, which will be a multiple of the block size. The second form allows reading at arbitrary locations within a block, and arbitrary lengths. Starting at block index *block_num*, and byte offset within that block of *offset*, read bytes from the device into *buf* (an array of bytes). The number of bytes to read is given by the length of *buf*. """ @overload def readblocks(self, block_num: int, buf: bytearray, offset: int, /) -> None: """ The first form reads aligned, multiples of blocks. Starting at the block given by the index *block_num*, read blocks from the device into *buf* (an array of bytes). The number of blocks to read is given by the length of *buf*, which will be a multiple of the block size. The second form allows reading at arbitrary locations within a block, and arbitrary lengths. Starting at block index *block_num*, and byte offset within that block of *offset*, read bytes from the device into *buf* (an array of bytes). The number of bytes to read is given by the length of *buf*. """ @overload def writeblocks(self, block_num: int, buf: bytes | bytearray, /) -> None: """ The first form writes aligned, multiples of blocks, and requires that the blocks that are written to be first erased (if necessary) by this method. Starting at the block given by the index *block_num*, write blocks from *buf* (an array of bytes) to the device. The number of blocks to write is given by the length of *buf*, which will be a multiple of the block size. The second form allows writing at arbitrary locations within a block, and arbitrary lengths. Only the bytes being written should be changed, and the caller of this method must ensure that the relevant blocks are erased via a prior ``ioctl`` call. Starting at block index *block_num*, and byte offset within that block of *offset*, write bytes from *buf* (an array of bytes) to the device. The number of bytes to write is given by the length of *buf*. Note that implementations must never implicitly erase blocks if the offset argument is specified, even if it is zero. """ @overload def writeblocks( self, block_num: int, buf: bytes | bytearray, offset: int, / ) -> None: """ The first form writes aligned, multiples of blocks, and requires that the blocks that are written to be first erased (if necessary) by this method. Starting at the block given by the index *block_num*, write blocks from *buf* (an array of bytes) to the device. The number of blocks to write is given by the length of *buf*, which will be a multiple of the block size. The second form allows writing at arbitrary locations within a block, and arbitrary lengths. Only the bytes being written should be changed, and the caller of this method must ensure that the relevant blocks are erased via a prior ``ioctl`` call. Starting at block index *block_num*, and byte offset within that block of *offset*, write bytes from *buf* (an array of bytes) to the device. The number of bytes to write is given by the length of *buf*. Note that implementations must never implicitly erase blocks if the offset argument is specified, even if it is zero. """ @overload def ioctl(self, op: int, arg: int) -> int | None: """ Control the block device and query its parameters. The operation to perform is given by *op* which is one of the following integers: - 1 -- initialise the device (*arg* is unused) - 2 -- shutdown the device (*arg* is unused) - 3 -- sync the device (*arg* is unused) - 4 -- get a count of the number of blocks, should return an integer (*arg* is unused) - 5 -- get the number of bytes in a block, should return an integer, or ``None`` in which case the default value of 512 is used (*arg* is unused) - 6 -- erase a block, *arg* is the block number to erase As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs ``ioctl(6, ...)`` must also be intercepted. The need for others is hardware dependent. Prior to any call to ``writeblocks(block, ...)`` littlefs issues ``ioctl(6, block)``. This enables a device driver to erase the block prior to a write if the hardware requires it. Alternatively a driver might intercept ``ioctl(6, block)`` and return 0 (success). In this case the driver assumes responsibility for detecting the need for erasure. Unless otherwise stated ``ioctl(op, arg)`` can return ``None``. Consequently an implementation can ignore unused values of ``op``. Where ``op`` is intercepted, the return value for operations 4 and 5 are as detailed above. Other operations should return 0 on success and non-zero for failure, with the value returned being an ``OSError`` errno code. """ @overload def ioctl(self, op: Literal[4, 5], arg: int) -> int: """ Control the block device and query its parameters. The operation to perform is given by *op* which is one of the following integers: - 1 -- initialise the device (*arg* is unused) - 2 -- shutdown the device (*arg* is unused) - 3 -- sync the device (*arg* is unused) - 4 -- get a count of the number of blocks, should return an integer (*arg* is unused) - 5 -- get the number of bytes in a block, should return an integer, or ``None`` in which case the default value of 512 is used (*arg* is unused) - 6 -- erase a block, *arg* is the block number to erase As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs ``ioctl(6, ...)`` must also be intercepted. The need for others is hardware dependent. Prior to any call to ``writeblocks(block, ...)`` littlefs issues ``ioctl(6, block)``. This enables a device driver to erase the block prior to a write if the hardware requires it. Alternatively a driver might intercept ``ioctl(6, block)`` and return 0 (success). In this case the driver assumes responsibility for detecting the need for erasure. Unless otherwise stated ``ioctl(op, arg)`` can return ``None``. Consequently an implementation can ignore unused values of ``op``. Where ``op`` is intercepted, the return value for operations 4 and 5 are as detailed above. Other operations should return 0 on success and non-zero for failure, with the value returned being an ``OSError`` errno code. """ @overload def ioctl(self, op: Literal[1, 2, 3, 6], arg: int) -> int | None: """ Control the block device and query its parameters. The operation to perform is given by *op* which is one of the following integers: - 1 -- initialise the device (*arg* is unused) - 2 -- shutdown the device (*arg* is unused) - 3 -- sync the device (*arg* is unused) - 4 -- get a count of the number of blocks, should return an integer (*arg* is unused) - 5 -- get the number of bytes in a block, should return an integer, or ``None`` in which case the default value of 512 is used (*arg* is unused) - 6 -- erase a block, *arg* is the block number to erase As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs ``ioctl(6, ...)`` must also be intercepted. The need for others is hardware dependent. Prior to any call to ``writeblocks(block, ...)`` littlefs issues ``ioctl(6, block)``. This enables a device driver to erase the block prior to a write if the hardware requires it. Alternatively a driver might intercept ``ioctl(6, block)`` and return 0 (success). In this case the driver assumes responsibility for detecting the need for erasure. Unless otherwise stated ``ioctl(op, arg)`` can return ``None``. Consequently an implementation can ignore unused values of ``op``. Where ``op`` is intercepted, the return value for operations 4 and 5 are as detailed above. Other operations should return 0 on success and non-zero for failure, with the value returned being an ``OSError`` errno code. """ ================================================ FILE: typehints/stdlib/ure.pyi ================================================ """ regular expressions. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/re.rst. ======================================= .. module:: re :synopsis: regular expressions |see_cpython_module| :mod:`python:re`. This module implements regular expression operations. Regular expression syntax supported is a subset of CPython ``re`` module (and actually is a subset of POSIX extended regular expressions). Supported operators and special sequences are: ``.`` Match any character. ``[...]`` Match set of characters. Individual characters and ranges are supported, including negated sets (e.g. ``[^a-c]``). ``^`` Match the start of the string. ``$`` Match the end of the string. ``?`` Match zero or one of the previous sub-pattern. ``*`` Match zero or more of the previous sub-pattern. ``+`` Match one or more of the previous sub-pattern. ``??`` Non-greedy version of ``?``, match zero or one, with the preference for zero. ``*?`` Non-greedy version of ``*``, match zero or more, with the preference for the shortest match. ``+?`` Non-greedy version of ``+``, match one or more, with the preference for the shortest match. ``|`` Match either the left-hand side or the right-hand side sub-patterns of this operator. ``(...)`` Grouping. Each group is capturing (a substring it captures can be accessed with `match.group()` method). ``\d`` Matches digit. Equivalent to ``[0-9]``. ``\D`` Matches non-digit. Equivalent to ``[^0-9]``. ``\s`` Matches whitespace. Equivalent to ``[ \t-\r]``. ``\S`` Matches non-whitespace. Equivalent to ``[^ \t-\r]``. ``\w`` Matches "word characters" (ASCII only). Equivalent to ``[A-Za-z0-9_]``. ``\W`` Matches non "word characters" (ASCII only). Equivalent to ``[^A-Za-z0-9_]``. ``\`` Escape character. Any other character following the backslash, except for those listed above, is taken literally. For example, ``\*`` is equivalent to literal ``*`` (not treated as the ``*`` operator). Note that ``\r``, ``\n``, etc. are not handled specially, and will be equivalent to literal letters ``r``, ``n``, etc. Due to this, it's not recommended to use raw Python strings (``r""``) for regular expressions. For example, ``r"\r\n"`` when used as the regular expression is equivalent to ``"rn"``. To match CR character followed by LF, use ``"\r\n"``. **NOT SUPPORTED**: * counted repetitions (``{m,n}``) * named groups (``(?P...)``) * non-capturing groups (``(?:...)``) * more advanced assertions (``\b``, ``\B``) * special character escapes like ``\r``, ``\n`` - use Python's own escaping instead * etc. Example:: import re # As re doesn't support escapes itself, use of r"" strings is not # recommended. regex = re.compile("[\r\n]") regex.split("line1\rline2\nline3\r\n") # Result: # ['line1', 'line2', 'line3', '', ''] """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import AnyStr, Callable, Generic, Final, Any _StrLike: Final = str | bytes def compile(regex_str: _StrLike, flags: int = ..., /) -> "ure": """ Compile regular expression, return `regex ` object. """ def match(regex_str: _StrLike, string: AnyStr, /) -> "Match[AnyStr]": """ Compile *regex_str* and match against *string*. Match always happens from starting position in a string. """ def search(regex_str: _StrLike, string: AnyStr, /) -> "Match[AnyStr]": """ Compile *regex_str* and search it in a *string*. Unlike `match`, this will search string for first position which matches regex (which still may be 0 if regex is anchored). """ def sub( regex_str: _StrLike, replace: AnyStr | Callable[["Match[AnyStr]"], AnyStr], string: AnyStr, count: int = 0, flags: int = 0, /, ) -> AnyStr: """ Compile *regex_str* and search for it in *string*, replacing all matches with *replace*, and returning the new string. *replace* can be a string or a function. If it is a string then escape sequences of the form ``\`` and ``\g`` can be used to expand to the corresponding group (or an empty string for unmatched groups). If *replace* is a function then it must take a single argument (the match) and should return a replacement string. If *count* is specified and non-zero then substitution will stop after this many substitutions are made. The *flags* argument is ignored. Note: availability of this function depends on :term:`MicroPython port`. """ DEBUG: Final[int] = ... """ Flag value, display debug information about compiled expression. (Availability depends on :term:`MicroPython port`.) """ # noinspection PyPep8Naming class ure: """ Compiled regular expression. Instances of this class are created using `re.compile()`. """ def match(self, string: AnyStr, /) -> "Match[AnyStr]": """ Similar to the module-level functions :meth:`match`, :meth:`search` and :meth:`sub`. Using methods is (much) more efficient if the same regex is applied to multiple strings. """ def search(self, string: AnyStr, /) -> "Match[AnyStr]": """ Similar to the module-level functions :meth:`match`, :meth:`search` and :meth:`sub`. Using methods is (much) more efficient if the same regex is applied to multiple strings. """ def sub( self, replace: AnyStr | Callable[["Match[AnyStr]"], AnyStr], string: AnyStr, count: int = 0, flags: int = 0, /, ) -> AnyStr: """ Similar to the module-level functions :meth:`match`, :meth:`search` and :meth:`sub`. Using methods is (much) more efficient if the same regex is applied to multiple strings. """ def split(self, string: AnyStr, max_split: int = -1, /) -> list[AnyStr]: """ Split a *string* using regex. If *max_split* is given, it specifies maximum number of splits to perform. Returns list of strings (there may be up to *max_split+1* elements if it's specified). """ class Match(Generic[AnyStr]): """ Match objects as returned by `match()` and `search()` methods, and passed to the replacement function in `sub()`. The name, `Match`, used for typing is not the same as the runtime name, `match` (note lowercase `m`). The reason for this difference is that the runtime uses `match` as both a class name and as a method name and this is not possible within code written entirely in Python and therefore not possible within typing code. """ def group(self, index: int, /) -> AnyStr: """ Return matching (sub)string. *index* is 0 for entire match, 1 and above for each capturing group. Only numeric groups are supported. """ def groups(self) -> tuple[AnyStr | Any, ...]: """ Return a tuple containing all the substrings of the groups of the match. Note: availability of this method depends on :term:`MicroPython port`. """ def start(self, index: int = ..., /) -> int: """ Return the index in the original string of the start or end of the substring group that was matched. *index* defaults to the entire group, otherwise it will select a group. Note: availability of these methods depends on :term:`MicroPython port`. """ def end(self, index: int = ..., /) -> int: """ Return the index in the original string of the start or end of the substring group that was matched. *index* defaults to the entire group, otherwise it will select a group. Note: availability of these methods depends on :term:`MicroPython port`. """ def span(self, index: int = ..., /) -> tuple[int, int]: """ Returns the 2-tuple ``(match.start(index), match.end(index))``. Note: availability of this method depends on :term:`MicroPython port`. """ ================================================ FILE: typehints/stdlib/uselect.pyi ================================================ """ wait for events on a set of streams. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/select.rst. ==================================================== .. module:: select :synopsis: wait for events on a set of streams |see_cpython_module| :mod:`python:select`. This module provides functions to efficiently wait for events on multiple `streams ` (select streams which are ready for operations). """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Iterable, Any, Final, Iterator from uio import IOBase POLLIN: Final[int] = ... """Data available for reading.""" POLLOUT: Final[int] = ... """More data can be written.""" POLLHUP: Final[int] = ... """Socket is no longer connected.""" POLLERR: Final[int] = ... """Socket got an asynchronous error.""" def poll() -> "Poll": """ Create an instance of the Poll class. """ def select( rlist: Iterable[Any], wlist: Iterable[Any], xlist: Iterable[Any], timeout: int = -1, /, ) -> list[tuple[Any, int, Any, ...]]: """ Wait for activity on a set of objects. This function is provided by some MicroPython ports for compatibility and is not efficient. Usage of :class:`Poll` is recommended instead. """ class Poll: """ The name, `Poll`, used for typing is not the same as the runtime name, `poll` (note lowercase `p`). The reason for this difference is that the runtime uses `poll` as both a class name and as a method name and this is not possible within code written entirely in Python and therefore not possible within typing code. """ def register(self, obj: IOBase, eventmask: int = POLLIN | POLLOUT, /) -> None: """ Register `stream` *obj* for polling. *eventmask* is logical OR of: * ``select.POLLIN`` - data available for reading * ``select.POLLOUT`` - more data can be written Note that flags like ``select.POLLHUP`` and ``select.POLLERR`` are *not* valid as input eventmask (these are unsolicited events which will be returned from `poll()` regardless of whether they are asked for). This semantics is per POSIX. *eventmask* defaults to ``select.POLLIN | select.POLLOUT``. It is OK to call this function multiple times for the same *obj*. Successive calls will update *obj*'s eventmask to the value of *eventmask* (i.e. will behave as `modify()`). """ def unregister(self, obj: IOBase, /) -> None: """ Unregister *obj* from polling. """ def modify(self, obj: IOBase, eventmask: int, /) -> None: """ Modify the *eventmask* for *obj*. If *obj* is not registered, `OSError` is raised with error of ENOENT. """ def poll(self, timeout: int = -1, /) -> list[tuple[Any, int, Any, ...]]: """ Wait for at least one of the registered objects to become ready or have an exceptional condition, with optional timeout in milliseconds (if *timeout* arg is not specified or -1, there is no timeout). Returns list of (``obj``, ``event``, ...) tuples. There may be other elements in tuple, depending on a platform and version, so don't assume that its size is 2. The ``event`` element specifies which events happened with a stream and is a combination of ``select.POLL*`` constants described above. Note that flags ``select.POLLHUP`` and ``select.POLLERR`` can be returned at any time (even if were not asked for), and must be acted on accordingly (the corresponding stream unregistered from poll and likely closed), because otherwise all further invocations of `poll()` may return immediately with these flags set for this stream again. In case of timeout, an empty list is returned. .. admonition:: Difference to CPython :class: attention Tuples returned may contain more than 2 elements as described above. """ def ipoll( self, timeout: int = -1, flags: int = 0, / ) -> Iterator[tuple[Any, int, Any, ...]]: """ Like :meth:`poll.poll`, but instead returns an iterator which yields a `callee-owned tuple`. This function provides an efficient, allocation-free way to poll on streams. If *flags* is 1, one-shot behaviour for events is employed: streams for which events happened will have their event masks automatically reset (equivalent to ``poll.modify(obj, 0)``), so new events for such a stream won't be processed until new mask is set with `poll.modify()`. This behaviour is useful for asynchronous I/O schedulers. .. admonition:: Difference to CPython :class: attention This function is a MicroPython extension. """ ================================================ FILE: typehints/stdlib/usocket.pyi ================================================ """ socket. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/socket.rst. ****************************** .. module:: socket :synopsis: socket module |see_cpython_module| :mod:`python:socket`. This module provides access to the BSD socket interface. .. admonition:: Difference to CPython :class: attention For efficiency and consistency, socket objects in MicroPython implement a `stream` (file-like) interface directly. In CPython, you need to convert a socket to a file-like object using `makefile()` method. This method is still supported by MicroPython (but is a no-op), so where compatibility with CPython matters, be sure to use it. Socket address format(s) ------------------------ The native socket address format of the ``socket`` module is an opaque data type returned by `getaddrinfo` function, which must be used to resolve textual address (including numeric addresses):: sockaddr = socket.getaddrinfo('www.micropython.org', 80)[0][-1] # You must use getaddrinfo() even for numeric addresses sockaddr = socket.getaddrinfo('127.0.0.1', 80)[0][-1] # Now you can use that address sock.connect(addr) Using `getaddrinfo` is the most efficient (both in terms of memory and processing power) and portable way to work with addresses. However, ``socket`` module (note the difference with native MicroPython ``socket`` module described here) provides CPython-compatible way to specify addresses using tuples, as described below. Note that depending on a :term:`MicroPython port`, ``socket`` module can be builtin or need to be installed from `micropython-lib` (as in the case of :term:`MicroPython Unix port`), and some ports still accept only numeric addresses in the tuple format, and require to use `getaddrinfo` function to resolve domain names. Summing up: * Always use `getaddrinfo` when writing portable applications. * Tuple addresses described below can be used as a shortcut for quick hacks and interactive use, if your port supports them. Tuple address format for ``socket`` module: * IPv4: *(ipv4_address, port)*, where *ipv4_address* is a string with dot-notation numeric IPv4 address, e.g. ``"8.8.8.8"``, and *port* is and integer port number in the range 1-65535. Note the domain names are not accepted as *ipv4_address*, they should be resolved first using `socket.getaddrinfo()`. * IPv6: *(ipv6_address, port, flowinfo, scopeid)*, where *ipv6_address* is a string with colon-notation numeric IPv6 address, e.g. ``"2001:db8::1"``, and *port* is an integer port number in the range 1-65535. *flowinfo* must be 0. *scopeid* is the interface scope identifier for link-local addresses. Note the domain names are not accepted as *ipv6_address*, they should be resolved first using `socket.getaddrinfo()`. Availability of IPv6 support depends on a :term:`MicroPython port`. .. exception:: socket.error MicroPython does NOT have this exception. .. admonition:: Difference to CPython :class: attention CPython used to have a ``socket.error`` exception which is now deprecated, and is an alias of `OSError`. In MicroPython, use `OSError` directly. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Final, Any, Literal, overload from uio import AnyReadableBuf, AnyWritableBuf _Address: Final = tuple[str, int] | tuple[str, int, int, int] | str def socket( af: int = "AF_INET", type: int = "SOCK_STREAM", proto: int = "IPPROTO_TCP", /, ) -> "Socket": """ Create a new socket using the given address family, socket type and protocol number. Note that specifying *proto* in most cases is not required (and not recommended, as some MicroPython ports may omit ``IPPROTO_*`` constants). Instead, *type* argument will select needed protocol automatically:: # Create STREAM TCP socket socket(AF_INET, SOCK_STREAM) # Create DGRAM UDP socket socket(AF_INET, SOCK_DGRAM) """ def getaddrinfo( host: str, port: int, af: int = 0, type: int = 0, proto: int = 0, flags: int = 0, /, ) -> list[tuple[int, int, int, str, tuple[str, int] | tuple[str, int, int, int]]]: """ Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. Arguments *af*, *type*, and *proto* (which have the same meaning as for the `socket()` function) can be used to filter which kind of addresses are returned. If a parameter is not specified or zero, all combinations of addresses can be returned (requiring filtering on the user side). The resulting list of 5-tuples has the following structure:: (family, type, proto, canonname, sockaddr) The following example shows how to connect to a given url:: s = socket.socket() # This assumes that if "type" is not specified, an address for # SOCK_STREAM will be returned, which may be not true s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][-1]) Recommended use of filtering params:: s = socket.socket() # Guaranteed to return an address which can be connect'ed to for # stream operation. s.connect(socket.getaddrinfo('www.micropython.org', 80, 0, SOCK_STREAM)[0][-1]) .. admonition:: Difference to CPython :class: attention CPython raises a ``socket.gaierror`` exception (`OSError` subclass) in case of error in this function. MicroPython doesn't have ``socket.gaierror`` and raises OSError directly. Note that error numbers of `getaddrinfo()` form a separate namespace and may not match error numbers from the :mod:`errno` module. To distinguish `getaddrinfo()` errors, they are represented by negative numbers, whereas standard system errors are positive numbers (error numbers are accessible using ``e.args[0]`` property from an exception object). The use of negative values is a provisional detail which may change in the future. """ def inet_ntop(af: int, bin_addr: bytes, /) -> str: """ Convert a binary network address *bin_addr* of the given address family *af* to a textual representation:: >>> socket.inet_ntop(socket.AF_INET, b"\x7f\0\0\1") '127.0.0.1' """ def inet_pton(af: int, txt_addr: str, /) -> bytes: """ Convert a textual network address *txt_addr* of the given address family *af* to a binary representation:: >>> socket.inet_pton(socket.AF_INET, "1.2.3.4") b'\x01\x02\x03\x04' """ AF_INET: Final[int] = ... """ Address family types. Availability depends on a particular :term:`MicroPython port`. """ AF_INET6: Final[int] = ... """ Address family types. Availability depends on a particular :term:`MicroPython port`. """ SOCK_STREAM: Final[int] = ... """ Socket types. """ SOCK_DGRAM: Final[int] = ... """ Socket types. """ IPPROTO_UDP: Final[int] = ... """ IP protocol numbers. Availability depends on a particular :term:`MicroPython port`. Note that you don't need to specify these in a call to `socket.socket()`, because `SOCK_STREAM` socket type automatically selects `IPPROTO_TCP`, and `SOCK_DGRAM` - `IPPROTO_UDP`. Thus, the only real use of these constants is as an argument to `setsockopt()`. """ IPPROTO_TCP: Final[int] = ... """ IP protocol numbers. Availability depends on a particular :term:`MicroPython port`. Note that you don't need to specify these in a call to `socket.socket()`, because `SOCK_STREAM` socket type automatically selects `IPPROTO_TCP`, and `SOCK_DGRAM` - `IPPROTO_UDP`. Thus, the only real use of these constants is as an argument to `setsockopt()`. """ SOL_SOCKET: Final[int] = ... """ Socket option levels (an argument to `setsockopt()`). The exact inventory depends on a :term:`MicroPython port`. """ SO_REUSEADDR: Final[int] = ... """ Socket options (an argument to `setsockopt()`). The exact inventory depends on a :term:`MicroPython port`. """ IPPROTO_SEC: Final[int] = ... """ Special protocol value to create SSL-compatible socket. Constants specific to WiPy: """ class Socket: """ A unix like socket, for more information see module ``socket``'s description. The name, `Socket`, used for typing is not the same as the runtime name, `socket` (note lowercase `s`). The reason for this difference is that the runtime uses `socket` as both a class name and as a method name and this is not possible within code written entirely in Python and therefore not possible within typing code. """ def close(self) -> None: """ Mark the socket closed and release all resources. Once that happens, all future operations on the socket object will fail. The remote end will receive EOF indication if supported by protocol. Sockets are automatically closed when they are garbage-collected, but it is recommended to `close()` them explicitly as soon you finished working with them. """ def bind(self, address: _Address | bytes, /) -> None: """ Bind the socket to *address*. The socket must not already be bound. """ def listen(self, backlog: int = ..., /) -> None: """ Enable a server to accept connections. If *backlog* is specified, it must be at least 0 (if it's lower, it will be set to 0); and specifies the number of unaccepted connections that the system will allow before refusing new connections. If not specified, a default reasonable value is chosen. """ def accept(self) -> None: """ Accept a connection. The socket must be bound to an address and listening for connections. The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection. """ def connect(self, address: _Address | bytes, /) -> None: """ Connect to a remote socket at *address*. """ def send(self, bytes: AnyReadableBuf, /) -> int: """ Send data to the socket. The socket must be connected to a remote socket. Returns number of bytes sent, which may be smaller than the length of data ("short write"). """ def sendall(self, bytes: AnyReadableBuf, /) -> None: """ Send all data to the socket. The socket must be connected to a remote socket. Unlike `send()`, this method will try to send all of data, by sending data chunk by chunk consecutively. The behaviour of this method on non-blocking sockets is undefined. Due to this, on MicroPython, it's recommended to use `write()` method instead, which has the same "no short writes" policy for blocking sockets, and will return number of bytes sent on non-blocking sockets. """ def recv(self, bufsize: int, /) -> bytes: """ Receive data from the socket. The return value is a bytes object representing the data received. The maximum amount of data to be received at once is specified by bufsize. """ def sendto(self, bytes: AnyReadableBuf, address: _Address, /) -> int: """ Send data to the socket. The socket should not be connected to a remote socket, since the destination socket is specified by *address*. """ def recvfrom(self, bufsize: int, /) -> tuple[bytes, Any]: """ Receive data from the socket. The return value is a pair *(bytes, address)* where *bytes* is a bytes object representing the data received and *address* is the address of the socket sending the data. """ def setsockopt( self, level: int, optname: int, value: AnyReadableBuf | int, / ) -> None: """ Set the value of the given socket option. The needed symbolic constants are defined in the socket module (SO_* etc.). The *value* can be an integer or a bytes-like object representing a buffer. """ def settimeout(self, value: float | None, /) -> None: """ **Note**: Not every port supports this method, see below. Set a timeout on blocking socket operations. The value argument can be a nonnegative floating point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations will raise an `OSError` exception if the timeout period value has elapsed before the operation has completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket is put in blocking mode. Not every :term:`MicroPython port` supports this method. A more portable and generic solution is to use `select.poll` object. This allows to wait on multiple objects at the same time (and not just on sockets, but on generic `stream` objects which support polling). Example:: # Instead of: s.settimeout(1.0) # time in seconds s.read(10) # may timeout # Use: poller = select.poll() poller.register(s, select.POLLIN) res = poller.poll(1000) # time in milliseconds if not res: # s is still not ready for input, i.e. operation timed out .. admonition:: Difference to CPython :class: attention CPython raises a ``socket.timeout`` exception in case of timeout, which is an `OSError` subclass. MicroPython raises an OSError directly instead. If you use ``except OSError:`` to catch the exception, your code will work both in MicroPython and CPython. """ def setblocking(self, value: bool, /) -> None: """ Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking, else to blocking mode. This method is a shorthand for certain `settimeout()` calls: * ``sock.setblocking(True)`` is equivalent to ``sock.settimeout(None)`` * ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0)`` """ @overload def makefile( self, mode: Literal["rb", "wb", "rwb"] = "rb", buffering: int = 0, / ) -> Socket: """ Return a file object associated with the socket. The exact returned type depends on the arguments given to makefile(). The support is limited to binary modes only ('rb', 'wb', and 'rwb'). CPython's arguments: *encoding*, *errors* and *newline* are not supported. .. admonition:: Difference to CPython :class: attention As MicroPython doesn't support buffered streams, values of *buffering* parameter is ignored and treated as if it was 0 (unbuffered). .. admonition:: Difference to CPython :class: attention Closing the file object returned by makefile() WILL close the original socket as well. """ @overload def makefile(self, mode: str, buffering: int = 0, /) -> Socket: """ Return a file object associated with the socket. The exact returned type depends on the arguments given to makefile(). The support is limited to binary modes only ('rb', 'wb', and 'rwb'). CPython's arguments: *encoding*, *errors* and *newline* are not supported. .. admonition:: Difference to CPython :class: attention As MicroPython doesn't support buffered streams, values of *buffering* parameter is ignored and treated as if it was 0 (unbuffered). .. admonition:: Difference to CPython :class: attention Closing the file object returned by makefile() WILL close the original socket as well. """ @overload def read(self) -> bytes: """ Read up to size bytes from the socket. Return a bytes object. If *size* is not given, it reads all data available from the socket until EOF; as such the method will not return until the socket is closed. This function tries to read as much data as requested (no "short reads"). This may be not possible with non-blocking socket though, and then less data will be returned. """ @overload def read(self, size: int, /) -> bytes: """ Read up to size bytes from the socket. Return a bytes object. If *size* is not given, it reads all data available from the socket until EOF; as such the method will not return until the socket is closed. This function tries to read as much data as requested (no "short reads"). This may be not possible with non-blocking socket though, and then less data will be returned. """ @overload def readinto(self, buf: AnyWritableBuf, /) -> int | None: """ Read bytes into the *buf*. If *nbytes* is specified then read at most that many bytes. Otherwise, read at most *len(buf)* bytes. Just as `read()`, this method follows "no short reads" policy. Return value: number of bytes read and stored into *buf*. """ @overload def readinto(self, buf: AnyWritableBuf, nbytes: int, /) -> int | None: """ Read bytes into the *buf*. If *nbytes* is specified then read at most that many bytes. Otherwise, read at most *len(buf)* bytes. Just as `read()`, this method follows "no short reads" policy. Return value: number of bytes read and stored into *buf*. """ def readline(self) -> bytes: """ Read a line, ending in a newline character. Return value: the line read. """ def write(self, buf: AnyReadableBuf, /) -> int | None: """ Write the buffer of bytes to the socket. This function will try to write all data to a socket (no "short writes"). This may be not possible with a non-blocking socket though, and returned value will be less than the length of *buf*. Return value: number of bytes written. """ ================================================ FILE: typehints/stdlib/ussl.pyi ================================================ """ TLS/SSL wrapper for socket objects. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/ssl.rst. |see_cpython_module| :mod:`python:ssl`. This module provides access to Transport Layer Security (previously and widely known as “Secure Sockets Layer”) encryption and peer authentication facilities for network sockets, both client-side and server-side. .. admonition:: Difference to CPython :class: attention The CPython version of ``ssl`` uses ``SSLError``. This exception does NOT exist. Instead its base class, OSError, is used. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Final from uio import StrOrBytesPath from usocket import Socket def wrap_socket( sock: Socket, server_side: bool = False, keyfile: StrOrBytesPath | None = None, certfile: StrOrBytesPath | None = None, cert_reqs: int = "CERT_NONE", ca_certs: str | None = None, do_handshake: bool = True, /, ) -> Socket: """ Takes a `stream` *sock* (usually socket.socket instance of ``SOCK_STREAM`` type), and returns an instance of ssl.SSLSocket, which wraps the underlying stream in an SSL context. Returned object has the usual `stream` interface methods like ``read()``, ``write()``, etc. A server-side SSL socket should be created from a normal socket returned from :meth:`~socket.socket.accept()` on a non-SSL listening server socket. - *do_handshake* determines whether the handshake is done as part of the ``wrap_socket`` or whether it is deferred to be done as part of the initial reads or writes (there is no ``do_handshake`` method as in CPython). For blocking sockets doing the handshake immediately is standard. For non-blocking sockets (i.e. when the *sock* passed into ``wrap_socket`` is in non-blocking mode) the handshake should generally be deferred because otherwise ``wrap_socket`` blocks until it completes. Note that in AXTLS the handshake can be deferred until the first read or write but it then blocks until completion. Depending on the underlying module implementation in a particular :term:`MicroPython port`, some or all keyword arguments above may be not supported. """ CERT_NONE: Final[int] = ... """ Supported values for *cert_reqs* parameter. """ CERT_OPTIONAL: Final[int] = ... """ Supported values for *cert_reqs* parameter. """ CERT_REQUIRED: Final[int] = ... """ Supported values for *cert_reqs* parameter. """ ================================================ FILE: typehints/stdlib/ustruct.pyi ================================================ """ pack and unpack primitive data types. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/struct.rst. ===================================================== .. module:: struct :synopsis: pack and unpack primitive data types |see_cpython_module| :mod:`python:struct`. Supported size/byte order prefixes: ``@``, ``<``, ``>``, ``!``. Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``, ``L``, ``q``, ``Q``, ``s``, ``P``, ``f``, ``d`` (the latter 2 depending on the floating-point support). .. admonition:: Difference to CPython :class: attention Whitespace is not supported in format strings. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Any from uio import AnyReadableBuf, AnyWritableBuf def calcsize(fmt: str | bytes, /,) -> int: """ Return the number of bytes needed to store the given *fmt*. """ def pack(fmt: str | bytes, /, *v: Any) -> bytes: """ Pack the values *v1*, *v2*, ... according to the format string *fmt*. The return value is a bytes object encoding the values. """ def pack_into( fmt: str | bytes, buffer: AnyWritableBuf, offset: int, /, *v: Any ) -> None: """ Pack the values *v1*, *v2*, ... according to the format string *fmt* into a *buffer* starting at *offset*. *offset* may be negative to count from the end of *buffer*. """ def unpack(fmt: str | bytes, data: AnyReadableBuf, /) -> tuple[Any, ...]: """ Unpack from the *data* according to the format string *fmt*. The return value is a tuple of the unpacked values. """ def unpack_from( fmt: str | bytes, data: AnyReadableBuf, offset: int = 0, / ) -> tuple[Any, ...]: """ Unpack from the *data* starting at *offset* according to the format string *fmt*. *offset* may be negative to count from the end of *buffer*. The return value is a tuple of the unpacked values. """ ================================================ FILE: typehints/stdlib/usys.pyi ================================================ """ system specific functions. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/sys.rst. ======================================= .. module:: sys :synopsis: system specific functions |see_cpython_module| :mod:`python:sys`. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Callable, Final, Literal, NoReturn from uio import IOBase class Implementation(tuple[str, tuple[int, int, int], int]): name: str version: tuple[int, int, int] mpy: int class ModuleType: __class__: str __name__: str def exit(retval: object = 0, /) -> NoReturn: """ Terminate current program with a given exit code. Underlyingly, this function raise as `SystemExit` exception. If an argument is given, its value given as an argument to `SystemExit`. """ def atexit(func: Callable[[], None] | None, /) -> Callable[[], None] | None: """ Register *func* to be called upon termination. *func* must be a callable that takes no arguments, or ``None`` to disable the call. The ``atexit`` function will return the previous value set by this function, which is initially ``None``. .. admonition:: Difference to CPython :class: attention This function is a MicroPython extension intended to provide similar functionality to the :mod:`atexit` module in CPython. """ def print_exception(exc: BaseException, file: IOBase[str] = "stdout", /) -> None: """ Print exception with a traceback to a file-like object *file* (or `sys.stdout` by default). .. admonition:: Difference to CPython :class: attention This is simplified version of a function which appears in the ``traceback`` module in CPython. Unlike ``traceback.print_exception()``, this function takes just exception value instead of exception type, exception value, and traceback object; *file* argument should be positional; further arguments are not supported. CPython-compatible ``traceback`` module can be found in `micropython-lib`. """ argv: Final[list[str]] = ... """ A mutable list of arguments the current program was started with. """ byteorder: Final[Literal["little", "big"]] = ... """ The byte order of the system (``"little"`` or ``"big"``). """ implementation: Final[Implementation] = ... """ Object with information about the current Python implementation. For MicroPython, it has following attributes: * *name* - string "micropython" * *version* - tuple (major, minor, micro), e.g. (1, 7, 0) This object is the recommended way to distinguish MicroPython from other Python implementations (note that it still may not exist in the very minimal ports). .. admonition:: Difference to CPython :class: attention CPython mandates more attributes for this object, but the actual useful bare minimum is implemented in MicroPython. """ maxsize: Final[int] = ... """ Maximum value which a native integer type can hold on the current platform, or maximum value representable by MicroPython integer type, if it's smaller than platform max value (that is the case for MicroPython ports without long int support). This attribute is useful for detecting "bitness" of a platform (32-bit vs 64-bit, etc.). It's recommended to not compare this attribute to some value directly, but instead count number of bits in it:: bits = 0 v = sys.maxsize while v: bits += 1 v >>= 1 if bits > 32: # 64-bit (or more) platform ... else: # 32-bit (or less) platform # Note that on 32-bit platform, value of bits may be less than 32 # (e.g. 31) due to peculiarities described above, so use "> 16", # "> 32", "> 64" style of comparisons. """ modules: Final[dict[str, ModuleType]] = ... """ Dictionary of loaded modules. On some ports, it may not include builtin modules. """ path: Final[list[str]] = ... """ A mutable list of directories to search for imported modules. """ platform: Final[str] = ... """ The platform that MicroPython is running on. For OS/RTOS ports, this is usually an identifier of the OS, e.g. ``"linux"``. For baremetal ports it is an identifier of a board, e.g. ``"pyboard"`` for the original MicroPython reference board. It thus can be used to distinguish one board from another. If you need to check whether your program runs on MicroPython (vs other Python implementation), use `sys.implementation` instead. """ stderr: Final[IOBase[str]] = ... """ Standard error `stream`. """ stdin: Final[IOBase[str]] = ... """ Standard input `stream`. """ stdout: Final[IOBase[str]] = ... """ Standard output `stream`. """ version: Final[str] = ... """ Python language version that this implementation conforms to, as a string. """ version_info: Final[tuple[int, int, int]] = ... """ Python language version that this implementation conforms to, as a tuple of ints. .. admonition:: Difference to CPython :class: attention Only the first three version numbers (major, minor, micro) are supported and they can be referenced only by index, not by name. """ ================================================ FILE: typehints/stdlib/utime.pyi ================================================ """ time related functions. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/time.rst. ===================================== .. module:: time :synopsis: time related functions |see_cpython_module| :mod:`python:time`. The ``time`` module provides functions for getting the current time and date, measuring time intervals, and for delays. **Time Epoch**: Unix port uses standard for POSIX systems epoch of 1970-01-01 00:00:00 UTC. However, embedded ports use epoch of 2000-01-01 00:00:00 UTC. **Maintaining actual calendar date/time**: This requires a Real Time Clock (RTC). On systems with underlying OS (including some RTOS), an RTC may be implicit. Setting and maintaining actual calendar time is responsibility of OS/RTOS and is done outside of MicroPython, it just uses OS API to query date/time. On baremetal ports however system time depends on ``machine.RTC()`` object. The current calendar time may be set using ``machine.RTC().datetime(tuple)`` function, and maintained by following means: * By a backup battery (which may be an additional, optional component for a particular board). * Using networked time protocol (requires setup by a port/user). * Set manually by a user on each power-up (many boards then maintain RTC time across hard resets, though some may require setting it again in such case). If actual calendar time is not maintained with a system/MicroPython RTC, functions below which require reference to current absolute time may behave not as expected. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from typing import Final, TypeVar class _TicksMs: ... class _TicksUs: ... class _TicksCPU: ... _Ticks: Final = TypeVar("_Ticks", _TicksMs, _TicksUs, _TicksCPU, int) def gmtime(secs: int | None = None, /) -> tuple[int, int, int, int, int, int, int, int]: """ Convert the time *secs* expressed in seconds since the Epoch (see above) into an 8-tuple which contains: ``(year, month, mday, hour, minute, second, weekday, yearday)`` If *secs* is not provided or None, then the current time from the RTC is used. The `gmtime()` function returns a date-time tuple in UTC, and `localtime()` returns a date-time tuple in local time. The format of the entries in the 8-tuple are: * year includes the century (for example 2014). * month is 1-12 * mday is 1-31 * hour is 0-23 * minute is 0-59 * second is 0-59 * weekday is 0-6 for Mon-Sun * yearday is 1-366 """ def localtime( secs: int | None = None, / ) -> tuple[int, int, int, int, int, int, int, int]: """ Convert the time *secs* expressed in seconds since the Epoch (see above) into an 8-tuple which contains: ``(year, month, mday, hour, minute, second, weekday, yearday)`` If *secs* is not provided or None, then the current time from the RTC is used. The `gmtime()` function returns a date-time tuple in UTC, and `localtime()` returns a date-time tuple in local time. The format of the entries in the 8-tuple are: * year includes the century (for example 2014). * month is 1-12 * mday is 1-31 * hour is 0-23 * minute is 0-59 * second is 0-59 * weekday is 0-6 for Mon-Sun * yearday is 1-366 """ def mktime(local_time: tuple[int, int, int, int, int, int, int, int], /) -> int: """ This is inverse function of localtime. It's argument is a full 8-tuple which expresses a time as per localtime. It returns an integer which is the number of seconds since Jan 1, 2000. """ def sleep(seconds: float, /) -> None: """ Sleep for the given number of seconds. Some boards may accept *seconds* as a floating-point number to sleep for a fractional number of seconds. Note that other boards may not accept a floating-point argument, for compatibility with them use `sleep_ms()` and `sleep_us()` functions. """ def sleep_ms(ms: int, /) -> None: """ Delay for given number of milliseconds, should be positive or 0. This function will delay for at least the given number of milliseconds, but may take longer than that if other processing must take place, for example interrupt handlers or other threads. Passing in 0 for *ms* will still allow this other processing to occur. Use `sleep_us()` for more precise delays. """ def sleep_us(us: int, /) -> None: """ Delay for given number of microseconds, should be positive or 0. This function attempts to provide an accurate delay of at least *us* microseconds, but it may take longer if the system has other higher priority processing to perform. """ def ticks_ms() -> _TicksMs: """ Returns an increasing millisecond counter with an arbitrary reference point, that wraps around after some value. The wrap-around value is not explicitly exposed, but we will refer to it as *TICKS_MAX* to simplify discussion. Period of the values is *TICKS_PERIOD = TICKS_MAX + 1*. *TICKS_PERIOD* is guaranteed to be a power of two, but otherwise may differ from port to port. The same period value is used for all of `ticks_ms()`, `ticks_us()`, `ticks_cpu()` functions (for simplicity). Thus, these functions will return a value in range [*0* .. *TICKS_MAX*], inclusive, total *TICKS_PERIOD* values. Note that only non-negative values are used. For the most part, you should treat values returned by these functions as opaque. The only operations available for them are `ticks_diff()` and `ticks_add()` functions described below. Note: Performing standard mathematical operations (+, -) or relational operators (<, <=, >, >=) directly on these value will lead to invalid result. Performing mathematical operations and then passing their results as arguments to `ticks_diff()` or `ticks_add()` will also lead to invalid results from the latter functions. """ def ticks_us() -> _TicksUs: """ Just like `ticks_ms()` above, but in microseconds. """ def ticks_cpu() -> _TicksCPU: """ Similar to `ticks_ms()` and `ticks_us()`, but with the highest possible resolution in the system. This is usually CPU clocks, and that's why the function is named that way. But it doesn't have to be a CPU clock, some other timing source available in a system (e.g. high-resolution timer) can be used instead. The exact timing unit (resolution) of this function is not specified on ``time`` module level, but documentation for a specific port may provide more specific information. This function is intended for very fine benchmarking or very tight real-time loops. Avoid using it in portable code. Availability: Not every port implements this function. """ def ticks_add(ticks: _Ticks, delta: int, /) -> _Ticks: """ Offset ticks value by a given number, which can be either positive or negative. Given a *ticks* value, this function allows to calculate ticks value *delta* ticks before or after it, following modular-arithmetic definition of tick values (see `ticks_ms()` above). *ticks* parameter must be a direct result of call to `ticks_ms()`, `ticks_us()`, or `ticks_cpu()` functions (or from previous call to `ticks_add()`). However, *delta* can be an arbitrary integer number or numeric expression. `ticks_add()` is useful for calculating deadlines for events/tasks. (Note: you must use `ticks_diff()` function to work with deadlines.) Examples:: # Find out what ticks value there was 100ms ago print(ticks_add(time.ticks_ms(), -100)) # Calculate deadline for operation and test for it deadline = ticks_add(time.ticks_ms(), 200) while ticks_diff(deadline, time.ticks_ms()) > 0: do_a_little_of_something() # Find out TICKS_MAX used by this port print(ticks_add(0, -1)) """ def ticks_diff(ticks1: _Ticks, ticks2: _Ticks, /) -> int: """ Measure ticks difference between values returned from `ticks_ms()`, `ticks_us()`, or `ticks_cpu()` functions, as a signed value which may wrap around. The argument order is the same as for subtraction operator, ``ticks_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``. However, values returned by `ticks_ms()`, etc. functions may wrap around, so directly using subtraction on them will produce incorrect result. That is why `ticks_diff()` is needed, it implements modular (or more specifically, ring) arithmetics to produce correct result even for wrap-around values (as long as they not too distant inbetween, see below). The function returns **signed** value in the range [*-TICKS_PERIOD/2* .. *TICKS_PERIOD/2-1*] (that's a typical range definition for two's-complement signed binary integers). If the result is negative, it means that *ticks1* occurred earlier in time than *ticks2*. Otherwise, it means that *ticks1* occurred after *ticks2*. This holds **only** if *ticks1* and *ticks2* are apart from each other for no more than *TICKS_PERIOD/2-1* ticks. If that does not hold, incorrect result will be returned. Specifically, if two tick values are apart for *TICKS_PERIOD/2-1* ticks, that value will be returned by the function. However, if *TICKS_PERIOD/2* of real-time ticks has passed between them, the function will return *-TICKS_PERIOD/2* instead, i.e. result value will wrap around to the negative range of possible values. Informal rationale of the constraints above: Suppose you are locked in a room with no means to monitor passing of time except a standard 12-notch clock. Then if you look at dial-plate now, and don't look again for another 13 hours (e.g., if you fall for a long sleep), then once you finally look again, it may seem to you that only 1 hour has passed. To avoid this mistake, just look at the clock regularly. Your application should do the same. "Too long sleep" metaphor also maps directly to application behaviour: don't let your application run any single task for too long. Run tasks in steps, and do time-keeping inbetween. `ticks_diff()` is designed to accommodate various usage patterns, among them: * Polling with timeout. In this case, the order of events is known, and you will deal only with positive results of `ticks_diff()`:: # Wait for GPIO pin to be asserted, but at most 500us start = time.ticks_us() while pin.value() == 0: if time.ticks_diff(time.ticks_us(), start) > 500: raise TimeoutError * Scheduling events. In this case, `ticks_diff()` result may be negative if an event is overdue:: # This code snippet is not optimized now = time.ticks_ms() scheduled_time = task.scheduled_time() if ticks_diff(scheduled_time, now) > 0: print("Too early, let's nap") sleep_ms(ticks_diff(scheduled_time, now)) task.run() elif ticks_diff(scheduled_time, now) == 0: print("Right at time!") task.run() elif ticks_diff(scheduled_time, now) < 0: print("Oops, running late, tell task to run faster!") task.run(run_faster=true) Note: Do not pass `time()` values to `ticks_diff()`, you should use normal mathematical operations on them. But note that `time()` may (and will) also overflow. This is known as https://en.wikipedia.org/wiki/Year_2038_problem . """ def time() -> int: """ Returns the number of seconds, as an integer, since the Epoch, assuming that underlying RTC is set and maintained as described above. If an RTC is not set, this function returns number of seconds since a port-specific reference point in time (for embedded boards without a battery-backed RTC, usually since power up or reset). If you want to develop portable MicroPython application, you should not rely on this function to provide higher than second precision. If you need higher precision, absolute timestamps, use `time_ns()`. If relative times are acceptable then use the `ticks_ms()` and `ticks_us()` functions. If you need calendar time, `gmtime()` or `localtime()` without an argument is a better choice. .. admonition:: Difference to CPython :class: attention In CPython, this function returns number of seconds since Unix epoch, 1970-01-01 00:00 UTC, as a floating-point, usually having microsecond precision. With MicroPython, only Unix port uses the same Epoch, and if floating-point precision allows, returns sub-second precision. Embedded hardware usually doesn't have floating-point precision to represent both long time ranges and subsecond precision, so they use integer value with second precision. Some embedded hardware also lacks battery-powered RTC, so returns number of seconds since last power-up or from other relative, hardware-specific point (e.g. reset). """ def time_ns() -> int: """ Similar to `time()` but returns nanoseconds since the Epoch, as an integer (usually a big integer, so will allocate on the heap). """ ================================================ FILE: typehints/stdlib/uzlib.pyi ================================================ """ zlib decompression. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/zlib.rst. ================================= .. module:: zlib :synopsis: zlib decompression |see_cpython_module| :mod:`python:zlib`. This module allows to decompress binary data compressed with `DEFLATE algorithm `_ (commonly used in zlib library and gzip archiver). Compression is not yet implemented. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from uio import IOBase def decompress(data: bytes, wbits: int = 0, bufsize: int = 0, /) -> bytes: """ Return decompressed *data* as bytes. *wbits* is DEFLATE dictionary window size used during compression (8-15, the dictionary size is power of 2 of that value). Additionally, if value is positive, *data* is assumed to be zlib stream (with zlib header). Otherwise, if it's negative, it's assumed to be raw DEFLATE stream. *bufsize* parameter is for compatibility with CPython and is ignored. """ class DecompIO(IOBase[bytes]): """ Steam wrapper that decompresses a given stream containing zlib compressed data. """ def __init__(self, stream: IOBase[bytes], wbits: int = 0, /): """ Create a `stream` wrapper which allows transparent decompression of compressed data in another *stream*. This allows to process compressed streams with data larger than available heap size. In addition to values described in :func:`decompress`, *wbits* may take values 24..31 (16 + 8..15), meaning that input stream has gzip header. .. admonition:: Difference to CPython :class: attention This class is MicroPython extension. It's included on provisional basis and may be changed considerably or removed in later versions. """ ================================================ FILE: typehints/stdlib/zlib.pyi ================================================ """ zlib decompression. Descriptions taken from: https://raw.githubusercontent.com/micropython/micropython/master/docs/library/zlib.rst. ================================= .. module:: zlib :synopsis: zlib decompression |see_cpython_module| :mod:`python:zlib`. This module allows to decompress binary data compressed with `DEFLATE algorithm `_ (commonly used in zlib library and gzip archiver). Compression is not yet implemented. """ __author__ = "Howard C Lovatt" __copyright__ = "Howard C Lovatt, 2020 onwards." __license__ = "MIT https://opensource.org/licenses/MIT (as used by MicroPython)." __version__ = "7.3.0" # Version set by https://github.com/hlovatt/tag2ver from uio import IOBase def decompress(data: bytes, wbits: int = 0, bufsize: int = 0, /) -> bytes: """ Return decompressed *data* as bytes. *wbits* is DEFLATE dictionary window size used during compression (8-15, the dictionary size is power of 2 of that value). Additionally, if value is positive, *data* is assumed to be zlib stream (with zlib header). Otherwise, if it's negative, it's assumed to be raw DEFLATE stream. *bufsize* parameter is for compatibility with CPython and is ignored. """ class DecompIO(IOBase[bytes]): """ Steam wrapper that decompresses a given stream containing zlib compressed data. """ def __init__(self, stream: IOBase[bytes], wbits: int = 0, /): """ Create a `stream` wrapper which allows transparent decompression of compressed data in another *stream*. This allows to process compressed streams with data larger than available heap size. In addition to values described in :func:`decompress`, *wbits* may take values 24..31 (16 + 8..15), meaning that input stream has gzip header. .. admonition:: Difference to CPython :class: attention This class is MicroPython extension. It's included on provisional basis and may be changed considerably or removed in later versions. """