├── .gitattributes ├── .github ├── PULL_REQUEST_TEMPLATE │ └── adafruit_circuitpython_pr.md └── workflows │ ├── build.yml │ ├── failure-help-text.yml │ ├── release_gh.yml │ └── release_pypi.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yaml ├── CODE_OF_CONDUCT.md ├── LICENSE ├── LICENSES ├── CC-BY-4.0.txt ├── MIT.txt └── Unlicense.txt ├── README.rst ├── README.rst.license ├── adafruit_circuitplayground ├── __init__.py ├── bluefruit.py ├── circuit_playground_base.py └── express.py ├── docs ├── _static │ ├── accelerometer.jpg │ ├── accelerometer.jpg.license │ ├── button_a.jpg │ ├── button_a.jpg.license │ ├── button_b.jpg │ ├── button_b.jpg.license │ ├── capacitive_touch_pad_A1.jpg │ ├── capacitive_touch_pad_A1.jpg.license │ ├── capacitive_touch_pad_A2.jpg │ ├── capacitive_touch_pad_A2.jpg.license │ ├── capacitive_touch_pad_A3.jpg │ ├── capacitive_touch_pad_A3.jpg.license │ ├── capacitive_touch_pad_A4.jpg │ ├── capacitive_touch_pad_A4.jpg.license │ ├── capacitive_touch_pad_A5.jpg │ ├── capacitive_touch_pad_A5.jpg.license │ ├── capacitive_touch_pad_A6.jpg │ ├── capacitive_touch_pad_A6.jpg.license │ ├── capacitive_touch_pad_A7.jpg │ ├── capacitive_touch_pad_A7.jpg.license │ ├── capacitive_touch_pads.jpg │ ├── capacitive_touch_pads.jpg.license │ ├── circuit_playground_bluefruit.jpg │ ├── circuit_playground_bluefruit.jpg.license │ ├── circuit_playground_bluefruit_small.jpg │ ├── circuit_playground_bluefruit_small.jpg.license │ ├── circuit_playground_express_small.jpg │ ├── circuit_playground_express_small.jpg.license │ ├── circuitplayground_express.jpg │ ├── circuitplayground_express.jpg.license │ ├── favicon.ico │ ├── favicon.ico.license │ ├── light_sensor.jpg │ ├── light_sensor.jpg.license │ ├── microphone.jpg │ ├── microphone.jpg.license │ ├── neopixel_numbering.jpg │ ├── neopixel_numbering.jpg.license │ ├── red_led.jpg │ ├── red_led.jpg.license │ ├── slide_switch.jpg │ ├── slide_switch.jpg.license │ ├── speaker.jpg │ ├── speaker.jpg.license │ ├── thermistor.jpg │ └── thermistor.jpg.license ├── api.rst ├── api.rst.license ├── conf.py ├── examples.rst ├── examples.rst.license ├── index.rst ├── index.rst.license ├── mocks │ └── keypad.py └── requirements.txt ├── examples ├── circuitplayground_acceleration.py ├── circuitplayground_acceleration_neopixels.py ├── circuitplayground_advanced_examples │ ├── circuitplayground_acceleration_mapping_neopixels.py │ ├── circuitplayground_gravity_pulls_pixel.py │ └── circuitplayground_tilting_arpeggios.py ├── circuitplayground_bluefruit_loud_sound.py ├── circuitplayground_bluefruit_loud_sound_threshold.py ├── circuitplayground_bluefruit_play_mp3.py ├── circuitplayground_bluefruit_sound_level.py ├── circuitplayground_bluefruit_sound_level_plotter.py ├── circuitplayground_button_a.py ├── circuitplayground_button_b.py ├── circuitplayground_buttons_1_neopixel.py ├── circuitplayground_buttons_neopixels.py ├── circuitplayground_ir_receive.py ├── circuitplayground_ir_transmit.py ├── circuitplayground_light.py ├── circuitplayground_light_neopixels.py ├── circuitplayground_light_plotter.py ├── circuitplayground_neopixel_0.py ├── circuitplayground_neopixel_0_1.py ├── circuitplayground_neopixels_fill.py ├── circuitplayground_pixels_simpletest.py ├── circuitplayground_play_file.py ├── circuitplayground_play_file_buttons.py ├── circuitplayground_play_tone.py ├── circuitplayground_play_tone_buttons.py ├── circuitplayground_red_led.py ├── circuitplayground_red_led_blinky.py ├── circuitplayground_red_led_blnky_short.py ├── circuitplayground_shake.py ├── circuitplayground_shake_red_led.py ├── circuitplayground_slide_switch.py ├── circuitplayground_slide_switch_red_led.py ├── circuitplayground_slide_switch_red_led_short.py ├── circuitplayground_sound_meter.py ├── circuitplayground_tap_red_led.py ├── circuitplayground_tapdetect.py ├── circuitplayground_tapdetect_single_double.py ├── circuitplayground_temperature.py ├── circuitplayground_temperature_neopixels.py ├── circuitplayground_temperature_plotter.py ├── circuitplayground_tone.py ├── circuitplayground_touch_a1.py ├── circuitplayground_touch_all.py ├── circuitplayground_touch_pixel_fill_rainbow.py ├── circuitplayground_touch_pixel_rainbow.py ├── dip.mp3 ├── dip.mp3.license ├── dip.wav ├── dip.wav.license ├── rise.mp3 ├── rise.mp3.license ├── rise.wav └── rise.wav.license ├── frozen_cpx └── adafruit_circuitplayground │ ├── __init__.py │ ├── circuit_playground_base.py │ └── express.py ├── optional_requirements.txt ├── pyproject.toml ├── requirements.txt └── ruff.toml /.gitattributes: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2024 Justin Myers for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: Unlicense 4 | 5 | .py text eol=lf 6 | .rst text eol=lf 7 | .txt text eol=lf 8 | .yaml text eol=lf 9 | .toml text eol=lf 10 | .license text eol=lf 11 | .md text eol=lf 12 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | Thank you for contributing! Before you submit a pull request, please read the following. 6 | 7 | Make sure any changes you're submitting are in line with the CircuitPython Design Guide, available here: https://docs.circuitpython.org/en/latest/docs/design_guide.html 8 | 9 | If your changes are to documentation, please verify that the documentation builds locally by following the steps found here: https://adafru.it/build-docs 10 | 11 | Before submitting the pull request, make sure you've run Pylint and Black locally on your code. You can do this manually or using pre-commit. Instructions are available here: https://adafru.it/check-your-code 12 | 13 | Please remove all of this text before submitting. Include an explanation or list of changes included in your PR, as well as, if applicable, a link to any related issues. 14 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | name: Build CI 6 | 7 | on: [pull_request, push] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Run Build CI workflow 14 | uses: adafruit/workflows-circuitpython-libs/build@main 15 | -------------------------------------------------------------------------------- /.github/workflows/failure-help-text.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Scott Shawcroft for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | name: Failure help text 6 | 7 | on: 8 | workflow_run: 9 | workflows: ["Build CI"] 10 | types: 11 | - completed 12 | 13 | jobs: 14 | post-help: 15 | runs-on: ubuntu-latest 16 | if: ${{ github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.event == 'pull_request' }} 17 | steps: 18 | - name: Post comment to help 19 | uses: adafruit/circuitpython-action-library-ci-failed@v1 20 | -------------------------------------------------------------------------------- /.github/workflows/release_gh.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | name: GitHub Release Actions 6 | 7 | on: 8 | release: 9 | types: [published] 10 | 11 | jobs: 12 | upload-release-assets: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Run GitHub Release CI workflow 16 | uses: adafruit/workflows-circuitpython-libs/release-gh@main 17 | with: 18 | github-token: ${{ secrets.GITHUB_TOKEN }} 19 | upload-url: ${{ github.event.release.upload_url }} 20 | -------------------------------------------------------------------------------- /.github/workflows/release_pypi.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | name: PyPI Release Actions 6 | 7 | on: 8 | release: 9 | types: [published] 10 | 11 | jobs: 12 | upload-release-assets: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Run PyPI Release CI workflow 16 | uses: adafruit/workflows-circuitpython-libs/release-pypi@main 17 | with: 18 | pypi-username: ${{ secrets.pypi_username }} 19 | pypi-password: ${{ secrets.pypi_password }} 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Kattni Rembor, written for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | # Do not include files and directories created by your personal work environment, such as the IDE 6 | # you use, except for those already listed here. Pull requests including changes to this file will 7 | # not be accepted. 8 | 9 | # This .gitignore file contains rules for files generated by working with CircuitPython libraries, 10 | # including building Sphinx, testing with pip, and creating a virual environment, as well as the 11 | # MacOS and IDE-specific files generated by using MacOS in general, or the PyCharm or VSCode IDEs. 12 | 13 | # If you find that there are files being generated on your machine that should not be included in 14 | # your git commit, you should create a .gitignore_global file on your computer to include the 15 | # files created by your personal setup. To do so, follow the two steps below. 16 | 17 | # First, create a file called .gitignore_global somewhere convenient for you, and add rules for 18 | # the files you want to exclude from git commits. 19 | 20 | # Second, configure Git to use the exclude file for all Git repositories by running the 21 | # following via commandline, replacing "path/to/your/" with the actual path to your newly created 22 | # .gitignore_global file: 23 | # git config --global core.excludesfile path/to/your/.gitignore_global 24 | 25 | # CircuitPython-specific files 26 | *.mpy 27 | 28 | # Python-specific files 29 | __pycache__ 30 | *.pyc 31 | 32 | # Sphinx build-specific files 33 | _build 34 | 35 | # This file results from running `pip -e install .` in a local repository 36 | *.egg-info 37 | 38 | # Virtual environment-specific files 39 | .env 40 | .venv 41 | 42 | # MacOS-specific files 43 | *.DS_Store 44 | 45 | # IDE-specific files 46 | .idea 47 | .vscode 48 | *~ 49 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2024 Justin Myers for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: Unlicense 4 | 5 | repos: 6 | - repo: https://github.com/pre-commit/pre-commit-hooks 7 | rev: v4.5.0 8 | hooks: 9 | - id: check-yaml 10 | - id: end-of-file-fixer 11 | - id: trailing-whitespace 12 | - repo: https://github.com/astral-sh/ruff-pre-commit 13 | rev: v0.3.4 14 | hooks: 15 | - id: ruff-format 16 | - id: ruff 17 | args: ["--fix"] 18 | - repo: https://github.com/fsfe/reuse-tool 19 | rev: v3.0.1 20 | hooks: 21 | - id: reuse 22 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: Unlicense 4 | 5 | # Read the Docs configuration file 6 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 7 | 8 | # Required 9 | version: 2 10 | 11 | sphinx: 12 | configuration: docs/conf.py 13 | 14 | build: 15 | os: ubuntu-20.04 16 | tools: 17 | python: "3" 18 | 19 | python: 20 | install: 21 | - requirements: docs/requirements.txt 22 | - requirements: requirements.txt 23 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Adafruit Community Code of Conduct 8 | 9 | ## Our Pledge 10 | 11 | In the interest of fostering an open and welcoming environment, we as 12 | contributors and leaders pledge to making participation in our project and 13 | our community a harassment-free experience for everyone, regardless of age, body 14 | size, disability, ethnicity, gender identity and expression, level or type of 15 | experience, education, socio-economic status, nationality, personal appearance, 16 | race, religion, or sexual identity and orientation. 17 | 18 | ## Our Standards 19 | 20 | We are committed to providing a friendly, safe and welcoming environment for 21 | all. 22 | 23 | Examples of behavior that contributes to creating a positive environment 24 | include: 25 | 26 | * Be kind and courteous to others 27 | * Using welcoming and inclusive language 28 | * Being respectful of differing viewpoints and experiences 29 | * Collaborating with other community members 30 | * Gracefully accepting constructive criticism 31 | * Focusing on what is best for the community 32 | * Showing empathy towards other community members 33 | 34 | Examples of unacceptable behavior by participants include: 35 | 36 | * The use of sexualized language or imagery and sexual attention or advances 37 | * The use of inappropriate images, including in a community member's avatar 38 | * The use of inappropriate language, including in a community member's nickname 39 | * Any spamming, flaming, baiting or other attention-stealing behavior 40 | * Excessive or unwelcome helping; answering outside the scope of the question 41 | asked 42 | * Trolling, insulting/derogatory comments, and personal or political attacks 43 | * Promoting or spreading disinformation, lies, or conspiracy theories against 44 | a person, group, organisation, project, or community 45 | * Public or private harassment 46 | * Publishing others' private information, such as a physical or electronic 47 | address, without explicit permission 48 | * Other conduct which could reasonably be considered inappropriate 49 | 50 | The goal of the standards and moderation guidelines outlined here is to build 51 | and maintain a respectful community. We ask that you don’t just aim to be 52 | "technically unimpeachable", but rather try to be your best self. 53 | 54 | We value many things beyond technical expertise, including collaboration and 55 | supporting others within our community. Providing a positive experience for 56 | other community members can have a much more significant impact than simply 57 | providing the correct answer. 58 | 59 | ## Our Responsibilities 60 | 61 | Project leaders are responsible for clarifying the standards of acceptable 62 | behavior and are expected to take appropriate and fair corrective action in 63 | response to any instances of unacceptable behavior. 64 | 65 | Project leaders have the right and responsibility to remove, edit, or 66 | reject messages, comments, commits, code, issues, and other contributions 67 | that are not aligned to this Code of Conduct, or to ban temporarily or 68 | permanently any community member for other behaviors that they deem 69 | inappropriate, threatening, offensive, or harmful. 70 | 71 | ## Moderation 72 | 73 | Instances of behaviors that violate the Adafruit Community Code of Conduct 74 | may be reported by any member of the community. Community members are 75 | encouraged to report these situations, including situations they witness 76 | involving other community members. 77 | 78 | You may report in the following ways: 79 | 80 | In any situation, you may send an email to . 81 | 82 | On the Adafruit Discord, you may send an open message from any channel 83 | to all Community Moderators by tagging @community moderators. You may 84 | also send an open message from any channel, or a direct message to 85 | @kattni#1507, @tannewt#4653, @Dan Halbert#1614, @cater#2442, 86 | @sommersoft#0222, @Mr. Certainly#0472 or @Andon#8175. 87 | 88 | Email and direct message reports will be kept confidential. 89 | 90 | In situations on Discord where the issue is particularly egregious, possibly 91 | illegal, requires immediate action, or violates the Discord terms of service, 92 | you should also report the message directly to Discord. 93 | 94 | These are the steps for upholding our community’s standards of conduct. 95 | 96 | 1. Any member of the community may report any situation that violates the 97 | Adafruit Community Code of Conduct. All reports will be reviewed and 98 | investigated. 99 | 2. If the behavior is an egregious violation, the community member who 100 | committed the violation may be banned immediately, without warning. 101 | 3. Otherwise, moderators will first respond to such behavior with a warning. 102 | 4. Moderators follow a soft "three strikes" policy - the community member may 103 | be given another chance, if they are receptive to the warning and change their 104 | behavior. 105 | 5. If the community member is unreceptive or unreasonable when warned by a 106 | moderator, or the warning goes unheeded, they may be banned for a first or 107 | second offense. Repeated offenses will result in the community member being 108 | banned. 109 | 110 | ## Scope 111 | 112 | This Code of Conduct and the enforcement policies listed above apply to all 113 | Adafruit Community venues. This includes but is not limited to any community 114 | spaces (both public and private), the entire Adafruit Discord server, and 115 | Adafruit GitHub repositories. Examples of Adafruit Community spaces include 116 | but are not limited to meet-ups, audio chats on the Adafruit Discord, or 117 | interaction at a conference. 118 | 119 | This Code of Conduct applies both within project spaces and in public spaces 120 | when an individual is representing the project or its community. As a community 121 | member, you are representing our community, and are expected to behave 122 | accordingly. 123 | 124 | ## Attribution 125 | 126 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 127 | version 1.4, available at 128 | , 129 | and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html). 130 | 131 | For other projects adopting the Adafruit Community Code of 132 | Conduct, please contact the maintainers of those projects for enforcement. 133 | If you wish to use this code of conduct for your own project, consider 134 | explicitly mentioning your moderation policy or making a copy with your 135 | own moderation policy so as to avoid confusion. 136 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Scott Shawcroft for Adafruit Industries 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSES/CC-BY-4.0.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Attribution 4.0 International Creative Commons Corporation 2 | ("Creative Commons") is not a law firm and does not provide legal services 3 | or legal advice. Distribution of Creative Commons public licenses does not 4 | create a lawyer-client or other relationship. Creative Commons makes its licenses 5 | and related information available on an "as-is" basis. Creative Commons gives 6 | no warranties regarding its licenses, any material licensed under their terms 7 | and conditions, or any related information. Creative Commons disclaims all 8 | liability for damages resulting from their use to the fullest extent possible. 9 | 10 | Using Creative Commons Public Licenses 11 | 12 | Creative Commons public licenses provide a standard set of terms and conditions 13 | that creators and other rights holders may use to share original works of 14 | authorship and other material subject to copyright and certain other rights 15 | specified in the public license below. The following considerations are for 16 | informational purposes only, are not exhaustive, and do not form part of our 17 | licenses. 18 | 19 | Considerations for licensors: Our public licenses are intended for use by 20 | those authorized to give the public permission to use material in ways otherwise 21 | restricted by copyright and certain other rights. Our licenses are irrevocable. 22 | Licensors should read and understand the terms and conditions of the license 23 | they choose before applying it. Licensors should also secure all rights necessary 24 | before applying our licenses so that the public can reuse the material as 25 | expected. Licensors should clearly mark any material not subject to the license. 26 | This includes other CC-licensed material, or material used under an exception 27 | or limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors 28 | 29 | Considerations for the public: By using one of our public licenses, a licensor 30 | grants the public permission to use the licensed material under specified 31 | terms and conditions. If the licensor's permission is not necessary for any 32 | reason–for example, because of any applicable exception or limitation to copyright–then 33 | that use is not regulated by the license. Our licenses grant only permissions 34 | under copyright and certain other rights that a licensor has authority to 35 | grant. Use of the licensed material may still be restricted for other reasons, 36 | including because others have copyright or other rights in the material. A 37 | licensor may make special requests, such as asking that all changes be marked 38 | or described. Although not required by our licenses, you are encouraged to 39 | respect those requests where reasonable. More considerations for the public 40 | : wiki.creativecommons.org/Considerations_for_licensees Creative Commons Attribution 41 | 4.0 International Public License 42 | 43 | By exercising the Licensed Rights (defined below), You accept and agree to 44 | be bound by the terms and conditions of this Creative Commons Attribution 45 | 4.0 International Public License ("Public License"). To the extent this Public 46 | License may be interpreted as a contract, You are granted the Licensed Rights 47 | in consideration of Your acceptance of these terms and conditions, and the 48 | Licensor grants You such rights in consideration of benefits the Licensor 49 | receives from making the Licensed Material available under these terms and 50 | conditions. 51 | 52 | Section 1 – Definitions. 53 | 54 | a. Adapted Material means material subject to Copyright and Similar Rights 55 | that is derived from or based upon the Licensed Material and in which the 56 | Licensed Material is translated, altered, arranged, transformed, or otherwise 57 | modified in a manner requiring permission under the Copyright and Similar 58 | Rights held by the Licensor. For purposes of this Public License, where the 59 | Licensed Material is a musical work, performance, or sound recording, Adapted 60 | Material is always produced where the Licensed Material is synched in timed 61 | relation with a moving image. 62 | 63 | b. Adapter's License means the license You apply to Your Copyright and Similar 64 | Rights in Your contributions to Adapted Material in accordance with the terms 65 | and conditions of this Public License. 66 | 67 | c. Copyright and Similar Rights means copyright and/or similar rights closely 68 | related to copyright including, without limitation, performance, broadcast, 69 | sound recording, and Sui Generis Database Rights, without regard to how the 70 | rights are labeled or categorized. For purposes of this Public License, the 71 | rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. 72 | 73 | d. Effective Technological Measures means those measures that, in the absence 74 | of proper authority, may not be circumvented under laws fulfilling obligations 75 | under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, 76 | and/or similar international agreements. 77 | 78 | e. Exceptions and Limitations means fair use, fair dealing, and/or any other 79 | exception or limitation to Copyright and Similar Rights that applies to Your 80 | use of the Licensed Material. 81 | 82 | f. Licensed Material means the artistic or literary work, database, or other 83 | material to which the Licensor applied this Public License. 84 | 85 | g. Licensed Rights means the rights granted to You subject to the terms and 86 | conditions of this Public License, which are limited to all Copyright and 87 | Similar Rights that apply to Your use of the Licensed Material and that the 88 | Licensor has authority to license. 89 | 90 | h. Licensor means the individual(s) or entity(ies) granting rights under this 91 | Public License. 92 | 93 | i. Share means to provide material to the public by any means or process that 94 | requires permission under the Licensed Rights, such as reproduction, public 95 | display, public performance, distribution, dissemination, communication, or 96 | importation, and to make material available to the public including in ways 97 | that members of the public may access the material from a place and at a time 98 | individually chosen by them. 99 | 100 | j. Sui Generis Database Rights means rights other than copyright resulting 101 | from Directive 96/9/EC of the European Parliament and of the Council of 11 102 | March 1996 on the legal protection of databases, as amended and/or succeeded, 103 | as well as other essentially equivalent rights anywhere in the world. 104 | 105 | k. You means the individual or entity exercising the Licensed Rights under 106 | this Public License. Your has a corresponding meaning. 107 | 108 | Section 2 – Scope. 109 | 110 | a. License grant. 111 | 112 | 1. Subject to the terms and conditions of this Public License, the Licensor 113 | hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, 114 | irrevocable license to exercise the Licensed Rights in the Licensed Material 115 | to: 116 | 117 | A. reproduce and Share the Licensed Material, in whole or in part; and 118 | 119 | B. produce, reproduce, and Share Adapted Material. 120 | 121 | 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions 122 | and Limitations apply to Your use, this Public License does not apply, and 123 | You do not need to comply with its terms and conditions. 124 | 125 | 3. Term. The term of this Public License is specified in Section 6(a). 126 | 127 | 4. Media and formats; technical modifications allowed. The Licensor authorizes 128 | You to exercise the Licensed Rights in all media and formats whether now known 129 | or hereafter created, and to make technical modifications necessary to do 130 | so. The Licensor waives and/or agrees not to assert any right or authority 131 | to forbid You from making technical modifications necessary to exercise the 132 | Licensed Rights, including technical modifications necessary to circumvent 133 | Effective Technological Measures. For purposes of this Public License, simply 134 | making modifications authorized by this Section 2(a)(4) never produces Adapted 135 | Material. 136 | 137 | 5. Downstream recipients. 138 | 139 | A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed 140 | Material automatically receives an offer from the Licensor to exercise the 141 | Licensed Rights under the terms and conditions of this Public License. 142 | 143 | B. No downstream restrictions. You may not offer or impose any additional 144 | or different terms or conditions on, or apply any Effective Technological 145 | Measures to, the Licensed Material if doing so restricts exercise of the Licensed 146 | Rights by any recipient of the Licensed Material. 147 | 148 | 6. No endorsement. Nothing in this Public License constitutes or may be construed 149 | as permission to assert or imply that You are, or that Your use of the Licensed 150 | Material is, connected with, or sponsored, endorsed, or granted official status 151 | by, the Licensor or others designated to receive attribution as provided in 152 | Section 3(a)(1)(A)(i). 153 | 154 | b. Other rights. 155 | 156 | 1. Moral rights, such as the right of integrity, are not licensed under this 157 | Public License, nor are publicity, privacy, and/or other similar personality 158 | rights; however, to the extent possible, the Licensor waives and/or agrees 159 | not to assert any such rights held by the Licensor to the limited extent necessary 160 | to allow You to exercise the Licensed Rights, but not otherwise. 161 | 162 | 2. Patent and trademark rights are not licensed under this Public License. 163 | 164 | 3. To the extent possible, the Licensor waives any right to collect royalties 165 | from You for the exercise of the Licensed Rights, whether directly or through 166 | a collecting society under any voluntary or waivable statutory or compulsory 167 | licensing scheme. In all other cases the Licensor expressly reserves any right 168 | to collect such royalties. 169 | 170 | Section 3 – License Conditions. 171 | 172 | Your exercise of the Licensed Rights is expressly made subject to the following 173 | conditions. 174 | 175 | a. Attribution. 176 | 177 | 1. If You Share the Licensed Material (including in modified form), You must: 178 | 179 | A. retain the following if it is supplied by the Licensor with the Licensed 180 | Material: 181 | 182 | i. identification of the creator(s) of the Licensed Material and any others 183 | designated to receive attribution, in any reasonable manner requested by the 184 | Licensor (including by pseudonym if designated); 185 | 186 | ii. a copyright notice; 187 | 188 | iii. a notice that refers to this Public License; 189 | 190 | iv. a notice that refers to the disclaimer of warranties; 191 | 192 | v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; 193 | 194 | B. indicate if You modified the Licensed Material and retain an indication 195 | of any previous modifications; and 196 | 197 | C. indicate the Licensed Material is licensed under this Public License, and 198 | include the text of, or the URI or hyperlink to, this Public License. 199 | 200 | 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner 201 | based on the medium, means, and context in which You Share the Licensed Material. 202 | For example, it may be reasonable to satisfy the conditions by providing a 203 | URI or hyperlink to a resource that includes the required information. 204 | 205 | 3. If requested by the Licensor, You must remove any of the information required 206 | by Section 3(a)(1)(A) to the extent reasonably practicable. 207 | 208 | 4. If You Share Adapted Material You produce, the Adapter's License You apply 209 | must not prevent recipients of the Adapted Material from complying with this 210 | Public License. 211 | 212 | Section 4 – Sui Generis Database Rights. 213 | 214 | Where the Licensed Rights include Sui Generis Database Rights that apply to 215 | Your use of the Licensed Material: 216 | 217 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, 218 | reuse, reproduce, and Share all or a substantial portion of the contents of 219 | the database; 220 | 221 | b. if You include all or a substantial portion of the database contents in 222 | a database in which You have Sui Generis Database Rights, then the database 223 | in which You have Sui Generis Database Rights (but not its individual contents) 224 | is Adapted Material; and 225 | 226 | c. You must comply with the conditions in Section 3(a) if You Share all or 227 | a substantial portion of the contents of the database. 228 | 229 | For the avoidance of doubt, this Section 4 supplements and does not replace 230 | Your obligations under this Public License where the Licensed Rights include 231 | other Copyright and Similar Rights. 232 | 233 | Section 5 – Disclaimer of Warranties and Limitation of Liability. 234 | 235 | a. Unless otherwise separately undertaken by the Licensor, to the extent possible, 236 | the Licensor offers the Licensed Material as-is and as-available, and makes 237 | no representations or warranties of any kind concerning the Licensed Material, 238 | whether express, implied, statutory, or other. This includes, without limitation, 239 | warranties of title, merchantability, fitness for a particular purpose, non-infringement, 240 | absence of latent or other defects, accuracy, or the presence or absence of 241 | errors, whether or not known or discoverable. Where disclaimers of warranties 242 | are not allowed in full or in part, this disclaimer may not apply to You. 243 | 244 | b. To the extent possible, in no event will the Licensor be liable to You 245 | on any legal theory (including, without limitation, negligence) or otherwise 246 | for any direct, special, indirect, incidental, consequential, punitive, exemplary, 247 | or other losses, costs, expenses, or damages arising out of this Public License 248 | or use of the Licensed Material, even if the Licensor has been advised of 249 | the possibility of such losses, costs, expenses, or damages. Where a limitation 250 | of liability is not allowed in full or in part, this limitation may not apply 251 | to You. 252 | 253 | c. The disclaimer of warranties and limitation of liability provided above 254 | shall be interpreted in a manner that, to the extent possible, most closely 255 | approximates an absolute disclaimer and waiver of all liability. 256 | 257 | Section 6 – Term and Termination. 258 | 259 | a. This Public License applies for the term of the Copyright and Similar Rights 260 | licensed here. However, if You fail to comply with this Public License, then 261 | Your rights under this Public License terminate automatically. 262 | 263 | b. Where Your right to use the Licensed Material has terminated under Section 264 | 6(a), it reinstates: 265 | 266 | 1. automatically as of the date the violation is cured, provided it is cured 267 | within 30 days of Your discovery of the violation; or 268 | 269 | 2. upon express reinstatement by the Licensor. 270 | 271 | c. For the avoidance of doubt, this Section 6(b) does not affect any right 272 | the Licensor may have to seek remedies for Your violations of this Public 273 | License. 274 | 275 | d. For the avoidance of doubt, the Licensor may also offer the Licensed Material 276 | under separate terms or conditions or stop distributing the Licensed Material 277 | at any time; however, doing so will not terminate this Public License. 278 | 279 | e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. 280 | 281 | Section 7 – Other Terms and Conditions. 282 | 283 | a. The Licensor shall not be bound by any additional or different terms or 284 | conditions communicated by You unless expressly agreed. 285 | 286 | b. Any arrangements, understandings, or agreements regarding the Licensed 287 | Material not stated herein are separate from and independent of the terms 288 | and conditions of this Public License. 289 | 290 | Section 8 – Interpretation. 291 | 292 | a. For the avoidance of doubt, this Public License does not, and shall not 293 | be interpreted to, reduce, limit, restrict, or impose conditions on any use 294 | of the Licensed Material that could lawfully be made without permission under 295 | this Public License. 296 | 297 | b. To the extent possible, if any provision of this Public License is deemed 298 | unenforceable, it shall be automatically reformed to the minimum extent necessary 299 | to make it enforceable. If the provision cannot be reformed, it shall be severed 300 | from this Public License without affecting the enforceability of the remaining 301 | terms and conditions. 302 | 303 | c. No term or condition of this Public License will be waived and no failure 304 | to comply consented to unless expressly agreed to by the Licensor. 305 | 306 | d. Nothing in this Public License constitutes or may be interpreted as a limitation 307 | upon, or waiver of, any privileges and immunities that apply to the Licensor 308 | or You, including from the legal processes of any jurisdiction or authority. 309 | 310 | Creative Commons is not a party to its public licenses. Notwithstanding, Creative 311 | Commons may elect to apply one of its public licenses to material it publishes 312 | and in those instances will be considered the "Licensor." The text of the 313 | Creative Commons public licenses is dedicated to the public domain under the 314 | CC0 Public Domain Dedication. Except for the limited purpose of indicating 315 | that material is shared under a Creative Commons public license or as otherwise 316 | permitted by the Creative Commons policies published at creativecommons.org/policies, 317 | Creative Commons does not authorize the use of the trademark "Creative Commons" 318 | or any other trademark or logo of Creative Commons without its prior written 319 | consent including, without limitation, in connection with any unauthorized 320 | modifications to any of its public licenses or any other arrangements, understandings, 321 | or agreements concerning use of licensed material. For the avoidance of doubt, 322 | this paragraph does not form part of the public licenses. 323 | 324 | Creative Commons may be contacted at creativecommons.org. 325 | -------------------------------------------------------------------------------- /LICENSES/MIT.txt: -------------------------------------------------------------------------------- 1 | MIT License Copyright (c) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice (including the next 11 | paragraph) shall be included in all copies or substantial portions of the 12 | Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 17 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 | OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /LICENSES/Unlicense.txt: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute 4 | this software, either in source code form or as a compiled binary, for any 5 | purpose, commercial or non-commercial, and by any means. 6 | 7 | In jurisdictions that recognize copyright laws, the author or authors of this 8 | software dedicate any and all copyright interest in the software to the public 9 | domain. We make this dedication for the benefit of the public at large and 10 | to the detriment of our heirs and successors. We intend this dedication to 11 | be an overt act of relinquishment in perpetuity of all present and future 12 | rights to this software under copyright law. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 17 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 18 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 19 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, 20 | please refer to 21 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | 2 | Introduction 3 | ============ 4 | 5 | .. image:: https://readthedocs.org/projects/adafruit-circuitpython-circuitplayground/badge/?version=latest 6 | :target: https://docs.circuitpython.org/projects/circuitplayground/en/latest/ 7 | :alt: Documentation Status 8 | 9 | .. image:: https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_Bundle/main/badges/adafruit_discord.svg 10 | :target: https://adafru.it/discord 11 | :alt: Discord 12 | 13 | .. image:: https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/workflows/Build%20CI/badge.svg 14 | :target: https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/actions/ 15 | :alt: Build Status 16 | 17 | .. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json 18 | :target: https://github.com/astral-sh/ruff 19 | :alt: Code Style: Ruff 20 | 21 | This high level library provides objects that represent Circuit Playground Express and Bluefruit hardware. 22 | 23 | .. image :: https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/main/docs/_static/circuit_playground_express_small.jpg 24 | :target: https://adafruit.com/product/3333 25 | :alt: Circuit Playground Express 26 | 27 | .. image :: https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/main/docs/_static/circuit_playground_bluefruit_small.jpg 28 | :target: https://adafruit.com/product/4333 29 | :alt: Circuit Playground Bluefruit 30 | 31 | Installation 32 | ============= 33 | For Circuit Playground Express, simply install CircuitPython to use this library - the library itself and 34 | all of its dependencies are built into CircuitPython for Circuit Playground Express. 35 | 36 | For Circuit Playground Bluefruit, you must install this library and all of its dependencies. Please download 37 | `the latest Adafruit CircuitPython library bundle `_. Open the resulting 38 | zip file, open the lib folder within, and copy the following folders and files to the lib folder on your 39 | CIRCUITPY drive: 40 | 41 | * adafruit_bus_device/ 42 | * adafruit_circuitplayground/ 43 | * adafruit_lis3dh.mpy 44 | * adafruit_thermistor.mpy 45 | * neopixel.mpy 46 | 47 | Usage Example 48 | ============= 49 | Using this library is super simple. Simply import the ``cp`` variable from the module and then use it. 50 | 51 | .. code-block :: python 52 | 53 | from adafruit_circuitplayground import cp 54 | 55 | while True: 56 | if cp.button_a: 57 | print("Temperature:", cp.temperature) 58 | cp.red_led = cp.button_b 59 | 60 | To learn more about all the features of this library, check out the 61 | `CircuitPython Made Easy on Circuit Playground Express and Bluefruit guide `_ 62 | on the Adafruit Learn System. 63 | 64 | Circuit Playground Library Details 65 | ================================== 66 | 67 | For a detailed explanation of how the Circuit Playground library functions, see 68 | `The Technical Side page `_ 69 | of the CircuitPython Made Easy on Circuit Playground Express and Bluefruit guide. 70 | 71 | Documentation 72 | ============= 73 | 74 | API documentation for this library can be found on `Read the Docs `_. 75 | 76 | For information on building library documentation, please check out `this guide `_. 77 | 78 | Contributing 79 | ============ 80 | 81 | Contributions are welcome! Please read our `Code of Conduct 82 | `_ 83 | before contributing to help this project stay welcoming. 84 | -------------------------------------------------------------------------------- /README.rst.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries 2 | 3 | SPDX-License-Identifier: MIT 4 | -------------------------------------------------------------------------------- /adafruit_circuitplayground/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2019 Kattni Rembor for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | """Verifies which board is being used and imports the appropriate module.""" 6 | 7 | import sys 8 | 9 | if sys.platform == "nRF52840": 10 | from .bluefruit import cpb as cp 11 | elif sys.platform == "Atmel SAMD21": 12 | from .express import cpx as cp 13 | -------------------------------------------------------------------------------- /adafruit_circuitplayground/bluefruit.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2019 Kattni Rembor for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | """ 6 | `adafruit_circuitplayground.bluefruit` 7 | ==================================================== 8 | 9 | CircuitPython helper for Circuit Playground Bluefruit. 10 | 11 | * Author(s): Kattni Rembor 12 | 13 | Implementation Notes 14 | -------------------- 15 | 16 | **Hardware:** 17 | 18 | * `Circuit Playground Bluefruit `_ 19 | 20 | """ 21 | 22 | try: 23 | import typing 24 | except ImportError: 25 | pass 26 | 27 | import array 28 | import math 29 | 30 | import audiobusio 31 | import audiomp3 32 | import audiopwmio 33 | import board 34 | import digitalio 35 | 36 | from adafruit_circuitplayground.circuit_playground_base import CircuitPlaygroundBase 37 | 38 | __version__ = "0.0.0+auto.0" 39 | __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground.git" 40 | 41 | 42 | class Bluefruit(CircuitPlaygroundBase): 43 | """Represents a single CircuitPlayground Bluefruit.""" 44 | 45 | _audio_out = audiopwmio.PWMAudioOut 46 | 47 | def __init__(self) -> None: 48 | # Only create the cpb module member when we aren't being imported by Sphinx 49 | if ( 50 | "__module__" in dir(digitalio.DigitalInOut) 51 | and digitalio.DigitalInOut.__module__ == "sphinx.ext.autodoc" 52 | ): 53 | return 54 | 55 | super().__init__() 56 | 57 | self._sample = None 58 | 59 | # Define mic/sound sensor: 60 | self._mic = audiobusio.PDMIn( 61 | board.MICROPHONE_CLOCK, 62 | board.MICROPHONE_DATA, 63 | sample_rate=16000, 64 | bit_depth=16, 65 | ) 66 | self._mic_samples = None 67 | 68 | @staticmethod 69 | def _normalized_rms(values) -> float: 70 | mean_values = int(sum(values) / len(values)) 71 | return math.sqrt( 72 | sum(float(sample - mean_values) * (sample - mean_values) for sample in values) 73 | / len(values) 74 | ) 75 | 76 | @property 77 | def sound_level(self) -> float: 78 | """Obtain the sound level from the microphone (sound sensor). 79 | 80 | .. image :: ../docs/_static/microphone.jpg 81 | :alt: Microphone (sound sensor) 82 | 83 | This example prints the sound levels. Try clapping or blowing on 84 | the microphone to see the levels change. 85 | 86 | .. code-block:: python 87 | 88 | from adafruit_circuitplayground.bluefruit import cpb 89 | 90 | while True: 91 | print(cpb.sound_level) 92 | """ 93 | if self._mic_samples is None: 94 | self._mic_samples = array.array("H", [0] * 160) 95 | self._mic.record(self._mic_samples, len(self._mic_samples)) 96 | return self._normalized_rms(self._mic_samples) 97 | 98 | def loud_sound(self, sound_threshold: int = 200) -> bool: 99 | """Utilise a loud sound as an input. 100 | 101 | :param int sound_threshold: Threshold sound level must exceed to return true (Default: 200) 102 | 103 | .. image :: ../docs/_static/microphone.jpg 104 | :alt: Microphone (sound sensor) 105 | 106 | This example turns the LEDs red each time you make a loud sound. 107 | Try clapping or blowing onto the microphone to trigger it. 108 | 109 | .. code-block:: python 110 | 111 | from adafruit_circuitplayground.bluefruit import cpb 112 | 113 | while True: 114 | if cpb.loud_sound(): 115 | cpb.pixels.fill((50, 0, 0)) 116 | else: 117 | cpb.pixels.fill(0) 118 | 119 | You may find that the code is not responding how you would like. 120 | If this is the case, you can change the loud sound threshold to 121 | make it more or less responsive. Setting it to a higher number 122 | means it will take a louder sound to trigger. Setting it to a 123 | lower number will take a quieter sound to trigger. The following 124 | example shows the threshold being set to a higher number than 125 | the default. 126 | 127 | .. code-block:: python 128 | 129 | from adafruit_circuitplayground.bluefruit import cpb 130 | 131 | while True: 132 | if cpb.loud_sound(sound_threshold=300): 133 | cpb.pixels.fill((50, 0, 0)) 134 | else: 135 | cpb.pixels.fill(0) 136 | """ 137 | 138 | return self.sound_level > sound_threshold 139 | 140 | def play_mp3(self, file_name: str) -> None: 141 | """Play a .mp3 file using the onboard speaker. 142 | 143 | :param file_name: The name of your .mp3 file in quotation marks including .mp3 144 | 145 | .. image :: ../docs/_static/speaker.jpg 146 | :alt: Onboard speaker 147 | 148 | To use with the Circuit Playground Bluefruit: 149 | 150 | .. code-block:: python 151 | 152 | from adafruit_circuitplayground import cp 153 | 154 | while True: 155 | if cp.button_a: 156 | cp.play_mp3("laugh.mp3") 157 | elif cp.button_b: 158 | cp.play_mp3("rimshot.mp3") 159 | """ 160 | if file_name.lower().endswith(".mp3"): 161 | # Play a specified file. 162 | self.stop_tone() 163 | self._speaker_enable.value = True 164 | with self._audio_out(board.SPEAKER) as audio, audiomp3.MP3Decoder( 165 | open(file_name, "rb") 166 | ) as mp3file: 167 | audio.play(mp3file) 168 | while audio.playing: 169 | pass 170 | self._speaker_enable.value = False 171 | else: 172 | raise ValueError("Filetype must be mp3") 173 | 174 | 175 | cpb = Bluefruit() 176 | """Object that is automatically created on import. 177 | 178 | To use, simply import it from the module: 179 | 180 | .. code-block:: python 181 | 182 | from adafruit_circuitplayground.bluefruit import cpb 183 | """ 184 | -------------------------------------------------------------------------------- /adafruit_circuitplayground/circuit_playground_base.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2016 Scott Shawcroft for Adafruit Industries 2 | # SPDX-FileCopyrightText: 2017-2019 Kattni Rembor for Adafruit Industries 3 | # SPDX-FileCopyrightText: 2022 Ryan Keith for Adafruit Industries 4 | # 5 | # SPDX-License-Identifier: MIT 6 | 7 | # We have a lot of attributes for this complex library, as well as a lot of documentation. 8 | 9 | """ 10 | `adafruit_circuitplayground.circuit_playground_base` 11 | ==================================================== 12 | 13 | CircuitPython base class for Circuit Playground. 14 | 15 | * `Circuit Playground Express `_ 16 | * `Circuit Playground Bluefruit `_. 17 | 18 | * Author(s): Kattni Rembor, Scott Shawcroft, Ryan Keith 19 | """ 20 | 21 | import array 22 | import math 23 | import os 24 | import time 25 | 26 | import adafruit_lis3dh 27 | import adafruit_thermistor 28 | import analogio 29 | import audiocore 30 | import board 31 | import busio 32 | import digitalio 33 | import neopixel 34 | import touchio 35 | 36 | try: 37 | from typing import Iterator, List, Optional 38 | 39 | from microcontroller import Pin 40 | from typing_extensions import Literal 41 | except ImportError: 42 | pass 43 | 44 | __version__ = "0.0.0+auto.0" 45 | __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground.git" 46 | 47 | 48 | class Photocell: 49 | """Simple driver for analog photocell on the Circuit Playground Express and Bluefruit.""" 50 | 51 | def __init__(self, pin: Pin) -> None: 52 | self._photocell = analogio.AnalogIn(pin) 53 | 54 | # TODO(tannewt): Calibrate this against another calibrated sensor. 55 | @property 56 | def light(self) -> int: 57 | """Light level.""" 58 | return self._photocell.value * 330 // (2**16) 59 | 60 | 61 | class CircuitPlaygroundBase: 62 | """Circuit Playground base class.""" 63 | 64 | _audio_out = None 65 | SINE_WAVE = 0 66 | SQUARE_WAVE = 1 67 | 68 | def __init__(self) -> None: 69 | # Define switch: 70 | self._switch = digitalio.DigitalInOut(board.SLIDE_SWITCH) 71 | self._switch.switch_to_input(pull=digitalio.Pull.UP) 72 | 73 | # Define LEDs: 74 | self._led = digitalio.DigitalInOut(board.D13) 75 | self._led.switch_to_output() 76 | self._pixels = neopixel.NeoPixel(board.NEOPIXEL, 10) 77 | 78 | # Define sensors: 79 | self._temp = adafruit_thermistor.Thermistor(board.TEMPERATURE, 10000, 10000, 25, 3950) 80 | self._light = Photocell(board.LIGHT) 81 | 82 | # Define touch: 83 | # Initially, self._touches is an empty dictionary. When a touch is used 84 | # for the first time, the pin is added as a key to the dictionary, with 85 | # the corresponding TouchIn object added as the value. This saves a 86 | # little RAM by only populating the dictionary as needed. For example, 87 | # after `cp.touch_A2`, self._touches is equivalent to: 88 | # { board.A2: TouchIn(board.A2) } 89 | self._touches = {} 90 | self._touch_threshold_adjustment = 0 91 | 92 | # Define acceleration: 93 | self._i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA) 94 | self._int1 = digitalio.DigitalInOut(board.ACCELEROMETER_INTERRUPT) 95 | self._lis3dh = adafruit_lis3dh.LIS3DH_I2C(self._i2c, address=0x19, int1=self._int1) 96 | self._lis3dh.range = adafruit_lis3dh.RANGE_8_G 97 | 98 | # Define audio: 99 | self._speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE) 100 | self._speaker_enable.switch_to_output(value=False) 101 | self._sample = None 102 | self._wave = None 103 | self._wave_sample = None 104 | 105 | # Initialise tap: 106 | self._detect_taps = 1 107 | self.detect_taps = 1 108 | 109 | # Initialise buttons: 110 | self._a = None 111 | self._b = None 112 | 113 | @property 114 | def detect_taps(self) -> Literal[1, 2]: 115 | """Configure what type of tap is detected by ``cp.tapped``. Use ``1`` for single-tap 116 | detection and ``2`` for double-tap detection. This does nothing without ``cp.tapped``. 117 | 118 | .. image :: ../docs/_static/accelerometer.jpg 119 | :alt: Accelerometer 120 | 121 | To use with the Circuit Playground Express or Bluefruit: 122 | 123 | .. code-block:: python 124 | 125 | from adafruit_circuitplayground import cp 126 | 127 | cp.detect_taps = 1 128 | while True: 129 | if cp.tapped: 130 | print("Single tap detected!") 131 | """ 132 | return self._detect_taps 133 | 134 | @staticmethod 135 | def _default_tap_threshold(tap: Literal[1, 2]) -> int: 136 | if "nRF52840" in os.uname().machine: # If we're on a CPB, use a higher tap threshold 137 | return 100 if tap == 1 else 70 138 | 139 | # If we're on a CPX 140 | return 90 if tap == 1 else 60 141 | 142 | @detect_taps.setter 143 | def detect_taps(self, value: Literal[1, 2]) -> None: 144 | self._detect_taps = value 145 | if value == 1: 146 | self._lis3dh.set_tap( 147 | value, 148 | self._default_tap_threshold(value), 149 | time_limit=4, 150 | time_latency=50, 151 | time_window=255, 152 | ) 153 | if value == 2: 154 | self._lis3dh.set_tap( 155 | value, 156 | self._default_tap_threshold(value), 157 | time_limit=10, 158 | time_latency=50, 159 | time_window=255, 160 | ) 161 | 162 | def configure_tap( 163 | self, 164 | tap: Literal[0, 1, 2], 165 | accel_range: Literal[0, 1, 2, 3] = adafruit_lis3dh.RANGE_8_G, 166 | threshold: Optional[int] = None, 167 | time_limit: Optional[int] = None, 168 | time_latency: int = 50, 169 | time_window: int = 255, 170 | ) -> None: 171 | """Granular configuration of tap parameters. Expose the power of the 172 | adafruit_lis3dh module. 173 | 174 | :param int tap: 0 to disable tap detection, 1 to detect only single 175 | taps, and 2 to detect only double taps. 176 | :param int accel_range: Takes the defined values from the adafruit_lis3dh 177 | module [ RANGE_2_G, RANGE_4_G, RANGE_8_G, RANGE_16_G ] 178 | (default sets the same value as the *detect_taps* setter) 179 | :param int threshold: A threshold for the tap detection. The higher the value 180 | the less sensitive the detection. This changes based on the 181 | accelerometer range. Good values are 5-10 for 16G, 10-20 182 | for 8G, 20-40 for 4G, and 40-80 for 2G. 183 | (default sets the same value as the *detect_taps* setter) 184 | :param int time_limit: TIME_LIMIT register value 185 | (default sets the same value as the *detect_taps* setter) 186 | :param int time_latency: TIME_LATENCY register value (default 50). 187 | :param int time_window: TIME_WINDOW register value (default 255). 188 | 189 | To use with the Circuit Playground Express or Bluefruit: 190 | 191 | .. code-block:: python 192 | 193 | from adafruit_circuitplayground import cp 194 | import adafruit_lis3dh 195 | 196 | cp.configure_tap(1, accel_range=adafruit_lis3dh.RANGE_2_G, threshold=50) 197 | while True: 198 | if cp.tapped: 199 | print("Single tap detected!") 200 | 201 | """ 202 | if tap < 0 or tap > 2: 203 | return 204 | 205 | self._detect_taps = tap 206 | 207 | if accel_range not in { 208 | adafruit_lis3dh.RANGE_2_G, 209 | adafruit_lis3dh.RANGE_4_G, 210 | adafruit_lis3dh.RANGE_8_G, 211 | adafruit_lis3dh.RANGE_16_G, 212 | }: 213 | accel_range = adafruit_lis3dh.RANGE_8_G 214 | self._lis3dh.range = accel_range 215 | 216 | if tap == 1: 217 | if threshold is None or threshold < 0 or threshold > 127: 218 | threshold = self._default_tap_threshold(tap) 219 | if time_limit is None: 220 | time_limit = 4 221 | elif tap == 2: 222 | if threshold is None or threshold < 0 or threshold > 127: 223 | threshold = self._default_tap_threshold(tap) 224 | if time_limit is None: 225 | time_limit = 10 226 | else: 227 | # reasonable values for turning the tap detection off 228 | threshold = 100 229 | time_limit = 1 230 | 231 | self._lis3dh.set_tap( 232 | tap, 233 | threshold, 234 | time_limit=time_limit, 235 | time_latency=time_latency, 236 | time_window=time_window, 237 | ) 238 | 239 | @property 240 | def tapped(self) -> bool: 241 | """True once after a detecting a tap. Requires ``cp.detect_taps``. 242 | 243 | .. image :: ../docs/_static/accelerometer.jpg 244 | :alt: Accelerometer 245 | 246 | Tap the Circuit Playground once for a single-tap, or quickly tap twice for a double-tap. 247 | 248 | To use with Circuit Playground Express or Bluefruit: 249 | 250 | .. code-block:: python 251 | 252 | from adafruit_circuitplayground import cp 253 | 254 | cp.detect_taps = 1 255 | 256 | while True: 257 | if cp.tapped: 258 | print("Single tap detected!") 259 | 260 | To use single and double tap together, you must have a delay between them. It 261 | will not function properly without it. This example uses both by counting a 262 | specified number of each type of tap before moving on in the code. 263 | 264 | .. code-block:: python 265 | 266 | from adafruit_circuitplayground import cp 267 | 268 | # Set to check for single-taps. 269 | cp.detect_taps = 1 270 | tap_count = 0 271 | 272 | # We're looking for 2 single-taps before moving on. 273 | while tap_count < 2: 274 | if cp.tapped: 275 | tap_count += 1 276 | print("Reached 2 single-taps!") 277 | 278 | # Now switch to checking for double-taps 279 | tap_count = 0 280 | cp.detect_taps = 2 281 | 282 | # We're looking for 2 double-taps before moving on. 283 | while tap_count < 2: 284 | if cp.tapped: 285 | tap_count += 1 286 | print("Reached 2 double-taps!") 287 | print("Done.") 288 | """ 289 | return self._lis3dh.tapped 290 | 291 | @property 292 | def acceleration(self) -> adafruit_lis3dh.AccelerationTuple: 293 | """Obtain data from the x, y and z axes. 294 | 295 | .. image :: ../docs/_static/accelerometer.jpg 296 | :alt: Accelerometer 297 | 298 | This example prints the values. Try moving the board to see how the 299 | printed values change. 300 | 301 | To use with the Circuit Playground Express or Bluefruit: 302 | 303 | .. code-block:: python 304 | 305 | from adafruit_circuitplayground import cp 306 | 307 | while True: 308 | x, y, z = cp.acceleration 309 | print(x, y, z) 310 | """ 311 | return self._lis3dh.acceleration 312 | 313 | def shake(self, shake_threshold: int = 30) -> bool: 314 | """Detect when device is shaken. 315 | 316 | :param int shake_threshold: The threshold shake must exceed to return true (Default: 30) 317 | 318 | .. image :: ../docs/_static/accelerometer.jpg 319 | :alt: Accelerometer 320 | 321 | To use with the Circuit Playground Express or Bluefruit: 322 | 323 | .. code-block:: python 324 | 325 | from adafruit_circuitplayground import cp 326 | 327 | while True: 328 | if cp.shake(): 329 | print("Shake detected!") 330 | 331 | Decreasing ``shake_threshold`` increases shake sensitivity, i.e. the code 332 | will return a shake detected more easily with a lower ``shake_threshold``. 333 | Increasing it causes the opposite. ``shake_threshold`` requires a minimum 334 | value of 10 - 10 is the value when the board is not moving, therefore 335 | anything less than 10 will erroneously report a constant shake detected. 336 | 337 | .. code-block:: python 338 | 339 | from adafruit_circuitplayground import cp 340 | 341 | while True: 342 | if cp.shake(shake_threshold=20): 343 | print("Shake detected more easily than before!") 344 | """ 345 | return self._lis3dh.shake(shake_threshold=shake_threshold) 346 | 347 | def _touch(self, pin: Pin) -> bool: 348 | touchin = self._touches.get(pin) 349 | if not touchin: 350 | # First time referenced. Make TouchIn object for the pin 351 | touchin = touchio.TouchIn(pin) 352 | touchin.threshold += self._touch_threshold_adjustment 353 | self._touches[pin] = touchin 354 | return touchin.value 355 | 356 | # We chose these verbose touch_A# names so that beginners could use it without understanding 357 | # lists and the capital A to match the pin name. The capitalization is not strictly Python 358 | # style, so everywhere we use these names, we whitelist the errors using: 359 | @property 360 | def touch_A1(self) -> bool: 361 | """Detect touch on capacitive touch pad A1. 362 | 363 | .. image :: ../docs/_static/capacitive_touch_pad_A1.jpg 364 | :alt: Capacitive touch pad A1 365 | 366 | To use with the Circuit Playground Express or Bluefruit: 367 | 368 | .. code-block:: python 369 | 370 | from adafruit_circuitplayground import cp 371 | 372 | while True: 373 | if cp.touch_A1: 374 | print('Touched pad A1') 375 | """ 376 | return self._touch(board.A1) 377 | 378 | @property 379 | def touch_A2(self) -> bool: 380 | """Detect touch on capacitive touch pad A2. 381 | 382 | .. image :: ../docs/_static/capacitive_touch_pad_A2.jpg 383 | :alt: Capacitive touch pad A2 384 | 385 | To use with the Circuit Playground Express or Bluefruit: 386 | 387 | .. code-block:: python 388 | 389 | from adafruit_circuitplayground import cp 390 | 391 | while True: 392 | if cp.touch_A2: 393 | print('Touched pad A2') 394 | """ 395 | return self._touch(board.A2) 396 | 397 | @property 398 | def touch_A3(self) -> bool: 399 | """Detect touch on capacitive touch pad A3. 400 | 401 | .. image :: ../docs/_static/capacitive_touch_pad_A3.jpg 402 | :alt: Capacitive touch pad A3 403 | 404 | To use with the Circuit Playground Express or Bluefruit: 405 | 406 | .. code-block:: python 407 | 408 | from adafruit_circuitplayground import cp 409 | 410 | while True: 411 | if cp.touch_A3: 412 | print('Touched pad A3') 413 | """ 414 | return self._touch(board.A3) 415 | 416 | @property 417 | def touch_A4(self) -> bool: 418 | """Detect touch on capacitive touch pad A4. 419 | 420 | .. image :: ../docs/_static/capacitive_touch_pad_A4.jpg 421 | :alt: Capacitive touch pad A4 422 | 423 | To use with the Circuit Playground Express or Bluefruit: 424 | 425 | .. code-block:: python 426 | 427 | from adafruit_circuitplayground import cp 428 | 429 | while True: 430 | if cp.touch_A4: 431 | print('Touched pad A4') 432 | """ 433 | return self._touch(board.A4) 434 | 435 | @property 436 | def touch_A5(self) -> bool: 437 | """Detect touch on capacitive touch pad A5. 438 | 439 | .. image :: ../docs/_static/capacitive_touch_pad_A5.jpg 440 | :alt: Capacitive touch pad A5 441 | 442 | To use with the Circuit Playground Express or Bluefruit: 443 | 444 | .. code-block:: python 445 | 446 | from adafruit_circuitplayground import cp 447 | 448 | while True: 449 | if cp.touch_A5: 450 | print('Touched pad A5') 451 | """ 452 | return self._touch(board.A5) 453 | 454 | @property 455 | def touch_A6(self) -> bool: 456 | """Detect touch on capacitive touch pad A6. 457 | 458 | .. image :: ../docs/_static/capacitive_touch_pad_A6.jpg 459 | :alt: Capacitive touch pad A6 460 | 461 | To use with the Circuit Playground Express or Bluefruit: 462 | 463 | .. code-block:: python 464 | 465 | from adafruit_circuitplayground import cp 466 | 467 | while True: 468 | if cp.touch_A6: 469 | print('Touched pad A6' 470 | """ 471 | return self._touch(board.A6) 472 | 473 | @property 474 | def touch_TX(self) -> bool: 475 | """Detect touch on capacitive touch pad TX (also known as A7 on the Circuit Playground 476 | Express) Note: can be called as ``touch_A7`` on Circuit Playground Express. 477 | 478 | .. image :: ../docs/_static/capacitive_touch_pad_A7.jpg 479 | :alt: Capacitive touch pad TX 480 | 481 | To use with the Circuit Playground Express or Bluefruit: 482 | 483 | .. code-block:: python 484 | 485 | from adafruit_circuitplayground import cp 486 | 487 | while True: 488 | if cp.touch_A7: 489 | print('Touched pad A7') 490 | """ 491 | return self._touch(board.TX) 492 | 493 | def adjust_touch_threshold(self, adjustment: int) -> None: 494 | """Adjust the threshold needed to activate the capacitive touch pads. 495 | Higher numbers make the touch pads less sensitive. 496 | 497 | :param int adjustment: The desired threshold increase 498 | 499 | .. image :: ../docs/_static/capacitive_touch_pads.jpg 500 | :alt: Capacitive touch pads 501 | 502 | To use with the Circuit Playground Express or Bluefruit: 503 | 504 | .. code-block:: python 505 | 506 | from adafruit_circuitplayground import cp 507 | 508 | cp.adjust_touch_threshold(200) 509 | 510 | while True: 511 | if cp.touch_A1: 512 | print('Touched pad A1') 513 | """ 514 | for touch_in in self._touches.values(): 515 | touch_in.threshold += adjustment 516 | self._touch_threshold_adjustment += adjustment 517 | 518 | @property 519 | def touch_pins(self) -> List[Pin]: 520 | """A list of all the pins that are set up as touchpad inputs""" 521 | return list(self._touches.keys()) 522 | 523 | @property 524 | def touched(self) -> List[Pin]: 525 | """A list of all the pins that are currently registering a touch""" 526 | return [pin for pin, touchpad in self._touches.items() if touchpad.value] 527 | 528 | @property 529 | def pixels(self) -> neopixel.NeoPixel: 530 | """Sequence-like object representing the ten NeoPixels around the outside 531 | of the Circuit Playground. Each pixel is at a certain index in the sequence 532 | as labeled below. Colors can be RGB hex like 0x110000 for red where each 533 | two digits are a color (0xRRGGBB) or a tuple like (17, 0, 0) where (R, G, B). 534 | Set the global brightness using any number from 0 to 1 to represent a 535 | percentage, i.e. 0.3 sets global brightness to 30%. 536 | 537 | See `neopixel.NeoPixel` for more info. 538 | 539 | .. image :: ../docs/_static/neopixel_numbering.jpg 540 | :alt: NeoPixel order diagram 541 | 542 | Here is an example that sets the first pixel green and the ninth red. 543 | 544 | To use with the Circuit Playground Express or Bluefruit: 545 | 546 | .. code-block:: python 547 | 548 | from adafruit_circuitplayground import cp 549 | 550 | cp.pixels.brightness = 0.3 551 | cp.pixels[0] = 0x00FF00 552 | cp.pixels[9] = (255, 0, 0) 553 | """ 554 | return self._pixels 555 | 556 | @property 557 | def button_a(self) -> bool: 558 | """``True`` when Button A is pressed. ``False`` if not. 559 | 560 | .. image :: ../docs/_static/button_a.jpg 561 | :alt: Button A 562 | 563 | To use with the Circuit Playground Express or Bluefruit: 564 | 565 | .. code-block:: python 566 | 567 | from adafruit_circuitplayground import cp 568 | 569 | while True: 570 | if cp.button_a: 571 | print("Button A pressed!") 572 | """ 573 | if self._a is None: 574 | self._a = digitalio.DigitalInOut(board.BUTTON_A) 575 | self._a.switch_to_input(pull=digitalio.Pull.DOWN) 576 | return self._a.value 577 | 578 | @property 579 | def button_b(self) -> bool: 580 | """``True`` when Button B is pressed. ``False`` if not. 581 | 582 | .. image :: ../docs/_static/button_b.jpg 583 | :alt: Button B 584 | 585 | To use with the Circuit Playground Express or Bluefruit: 586 | 587 | .. code-block:: python 588 | 589 | from adafruit_circuitplayground import cp 590 | 591 | while True: 592 | if cp.button_b: 593 | print("Button B pressed!") 594 | """ 595 | if self._b is None: 596 | self._b = digitalio.DigitalInOut(board.BUTTON_B) 597 | self._b.switch_to_input(pull=digitalio.Pull.DOWN) 598 | return self._b.value 599 | 600 | @property 601 | def switch(self) -> bool: 602 | """``True`` when the switch is to the left next to the music notes. 603 | ``False`` when it is to the right towards the ear. 604 | 605 | .. image :: ../docs/_static/slide_switch.jpg 606 | :alt: Slide switch 607 | 608 | To use with the Circuit Playground Express or Bluefruit: 609 | 610 | .. code-block:: python 611 | 612 | from adafruit_circuitplayground import cp 613 | import time 614 | 615 | while True: 616 | print("Slide switch:", cp.switch) 617 | time.sleep(0.1) 618 | """ 619 | return self._switch.value 620 | 621 | @property 622 | def temperature(self) -> float: 623 | """The temperature in Celsius. 624 | 625 | .. image :: ../docs/_static/thermistor.jpg 626 | :alt: Temperature sensor 627 | 628 | Converting this to Fahrenheit is easy! 629 | 630 | To use with the Circuit Playground Express or Bluefruit: 631 | 632 | .. code-block:: python 633 | 634 | from adafruit_circuitplayground import cp 635 | import time 636 | 637 | while True: 638 | temperature_c = cp.temperature 639 | temperature_f = temperature_c * 1.8 + 32 640 | print("Temperature celsius:", temperature_c) 641 | print("Temperature fahrenheit:", temperature_f) 642 | time.sleep(1) 643 | """ 644 | return self._temp.temperature 645 | 646 | @property 647 | def light(self) -> int: 648 | """The light level. 649 | 650 | .. image :: ../docs/_static/light_sensor.jpg 651 | :alt: Light sensor 652 | 653 | Try covering the sensor next to the eye to see it change. 654 | 655 | To use with the Circuit Playground Express or Bluefruit: 656 | 657 | .. code-block:: python 658 | 659 | from adafruit_circuitplayground import cp 660 | import time 661 | 662 | while True: 663 | print("Light:", cp.light) 664 | time.sleep(1) 665 | """ 666 | return self._light.light 667 | 668 | @property 669 | def red_led(self) -> bool: 670 | """The red led next to the USB plug marked D13. 671 | 672 | .. image :: ../docs/_static/red_led.jpg 673 | :alt: D13 LED 674 | 675 | To use with the Circuit Playground Express or Bluefruit: 676 | 677 | .. code-block:: python 678 | 679 | from adafruit_circuitplayground import cp 680 | import time 681 | 682 | while True: 683 | cp.red_led = True 684 | time.sleep(0.5) 685 | cp.red_led = False 686 | time.sleep(0.5) 687 | """ 688 | return self._led.value 689 | 690 | @red_led.setter 691 | def red_led(self, value: bool) -> None: 692 | self._led.value = value 693 | 694 | @staticmethod 695 | def _sine_sample(length: int) -> Iterator[int]: 696 | tone_volume = (2**15) - 1 697 | # Amplitude shift up in order to not have negative numbers 698 | shift = 2**15 699 | for i in range(length): 700 | yield int(tone_volume * math.sin(2 * math.pi * (i / length)) + shift) 701 | 702 | @staticmethod 703 | def _square_sample(length: int) -> Iterator[int]: 704 | # Square waves are MUCH louder than then sine 705 | tone_volume = (2**16) - 1 706 | half_length = length // 2 707 | for _ in range(half_length): 708 | yield tone_volume 709 | for _ in range(half_length): 710 | yield 0 711 | 712 | def _generate_sample(self, length: int = 100, waveform: int = SINE_WAVE) -> None: 713 | if self._sample is not None: 714 | return 715 | if waveform == self.SQUARE_WAVE: 716 | self._wave = array.array("H", self._square_sample(length)) 717 | else: 718 | self._wave = array.array("H", self._sine_sample(length)) 719 | self._sample = self._audio_out(board.SPEAKER) 720 | self._wave_sample = audiocore.RawSample(self._wave) 721 | 722 | def play_tone(self, frequency: int, duration: float, waveform: int = SINE_WAVE) -> None: 723 | """Produce a tone using the speaker. Try changing frequency to change 724 | the pitch of the tone. 725 | 726 | :param int frequency: The frequency of the tone in Hz 727 | :param float duration: The duration of the tone in seconds 728 | :param int waveform: Type of waveform to be generated [SINE_WAVE, SQUARE_WAVE]. 729 | 730 | Default is SINE_WAVE. 731 | 732 | .. image :: ../docs/_static/speaker.jpg 733 | :alt: Onboard speaker 734 | 735 | To use with the Circuit Playground Express or Bluefruit: 736 | 737 | .. code-block:: python 738 | 739 | from adafruit_circuitplayground import cp 740 | 741 | cp.play_tone(440, 1) 742 | """ 743 | # Play a tone of the specified frequency (hz). 744 | self.start_tone(frequency, waveform) 745 | time.sleep(duration) 746 | self.stop_tone() 747 | 748 | def start_tone(self, frequency: int, waveform: int = SINE_WAVE) -> None: 749 | """Produce a tone using the speaker. Try changing frequency to change 750 | the pitch of the tone. 751 | 752 | :param int frequency: The frequency of the tone in Hz 753 | :param int waveform: Type of waveform to be generated [SINE_WAVE, SQUARE_WAVE]. 754 | 755 | Default is SINE_WAVE. 756 | 757 | .. image :: ../docs/_static/speaker.jpg 758 | :alt: Onboard speaker 759 | 760 | To use with the Circuit Playground Express or Bluefruit: 761 | 762 | .. code-block:: python 763 | 764 | from adafruit_circuitplayground import cp 765 | 766 | while True: 767 | if cp.button_a: 768 | cp.start_tone(262) 769 | elif cp.button_b: 770 | cp.start_tone(294) 771 | else: 772 | cp.stop_tone() 773 | """ 774 | self._speaker_enable.value = True 775 | length = 100 776 | if length * frequency > 350000: 777 | length = 350000 // frequency 778 | self._generate_sample(length, waveform) 779 | # Start playing a tone of the specified frequency (hz). 780 | self._wave_sample.sample_rate = int(len(self._wave) * frequency) 781 | if not self._sample.playing: 782 | self._sample.play(self._wave_sample, loop=True) 783 | 784 | def stop_tone(self) -> None: 785 | """Use with start_tone to stop the tone produced. 786 | 787 | .. image :: ../docs/_static/speaker.jpg 788 | :alt: Onboard speaker 789 | 790 | To use with the Circuit Playground Express or Bluefruit: 791 | 792 | .. code-block:: python 793 | 794 | from adafruit_circuitplayground import cp 795 | 796 | while True: 797 | if cp.button_a: 798 | cp.start_tone(262) 799 | elif cp.button_b: 800 | cp.start_tone(294) 801 | else: 802 | cp.stop_tone() 803 | """ 804 | # Stop playing any tones. 805 | if self._sample is not None and self._sample.playing: 806 | self._sample.stop() 807 | self._sample.deinit() 808 | self._sample = None 809 | self._speaker_enable.value = False 810 | 811 | def play_file(self, file_name: str) -> None: 812 | """Play a .wav file using the onboard speaker. 813 | 814 | :param file_name: The name of your .wav file in quotation marks including .wav 815 | 816 | .. image :: ../docs/_static/speaker.jpg 817 | :alt: Onboard speaker 818 | 819 | To use with the Circuit Playground Express or Bluefruit: 820 | 821 | .. code-block:: python 822 | 823 | from adafruit_circuitplayground import cp 824 | 825 | while True: 826 | if cp.button_a: 827 | cp.play_file("laugh.wav") 828 | elif cp.button_b: 829 | cp.play_file("rimshot.wav") 830 | """ 831 | # Play a specified file. 832 | self.stop_tone() 833 | self._speaker_enable.value = True 834 | with self._audio_out(board.SPEAKER) as audio, audiocore.WaveFile( 835 | open(file_name, "rb") 836 | ) as wavefile: 837 | audio.play(wavefile) 838 | while audio.playing: 839 | pass 840 | self._speaker_enable.value = False 841 | -------------------------------------------------------------------------------- /adafruit_circuitplayground/express.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2016 Scott Shawcroft for Adafruit Industries 2 | # SPDX-FileCopyrightText: 2017-2019 Kattni Rembor for Adafruit Industries 3 | # 4 | # SPDX-License-Identifier: MIT 5 | 6 | """ 7 | `adafruit_circuitplayground.express` 8 | ==================================================== 9 | 10 | CircuitPython helper for Circuit Playground Express. 11 | 12 | **Hardware:** 13 | 14 | * `Circuit Playground Express `_ 15 | 16 | * Author(s): Kattni Rembor, Scott Shawcroft 17 | """ 18 | 19 | import sys 20 | 21 | import audioio 22 | import digitalio 23 | 24 | try: 25 | lib_index = sys.path.index("/lib") 26 | if lib_index < sys.path.index(".frozen"): 27 | # Prefer frozen modules over those in /lib. 28 | sys.path.insert(lib_index, ".frozen") 29 | except ValueError: 30 | # Don't change sys.path if it doesn't contain "lib" or ".frozen". 31 | pass 32 | from adafruit_circuitplayground.circuit_playground_base import ( 33 | CircuitPlaygroundBase, 34 | ) 35 | 36 | __version__ = "0.0.0+auto.0" 37 | __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground.git" 38 | 39 | 40 | class Express(CircuitPlaygroundBase): 41 | """Represents a single CircuitPlayground Express. Do not use more than one at 42 | a time.""" 43 | 44 | # Touch pad A7 is labeled both A7/TX on Circuit Playground Express and only TX on 45 | # the Circuit Playground Bluefruit. It is therefore referred to as TX in the 46 | # CircuitPlaygroundBase class, but can be used as either for Express. 47 | touch_A7 = CircuitPlaygroundBase.touch_TX 48 | _audio_out = audioio.AudioOut 49 | 50 | def __init__(self): 51 | # Only create the cpx module member when we aren't being imported by Sphinx 52 | if ( 53 | "__module__" in dir(digitalio.DigitalInOut) 54 | and digitalio.DigitalInOut.__module__ == "sphinx.ext.autodoc" 55 | ): 56 | return 57 | 58 | super().__init__() 59 | 60 | @property 61 | def _unsupported(self): 62 | """This feature is not supported on Circuit Playground Express.""" 63 | raise NotImplementedError("This feature is not supported on Circuit Playground Express.") 64 | 65 | # The following is a list of the features available in other Circuit Playground modules but 66 | # not available for Circuit Playground Express. If called while using a Circuit Playground 67 | # Express, they will result in the NotImplementedError raised in the property above. 68 | sound_level = _unsupported 69 | loud_sound = _unsupported 70 | play_mp3 = _unsupported 71 | 72 | 73 | cpx = Express() 74 | """Object that is automatically created on import. 75 | 76 | To use, simply import it from the module: 77 | 78 | .. code-block:: python 79 | 80 | from adafruit_circuitplayground.express import cpx 81 | """ 82 | -------------------------------------------------------------------------------- /docs/_static/accelerometer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/accelerometer.jpg -------------------------------------------------------------------------------- /docs/_static/accelerometer.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/button_a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/button_a.jpg -------------------------------------------------------------------------------- /docs/_static/button_a.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/button_b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/button_b.jpg -------------------------------------------------------------------------------- /docs/_static/button_b.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/capacitive_touch_pad_A1.jpg -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A1.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/capacitive_touch_pad_A2.jpg -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A2.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/capacitive_touch_pad_A3.jpg -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A3.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/capacitive_touch_pad_A4.jpg -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A4.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/capacitive_touch_pad_A5.jpg -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A5.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/capacitive_touch_pad_A6.jpg -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A6.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/capacitive_touch_pad_A7.jpg -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pad_A7.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pads.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/capacitive_touch_pads.jpg -------------------------------------------------------------------------------- /docs/_static/capacitive_touch_pads.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/circuit_playground_bluefruit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/circuit_playground_bluefruit.jpg -------------------------------------------------------------------------------- /docs/_static/circuit_playground_bluefruit.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/circuit_playground_bluefruit_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/circuit_playground_bluefruit_small.jpg -------------------------------------------------------------------------------- /docs/_static/circuit_playground_bluefruit_small.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/circuit_playground_express_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/circuit_playground_express_small.jpg -------------------------------------------------------------------------------- /docs/_static/circuit_playground_express_small.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/circuitplayground_express.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/circuitplayground_express.jpg -------------------------------------------------------------------------------- /docs/_static/circuitplayground_express.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/favicon.ico -------------------------------------------------------------------------------- /docs/_static/favicon.ico.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/light_sensor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/light_sensor.jpg -------------------------------------------------------------------------------- /docs/_static/light_sensor.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/microphone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/microphone.jpg -------------------------------------------------------------------------------- /docs/_static/microphone.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/neopixel_numbering.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/neopixel_numbering.jpg -------------------------------------------------------------------------------- /docs/_static/neopixel_numbering.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/red_led.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/red_led.jpg -------------------------------------------------------------------------------- /docs/_static/red_led.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/slide_switch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/slide_switch.jpg -------------------------------------------------------------------------------- /docs/_static/slide_switch.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/speaker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/speaker.jpg -------------------------------------------------------------------------------- /docs/_static/speaker.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/_static/thermistor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/docs/_static/thermistor.jpg -------------------------------------------------------------------------------- /docs/_static/thermistor.jpg.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/api.rst: -------------------------------------------------------------------------------- 1 | 2 | .. If you created a package, create one automodule per module in the package. 3 | 4 | API Reference 5 | ############# 6 | 7 | .. automodule:: adafruit_circuitplayground.circuit_playground_base 8 | :members: 9 | 10 | .. automodule:: adafruit_circuitplayground.bluefruit 11 | :members: 12 | 13 | .. automodule:: adafruit_circuitplayground.express 14 | :members: 15 | -------------------------------------------------------------------------------- /docs/api.rst.license: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 ladyada for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | import datetime 6 | import os 7 | import sys 8 | 9 | sys.path.insert(0, os.path.abspath("..")) 10 | sys.path.insert(0, os.path.abspath("mocks")) 11 | 12 | # -- General configuration ------------------------------------------------ 13 | 14 | # Add any Sphinx extension module names here, as strings. They can be 15 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 16 | # ones. 17 | extensions = [ 18 | "sphinx.ext.autodoc", 19 | "sphinxcontrib.jquery", 20 | "sphinx.ext.intersphinx", 21 | "sphinx.ext.viewcode", 22 | ] 23 | 24 | intersphinx_mapping = { 25 | "python": ("https://docs.python.org/3", None), 26 | "CircuitPython": ("https://docs.circuitpython.org/en/latest/", None), 27 | "NeoPixel": ( 28 | "https://docs.circuitpython.org/projects/neopixel/en/latest/", 29 | None, 30 | ), 31 | } 32 | 33 | # Libraries we depend on but don't need for generating docs. 34 | autodoc_mock_imports = [ 35 | "board", 36 | "analogio", 37 | "digitalio", 38 | "neopixel", 39 | "adafruit_thermistor", 40 | "audioio", 41 | "touchio", 42 | "adafruit_lis3dh", 43 | "busio", 44 | "audiocore", 45 | "audiopwmio", 46 | "audiobusio", 47 | "audiomp3", 48 | ] 49 | 50 | # Add any paths that contain templates here, relative to this directory. 51 | templates_path = ["_templates"] 52 | 53 | source_suffix = ".rst" 54 | 55 | # The master toctree document. 56 | master_doc = "index" 57 | 58 | # General information about the project. 59 | project = "Adafruit CircuitPlayground Library" 60 | creation_year = "2017" 61 | current_year = str(datetime.datetime.now().year) 62 | year_duration = ( 63 | current_year if current_year == creation_year else creation_year + " - " + current_year 64 | ) 65 | copyright = year_duration + " Scott Shawcroft" 66 | author = "Scott Shawcroft" 67 | 68 | # The version info for the project you're documenting, acts as replacement for 69 | # |version| and |release|, also used in various other places throughout the 70 | # built documents. 71 | # 72 | # The short X.Y version. 73 | version = "1.0" 74 | # The full version, including alpha/beta/rc tags. 75 | release = "1.0" 76 | 77 | # The language for content autogenerated by Sphinx. Refer to documentation 78 | # for a list of supported languages. 79 | # 80 | # This is also used if you do content translation via gettext catalogs. 81 | # Usually you set "language" from the command line for these cases. 82 | language = "en" 83 | 84 | # List of patterns, relative to source directory, that match files and 85 | # directories to ignore when looking for source files. 86 | # This patterns also effect to html_static_path and html_extra_path 87 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".env", "CODE_OF_CONDUCT.md"] 88 | 89 | # The reST default role (used for this markup: `text`) to use for all 90 | # documents. 91 | # 92 | default_role = "any" 93 | 94 | # If true, '()' will be appended to :func: etc. cross-reference text. 95 | # 96 | add_function_parentheses = True 97 | 98 | # The name of the Pygments (syntax highlighting) style to use. 99 | pygments_style = "sphinx" 100 | 101 | # If true, `todo` and `todoList` produce output, else they produce nothing. 102 | todo_include_todos = False 103 | 104 | # If this is True, todo emits a warning for each TODO entries. The default is False. 105 | todo_emit_warnings = True 106 | 107 | 108 | # -- Options for HTML output ---------------------------------------------- 109 | 110 | # The theme to use for HTML and HTML Help pages. See the documentation for 111 | # a list of builtin themes. 112 | # 113 | import sphinx_rtd_theme 114 | 115 | html_theme = "sphinx_rtd_theme" 116 | 117 | # Add any paths that contain custom static files (such as style sheets) here, 118 | # relative to this directory. They are copied after the builtin static files, 119 | # so a file named "default.css" will overwrite the builtin "default.css". 120 | html_static_path = ["_static"] 121 | 122 | # The name of an image file (relative to this directory) to use as a favicon of 123 | # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 124 | # pixels large. 125 | # 126 | html_favicon = "_static/favicon.ico" 127 | 128 | # Output file base name for HTML help builder. 129 | htmlhelp_basename = "AdafruitCircuitPlaygroundLibrarydoc" 130 | 131 | # -- Options for LaTeX output --------------------------------------------- 132 | 133 | latex_elements = { 134 | # The paper size ('letterpaper' or 'a4paper'). 135 | # 136 | # 'papersize': 'letterpaper', 137 | # The font size ('10pt', '11pt' or '12pt'). 138 | # 139 | # 'pointsize': '10pt', 140 | # Additional stuff for the LaTeX preamble. 141 | # 142 | # 'preamble': '', 143 | # Latex figure (float) alignment 144 | # 145 | # 'figure_align': 'htbp', 146 | } 147 | 148 | # Grouping the document tree into LaTeX files. List of tuples 149 | # (source start file, target name, title, 150 | # author, documentclass [howto, manual, or own class]). 151 | latex_documents = [ 152 | ( 153 | master_doc, 154 | "AdafruitCircuitPlaygroundLibrary.tex", 155 | "Adafruit CircuitPlayground Library Documentation", 156 | author, 157 | "manual", 158 | ), 159 | ] 160 | 161 | # -- Options for manual page output --------------------------------------- 162 | 163 | # One entry per manual page. List of tuples 164 | # (source start file, name, description, authors, manual section). 165 | man_pages = [ 166 | ( 167 | master_doc, 168 | "adafruitCircuitPlaygroundlibrary", 169 | "Adafruit CircuitPlayground Library Documentation", 170 | [author], 171 | 1, 172 | ) 173 | ] 174 | 175 | # -- Options for Texinfo output ------------------------------------------- 176 | 177 | # Grouping the document tree into Texinfo files. List of tuples 178 | # (source start file, target name, title, author, 179 | # dir menu entry, description, category) 180 | texinfo_documents = [ 181 | ( 182 | master_doc, 183 | "AdafruitCircuitPlaygroundLibrary", 184 | "Adafruit CircuitPlayground Library Documentation", 185 | author, 186 | "AdafruitCircuitPlaygroundLibrary", 187 | "One line description of project.", 188 | "Miscellaneous", 189 | ), 190 | ] 191 | -------------------------------------------------------------------------------- /docs/examples.rst: -------------------------------------------------------------------------------- 1 | Simple test 2 | ------------ 3 | 4 | Ensure your device works with this simple test. 5 | 6 | .. literalinclude:: ../examples/circuitplayground_acceleration.py 7 | :caption: examples/circuitplayground_acceleration.py 8 | :linenos: 9 | 10 | .. literalinclude:: ../examples/circuitplayground_pixels_simpletest.py 11 | :caption: examples/circuitplayground_pixels_simpletest.py 12 | :linenos: 13 | 14 | .. literalinclude:: ../examples/circuitplayground_shake.py 15 | :caption: examples/circuitplayground_shake.py 16 | :linenos: 17 | 18 | .. literalinclude:: ../examples/circuitplayground_tapdetect_single_double.py 19 | :caption: examples/circuitplayground_tapdetect_single_double.py 20 | :linenos: 21 | 22 | .. literalinclude:: ../examples/circuitplayground_tapdetect.py 23 | :caption: examples/circuitplayground_tapdetect.py 24 | :linenos: 25 | 26 | .. literalinclude:: ../examples/circuitplayground_tone.py 27 | :caption: examples/circuitplayground_tone.py 28 | :linenos: 29 | 30 | .. literalinclude:: ../examples/circuitplayground_touch_all.py 31 | :caption: examples/circuitplayground_touched.py 32 | :linenos: 33 | 34 | .. literalinclude:: ../examples/circuitplayground_acceleration_neopixels.py 35 | :caption: examples/circuitplayground_acceleration_neopixels.py 36 | :linenos: 37 | 38 | .. literalinclude:: ../examples/circuitplayground_button_a.py 39 | :caption: examples/circuitplayground_button_a.py 40 | :linenos: 41 | 42 | .. literalinclude:: ../examples/circuitplayground_button_b.py 43 | :caption: examples/circuitplayground_button_b.py 44 | :linenos: 45 | 46 | .. literalinclude:: ../examples/circuitplayground_buttons_1_neopixel.py 47 | :caption: examples/circuitplayground_buttons_1_neopixel.py 48 | :linenos: 49 | 50 | .. literalinclude:: ../examples/circuitplayground_buttons_neopixels.py 51 | :caption: examples/circuitplayground_buttons_neopixels.py 52 | :linenos: 53 | 54 | .. literalinclude:: ../examples/circuitplayground_ir_receive.py 55 | :caption: examples/circuitplayground_ir_receive.py 56 | :linenos: 57 | 58 | .. literalinclude:: ../examples/circuitplayground_ir_transmit.py 59 | :caption: examples/circuitplayground_ir_transmit.py 60 | :linenos: 61 | 62 | .. literalinclude:: ../examples/circuitplayground_light_neopixels.py 63 | :caption: examples/circuitplayground_light_neopixels.py 64 | :linenos: 65 | 66 | .. literalinclude:: ../examples/circuitplayground_light.py 67 | :caption: examples/circuitplayground_light.py 68 | :linenos: 69 | 70 | .. literalinclude:: ../examples/circuitplayground_neopixel_0_1.py 71 | :caption: examples/circuitplayground_neopixel_0_1.py 72 | :linenos: 73 | 74 | .. literalinclude:: ../examples/circuitplayground_light_plotter.py 75 | :caption: examples/circuitplayground_light_plotter.py 76 | :linenos: 77 | 78 | .. literalinclude:: ../examples/circuitplayground_play_file_buttons.py 79 | :caption: examples/circuitplayground_play_file_buttons.py 80 | :linenos: 81 | 82 | .. literalinclude:: ../examples/circuitplayground_play_file.py 83 | :caption: examples/circuitplayground_play_file.py 84 | :linenos: 85 | 86 | .. literalinclude:: ../examples/circuitplayground_play_tone_buttons.py 87 | :caption: examples/circuitplayground_play_tone_buttons.py 88 | :linenos: 89 | 90 | .. literalinclude:: ../examples/circuitplayground_play_tone.py 91 | :caption: examples/circuitplayground_play_tone.py 92 | :linenos: 93 | 94 | .. literalinclude:: ../examples/circuitplayground_red_led_blinky.py 95 | :caption: examples/circuitplayground_red_led_blinky.py 96 | :linenos: 97 | 98 | .. literalinclude:: ../examples/circuitplayground_red_led_blnky_short.py 99 | :caption: examples/circuitplayground_red_led_blnky_short.py 100 | :linenos: 101 | 102 | .. literalinclude:: ../examples/circuitplayground_red_led.py 103 | :caption: examples/circuitplayground_red_led.py 104 | :linenos: 105 | 106 | .. literalinclude:: ../examples/circuitplayground_slide_switch_red_led.py 107 | :caption: examples/circuitplayground_slide_switch_red_led.py 108 | :linenos: 109 | 110 | .. literalinclude:: ../examples/circuitplayground_slide_switch_red_led_short.py 111 | :caption: examples/circuitplayground_slide_switch_red_led_short.py 112 | :linenos: 113 | 114 | .. literalinclude:: ../examples/circuitplayground_slide_switch.py 115 | :caption: examples/circuitplayground_slide_switch.py 116 | :linenos: 117 | 118 | .. literalinclude:: ../examples/circuitplayground_sound_meter.py 119 | :caption: examples/circuitplayground_sound_meter.py 120 | :linenos: 121 | 122 | .. literalinclude:: ../examples/circuitplayground_tap_red_led.py 123 | :caption: examples/circuitplayground_tap_red_led.py 124 | :linenos: 125 | 126 | .. literalinclude:: ../examples/circuitplayground_temperature_neopixels.py 127 | :caption: examples/circuitplayground_temperature_neopixels.py 128 | :linenos: 129 | 130 | .. literalinclude:: ../examples/circuitplayground_temperature_plotter.py 131 | :caption: examples/circuitplayground_temperature_plotter.py 132 | :linenos: 133 | 134 | .. literalinclude:: ../examples/circuitplayground_temperature.py 135 | :caption: examples/circuitplayground_temperature.py 136 | :linenos: 137 | 138 | .. literalinclude:: ../examples/circuitplayground_touch_pixel_fill_rainbow.py 139 | :caption: examples/circuitplayground_touch_pixel_fill_rainbow.py 140 | :linenos: 141 | 142 | .. literalinclude:: ../examples/circuitplayground_touch_pixel_rainbow.py 143 | :caption: examples/circuitplayground_touch_pixel_rainbow.py 144 | :linenos: 145 | -------------------------------------------------------------------------------- /docs/examples.rst.license: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 ladyada for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.rst 2 | 3 | Table of Contents 4 | ================= 5 | 6 | .. toctree:: 7 | :maxdepth: 4 8 | :hidden: 9 | 10 | self 11 | 12 | .. toctree:: 13 | :caption: Examples 14 | 15 | examples 16 | 17 | .. toctree:: 18 | :caption: API Reference 19 | :maxdepth: 3 20 | 21 | api 22 | 23 | .. toctree:: 24 | :caption: Tutorials 25 | 26 | .. toctree:: 27 | :caption: Related Products 28 | 29 | Adafruit CircuitPlayground Express 30 | 31 | .. toctree:: 32 | :caption: Other Links 33 | 34 | Download from GitHub 35 | Download Library Bundle 36 | CircuitPython Reference Documentation 37 | CircuitPython Support Forum 38 | Discord Chat 39 | Adafruit Learning System 40 | Adafruit Blog 41 | Adafruit Store 42 | 43 | Indices and tables 44 | ================== 45 | 46 | * :ref:`genindex` 47 | * :ref:`modindex` 48 | * :ref:`search` 49 | -------------------------------------------------------------------------------- /docs/index.rst.license: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 ladyada for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | -------------------------------------------------------------------------------- /docs/mocks/keypad.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Jeff Eplerfor Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | class EventQueue: 5 | def __init__(self): 6 | self.overflowed = False 7 | 8 | def get(self): # noqa: PLR6301 9 | return None 10 | 11 | 12 | class Keys: 13 | def __init__(self, pins, value_when_pressed, pull): 14 | self.key_count = len(pins) 15 | self.events = EventQueue() 16 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: Unlicense 4 | 5 | sphinx 6 | sphinxcontrib-jquery 7 | sphinx-rtd-theme 8 | -------------------------------------------------------------------------------- /examples/circuitplayground_acceleration.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """ 5 | This example uses the accelerometer on the Circuit Playground. It prints the values. Try moving 6 | the board to see the values change. If you're using Mu, open the plotter to see the values plotted. 7 | """ 8 | 9 | import time 10 | 11 | from adafruit_circuitplayground import cp 12 | 13 | while True: 14 | x, y, z = cp.acceleration 15 | print((x, y, z)) 16 | 17 | time.sleep(0.1) 18 | -------------------------------------------------------------------------------- /examples/circuitplayground_acceleration_neopixels.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """If the switch is to the right, it will appear that nothing is happening. Move the switch to the 5 | left to see the NeoPixels light up in colors related to the accelerometer! The Circuit Playground 6 | has an accelerometer in the center that returns (x, y, z) acceleration values. This program uses 7 | those values to light up the NeoPixels based on those acceleration values.""" 8 | 9 | from adafruit_circuitplayground import cp 10 | 11 | # Main loop gets x, y and z axis acceleration, prints the values, and turns on 12 | # red, green and blue, at levels related to the x, y and z values. 13 | while True: 14 | if not cp.switch: 15 | # If the switch is to the right, it returns False! 16 | print("Slide switch off!") 17 | cp.pixels.fill((0, 0, 0)) 18 | continue 19 | R = 0 20 | G = 0 21 | B = 0 22 | x, y, z = cp.acceleration 23 | print((x, y, z)) 24 | cp.pixels.fill(((R + abs(int(x))), (G + abs(int(y))), (B + abs(int(z))))) 25 | -------------------------------------------------------------------------------- /examples/circuitplayground_advanced_examples/circuitplayground_acceleration_mapping_neopixels.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """Maps acceleration (tilt) to Neopixel colors. 5 | 6 | x, y, and z acceleration components map to red, green and blue, 7 | respectively. 8 | 9 | When the Circuit Playground is level, the lights are blue because there is no acceleration 10 | on x or y, but on z, gravity pulls at 9.81 meters per second per second (m/s²). 11 | When banking, the vertical (z) axis is no longer directly aligned with gravity, 12 | so the blue decreases, and red increases because gravity is now pulling more 13 | along the x axis. Similarly, when changing the pitch from level, we see blue change 14 | to green. 15 | 16 | This video walks you through the code: https://youtu.be/eNpPLbYx-iA 17 | """ 18 | 19 | import time 20 | 21 | from adafruit_circuitplayground import cp 22 | 23 | cp.pixels.brightness = 0.2 # Adjust overall brightness as desired, between 0 and 1 24 | 25 | 26 | def color_amount(accel_component): 27 | """Convert acceleration component (x, y, or z) to color amount (r, g, or b)""" 28 | standard_gravity = 9.81 # Acceleration (m/s²) due to gravity at the earth’s surface 29 | accel_magnitude = abs(accel_component) # Ignore the direction 30 | constrained_accel = min(accel_magnitude, standard_gravity) # Constrain values 31 | normalized_accel = constrained_accel / standard_gravity # Convert to 0–1 32 | return round(normalized_accel * 255) # Convert to 0–255 33 | 34 | 35 | def format_acceleration(): 36 | return ", ".join(f"{axis_value:>6.2f}" for axis_value in acceleration) 37 | 38 | 39 | def format_rgb(): 40 | return ", ".join(f"{rgb_amount:>3d}" for rgb_amount in rgb_amounts) 41 | 42 | 43 | def log_values(): 44 | print(f"({format_acceleration()}) ==> ({format_rgb()})") 45 | 46 | 47 | while True: 48 | acceleration = cp.acceleration 49 | rgb_amounts = [color_amount(axis_value) for axis_value in acceleration] 50 | cp.pixels.fill(rgb_amounts) 51 | log_values() 52 | time.sleep(0.1) 53 | -------------------------------------------------------------------------------- /examples/circuitplayground_advanced_examples/circuitplayground_gravity_pulls_pixel.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """Gravity Pulls Pixel 5 | 6 | This program uses the Circuit Playground's accelerometer to position 7 | a white pixel as if gravity were pulling it. 8 | 9 | Flip the switch left (toward the notes) to turn on debugging messages and 10 | slow down the action. See a code walkthrough here: https://youtu.be/sZ4tNOUKRpw 11 | """ 12 | 13 | import math 14 | import time 15 | 16 | from adafruit_circuitplayground import cp 17 | 18 | PIXEL_SPACING_ANGLE = 30 19 | STANDARD_GRAVITY = 9.81 20 | 21 | BACKGROUND_COLOR = 0, 0, 64 22 | MIN_BRIGHTNESS = 15 # Minimum brightness for anti-aliasing 23 | LIGHTING_ARC_LENGTH = 45 24 | 25 | 26 | def compute_pixel_angles(): 27 | """Return a list of rotation angles of the ten NeoPixels. 28 | 29 | On the Circuit Playground there are ten pixels arranged like the 12 hours of a clock, except 30 | that positions 6 and 12 are empty. The numbers in the list are the angles from the (x, y) 31 | accelerometer values for each pixel when the Circuit Playground is rotated with that pixel at 32 | the bottom. For example, with pixel 0 at the bottom (and pixel 5 at the top), the 33 | accelerometer’s (x, y) values give an angle of 300°. Rotated clockwise 1/12 turn (30°), so 34 | that pixel 1 is at the bottom, the angle is 330°. 35 | """ 36 | return [(300 + PIXEL_SPACING_ANGLE * n) % 360 for n in range(12) if n not in {5, 11}] 37 | 38 | 39 | def degrees_between(a1, a2): 40 | smaller = min(a1, a2) 41 | larger = max(a1, a2) 42 | return min(larger - smaller, 360 + smaller - larger) 43 | 44 | 45 | def pixel_brightness(distance_from_down, accel_magnitude): 46 | """Return the a brightness for a pixel, or None if the pixel is not in the lighting arc""" 47 | half_lighting_arc_length = LIGHTING_ARC_LENGTH / 2 48 | 49 | if accel_magnitude < 0.1 or distance_from_down > half_lighting_arc_length: 50 | return None 51 | 52 | normalized_nearness = 1 - distance_from_down / half_lighting_arc_length 53 | scale_factor = (255 - MIN_BRIGHTNESS) * accel_magnitude 54 | color_part = MIN_BRIGHTNESS + round(normalized_nearness * scale_factor) 55 | return color_part 56 | 57 | 58 | def angle_in_degrees(x, y): 59 | """Return the angle of the point (x, y), in degrees from -180 to 180""" 60 | return math.atan2(y, x) / math.pi * 180 61 | 62 | 63 | def positive_degrees(angle): 64 | """Convert -180 through 180 to 0 through 360""" 65 | return (angle + 360) % 360 66 | 67 | 68 | cp.pixels.brightness = 0.1 # Adjust overall brightness as desired, between 0 and 1 69 | pixel_positions = compute_pixel_angles() 70 | 71 | while True: 72 | debug = cp.switch # True is toward the left 73 | accel_x, accel_y = cp.acceleration[:2] # Ignore z 74 | down_angle = positive_degrees(angle_in_degrees(accel_x, accel_y)) 75 | magnitude_limit = STANDARD_GRAVITY 76 | normalized_magnitude = ( 77 | min(math.sqrt(accel_x * accel_x + accel_y * accel_y), magnitude_limit) / magnitude_limit 78 | ) 79 | 80 | pixels_lit = [] 81 | for i, pixel_position in enumerate(pixel_positions): 82 | pe = pixel_brightness(degrees_between(pixel_position, down_angle), normalized_magnitude) 83 | cp.pixels[i] = (pe, pe, pe) if pe else BACKGROUND_COLOR 84 | if pe: 85 | pixels_lit.append((i, pe)) 86 | 87 | if debug: 88 | lit_formatted = ", ".join((f"{p}: {i:>3d}" for p, i in pixels_lit)) 89 | print( 90 | f"x: {accel_x:>6.2f}, y: {accel_y:>6.2f}, angle: {down_angle:>6.2f}, mag: {normalized_magnitude:>3.2f}, pixels: [{lit_formatted}]" # noqa: E501 91 | ) 92 | time.sleep(0.5) 93 | -------------------------------------------------------------------------------- /examples/circuitplayground_advanced_examples/circuitplayground_tilting_arpeggios.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """Tilting Arpeggios 5 | 6 | This program plays notes from arpeggios in a circle of fourths. Y-axis tilt chooses the note. 7 | Buttons A and B advance forward and backward through the circle. The switch selects 8 | the type of arpeggio, either dominant seventh or blues. 9 | 10 | You can ignore the FrequencyProvider class if you’re just interested in the Circuit Playground 11 | interface. 12 | 13 | See a code walkthrough here: https://www.youtube.com/watch?v=cDhqyT3ZN0g 14 | """ 15 | 16 | import time 17 | 18 | from adafruit_circuitplayground import cp 19 | 20 | HS_OCT = 12 # Half-steps per octave 21 | HS_4TH = 5 # Half-steps in a fourth 22 | ARPEGGIOS = ((0, 4, 7, 10), (0, 3, 5, 6, 7, 10)) # Dominant seventh # Blues 23 | NUM_OCTAVES = 2 24 | STARTING_NOTE = 233.08 25 | MIN_NOTE_PLAY_SECONDS = 0.25 26 | BUTTON_REPEAT_AFTER_SECONDS = 0.25 27 | 28 | 29 | class FrequencyMaker: 30 | """Provide frequencies for playing notes""" 31 | 32 | def __init__(self): 33 | num_octaves_to_pre_compute = NUM_OCTAVES + 2 34 | num_freqs = HS_OCT * num_octaves_to_pre_compute 35 | 36 | def calc_freq(i): 37 | return STARTING_NOTE * 2 ** (i / HS_OCT) 38 | 39 | self.note_frequencies = [calc_freq(i) for i in range(num_freqs)] 40 | self.arpeg_note_indexes = FrequencyMaker.create_arpeggios(num_octaves_to_pre_compute) 41 | self.circle_pos = 0 42 | self.key_offset = 0 43 | 44 | @staticmethod 45 | def create_arpeggios(num_octaves): 46 | """Create a list of arpeggios, where each one is a list of chromatic scale note indexes""" 47 | return [FrequencyMaker.create_arpeggio(arpeggio, num_octaves) for arpeggio in ARPEGGIOS] 48 | 49 | @staticmethod 50 | def create_arpeggio(arpeggio, num_octaves): 51 | return [octave * HS_OCT + note for octave in range(num_octaves) for note in arpeggio] 52 | 53 | def advance(self, amount): 54 | """Advance forward or backward through the circle of fourths""" 55 | self.circle_pos = (self.circle_pos + amount) % HS_OCT 56 | self.key_offset = self.circle_pos * HS_4TH % HS_OCT 57 | 58 | def freq(self, normalized_position, selected_arpeg): 59 | """Return the frequency for the note at the specified position in the specified arpeggio""" 60 | selected_arpeg_note_indexes = self.arpeg_note_indexes[selected_arpeg] 61 | num_notes_in_selected_arpeg = len(ARPEGGIOS[selected_arpeg]) 62 | num_arpeg_notes_in_range = num_notes_in_selected_arpeg * NUM_OCTAVES + 1 63 | arpeg_index = int(normalized_position * num_arpeg_notes_in_range) 64 | note_index = self.key_offset + selected_arpeg_note_indexes[arpeg_index] 65 | return self.note_frequencies[note_index] 66 | 67 | 68 | class ButtonDetector: 69 | def __init__(self): 70 | self.next_press_allowed_at = time.monotonic() 71 | self.buttons_on = (cp.button_a, cp.button_b) 72 | 73 | def pressed(self, index): 74 | """Return whether the specified button (0=A, 1=B) was pressed, limiting the repeat rate""" 75 | pressed = cp.button_b if index else cp.button_a 76 | if pressed: 77 | now = time.monotonic() 78 | if now >= self.next_press_allowed_at: 79 | self.next_press_allowed_at = now + BUTTON_REPEAT_AFTER_SECONDS 80 | return True 81 | return False 82 | 83 | 84 | class TiltingArpeggios: 85 | def __init__(self): 86 | cp.pixels.brightness = 0.2 87 | self.freq_maker = FrequencyMaker() 88 | TiltingArpeggios.update_pixel(self.freq_maker.circle_pos) 89 | self.button = ButtonDetector() 90 | self.last_freq = None 91 | self.next_freq_change_allowed_at = time.monotonic() 92 | 93 | def run(self): 94 | while True: 95 | self.process_button_presses() 96 | if time.monotonic() >= self.next_freq_change_allowed_at: 97 | self.next_freq_change_allowed_at = time.monotonic() + MIN_NOTE_PLAY_SECONDS 98 | self.change_tone_if_needed() 99 | 100 | @staticmethod 101 | def update_pixel(circle_pos): 102 | """Manage the display on the NeoPixels of the current circle position""" 103 | cp.pixels.fill((0, 0, 0)) 104 | # Light the pixels clockwise from “1 o’clock” with the USB connector on the bottom 105 | pixel_index = (4 - circle_pos) % 10 106 | # Use a different color after all ten LEDs used 107 | color = (0, 255, 0) if circle_pos <= 9 else (255, 255, 0) 108 | cp.pixels[pixel_index] = color 109 | 110 | @staticmethod 111 | def tilt(): 112 | """Normalize the Y-Axis Tilt""" 113 | standard_gravity = 9.81 # Acceleration (m/s²) due to gravity at the earth’s surface 114 | constrained_accel = min(max(0.0, -cp.acceleration[1]), standard_gravity) 115 | return constrained_accel / standard_gravity 116 | 117 | def process_button_presses(self): 118 | """For each of the buttons A and B, if pushed, advance forward or backward""" 119 | for button_index, direction in enumerate((1, -1)): 120 | if self.button.pressed(button_index): 121 | self.freq_maker.advance(direction) 122 | TiltingArpeggios.update_pixel(self.freq_maker.circle_pos) 123 | 124 | def change_tone_if_needed(self): 125 | """Find the frequency for the current arpeggio and tilt, and restart the tone if changed""" 126 | arpeggio_index = 0 if cp.switch else 1 127 | freq = self.freq_maker.freq(TiltingArpeggios.tilt(), arpeggio_index) 128 | if freq != self.last_freq: 129 | self.last_freq = freq 130 | cp.stop_tone() 131 | cp.start_tone(freq) 132 | 133 | 134 | TiltingArpeggios().run() 135 | -------------------------------------------------------------------------------- /examples/circuitplayground_bluefruit_loud_sound.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """ 5 | This example lights up the NeoPixels on a Circuit Playground Bluefruit in response to a loud sound. 6 | Try snapping or clapping near the board to trigger the LEDs. 7 | 8 | NOTE: This example does NOT support Circuit Playground Express. 9 | """ 10 | 11 | import time 12 | 13 | from adafruit_circuitplayground import cp 14 | 15 | while True: 16 | if cp.loud_sound(): 17 | cp.pixels.fill((50, 0, 50)) 18 | time.sleep(0.2) 19 | else: 20 | cp.pixels.fill((0, 0, 0)) 21 | -------------------------------------------------------------------------------- /examples/circuitplayground_bluefruit_loud_sound_threshold.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """ 5 | This example lights up the NeoPixels on a Circuit Playground Bluefruit in response to a loud sound. 6 | Try snapping or clapping near the board to trigger the LEDs. 7 | 8 | NOTE: This example does NOT support Circuit Playground Express. 9 | """ 10 | 11 | import time 12 | 13 | from adafruit_circuitplayground import cp 14 | 15 | while True: 16 | if cp.loud_sound(sound_threshold=250): 17 | cp.pixels.fill((50, 0, 50)) 18 | time.sleep(0.2) 19 | else: 20 | cp.pixels.fill((0, 0, 0)) 21 | -------------------------------------------------------------------------------- /examples/circuitplayground_bluefruit_play_mp3.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """ 5 | This example plays mp3 audio files from the built-in speaker when the A or B buttons are pressed. 6 | 7 | NOTE: This example does NOT support Circuit Playground Express. 8 | """ 9 | 10 | from adafruit_circuitplayground import cp 11 | 12 | while True: 13 | if cp.button_a: 14 | cp.play_mp3("dip.mp3") 15 | if cp.button_b: 16 | cp.play_mp3("rise.mp3") 17 | -------------------------------------------------------------------------------- /examples/circuitplayground_bluefruit_sound_level.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """ 5 | This example prints out sound levels using the sound sensor on a Circuit Playground Bluefruit. 6 | Try making sounds towards the board to see the values change. 7 | 8 | NOTE: This example does NOT support Circuit Playground Express. 9 | """ 10 | 11 | import time 12 | 13 | from adafruit_circuitplayground import cp 14 | 15 | while True: 16 | print("Sound level:", cp.sound_level) 17 | time.sleep(0.1) 18 | -------------------------------------------------------------------------------- /examples/circuitplayground_bluefruit_sound_level_plotter.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """ 5 | This example prints out sound levels using the sound sensor on a Circuit Playground Bluefruit. If 6 | you are using Mu, open the plotter to see the sound level plotted. Try making sounds towards the 7 | board to see the values change. 8 | 9 | NOTE: This example does NOT support Circuit Playground Express. 10 | """ 11 | 12 | import time 13 | 14 | from adafruit_circuitplayground import cp 15 | 16 | while True: 17 | print("Sound level:", cp.sound_level) 18 | print((cp.sound_level,)) 19 | time.sleep(0.1) 20 | -------------------------------------------------------------------------------- /examples/circuitplayground_button_a.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example turns on the little red LED when button A is pressed.""" 5 | 6 | from adafruit_circuitplayground import cp 7 | 8 | while True: 9 | if cp.button_a: 10 | print("Button A pressed!") 11 | cp.red_led = True 12 | -------------------------------------------------------------------------------- /examples/circuitplayground_button_b.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example turns the little red LED on only while button B is currently being pressed.""" 5 | 6 | from adafruit_circuitplayground import cp 7 | 8 | while True: 9 | if cp.button_b: 10 | cp.red_led = True 11 | else: 12 | cp.red_led = False 13 | 14 | # Can also be written as: 15 | # cp.red_led = cp.button_b 16 | -------------------------------------------------------------------------------- /examples/circuitplayground_buttons_1_neopixel.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example lights up the third NeoPixel while button A is being pressed, and lights up the 5 | eighth NeoPixel while button B is being pressed.""" 6 | 7 | from adafruit_circuitplayground import cp 8 | 9 | cp.pixels.brightness = 0.3 10 | cp.pixels.fill((0, 0, 0)) # Turn off the NeoPixels if they're on! 11 | 12 | while True: 13 | if cp.button_a: 14 | cp.pixels[2] = (0, 255, 0) 15 | else: 16 | cp.pixels[2] = (0, 0, 0) 17 | 18 | if cp.button_b: 19 | cp.pixels[7] = (0, 0, 255) 20 | else: 21 | cp.pixels[7] = (0, 0, 0) 22 | -------------------------------------------------------------------------------- /examples/circuitplayground_buttons_neopixels.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example lights up half the NeoPixels red while button A is being pressed, and half the 5 | NeoPixels green while button B is being pressed.""" 6 | 7 | from adafruit_circuitplayground import cp 8 | 9 | cp.pixels.brightness = 0.3 10 | cp.pixels.fill((0, 0, 0)) # Turn off the NeoPixels if they're on! 11 | 12 | while True: 13 | if cp.button_a: 14 | cp.pixels[0:5] = [(255, 0, 0)] * 5 15 | else: 16 | cp.pixels[0:5] = [(0, 0, 0)] * 5 17 | 18 | if cp.button_b: 19 | cp.pixels[5:10] = [(0, 255, 0)] * 5 20 | else: 21 | cp.pixels[5:10] = [(0, 0, 0)] * 5 22 | -------------------------------------------------------------------------------- /examples/circuitplayground_ir_receive.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """THIS EXAMPLE REQUIRES A SEPARATE LIBRARY BE LOADED ONTO YOUR CIRCUITPY DRIVE. 5 | This example requires the adafruit_irremote.mpy library. 6 | 7 | THIS EXAMPLE WORKS WITH CIRCUIT PLAYGROUND EXPRESS ONLY. 8 | 9 | This example uses the IR receiver found near the center of the board. Works with another Circuit 10 | Playground Express running the circuitplayground_ir_transmit.py example. The NeoPixels will light 11 | up when the buttons on the TRANSMITTING Circuit Playground Express are pressed!""" 12 | 13 | import adafruit_irremote 14 | import board 15 | import pulseio 16 | 17 | from adafruit_circuitplayground import cp 18 | 19 | # Create a 'pulseio' input, to listen to infrared signals on the IR receiver 20 | try: 21 | pulsein = pulseio.PulseIn(board.IR_RX, maxlen=120, idle_state=True) 22 | except AttributeError as err: 23 | raise NotImplementedError( 24 | "This example does not work with Circuit Playground Bluefruti!" 25 | ) from err 26 | 27 | # Create a decoder that will take pulses and turn them into numbers 28 | decoder = adafruit_irremote.GenericDecode() 29 | 30 | while True: 31 | cp.red_led = True 32 | pulses = decoder.read_pulses(pulsein) 33 | try: 34 | # Attempt to convert received pulses into numbers 35 | received_code = decoder.decode_bits(pulses) 36 | except adafruit_irremote.IRNECRepeatException: 37 | # We got an unusual short code, probably a 'repeat' signal 38 | continue 39 | except adafruit_irremote.IRDecodeException: 40 | # Something got distorted 41 | continue 42 | 43 | print("Infrared code received: ", received_code) 44 | if received_code == [66, 84, 78, 65]: 45 | print("Button A signal") 46 | cp.pixels.fill((100, 0, 155)) 47 | if received_code == [66, 84, 78, 64]: 48 | print("Button B Signal") 49 | cp.pixels.fill((210, 45, 0)) 50 | -------------------------------------------------------------------------------- /examples/circuitplayground_ir_transmit.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """THIS EXAMPLE REQUIRES A SEPARATE LIBRARY BE LOADED ONTO YOUR CIRCUITPY DRIVE. 5 | This example requires the adafruit_irremote.mpy library. 6 | 7 | THIS EXAMPLE WORKS WITH CIRCUIT PLAYGROUND EXPRESS ONLY. 8 | 9 | This example uses the IR transmitter found near the center of the board. Works with another Circuit 10 | Playground Express running the circuitplayground_ir_receive.py example. Press the buttons to light 11 | up the NeoPixels on the RECEIVING Circuit Playground Express!""" 12 | 13 | import time 14 | 15 | import adafruit_irremote 16 | import board 17 | import pulseio 18 | 19 | from adafruit_circuitplayground import cp 20 | 21 | # Create a 'PulseOut' output, to send infrared signals from the IR transmitter 22 | try: 23 | pulseout = pulseio.PulseOut(board.IR_TX, frequency=38000, duty_cycle=2**15) 24 | except AttributeError as err: 25 | # Catch no board.IR_TX pin 26 | raise NotImplementedError( 27 | "This example does not work with Circuit Playground Bluefruit!" 28 | ) from err 29 | 30 | # Create an encoder that will take numbers and turn them into NEC IR pulses 31 | encoder = adafruit_irremote.GenericTransmit( 32 | header=[9500, 4500], one=[550, 550], zero=[550, 1700], trail=0 33 | ) 34 | 35 | while True: 36 | if cp.button_a: 37 | print("Button A pressed! \n") 38 | cp.red_led = True 39 | encoder.transmit(pulseout, [66, 84, 78, 65]) 40 | cp.red_led = False 41 | # wait so the receiver can get the full message 42 | time.sleep(0.2) 43 | if cp.button_b: 44 | print("Button B pressed! \n") 45 | cp.red_led = True 46 | encoder.transmit(pulseout, [66, 84, 78, 64]) 47 | cp.red_led = False 48 | time.sleep(0.2) 49 | -------------------------------------------------------------------------------- /examples/circuitplayground_light.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example uses the light sensor on your Circuit Playground, located next to the picture of 5 | the eye. Try shining a flashlight on your Circuit Playground, or covering the light sensor with 6 | your finger to see the values increase and decrease.""" 7 | 8 | import time 9 | 10 | from adafruit_circuitplayground import cp 11 | 12 | while True: 13 | print("Light:", cp.light) 14 | time.sleep(0.2) 15 | -------------------------------------------------------------------------------- /examples/circuitplayground_light_neopixels.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """ 5 | This example uses the light sensor on the Circuit Playground, located next to the picture of the 6 | eye on the board. Once you have the library loaded, try shining a flashlight on your Circuit 7 | Playground to watch the number of NeoPixels lit up increase, or try covering up the light sensor 8 | to watch the number decrease. 9 | """ 10 | 11 | import time 12 | 13 | from adafruit_circuitplayground import cp 14 | 15 | cp.pixels.auto_write = False 16 | cp.pixels.brightness = 0.3 17 | 18 | 19 | def scale_range(value): 20 | """Scale a value from 0-320 (light range) to 0-9 (NeoPixel range). 21 | Allows remapping light value to pixel position.""" 22 | return round(value / 320 * 9) 23 | 24 | 25 | while True: 26 | peak = scale_range(cp.light) 27 | print(cp.light) 28 | print(int(peak)) 29 | 30 | for i in range(10): 31 | if i <= peak: 32 | cp.pixels[i] = (0, 255, 255) 33 | else: 34 | cp.pixels[i] = (0, 0, 0) 35 | cp.pixels.show() 36 | time.sleep(0.05) 37 | -------------------------------------------------------------------------------- /examples/circuitplayground_light_plotter.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """If you're using Mu, this example will plot the light levels from the light sensor (located next 5 | to the eye) on your Circuit Playground. Try shining a flashlight on your Circuit Playground, or 6 | covering the light sensor to see the plot increase and decrease.""" 7 | 8 | import time 9 | 10 | from adafruit_circuitplayground import cp 11 | 12 | while True: 13 | print("Light:", cp.light) 14 | print((cp.light,)) 15 | time.sleep(0.1) 16 | -------------------------------------------------------------------------------- /examples/circuitplayground_neopixel_0.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example lights up the first NeoPixel red.""" 5 | 6 | from adafruit_circuitplayground import cp 7 | 8 | cp.pixels.brightness = 0.3 9 | 10 | while True: 11 | cp.pixels[0] = (255, 0, 0) 12 | -------------------------------------------------------------------------------- /examples/circuitplayground_neopixel_0_1.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example lights up the first and second NeoPixel, red and blue respectively.""" 5 | 6 | from adafruit_circuitplayground import cp 7 | 8 | cp.pixels.brightness = 0.3 9 | 10 | while True: 11 | cp.pixels[0] = (255, 0, 0) 12 | cp.pixels[1] = (0, 0, 255) 13 | -------------------------------------------------------------------------------- /examples/circuitplayground_neopixels_fill.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example lights up all the NeoPixel LEDs red.""" 5 | 6 | from adafruit_circuitplayground import cp 7 | 8 | while True: 9 | cp.pixels.fill((50, 0, 0)) 10 | -------------------------------------------------------------------------------- /examples/circuitplayground_pixels_simpletest.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example lights up the NeoPixels with a rainbow swirl.""" 5 | 6 | import time 7 | 8 | from rainbowio import colorwheel 9 | 10 | from adafruit_circuitplayground import cp 11 | 12 | 13 | def rainbow_cycle(wait): 14 | for j in range(255): 15 | for i in range(cp.pixels.n): 16 | idx = int((i * 256 / len(cp.pixels)) + j) 17 | cp.pixels[i] = colorwheel(idx & 255) 18 | cp.pixels.show() 19 | time.sleep(wait) 20 | 21 | 22 | cp.pixels.auto_write = False 23 | cp.pixels.brightness = 0.3 24 | while True: 25 | rainbow_cycle(0.001) # rainbowcycle with 1ms delay per step 26 | -------------------------------------------------------------------------------- /examples/circuitplayground_play_file.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """THIS EXAMPLE REQUIRES A WAV FILE FROM THE examples FOLDER IN THE 5 | Adafruit_CircuitPython_CircuitPlayground REPO found at: 6 | https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/tree/main/examples 7 | 8 | Copy the "dip.wav" file to your CIRCUITPY drive. 9 | 10 | Once the file is copied, this example plays a wav file!""" 11 | 12 | from adafruit_circuitplayground import cp 13 | 14 | cp.play_file("dip.wav") 15 | -------------------------------------------------------------------------------- /examples/circuitplayground_play_file_buttons.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """THIS EXAMPLE REQUIRES A WAV FILE FROM THE examples FOLDER IN THE 5 | Adafruit_CircuitPython_CircuitPlayground REPO found at: 6 | https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/tree/main/examples 7 | 8 | Copy the "dip.wav" and "rise.wav" files to your CIRCUITPY drive. 9 | 10 | Once the files are copied, this example plays a different wav file for each button pressed!""" 11 | 12 | from adafruit_circuitplayground import cp 13 | 14 | while True: 15 | if cp.button_a: 16 | cp.play_file("dip.wav") 17 | if cp.button_b: 18 | cp.play_file("rise.wav") 19 | -------------------------------------------------------------------------------- /examples/circuitplayground_play_tone.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example plays two tones for 1 second each. Note that the tones are not in a loop - this is 5 | to prevent them from playing indefinitely!""" 6 | 7 | from adafruit_circuitplayground import cp 8 | 9 | cp.play_tone(262, 1) 10 | cp.play_tone(294, 1) 11 | -------------------------------------------------------------------------------- /examples/circuitplayground_play_tone_buttons.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example plays a different tone for a duration of 1 second for each button pressed.""" 5 | 6 | from adafruit_circuitplayground import cp 7 | 8 | while True: 9 | if cp.button_a: 10 | cp.play_tone(262, 1) 11 | if cp.button_b: 12 | cp.play_tone(294, 1) 13 | -------------------------------------------------------------------------------- /examples/circuitplayground_red_led.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example turns on the little red LED.""" 5 | 6 | from adafruit_circuitplayground import cp 7 | 8 | while True: 9 | cp.red_led = True 10 | -------------------------------------------------------------------------------- /examples/circuitplayground_red_led_blinky.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This is the "Hello, world!" of CircuitPython: Blinky! This example blinks the little red LED on 5 | and off!""" 6 | 7 | import time 8 | 9 | from adafruit_circuitplayground import cp 10 | 11 | while True: 12 | cp.red_led = True 13 | time.sleep(0.5) 14 | cp.red_led = False 15 | time.sleep(0.5) 16 | -------------------------------------------------------------------------------- /examples/circuitplayground_red_led_blnky_short.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This is the "Hello, world!" of CircuitPython: Blinky! This example blinks the little red LED on 5 | and off! It's a shorter version of the other Blinky example.""" 6 | 7 | import time 8 | 9 | from adafruit_circuitplayground import cp 10 | 11 | while True: 12 | cp.red_led = not cp.red_led 13 | time.sleep(0.5) 14 | -------------------------------------------------------------------------------- /examples/circuitplayground_shake.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example prints to the serial console when the Circuit Playground is shaken.""" 5 | 6 | from adafruit_circuitplayground import cp 7 | 8 | while True: 9 | if cp.shake(): 10 | print("Shake detected!") 11 | -------------------------------------------------------------------------------- /examples/circuitplayground_shake_red_led.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example flashes the little red LED when the Circuit Playground is shaken.""" 5 | 6 | from adafruit_circuitplayground import cp 7 | 8 | while True: 9 | if cp.shake(shake_threshold=20): 10 | print("Shake detected!") 11 | cp.red_led = True 12 | else: 13 | cp.red_led = False 14 | -------------------------------------------------------------------------------- /examples/circuitplayground_slide_switch.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example prints the status of the slide switch. Try moving the switch back and forth to see 5 | what's printed to the serial console!""" 6 | 7 | import time 8 | 9 | from adafruit_circuitplayground import cp 10 | 11 | while True: 12 | print("Slide switch:", cp.switch) 13 | time.sleep(0.1) 14 | -------------------------------------------------------------------------------- /examples/circuitplayground_slide_switch_red_led.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example uses the slide switch to control the little red LED.""" 5 | 6 | from adafruit_circuitplayground import cp 7 | 8 | while True: 9 | if cp.switch: 10 | cp.red_led = True 11 | else: 12 | cp.red_led = False 13 | -------------------------------------------------------------------------------- /examples/circuitplayground_slide_switch_red_led_short.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example uses the slide switch to control the little red LED. When the switch is to the 5 | right it returns False, and when it's to the left, it returns True.""" 6 | 7 | from adafruit_circuitplayground import cp 8 | 9 | while True: 10 | cp.red_led = cp.switch 11 | -------------------------------------------------------------------------------- /examples/circuitplayground_sound_meter.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example uses the sound sensor, located next to the picture of the ear on your board, to 5 | light up the NeoPixels as a sound meter. Try talking to your Circuit Playground or clapping, etc, 6 | to see the NeoPixels light up!""" 7 | 8 | import array 9 | import math 10 | 11 | import audiobusio 12 | import board 13 | 14 | from adafruit_circuitplayground import cp 15 | 16 | 17 | def constrain(value, floor, ceiling): 18 | return max(floor, min(value, ceiling)) 19 | 20 | 21 | def log_scale(input_value, input_min, input_max, output_min, output_max): 22 | normalized_input_value = (input_value - input_min) / (input_max - input_min) 23 | return output_min + math.pow(normalized_input_value, 0.630957) * (output_max - output_min) 24 | 25 | 26 | def normalized_rms(values): 27 | minbuf = int(sum(values) / len(values)) 28 | return math.sqrt( 29 | sum(float(sample - minbuf) * (sample - minbuf) for sample in values) / len(values) 30 | ) 31 | 32 | 33 | mic = audiobusio.PDMIn( 34 | board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000, bit_depth=16 35 | ) 36 | 37 | samples = array.array("H", [0] * 160) 38 | mic.record(samples, len(samples)) 39 | input_floor = normalized_rms(samples) + 10 40 | 41 | # Lower number means more sensitive - more LEDs will light up with less sound. 42 | sensitivity = 500 43 | input_ceiling = input_floor + sensitivity 44 | 45 | peak = 0 46 | while True: 47 | mic.record(samples, len(samples)) 48 | magnitude = normalized_rms(samples) 49 | print((magnitude,)) 50 | 51 | c = log_scale( 52 | constrain(magnitude, input_floor, input_ceiling), 53 | input_floor, 54 | input_ceiling, 55 | 0, 56 | 10, 57 | ) 58 | 59 | cp.pixels.fill((0, 0, 0)) 60 | for i in range(10): 61 | if i < c: 62 | cp.pixels[i] = (i * (255 // 10), 50, 0) 63 | if c >= peak: 64 | peak = min(c, 10 - 1) 65 | elif peak > 0: 66 | peak = peak - 1 67 | if peak > 0: 68 | cp.pixels[int(peak)] = (80, 0, 255) 69 | cp.pixels.show() 70 | -------------------------------------------------------------------------------- /examples/circuitplayground_tap_red_led.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example turns on the little red LED and prints to the serial console when you double-tap 5 | the Circuit Playground!""" 6 | 7 | import time 8 | 9 | from adafruit_circuitplayground import cp 10 | 11 | # Change to 1 for detecting a single-tap! 12 | cp.detect_taps = 2 13 | 14 | while True: 15 | if cp.tapped: 16 | print("Tapped!") 17 | cp.red_led = True 18 | time.sleep(0.1) 19 | else: 20 | cp.red_led = False 21 | -------------------------------------------------------------------------------- /examples/circuitplayground_tapdetect.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example prints to the serial console when the board is double-tapped.""" 5 | 6 | import time 7 | 8 | from adafruit_circuitplayground import cp 9 | 10 | # Change to 1 for single-tap detection. 11 | cp.detect_taps = 2 12 | 13 | while True: 14 | if cp.tapped: 15 | print("Tapped!") 16 | time.sleep(0.05) 17 | -------------------------------------------------------------------------------- /examples/circuitplayground_tapdetect_single_double.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example shows how you can use single-tap and double-tap together with a delay between. 5 | Single-tap the board twice and then double-tap the board twice to complete the program.""" 6 | 7 | from adafruit_circuitplayground import cp 8 | 9 | # Set to check for single-taps. 10 | cp.detect_taps = 1 11 | tap_count = 0 12 | 13 | # We're looking for 2 single-taps before moving on. 14 | while tap_count < 2: 15 | if cp.tapped: 16 | tap_count += 1 17 | print("Reached 2 single-taps!") 18 | 19 | # Now switch to checking for double-taps 20 | tap_count = 0 21 | cp.detect_taps = 2 22 | 23 | # We're looking for 2 double-taps before moving on. 24 | while tap_count < 2: 25 | if cp.tapped: 26 | tap_count += 1 27 | print("Reached 2 double-taps!") 28 | print("Done.") 29 | while True: 30 | cp.red_led = True 31 | -------------------------------------------------------------------------------- /examples/circuitplayground_temperature.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example uses the temperature sensor on the Circuit Playground, located next to the image of 5 | a thermometer on the board. It prints the temperature in both C and F to the serial console. Try 6 | putting your finger over the sensor to see the numbers change!""" 7 | 8 | import time 9 | 10 | from adafruit_circuitplayground import cp 11 | 12 | while True: 13 | print("Temperature C:", cp.temperature) 14 | print("Temperature F:", cp.temperature * 1.8 + 32) 15 | time.sleep(1) 16 | -------------------------------------------------------------------------------- /examples/circuitplayground_temperature_neopixels.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """ 5 | This example use the temperature sensor on the Circuit Playground, located next to the picture of 6 | the thermometer on the board. Try warming up the board to watch the number of NeoPixels lit up 7 | increase, or cooling it down to see the number decrease. You can set the min and max temperatures 8 | to make it more or less sensitive to temperature changes. 9 | """ 10 | 11 | import time 12 | 13 | from adafruit_circuitplayground import cp 14 | 15 | cp.pixels.auto_write = False 16 | cp.pixels.brightness = 0.3 17 | 18 | # Set these based on your ambient temperature in Celsius for best results! 19 | minimum_temp = 24 20 | maximum_temp = 30 21 | 22 | 23 | def scale_range(value): 24 | """Scale a value from the range of minimum_temp to maximum_temp (temperature range) to 0-10 25 | (the number of NeoPixels). Allows remapping temperature value to pixel position.""" 26 | return int((value - minimum_temp) / (maximum_temp - minimum_temp) * 10) 27 | 28 | 29 | while True: 30 | peak = scale_range(cp.temperature) 31 | print(cp.temperature) 32 | print(int(peak)) 33 | 34 | for i in range(10): 35 | if i <= peak: 36 | cp.pixels[i] = (0, 255, 255) 37 | else: 38 | cp.pixels[i] = (0, 0, 0) 39 | cp.pixels.show() 40 | time.sleep(0.05) 41 | -------------------------------------------------------------------------------- /examples/circuitplayground_temperature_plotter.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """If you're using Mu, this example will plot the temperature in C and F on the plotter! Click 5 | "Plotter" to open it, and place your finger over the sensor to see the numbers change. The 6 | sensor is located next to the picture of the thermometer on the CPX.""" 7 | 8 | import time 9 | 10 | from adafruit_circuitplayground import cp 11 | 12 | while True: 13 | print("Temperature C:", cp.temperature) 14 | print("Temperature F:", cp.temperature * 1.8 + 32) 15 | print((cp.temperature, cp.temperature * 1.8 + 32)) 16 | time.sleep(0.1) 17 | -------------------------------------------------------------------------------- /examples/circuitplayground_tone.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example plays a different tone for each button, while the button is pressed.""" 5 | 6 | from adafruit_circuitplayground import cp 7 | 8 | while True: 9 | if cp.button_a: 10 | cp.start_tone(262) 11 | elif cp.button_b: 12 | cp.start_tone(294) 13 | else: 14 | cp.stop_tone() 15 | -------------------------------------------------------------------------------- /examples/circuitplayground_touch_a1.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example prints to the serial console when you touch capacitive touch pad A1.""" 5 | 6 | from adafruit_circuitplayground import cp 7 | 8 | while True: 9 | if cp.touch_A1: 10 | print("Touched pad A1") 11 | -------------------------------------------------------------------------------- /examples/circuitplayground_touch_all.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example prints to the serial console when you touch the capacitive touch pads.""" 5 | 6 | import time 7 | 8 | import board 9 | 10 | from adafruit_circuitplayground import cp 11 | 12 | # You'll need to first use the touchpads individually to register them as active touchpads 13 | # You don't have to use the result though 14 | is_a1_touched = cp.touch_A1 # This result can be used if you want 15 | if is_a1_touched: 16 | print("A1 was touched upon startup!") 17 | is_a2_touched = cp.touch_A2 18 | is_a3_touched = cp.touch_A3 19 | is_a4_touched = cp.touch_A4 20 | 21 | print("Pads that are currently setup as touchpads:") 22 | print(cp.touch_pins) 23 | 24 | while True: 25 | current_touched = cp.touched 26 | 27 | if current_touched: 28 | print("Touchpads currently registering a touch:") 29 | print(current_touched) 30 | else: 31 | print("No touchpads are currently registering a touch.") 32 | 33 | if all(pad in current_touched for pad in (board.A2, board.A3, board.A4)): 34 | print("This only prints when A2, A3, and A4 are being held at the same time!") 35 | 36 | time.sleep(0.25) 37 | -------------------------------------------------------------------------------- /examples/circuitplayground_touch_pixel_fill_rainbow.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example uses the capacitive touch pads on the Circuit Playground. They are located around 5 | the outer edge of the board and are labeled A1-A6 and TX. (A0 is not a touch pad.) This example 6 | lights up all the NeoPixels a different color of the rainbow for each pad touched!""" 7 | 8 | import time 9 | 10 | from adafruit_circuitplayground import cp 11 | 12 | cp.pixels.brightness = 0.3 13 | 14 | while True: 15 | if cp.touch_A1: 16 | print("Touched A1!") 17 | cp.pixels.fill((255, 0, 0)) 18 | if cp.touch_A2: 19 | print("Touched A2!") 20 | cp.pixels.fill((210, 45, 0)) 21 | if cp.touch_A3: 22 | print("Touched A3!") 23 | cp.pixels.fill((155, 100, 0)) 24 | if cp.touch_A4: 25 | print("Touched A4!") 26 | cp.pixels.fill((0, 255, 0)) 27 | if cp.touch_A5: 28 | print("Touched A5!") 29 | cp.pixels.fill((0, 135, 125)) 30 | if cp.touch_A6: 31 | print("Touched A6!") 32 | cp.pixels.fill((0, 0, 255)) 33 | if cp.touch_TX: 34 | print("Touched TX!") 35 | cp.pixels.fill((100, 0, 155)) 36 | time.sleep(0.1) 37 | -------------------------------------------------------------------------------- /examples/circuitplayground_touch_pixel_rainbow.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | 4 | """This example uses the capacitive touch pads on the Circuit Playground. They are located around 5 | the outer edge of the board and are labeled A1-A6 and TX. (A0 is not a touch pad.) This example 6 | lights up the nearest NeoPixel to that pad a different color of the rainbow!""" 7 | 8 | import time 9 | 10 | from adafruit_circuitplayground import cp 11 | 12 | cp.pixels.brightness = 0.3 13 | 14 | while True: 15 | if cp.touch_A1: 16 | print("Touched A1!") 17 | cp.pixels[6] = (255, 0, 0) 18 | if cp.touch_A2: 19 | print("Touched A2!") 20 | cp.pixels[8] = (210, 45, 0) 21 | if cp.touch_A3: 22 | print("Touched A3!") 23 | cp.pixels[9] = (155, 100, 0) 24 | if cp.touch_A4: 25 | print("Touched A4!") 26 | cp.pixels[0] = (0, 255, 0) 27 | if cp.touch_A5: 28 | print("Touched A5!") 29 | cp.pixels[1] = (0, 135, 125) 30 | if cp.touch_A6: 31 | print("Touched A6!") 32 | cp.pixels[3] = (0, 0, 255) 33 | if cp.touch_TX: 34 | print("Touched TX!") 35 | cp.pixels[4] = (100, 0, 155) 36 | time.sleep(0.1) 37 | -------------------------------------------------------------------------------- /examples/dip.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/examples/dip.mp3 -------------------------------------------------------------------------------- /examples/dip.mp3.license: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | -------------------------------------------------------------------------------- /examples/dip.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/examples/dip.wav -------------------------------------------------------------------------------- /examples/dip.wav.license: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | -------------------------------------------------------------------------------- /examples/rise.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/examples/rise.mp3 -------------------------------------------------------------------------------- /examples/rise.mp3.license: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | -------------------------------------------------------------------------------- /examples/rise.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/e5bb3d3141bb29e42736918d986435ee05b8ea14/examples/rise.wav -------------------------------------------------------------------------------- /examples/rise.wav.license: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 | # SPDX-License-Identifier: MIT 3 | -------------------------------------------------------------------------------- /frozen_cpx/adafruit_circuitplayground/__init__.py: -------------------------------------------------------------------------------- 1 | ../../adafruit_circuitplayground/__init__.py -------------------------------------------------------------------------------- /frozen_cpx/adafruit_circuitplayground/circuit_playground_base.py: -------------------------------------------------------------------------------- 1 | ../../adafruit_circuitplayground/circuit_playground_base.py -------------------------------------------------------------------------------- /frozen_cpx/adafruit_circuitplayground/express.py: -------------------------------------------------------------------------------- 1 | ../../adafruit_circuitplayground/express.py -------------------------------------------------------------------------------- /optional_requirements.txt: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Alec Delaney, for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: Unlicense 4 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Alec Delaney for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | [build-system] 6 | requires = [ 7 | "setuptools", 8 | "wheel", 9 | "setuptools-scm", 10 | ] 11 | 12 | [project] 13 | name = "adafruit-circuitpython-circuitplayground" 14 | description = "CircuitPython library for Circuit Playground Express" 15 | version = "0.0.0+auto.0" 16 | readme = "README.rst" 17 | authors = [ 18 | {name = "Adafruit Industries", email = "circuitpython@adafruit.com"} 19 | ] 20 | urls = {Homepage = "https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground"} 21 | keywords = [ 22 | "adafruit", 23 | "circuitplayground", 24 | "circuit", 25 | "playground", 26 | "microcontrollerbluetooth", 27 | "bluefruit", 28 | "BLE", 29 | "hardware", 30 | "micropython", 31 | "circuitpython", 32 | ] 33 | license = {text = "MIT"} 34 | classifiers = [ 35 | "Intended Audience :: Developers", 36 | "Topic :: Software Development :: Libraries", 37 | "Topic :: Software Development :: Embedded Systems", 38 | "Topic :: System :: Hardware", 39 | "License :: OSI Approved :: MIT License", 40 | "Programming Language :: Python :: 3", 41 | ] 42 | dynamic = ["dependencies", "optional-dependencies"] 43 | 44 | [tool.setuptools] 45 | packages = ["adafruit_circuitplayground"] 46 | 47 | [tool.setuptools.dynamic] 48 | dependencies = {file = ["requirements.txt"]} 49 | optional-dependencies = {optional = {file = ["optional_requirements.txt"]}} 50 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Alec Delaney, for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: Unlicense 4 | 5 | adafruit-circuitpython-lis3dh 6 | adafruit-circuitpython-neopixel 7 | adafruit-circuitpython-thermistor 8 | typing-extensions 9 | -------------------------------------------------------------------------------- /ruff.toml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | target-version = "py38" 6 | line-length = 100 7 | 8 | [lint] 9 | preview = true 10 | select = ["I", "PL", "UP"] 11 | 12 | extend-select = [ 13 | "D419", # empty-docstring 14 | "E501", # line-too-long 15 | "W291", # trailing-whitespace 16 | "PLC0414", # useless-import-alias 17 | "PLC2401", # non-ascii-name 18 | "PLC2801", # unnecessary-dunder-call 19 | "PLC3002", # unnecessary-direct-lambda-call 20 | "E999", # syntax-error 21 | "PLE0101", # return-in-init 22 | "F706", # return-outside-function 23 | "F704", # yield-outside-function 24 | "PLE0116", # continue-in-finally 25 | "PLE0117", # nonlocal-without-binding 26 | "PLE0241", # duplicate-bases 27 | "PLE0302", # unexpected-special-method-signature 28 | "PLE0604", # invalid-all-object 29 | "PLE0605", # invalid-all-format 30 | "PLE0643", # potential-index-error 31 | "PLE0704", # misplaced-bare-raise 32 | "PLE1141", # dict-iter-missing-items 33 | "PLE1142", # await-outside-async 34 | "PLE1205", # logging-too-many-args 35 | "PLE1206", # logging-too-few-args 36 | "PLE1307", # bad-string-format-type 37 | "PLE1310", # bad-str-strip-call 38 | "PLE1507", # invalid-envvar-value 39 | "PLE2502", # bidirectional-unicode 40 | "PLE2510", # invalid-character-backspace 41 | "PLE2512", # invalid-character-sub 42 | "PLE2513", # invalid-character-esc 43 | "PLE2514", # invalid-character-nul 44 | "PLE2515", # invalid-character-zero-width-space 45 | "PLR0124", # comparison-with-itself 46 | "PLR0202", # no-classmethod-decorator 47 | "PLR0203", # no-staticmethod-decorator 48 | "UP004", # useless-object-inheritance 49 | "PLR0206", # property-with-parameters 50 | "PLR0904", # too-many-public-methods 51 | "PLR0911", # too-many-return-statements 52 | "PLR0912", # too-many-branches 53 | "PLR0913", # too-many-arguments 54 | "PLR0914", # too-many-locals 55 | "PLR0915", # too-many-statements 56 | "PLR0916", # too-many-boolean-expressions 57 | "PLR1702", # too-many-nested-blocks 58 | "PLR1704", # redefined-argument-from-local 59 | "PLR1711", # useless-return 60 | "C416", # unnecessary-comprehension 61 | "PLR1733", # unnecessary-dict-index-lookup 62 | "PLR1736", # unnecessary-list-index-lookup 63 | 64 | # ruff reports this rule is unstable 65 | #"PLR6301", # no-self-use 66 | 67 | "PLW0108", # unnecessary-lambda 68 | "PLW0120", # useless-else-on-loop 69 | "PLW0127", # self-assigning-variable 70 | "PLW0129", # assert-on-string-literal 71 | "B033", # duplicate-value 72 | "PLW0131", # named-expr-without-context 73 | "PLW0245", # super-without-brackets 74 | "PLW0406", # import-self 75 | "PLW0602", # global-variable-not-assigned 76 | "PLW0603", # global-statement 77 | "PLW0604", # global-at-module-level 78 | 79 | # fails on the try: import typing used by libraries 80 | #"F401", # unused-import 81 | 82 | "F841", # unused-variable 83 | "E722", # bare-except 84 | "PLW0711", # binary-op-exception 85 | "PLW1501", # bad-open-mode 86 | "PLW1508", # invalid-envvar-default 87 | "PLW1509", # subprocess-popen-preexec-fn 88 | "PLW2101", # useless-with-lock 89 | "PLW3301", # nested-min-max 90 | ] 91 | 92 | ignore = [ 93 | "PLR2004", # magic-value-comparison 94 | "UP030", # format literals 95 | "PLW1514", # unspecified-encoding 96 | "PLR0913", # too-many-arguments 97 | "PLR0915", # too-many-statements 98 | "PLR0917", # too-many-positional-arguments 99 | "PLR0904", # too-many-public-methods 100 | "PLR0912", # too-many-branches 101 | "PLR0916", # too-many-boolean-expressions 102 | ] 103 | 104 | [format] 105 | line-ending = "lf" 106 | --------------------------------------------------------------------------------