Compare commits

..

No commits in common. "main" and "REUSE" have entirely different histories.
main ... REUSE

70 changed files with 947 additions and 1640 deletions

11
.gitattributes vendored
View file

@ -1,11 +0,0 @@
# SPDX-FileCopyrightText: 2024 Justin Myers for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
.py text eol=lf
.rst text eol=lf
.txt text eol=lf
.yaml text eol=lf
.toml text eol=lf
.license text eol=lf
.md text eol=lf

View file

@ -1,13 +0,0 @@
# SPDX-FileCopyrightText: 2021 Adafruit Industries
#
# SPDX-License-Identifier: MIT
Thank you for contributing! Before you submit a pull request, please read the following.
Make sure any changes you're submitting are in line with the CircuitPython Design Guide, available here: https://circuitpython.readthedocs.io/en/latest/docs/design_guide.html
If your changes are to documentation, please verify that the documentation builds locally by following the steps found here: https://adafru.it/build-docs
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
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.

View file

@ -10,5 +10,68 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Run Build CI workflow
uses: adafruit/workflows-circuitpython-libs/build@main
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Translate Repo Name For Build Tools filename_prefix
id: repo-name
run: |
echo ::set-output name=repo-name::$(
echo ${{ github.repository }} |
awk -F '\/' '{ print tolower($2) }' |
tr '_' '-'
)
- name: Set up Python 3.6
uses: actions/setup-python@v1
with:
python-version: 3.6
- name: Versions
run: |
python3 --version
- name: Checkout Current Repo
uses: actions/checkout@v1
with:
submodules: true
- name: Checkout tools repo
uses: actions/checkout@v2
with:
repository: adafruit/actions-ci-circuitpython-libs
path: actions-ci
- name: Install dependencies
# (e.g. - apt-get: gettext, etc; pip: circuitpython-build-tools, requirements.txt; etc.)
run: |
source actions-ci/install.sh
- name: Pip install pylint, Sphinx, pre-commit
run: |
pip install --force-reinstall pylint Sphinx sphinx-rtd-theme pre-commit
- name: Library version
run: git describe --dirty --always --tags
- name: Pre-commit hooks
run: |
pre-commit run --all-files
- name: PyLint
run: |
pylint $( find . -path './adafruit*.py' )
([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace $( find . -path "./examples/*.py" ))
- name: Build assets
run: circuitpython-build-bundles --filename_prefix ${{ steps.repo-name.outputs.repo-name }} --library_location .
- name: Archive bundles
uses: actions/upload-artifact@v2
with:
name: bundles
path: ${{ github.workspace }}/bundles/
- name: Build docs
working-directory: docs
run: sphinx-build -E -W -b html . _build/html
- name: Check For setup.py
id: need-pypi
run: |
echo ::set-output name=setup-py::$( find . -wholename './setup.py' )
- name: Build Python package
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
run: |
pip install --upgrade setuptools wheel twine readme_renderer testresources
python setup.py sdist
python setup.py bdist_wheel --universal
twine check dist/*

View file

@ -1,19 +0,0 @@
# SPDX-FileCopyrightText: 2021 Scott Shawcroft for Adafruit Industries
#
# SPDX-License-Identifier: MIT
name: Failure help text
on:
workflow_run:
workflows: ["Build CI"]
types:
- completed
jobs:
post-help:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.event == 'pull_request' }}
steps:
- name: Post comment to help
uses: adafruit/circuitpython-action-library-ci-failed@v1

85
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,85 @@
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: MIT
name: Release Actions
on:
release:
types: [published]
jobs:
upload-release-assets:
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Translate Repo Name For Build Tools filename_prefix
id: repo-name
run: |
echo ::set-output name=repo-name::$(
echo ${{ github.repository }} |
awk -F '\/' '{ print tolower($2) }' |
tr '_' '-'
)
- name: Set up Python 3.6
uses: actions/setup-python@v1
with:
python-version: 3.6
- name: Versions
run: |
python3 --version
- name: Checkout Current Repo
uses: actions/checkout@v1
with:
submodules: true
- name: Checkout tools repo
uses: actions/checkout@v2
with:
repository: adafruit/actions-ci-circuitpython-libs
path: actions-ci
- name: Install deps
run: |
source actions-ci/install.sh
- name: Build assets
run: circuitpython-build-bundles --filename_prefix ${{ steps.repo-name.outputs.repo-name }} --library_location .
- name: Upload Release Assets
# the 'official' actions version does not yet support dynamically
# supplying asset names to upload. @csexton's version chosen based on
# discussion in the issue below, as its the simplest to implement and
# allows for selecting files with a pattern.
# https://github.com/actions/upload-release-asset/issues/4
#uses: actions/upload-release-asset@v1.0.1
uses: csexton/release-asset-action@master
with:
pattern: "bundles/*"
github-token: ${{ secrets.GITHUB_TOKEN }}
upload-pypi:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Check For setup.py
id: need-pypi
run: |
echo ::set-output name=setup-py::$( find . -wholename './setup.py' )
- name: Set up Python
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Install dependencies
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
env:
TWINE_USERNAME: ${{ secrets.pypi_username }}
TWINE_PASSWORD: ${{ secrets.pypi_password }}
run: |
python setup.py sdist
twine upload dist/*

View file

@ -1,19 +0,0 @@
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: MIT
name: GitHub Release Actions
on:
release:
types: [published]
jobs:
upload-release-assets:
runs-on: ubuntu-latest
steps:
- name: Run GitHub Release CI workflow
uses: adafruit/workflows-circuitpython-libs/release-gh@main
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
upload-url: ${{ github.event.release.upload_url }}

View file

@ -1,19 +0,0 @@
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: MIT
name: PyPI Release Actions
on:
release:
types: [published]
jobs:
upload-release-assets:
runs-on: ubuntu-latest
steps:
- name: Run PyPI Release CI workflow
uses: adafruit/workflows-circuitpython-libs/release-pypi@main
with:
pypi-username: ${{ secrets.pypi_username }}
pypi-password: ${{ secrets.pypi_password }}

47
.gitignore vendored
View file

@ -1,48 +1,9 @@
# SPDX-FileCopyrightText: 2022 Kattni Rembor, written for Adafruit Industries
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# SPDX-License-Identifier: Unlicense
# Do not include files and directories created by your personal work environment, such as the IDE
# you use, except for those already listed here. Pull requests including changes to this file will
# not be accepted.
# This .gitignore file contains rules for files generated by working with CircuitPython libraries,
# including building Sphinx, testing with pip, and creating a virual environment, as well as the
# MacOS and IDE-specific files generated by using MacOS in general, or the PyCharm or VSCode IDEs.
# If you find that there are files being generated on your machine that should not be included in
# your git commit, you should create a .gitignore_global file on your computer to include the
# files created by your personal setup. To do so, follow the two steps below.
# First, create a file called .gitignore_global somewhere convenient for you, and add rules for
# the files you want to exclude from git commits.
# Second, configure Git to use the exclude file for all Git repositories by running the
# following via commandline, replacing "path/to/your/" with the actual path to your newly created
# .gitignore_global file:
# git config --global core.excludesfile path/to/your/.gitignore_global
# CircuitPython-specific files
*.mpy
# Python-specific files
__pycache__
*.pyc
# Sphinx build-specific files
_build
# This file results from running `pip -e install .` in a local repository
*.egg-info
# Virtual environment-specific files
*.pyc
.env
.venv
# MacOS-specific files
*.DS_Store
# IDE-specific files
.idea
.vscode
*~
bundles

View file

@ -1,21 +1,19 @@
# SPDX-FileCopyrightText: 2024 Justin Myers for Adafruit Industries
# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò
#
# SPDX-License-Identifier: Unlicense
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
- repo: https://github.com/python/black
rev: stable
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.4
- id: black
- repo: https://github.com/fsfe/reuse-tool
rev: latest
hooks:
- id: ruff-format
- id: ruff
args: ["--fix"]
- repo: https://github.com/fsfe/reuse-tool
rev: v3.0.1
- id: reuse
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: reuse
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace

437
.pylintrc Normal file
View file

@ -0,0 +1,437 @@
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
[MASTER]
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code
extension-pkg-whitelist=
# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS
# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
ignore-patterns=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Use multiple processes to speed up Pylint.
# jobs=1
jobs=2
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
# Pickle collected data for later comparisons.
persistent=yes
# Specify a configuration file.
#rcfile=
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
confidence=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once).You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
# disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=
[REPORTS]
# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details
#msg-template=
# Set the output format. Available formats are text, parseable, colorized, json
# and msvs (visual studio).You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=text
# Tells whether to display a full report or only the messages
reports=no
# Activate the evaluation score.
score=yes
[REFACTORING]
# Maximum number of nested blocks for function / method body
max-nested-blocks=5
[LOGGING]
# Logging modules to check that the string format arguments are in logging
# function parameter format
logging-modules=logging
[SPELLING]
# Spelling dictionary name. Available dictionaries: none. To make it working
# install python-enchant package.
spelling-dict=
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
# notes=FIXME,XXX,TODO
notes=FIXME,XXX
[TYPECHECK]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=board
# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes
# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1
# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=
# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,_cb
# A regular expression matching the name of dummy variables (i.e. expectedly
# not used).
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
# Argument names that match this expression will be ignored. Default to name
# with leading underscore
ignored-argument-names=_.*|^ignored_|^unused_
# Tells whether we should check for unused import in __init__ files.
init-import=no
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,future.builtins
[FORMAT]
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
# expected-line-ending-format=
expected-line-ending-format=LF
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Maximum number of characters on a single line.
max-line-length=100
# Maximum number of lines in a module
max-module-lines=1000
# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,dict-separator
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
[SIMILARITIES]
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=no
# Minimum lines number of a similarity.
min-similarity-lines=4
[BASIC]
# Naming hint for argument names
argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct argument names
argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Naming hint for attribute names
attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct attribute names
attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata
# Naming hint for class attribute names
class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Regular expression matching correct class attribute names
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Naming hint for class names
# class-name-hint=[A-Z_][a-zA-Z0-9]+$
class-name-hint=[A-Z_][a-zA-Z0-9_]+$
# Regular expression matching correct class names
# class-rgx=[A-Z_][a-zA-Z0-9]+$
class-rgx=[A-Z_][a-zA-Z0-9_]+$
# Naming hint for constant names
const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Regular expression matching correct constant names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
# Naming hint for function names
function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct function names
function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Good variable names which should always be accepted, separated by a comma
# good-names=i,j,k,ex,Run,_
good-names=r,g,b,w,i,j,k,n,x,y,z,ex,ok,Run,_
# Include a hint for the correct naming format with invalid-name
include-naming-hint=no
# Naming hint for inline iteration names
inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
# Regular expression matching correct inline iteration names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Naming hint for method names
method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct method names
method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Naming hint for module names
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression matching correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_
# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties.
property-classes=abc.abstractproperty
# Naming hint for variable names
variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct variable names
variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
[IMPORTS]
# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no
# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=optparse,tkinter.tix
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=
# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=
# Force import order to recognize a module as part of a third party library.
known-third-party=enchant
[CLASSES]
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,_fields,_replace,_source,_make
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
[DESIGN]
# Maximum number of arguments for function / method
max-args=5
# Maximum number of attributes for a class (see R0902).
# max-attributes=7
max-attributes=11
# Maximum number of boolean expressions in a if statement
max-bool-expr=5
# Maximum number of branch for function / method body
max-branches=12
# Maximum number of locals for function / method body
max-locals=15
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of return / yield for function / method body
max-returns=6
# Maximum number of statements in function / method body
max-statements=50
# Minimum number of public methods for a class (see R0903).
min-public-methods=1
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception

View file

@ -1,22 +0,0 @@
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
sphinx:
configuration: docs/conf.py
build:
os: ubuntu-lts-latest
tools:
python: "3"
python:
install:
- requirements: docs/requirements.txt
- requirements: requirements.txt

7
.readthedocs.yml Normal file
View file

@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
python:
version: 3
requirements_file: requirements.txt

View file

@ -2,10 +2,10 @@ Introduction
============
.. image:: https://readthedocs.org/projects/adafruit_circuitpython_led_animation/badge/?version=latest
:target: https://docs.circuitpython.org/projects/led-animation/en/latest/
:target: https://circuitpython.readthedocs.io/projects/led-animation/en/latest/
:alt: Documentation Status
.. image:: https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_Bundle/main/badges/adafruit_discord.svg
.. image:: https://img.shields.io/discord/327254708534116352.svg
:target: https://adafru.it/discord
:alt: Discord
@ -13,10 +13,6 @@ Introduction
:target: https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation/actions
:alt: Build Status
.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
:target: https://github.com/astral-sh/ruff
:alt: Code Style: Ruff
Perform a variety of LED animation tasks
Dependencies
@ -50,8 +46,8 @@ To install in a virtual environment in your current project:
.. code-block:: shell
mkdir project-name && cd project-name
python3 -m venv .venv
source .venv/bin/activate
python3 -m venv .env
source .env/bin/activate
pip3 install adafruit-circuitpython-led-animation
Usage Example
@ -61,7 +57,7 @@ Usage Example
import board
import neopixel
from adafruit_led_animation.animation.blink import Blink
from adafruit_led_animation.animation import Blink
import adafruit_led_animation.color as color
# Works on Circuit Playground Express and Bluefruit.
@ -76,18 +72,11 @@ Usage Example
while True:
blink.animate()
Documentation
=============
API documentation for this library can be found on `Read the Docs <https://docs.circuitpython.org/projects/led-animation/en/latest/>`_.
For information on building library documentation, please check out `this guide <https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/sharing-our-docs-on-readthedocs#sphinx-5-1>`_.
Contributing
============
Contributions are welcome! Please read our `Code of Conduct
<https://github.com/apatt/CircuitPython_LED_Animation/blob/main/CODE_OF_CONDUCT.md>`_
<https://github.com/apatt/CircuitPython_LED_Animation/blob/master/CODE_OF_CONDUCT.md>`_
before contributing to help this project stay welcoming.
Building locally
@ -101,15 +90,15 @@ To build this library locally you'll need to install the
.. code-block:: shell
python3 -m venv .venv
source .venv/bin/activate
python3 -m venv .env
source .env/bin/activate
pip install circuitpython-build-tools
Once installed, make sure you are in the virtual environment:
.. code-block:: shell
source .venv/bin/activate
source .env/bin/activate
Then run the build:
@ -125,8 +114,8 @@ install dependencies (feel free to reuse the virtual environment from above):
.. code-block:: shell
python3 -m venv .venv
source .venv/bin/activate
python3 -m venv .env
source .env/bin/activate
pip install Sphinx sphinx-rtd-theme
Now, once you have the virtual environment activated:

View file

@ -12,7 +12,7 @@ try:
from micropython import const
except ImportError:
def const(value):
def const(value): # pylint: disable=missing-docstring
return value
@ -27,6 +27,7 @@ try:
"""
return monotonic_ns() // NANOS_PER_MS
except (ImportError, NotImplementedError):
import time

View file

@ -25,19 +25,20 @@ Implementation Notes
"""
__version__ = "0.0.0+auto.0"
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation.git"
from adafruit_led_animation import MS_PER_SECOND, monotonic_ms
class Animation:
# pylint: disable=too-many-instance-attributes
"""
Base class for animations.
"""
on_cycle_complete_supported = False
# pylint: disable=too-many-arguments
def __init__(self, pixel_object, speed, color, peers=None, paused=False, name=None):
self.pixel_object = pixel_object
self.pixel_object.auto_write = False
@ -60,7 +61,7 @@ class Animation:
"""Number of animation cycles completed."""
def __str__(self):
return f"<{self.__class__.__name__}: {self.name}>"
return "<%s: %s>" % (self.__class__.__name__, self.name)
def animate(self, show=True):
"""

View file

@ -37,14 +37,10 @@ class Blink(ColorCycle):
:param pixel_object: The initialised LED object.
:param float speed: Animation speed in seconds, e.g. ``0.1``.
:param color: Animation color in ``(r, g, b)`` tuple, or ``0x000000`` hex format.
:param background_color: Background color in ``(r, g, b)`` tuple, or ``0x000000``
hex format. Defaults to BLACK.
:param name: A human-readable name for the Animation. Used by the string function.
"""
def __init__(self, pixel_object, speed, color, background_color=BLACK, name=None):
self._background_color = background_color
super().__init__(pixel_object, speed, [color, background_color], name=name)
def __init__(self, pixel_object, speed, color, name=None):
super().__init__(pixel_object, speed, [color, BLACK], name=name)
def _set_color(self, color):
self.colors = [color, self._background_color]
self.colors = [color, BLACK]

View file

@ -43,7 +43,10 @@ class Chase(Animation):
:param reverse: Reverse direction of movement.
"""
def __init__(self, pixel_object, speed, color, size=2, spacing=3, reverse=False, name=None):
# pylint: disable=too-many-arguments
def __init__(
self, pixel_object, speed, color, size=2, spacing=3, reverse=False, name=None
):
self._size = size
self._spacing = spacing
self._repeat_width = size + spacing
@ -51,10 +54,10 @@ class Chase(Animation):
self._overflow = len(pixel_object) % self._repeat_width
self._direction = 1 if not reverse else -1
self._reverse = reverse
self._offset = 0 if not reverse else len(pixel_object) - size
self._offset = 0
def _resetter():
self._offset = 0 if not reverse else len(self.pixel_object) - size
self._offset = 0
self._reverse = reverse
self._direction = 1 if not reverse else -1
@ -93,13 +96,13 @@ class Chase(Animation):
bar_no += 1
colorgen = bar_colors()
self.pixel_object[:] = [next(colorgen) for _ in range(len(self.pixel_object))]
self.pixel_object[:] = [next(colorgen) for _ in self.pixel_object]
if self.draw_count % len(self.pixel_object) == 0:
self.cycle_complete = True
self._offset = (self._offset + self._direction) % self._repeat_width
def bar_color(self, n, pixel_no=0):
def bar_color(self, n, pixel_no=0): # pylint: disable=unused-argument
"""
Generate the color for the n'th bar_color in the Chase
@ -108,8 +111,7 @@ class Chase(Animation):
"""
return self.color
@staticmethod
def space_color(n, pixel_no=0):
def space_color(self, n, pixel_no=0): # pylint: disable=unused-argument,no-self-use
"""
Generate the spacing color for the n'th bar_color in the Chase

View file

@ -38,14 +38,12 @@ class ColorCycle(Animation):
:param float speed: Animation speed in seconds, e.g. ``0.1``.
:param colors: A list of colors to cycle through in ``(r, g, b)`` tuple, or ``0x000000`` hex
format. Defaults to a rainbow color cycle.
:param start_color: An index (from 0) for which color to start from. Default 0 (first color).
"""
def __init__(self, pixel_object, speed, colors=RAINBOW, name=None, start_color=0):
def __init__(self, pixel_object, speed, colors=RAINBOW, name=None):
self.colors = colors
self.start_color = start_color
super().__init__(pixel_object, speed, colors[start_color], name=name)
self._generator = self._color_generator(start_color)
super().__init__(pixel_object, speed, colors[0], name=name)
self._generator = self._color_generator()
next(self._generator)
on_cycle_complete_supported = True
@ -54,17 +52,17 @@ class ColorCycle(Animation):
self.pixel_object.fill(self.color)
next(self._generator)
def _color_generator(self, start_color):
index = start_color
def _color_generator(self):
index = 0
while True:
self._color = self.colors[index]
yield
index = (index + 1) % len(self.colors)
if index == start_color:
if index == 0:
self.cycle_complete = True
def reset(self):
"""
Resets to the first color.
"""
self._generator = self._color_generator(self.start_color)
self._generator = self._color_generator()

View file

@ -37,24 +37,20 @@ class Comet(Animation):
:param pixel_object: The initialised LED object.
:param float speed: Animation speed in seconds, e.g. ``0.1``.
:param color: Animation color in ``(r, g, b)`` tuple, or ``0x000000`` hex format.
:param background_color: Background color in ``(r, g, b)`` tuple, or ``0x000000`` hex format.
Defaults to BLACK.
:param int tail_length: The length of the comet. Defaults to 25% of the length of the
``pixel_object``. Automatically compensates for a minimum of 2 and a
maximum of the length of the ``pixel_object``.
:param bool reverse: Animates the comet in the reverse order. Defaults to ``False``.
:param bool bounce: Comet will bounce back and forth. Defaults to ``False``.
:param Optional[string] name: A human-readable name for the Animation.
Used by the to string function.
:param bool bounce: Comet will bounce back and forth. Defaults to ``True``.
:param bool ring: Ring mode. Defaults to ``False``.
"""
# pylint: disable=too-many-arguments,too-many-instance-attributes
def __init__(
self,
pixel_object,
speed,
color,
background_color=BLACK,
tail_length=0,
reverse=False,
bounce=False,
@ -65,14 +61,13 @@ class Comet(Animation):
tail_length = len(pixel_object) // 4
if bounce and ring:
raise ValueError("Cannot combine bounce and ring mode")
self.reverse = reverse
self.bounce = bounce
self._reverse = reverse
self._initial_reverse = reverse
self._tail_length = tail_length
self._color_step = 0.95 / tail_length
self._comet_colors = None
self._computed_color = color
self._background_color = background_color
self._num_pixels = len(pixel_object)
self._direction = -1 if reverse else 1
self._left_side = -self._tail_length
@ -87,79 +82,44 @@ class Comet(Animation):
on_cycle_complete_supported = True
def _set_color(self, color):
self._comet_colors = [self._background_color]
self._comet_colors = [BLACK]
for n in range(self._tail_length):
self._comet_colors.append(calculate_intensity(color, n * self._color_step + 0.05))
self._comet_colors.append(
calculate_intensity(color, n * self._color_step + 0.05)
)
self._computed_color = color
@property
def reverse(self):
"""
Whether the animation is reversed
"""
return self._reverse
@reverse.setter
def reverse(self, value):
self._reverse = value
self._direction = -1 if self._reverse else 1
@property
def ring(self):
"""
Ring mode.
"""
return self._ring
@ring.setter
def ring(self, value):
if self.bounce and value:
raise ValueError("Cannot combine bounce and ring mode")
self._ring = value
self._left_side = 0 if value else -self._tail_length
self.reset()
def draw(self):
colors = self._comet_colors
if self.reverse:
colors = reversed(colors)
for pixel_no, color in enumerate(colors):
draw_at = self._tail_start + pixel_no
if draw_at < 0 or draw_at >= self._num_pixels:
if not self._ring:
continue
draw_at = draw_at % self._num_pixels
pixels = self.pixel_object
start = self._tail_start
npixels = len(pixels)
if self._ring:
start %= npixels
for color in colors:
pixels[start] = color
start += 1
if start == npixels:
start = 0
else:
for color in colors:
if start >= npixels:
break
if start >= 0:
pixels[start] = color
start += 1
self.pixel_object[draw_at] = color
self._tail_start += self._direction
if self._tail_start < self._left_side or (
self._tail_start >= self._right_side and not self._reverse
):
if self._tail_start < self._left_side or self._tail_start >= self._right_side:
if self.bounce:
self.reverse = not self.reverse
self._direction = -self._direction
elif self._ring:
self._tail_start = self._tail_start % self._num_pixels
else:
self.reset()
self.cycle_complete = True
if self.reverse == self._initial_reverse and self.draw_count > 0:
self.cycle_complete = True
def reset(self):
"""
Resets to the first state.
"""
self.reverse = self._initial_reverse
if self.reverse:
self._tail_start = self._num_pixels + self._tail_length + 1
else:

View file

@ -43,6 +43,7 @@ class CustomColorChase(Chase):
:param reverse: Reverse direction of movement.
"""
# pylint: disable=too-many-arguments
def __init__(
self,
pixel_object,

View file

@ -26,13 +26,12 @@ Implementation Notes
"""
import random
from adafruit_led_animation.animation import Animation
__version__ = "0.0.0+auto.0"
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation.git"
from adafruit_led_animation.color import BLACK, GREEN, calculate_intensity, colorwheel
from adafruit_led_animation.color import BLACK, colorwheel, calculate_intensity, GREEN
class Rain(Animation):
@ -47,7 +46,10 @@ class Rain(Animation):
:param background: Background color (Default BLACK).
"""
def __init__(self, grid_object, speed, color, count=1, length=3, background=BLACK, name=None):
# pylint: disable=too-many-arguments
def __init__(
self, grid_object, speed, color, count=1, length=3, background=BLACK, name=None
):
self._count = count
self._length = length
self._background = background
@ -55,6 +57,7 @@ class Rain(Animation):
super().__init__(grid_object, speed, color, name=name)
def draw(self):
# Move raindrops down
keep = []
for raindrop in self._raindrops:
@ -80,7 +83,7 @@ class Rain(Animation):
if y >= 0:
self.pixel_object[x, y] = color
def _generate_droplet(self, x, length):
def _generate_droplet(self, x, length): # pylint: disable=unused-argument
return [[n, self.color] for n in range(-length, 0)]
@ -89,7 +92,9 @@ class RainbowRain(Rain):
Rainbow Rain animation.
"""
def __init__(self, grid_object, speed, count=1, length=3, background=BLACK, name=None):
def __init__( # pylint: disable=too-many-arguments
self, grid_object, speed, count=1, length=3, background=BLACK, name=None
):
super().__init__(grid_object, speed, BLACK, count, length, background, name)
def _generate_droplet(self, x, length):
@ -105,7 +110,7 @@ class MatrixRain(Rain):
The Matrix style animation.
"""
def __init__(
def __init__( # pylint: disable=too-many-arguments
self,
grid_object,
speed,

View file

@ -1,114 +0,0 @@
# SPDX-FileCopyrightText: 2022 Tim Cocks
#
# SPDX-License-Identifier: MIT
"""
`adafruit_led_animation.animation.multicolor_comet`
================================================================================
Multi-color Comet animation for CircuitPython helper library for LED animations.
* Author(s): Kattni Rembor, Tim Cocks
Implementation Notes
--------------------
**Hardware:**
* `Adafruit NeoPixels <https://www.adafruit.com/category/168>`_
* `Adafruit DotStars <https://www.adafruit.com/category/885>`_
**Software and Dependencies:**
* Adafruit CircuitPython firmware for the supported boards:
https://circuitpython.org/downloads
"""
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.color import BLACK
class MulticolorComet(Comet):
"""
A multi-color comet animation.
:param pixel_object: The initialised LED object.
:param float speed: Animation speed in seconds, e.g. ``0.1``.
:param colors: Animation colors in a list or tuple of entries in
``(r, g, b)`` tuple, or ``0x000000`` hex format.
:param int tail_length: The length of the comet. Defaults to 25% of the length of the
``pixel_object``. Automatically compensates for a minimum of 2 and a
maximum of the length of the ``pixel_object``.
:param bool reverse: Animates the comet in the reverse order. Defaults to ``False``.
:param bool bounce: Comet will bounce back and forth. Defaults to ``True``.
:param Optional[string] name: A human-readable name for the Animation.
Used by the to string function.
:param bool ring: Ring mode. Defaults to ``False``.
:param bool off_pixels: Turn pixels off after the animation passes them. Defaults to ``True``.
Setting to False will result in all pixels not currently in the comet
to remain on and set to a color after the comet passes.
"""
def __init__(
self,
pixel_object,
speed,
colors,
*,
tail_length=0,
reverse=False,
bounce=False,
name=None,
ring=False,
off_pixels=True,
):
if tail_length == 0:
tail_length = len(pixel_object) // 4
if bounce and ring:
raise ValueError("Cannot combine bounce and ring mode")
self.bounce = bounce
self._reverse = reverse
self._initial_reverse = reverse
self._tail_length = tail_length
self._comet_colors = None
self._num_pixels = len(pixel_object)
self._direction = -1 if reverse else 1
self._left_side = -self._tail_length
self._right_side = self._num_pixels
self._tail_start = 0
self._ring = ring
self._colors = colors
if colors is None or len(colors) < 2:
raise ValueError("Must pass at least two colors.")
self._off_pixels = off_pixels
if ring:
self._left_side = 0
self.reset()
super().__init__(
pixel_object,
speed,
0x0,
name=name,
tail_length=tail_length,
bounce=bounce,
ring=ring,
reverse=reverse,
)
on_cycle_complete_supported = True
def _set_color(self, color):
if self._off_pixels:
self._comet_colors = [BLACK]
else:
self._comet_colors = []
for n in range(self._tail_length):
_float_index = ((len(self._colors)) / self._tail_length) * n
_color_index = int(_float_index)
self._comet_colors.append(self._colors[_color_index])

View file

@ -1,126 +0,0 @@
# SPDX-FileCopyrightText: 2025 Bob Loeffler
# SPDX-FileCopyrightText: 2025 Jose D. Montoya
#
# SPDX-License-Identifier: MIT
"""
`adafruit_led_animation.animation.pacman`
================================================================================
PacMan Animation for CircuitPython helper library for LED animations.
PACMAN ANIMATION Adapted from https://github.com/wled-dev/WLED/pull/4536 # by BobLoeffler68
* Author(s): Bob Loeffler, Jose D. Montoya
Implementation Notes
--------------------
**Software and Dependencies:**
* Adafruit CircuitPython firmware for the supported boards:
https://circuitpython.org/downloads
"""
import time
from adafruit_led_animation.animation import Animation
from adafruit_led_animation.color import (
BLACK,
BLUE,
CYAN,
ORANGE,
PURPLE,
RED,
WHITE,
YELLOW,
)
ORANGEYELLOW = (255, 136, 0)
class Pacman(Animation):
"""
Simulate the Pacman game in a single led strip.
:param pixel_object: The initialised LED object.
:param float speed: Animation speed rate in seconds, e.g. ``0.1``.
"""
def __init__(
self,
pixel_object,
speed,
color=WHITE,
name=None,
):
self.num_leds = len(pixel_object)
self.pacman = [YELLOW, 10]
self.ghosts_original = [[RED, 6], [PURPLE, 4], [CYAN, 2], [ORANGE, 0]]
self.ghosts = [[RED, 6], [PURPLE, 4], [CYAN, 2], [ORANGE, 0]]
self.direction = 1
self.black_dir = -1
self.flag = "beep"
self.power_pellet = [ORANGEYELLOW, self.num_leds]
self.ghost_timer = time.monotonic()
if self.num_leds > 150:
self.start_blinking_ghosts = self.num_leds // 4
else:
self.start_blinking_ghosts = self.num_leds // 3
super().__init__(pixel_object, speed, color, name=name)
on_cycle_complete_supported = True
def draw(self):
"""
Draw the Pacman animation.
:param led_object: led object
:param neopixel_list: list of neopixel colors
:param int num_leds: number of leds.
:param int duration: duration in seconds. Default is 15 seconds
"""
pixel_list = self.pixel_object
pixel_list[-1] = self.power_pellet[0]
delta = time.monotonic() - self.ghost_timer
if delta > 1:
if self.power_pellet[0] == ORANGEYELLOW:
self.power_pellet[0] = BLACK
else:
self.power_pellet[0] = ORANGEYELLOW
pixel_list[self.power_pellet[1] - 1] = self.power_pellet[0]
self.ghost_timer = time.monotonic()
if self.pacman[1] >= self.num_leds - 2:
self.direction = self.direction * -1
self.black_dir = self.black_dir * -1
for ghost in self.ghosts:
ghost[0] = BLUE
pixel_list[self.pacman[1]] = self.pacman[0]
pixel_list[self.pacman[1] + self.black_dir] = BLACK
self.pacman[1] += self.direction
if self.ghosts[3][1] <= self.start_blinking_ghosts and self.direction == -1:
if self.flag == "beep":
for i, ghost in enumerate(self.ghosts):
ghost[0] = BLACK
self.flag = "bop"
else:
for i, ghost in enumerate(self.ghosts):
ghost[0] = self.ghosts_original[i][0]
self.flag = "beep"
for i, ghost in enumerate(self.ghosts):
pixel_list[ghost[1]] = ghost[0]
pixel_list[ghost[1] + self.black_dir] = BLACK
ghost[1] += self.direction
if self.ghosts[3][1] <= 0:
self.direction = self.direction * -1
self.black_dir = self.black_dir * -1
for i, ghost in enumerate(self.ghosts):
ghost[0] = self.ghosts_original[i][0]

View file

@ -37,27 +37,12 @@ class Pulse(Animation):
:param float speed: Animation refresh rate in seconds, e.g. ``0.1``.
:param color: Animation color in ``(r, g, b)`` tuple, or ``0x000000`` hex format.
:param period: Period to pulse the LEDs over. Default 5.
:param breath: Duration to hold minimum and maximum intensity levels. Default 0.
:param min_intensity: Lowest brightness level of the pulse. Default 0.
:param max_intensity: Highest brightness level of the pulse. Default 1.
"""
def __init__(
self,
pixel_object,
speed,
color,
period=5,
breath=0,
min_intensity=0,
max_intensity=1,
name=None,
):
# pylint: disable=too-many-arguments
def __init__(self, pixel_object, speed, color, period=5, name=None):
super().__init__(pixel_object, speed, color, name=name)
self._period = period
self.breath = breath
self.min_intensity = min_intensity
self.max_intensity = max_intensity
self._generator = None
self.reset()
@ -71,21 +56,11 @@ class Pulse(Animation):
"""
Resets the animation.
"""
dotstar = len(self.pixel_object[0]) == 4 and isinstance(self.pixel_object[0][-1], float)
from adafruit_led_animation.pulse_generator import (
dotstar = len(self.pixel_object[0]) == 4 and isinstance(
self.pixel_object[0][-1], float
)
from adafruit_led_animation.helper import ( # pylint: disable=import-outside-toplevel
pulse_generator,
)
self._generator = pulse_generator(self._period, self, dotstar_pwm=dotstar)
@property
def period(self):
"""
Period to pulse the LEDs over in seconds
"""
return self._period
@period.setter
def period(self, new_value):
self._period = new_value
self.reset()

View file

@ -25,11 +25,11 @@ Implementation Notes
"""
from adafruit_led_animation import MS_PER_SECOND, monotonic_ms
from adafruit_led_animation.animation import Animation
from adafruit_led_animation.color import BLACK, colorwheel
from adafruit_led_animation import MS_PER_SECOND, monotonic_ms
__version__ = "0.0.0+auto.0"
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation.git"
@ -46,7 +46,10 @@ class Rainbow(Animation):
(default True).
"""
def __init__(self, pixel_object, speed, period=5, step=1, name=None, precompute_rainbow=True):
# pylint: disable=too-many-arguments
def __init__(
self, pixel_object, speed, period=5, step=1, name=None, precompute_rainbow=True
):
super().__init__(pixel_object, speed, BLACK, name=name)
self._period = period
self._step = step
@ -82,9 +85,9 @@ class Rainbow(Animation):
if pos < last_pos:
cycle_completed = True
last_pos = pos
wheel_index = int((pos / period) * len(self.colors))
if self.colors:
wheel_index = int((pos / period) * len(self.colors))
self._draw_precomputed(num_pixels, wheel_index)
else:
wheel_index = int((pos / period) * 256)
@ -104,9 +107,13 @@ class Rainbow(Animation):
if wheel_index + num > len(self.colors):
colors_left = len(self.colors) - wheel_index
self.pixel_object[i : i + colors_left] = self.colors[wheel_index:]
self.pixel_object[i + colors_left : i + num] = self.colors[: num - colors_left]
self.pixel_object[i + colors_left : i + num] = self.colors[
: num - colors_left
]
else:
self.pixel_object[i : i + num] = self.colors[wheel_index : wheel_index + num]
self.pixel_object[i : i + num] = self.colors[
wheel_index : wheel_index + num
]
def draw(self):
next(self._generator)
@ -116,15 +123,3 @@ class Rainbow(Animation):
Resets the animation.
"""
self._generator = self._color_wheel_generator()
@property
def period(self) -> float:
"""
Period to cycle the rainbow over in seconds.
"""
return self._period
@period.setter
def period(self, new_value: float) -> None:
self._period = new_value
self.reset()

View file

@ -26,8 +26,8 @@ Implementation Notes
"""
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.color import colorwheel
from adafruit_led_animation.animation.chase import Chase
class RainbowChase(Chase):
@ -40,9 +40,10 @@ class RainbowChase(Chase):
:param size: Number of pixels to turn on in a row.
:param spacing: Number of pixels to turn off in a row.
:param reverse: Reverse direction of movement.
:param step: How many colors to skip in ``colorwheel`` per bar (default 8)
:param step: How many colors to skip in `colorwheel` per bar (default 8)
"""
# pylint: disable=too-many-arguments
def __init__(
self,
pixel_object,

View file

@ -27,7 +27,7 @@ Implementation Notes
"""
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.color import BLACK, calculate_intensity, colorwheel
from adafruit_led_animation.color import colorwheel, BLACK, calculate_intensity
class RainbowComet(Comet):
@ -40,12 +40,13 @@ class RainbowComet(Comet):
pixels present in the pixel object, e.g. if the strip is 30 pixels
long, the ``tail_length`` cannot exceed 30 pixels.
:param bool reverse: Animates the comet in the reverse order. Defaults to ``False``.
:param bool bounce: Comet will bounce back and forth. Defaults to ``False``.
:param bool bounce: Comet will bounce back and forth. Defaults to ``True``.
:param int colorwheel_offset: Offset from start of colorwheel (0-255).
:param int step: Colorwheel step (defaults to automatic).
:param bool ring: Ring mode. Defaults to ``False``.
"""
# pylint: disable=too-many-arguments
def __init__(
self,
pixel_object,
@ -59,11 +60,13 @@ class RainbowComet(Comet):
ring=False,
):
if step == 0:
self._colorwheel_step = max(256 // tail_length, 1)
self._colorwheel_step = int(256 / tail_length)
else:
self._colorwheel_step = step
self._colorwheel_offset = colorwheel_offset
super().__init__(pixel_object, speed, 0, 0, tail_length, reverse, bounce, name, ring)
super().__init__(
pixel_object, speed, 0, tail_length, reverse, bounce, name, ring
)
def _set_color(self, color):
self._comet_colors = [BLACK]
@ -72,7 +75,8 @@ class RainbowComet(Comet):
self._comet_colors.append(
calculate_intensity(
colorwheel(
int((invert * self._colorwheel_step) + self._colorwheel_offset) % 256
int((invert * self._colorwheel_step) + self._colorwheel_offset)
% 256
),
n * self._color_step + 0.05,
)

View file

@ -26,7 +26,6 @@ Implementation Notes
"""
import random
from adafruit_led_animation.animation.rainbow import Rainbow
@ -46,6 +45,7 @@ class RainbowSparkle(Rainbow):
(default True).
"""
# pylint: disable=too-many-arguments
def __init__(
self,
pixel_object,
@ -91,7 +91,10 @@ class RainbowSparkle(Rainbow):
def after_draw(self):
self.show()
pixels = [random.randint(0, len(self.pixel_object) - 1) for n in range(self._num_sparkles)]
pixels = [
random.randint(0, len(self.pixel_object) - 1)
for n in range(self._num_sparkles)
]
for pixel in pixels:
self.pixel_object[pixel] = self._bright_colors[
(self._wheel_index + pixel) % len(self._bright_colors)

View file

@ -26,10 +26,9 @@ Implementation Notes
"""
import random
from adafruit_led_animation.animation import Animation
__version__ = "0.0.0+auto.0"
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation.git"
@ -41,18 +40,12 @@ class Sparkle(Animation):
:param float speed: Animation speed in seconds, e.g. ``0.1``.
:param color: Animation color in ``(r, g, b)`` tuple, or ``0x000000`` hex format.
:param num_sparkles: Number of sparkles to generate per animation cycle.
:param mask: array to limit sparkles within range of the mask
"""
def __init__(self, pixel_object, speed, color, num_sparkles=1, name=None, mask=None):
# pylint: disable=too-many-arguments
def __init__(self, pixel_object, speed, color, num_sparkles=1, name=None):
if len(pixel_object) < 2:
raise ValueError("Sparkle needs at least 2 pixels")
if mask:
self._mask = mask
else:
self._mask = []
if len(self._mask) >= len(pixel_object):
raise ValueError("Sparkle mask should be smaller than number pixel array")
self._half_color = color
self._dim_color = color
self._sparkle_color = color
@ -73,13 +66,11 @@ class Sparkle(Animation):
self._dim_color = dim_color
self._sparkle_color = color
def _random_in_mask(self):
if len(self._mask) == 0:
return random.randint(0, (len(self.pixel_object) - 1))
return self._mask[random.randint(0, (len(self._mask) - 1))]
def draw(self):
self._pixels = [self._random_in_mask() for _ in range(self._num_sparkles)]
self._pixels = [
random.randint(0, (len(self.pixel_object) - 1))
for _ in range(self._num_sparkles)
]
for pixel in self._pixels:
self.pixel_object[pixel] = self._sparkle_color
@ -87,5 +78,4 @@ class Sparkle(Animation):
self.show()
for pixel in self._pixels:
self.pixel_object[pixel % self._num_pixels] = self._half_color
if (pixel + 1) % self._num_pixels in self._mask:
self.pixel_object[(pixel + 1) % self._num_pixels] = self._dim_color
self.pixel_object[(pixel + 1) % self._num_pixels] = self._dim_color

View file

@ -27,7 +27,7 @@ Implementation Notes
"""
from adafruit_led_animation.animation.sparkle import Sparkle
from adafruit_led_animation.pulse_generator import pulse_generator
from adafruit_led_animation.helper import pulse_generator
class SparklePulse(Sparkle):
@ -38,28 +38,28 @@ class SparklePulse(Sparkle):
:param int speed: Animation refresh rate in seconds, e.g. ``0.1``.
:param color: Animation color in ``(r, g, b)`` tuple, or ``0x000000`` hex format.
:param period: Period to pulse the LEDs over. Default 5.
:param breath: Duration to hold minimum and maximum intensity. Default 0.
:param max_intensity: The maximum intensity to pulse, between 0 and 1.0. Default 1.
:param min_intensity: The minimum intensity to pulse, between 0 and 1.0. Default 0.
"""
# pylint: disable=too-many-arguments
def __init__(
self,
pixel_object,
speed,
color,
period=5,
breath=0,
max_intensity=1,
min_intensity=0,
name=None,
):
self._max_intensity = max_intensity
self._min_intensity = min_intensity
self._period = period
self.breath = breath
self.min_intensity = min_intensity
self.max_intensity = max_intensity
dotstar = len(pixel_object) == 4 and isinstance(pixel_object[0][-1], float)
super().__init__(pixel_object, speed=speed, color=color, num_sparkles=1, name=name)
super().__init__(
pixel_object, speed=speed, color=color, num_sparkles=1, name=name
)
self._generator = pulse_generator(self._period, self, dotstar_pwm=dotstar)
def _set_color(self, color):
@ -71,19 +71,3 @@ class SparklePulse(Sparkle):
def after_draw(self):
self.show()
@property
def period(self):
"""
Period to pulse the LEDs over in seconds
"""
return self._period
@period.setter
def period(self, new_value):
self._period = new_value
self.reset()
def reset(self):
dotstar = len(self.pixel_object) == 4 and isinstance(self.pixel_object[0][-1], float)
self._generator = pulse_generator(self._period, self, dotstar_pwm=dotstar)

View file

@ -1,111 +0,0 @@
# SPDX-FileCopyrightText: 2020 Gamblor21
#
# SPDX-License-Identifier: MIT
"""
`adafruit_led_animation.animation.volume`
================================================================================
Volume animation for CircuitPython helper library for LED animations.
* Author(s): Mark Komus
Implementation Notes
--------------------
**Hardware:**
* `Adafruit NeoPixels <https://www.adafruit.com/category/168>`_
* `Adafruit DotStars <https://www.adafruit.com/category/885>`_
**Software and Dependencies:**
* Adafruit CircuitPython firmware for the supported boards:
https://circuitpython.org/downloads
"""
from adafruit_led_animation.animation import Animation
def map_range(x, in_min, in_max, out_min, out_max):
"""
Maps a number from one range to another.
:return: Returns value mapped to new range
:rtype: float
"""
mapped = (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
if out_min <= out_max:
return max(min(mapped, out_max), out_min)
return min(max(mapped, out_max), out_min)
class Volume(Animation):
"""
Animate the brightness and number of pixels based on volume.
:param pixel_object: The initialised LED object.
:param float speed: Animation update speed in seconds, e.g. ``0.1``.
:param brightest_color: Color at max volume ``(r, g, b)`` tuple, or ``0x000000`` hex format
:param decoder: a MP3Decoder object that the volume will be taken from
:param float max_volume: what volume is considered maximum where everything is lit up
"""
def __init__(
self,
pixel_object,
speed,
brightest_color,
decoder,
max_volume=500,
name=None,
):
self._decoder = decoder
self._num_pixels = len(pixel_object)
self._max_volume = max_volume
self._brightest_color = brightest_color
super().__init__(pixel_object, speed, brightest_color, name=name)
def set_brightest_color(self, brightest_color):
"""
Animate the brightness and number of pixels based on volume.
:param brightest_color: Color at max volume ``(r, g, b)`` tuple, or ``0x000000`` hex format
"""
self._brightest_color = brightest_color
def draw(self):
red = int(
map_range(
self._decoder.rms_level,
0,
self._max_volume,
0,
self._brightest_color[0],
)
)
green = int(
map_range(
self._decoder.rms_level,
0,
self._max_volume,
0,
self._brightest_color[1],
)
)
blue = int(
map_range(
self._decoder.rms_level,
0,
self._max_volume,
0,
self._brightest_color[2],
)
)
lit_pixels = int(
map_range(
self._decoder.rms_level,
0,
self._max_volume,
0,
self._num_pixels,
)
)
if lit_pixels > self._num_pixels:
lit_pixels = self._num_pixels
self.pixel_object[0:lit_pixels] = [(red, green, blue)] * lit_pixels
self.pixel_object[lit_pixels : self._num_pixels] = [(0, 0, 0)] * (
self._num_pixels - lit_pixels
)

View file

@ -23,10 +23,6 @@ Implementation Notes
* Adafruit CircuitPython firmware for the supported boards:
https://circuitpython.org/downloads
"""
# Makes colorwheel() available.
from rainbowio import colorwheel
RED = (255, 0, 0)
"""Red."""
YELLOW = (255, 150, 0)
@ -74,6 +70,29 @@ RAINBOW = (RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE)
"""RAINBOW is a list of colors to use for cycling through.
Includes, in order: red, orange, yellow, green, blue, and purple."""
try:
try:
# Backwards compatibility for 5.3.0 and prior
from _pixelbuf import colorwheel # pylint: disable=unused-import
except ImportError:
from _pixelbuf import wheel as colorwheel # pylint: disable=unused-import
except ImportError:
def colorwheel(pos):
"""Colorwheel is built into CircuitPython's _pixelbuf. A separate colorwheel is included
here for use with CircuitPython builds that do not include _pixelbuf, as with some of the
SAMD21 builds. To use: input a value 0 to 255 to get a color value.
The colours are a transition from red to green to blue and back to red."""
if pos < 0 or pos > 255:
return 0, 0, 0
if pos < 85:
return int(255 - pos * 3), int(pos * 3), 0
if pos < 170:
pos -= 85
return 0, int(255 - pos * 3), int(pos * 3)
pos -= 170
return int(pos * 3), 0, int(255 - (pos * 3))
def calculate_intensity(color, intensity=1.0):
"""

View file

@ -24,11 +24,11 @@ Implementation Notes
https://circuitpython.org/downloads
"""
from micropython import const
from .helper import PixelMap, horizontal_strip_gridmap, vertical_strip_gridmap
HORIZONTAL = const(1)
VERTICAL = const(2)
@ -79,7 +79,7 @@ class PixelGrid:
reverse_y=False,
top=0,
bottom=0,
):
): # pylint: disable=too-many-arguments,too-many-locals
self._pixels = strip
self._x = []
self.height = height
@ -154,6 +154,7 @@ class PixelGrid:
@brightness.setter
def brightness(self, brightness):
# pylint: disable=attribute-defined-outside-init
self._pixels.brightness = min(max(brightness, 0.0), 1.0)
def fill(self, color):

View file

@ -26,7 +26,7 @@ Implementation Notes
"""
__version__ = "0.0.0+auto.0"
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation.git"
from adafruit_led_animation.animation import Animation
@ -44,7 +44,7 @@ class AnimationGroup:
Example:
.. code-block:: python
.. code-block::
import board
import neopixel
@ -107,9 +107,9 @@ class AnimationGroup:
self.on_cycle_complete_supported = self._members[-1].on_cycle_complete_supported
def __str__(self):
return f"<AnimationGroup {self.__class__.__name__}: {self.name}>"
return "<AnimationGroup %s: %s>" % (self.__class__.__name__, self.name)
def _group_done(self, animation):
def _group_done(self, animation): # pylint: disable=unused-argument
self.on_cycle_complete()
def on_cycle_complete(self):
@ -152,11 +152,7 @@ class AnimationGroup:
member.show()
return result
ret = False
for item in self._members:
if item.animate(show):
ret = True
return ret
return any([item.animate(show) for item in self._members])
@property
def color(self):

View file

@ -27,6 +27,9 @@ Implementation Notes
import math
from . import MS_PER_SECOND, monotonic_ms
from .color import calculate_intensity
class PixelMap:
"""
@ -165,6 +168,7 @@ class PixelMap:
@brightness.setter
def brightness(self, brightness):
# pylint: disable=attribute-defined-outside-init
self._pixels.brightness = min(max(brightness, 0.0), 1.0)
def fill(self, color):
@ -309,3 +313,39 @@ class PixelSubset(PixelMap):
pixel_ranges=[[n] for n in range(start, end)],
individual_pixels=True,
)
def pulse_generator(period: float, animation_object, dotstar_pwm=False):
"""
Generates a sequence of colors for a pulse, based on the time period specified.
:param period: Pulse duration in seconds.
:param animation_object: An animation object to interact with.
:param dotstar_pwm: Whether to use the dostar per pixel PWM value for brightness control.
"""
period = int(period * MS_PER_SECOND)
half_period = period // 2
last_update = monotonic_ms()
cycle_position = 0
last_pos = 0
while True:
now = monotonic_ms()
time_since_last_draw = now - last_update
last_update = now
pos = cycle_position = (cycle_position + time_since_last_draw) % period
if pos < last_pos:
animation_object.cycle_complete = True
last_pos = pos
if pos > half_period:
pos = period - pos
intensity = pos / half_period
if dotstar_pwm:
fill_color = (
animation_object.color[0],
animation_object.color[1],
animation_object.color[2],
intensity,
)
yield fill_color
continue
yield calculate_intensity(animation_object.color, intensity)

View file

@ -1,74 +0,0 @@
# SPDX-FileCopyrightText: 2019 Kattni Rembor for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
`adafruit_led_animation.pulse_generator`
================================================================================
Helper method for pulse generation
* Author(s): Kattni Rembor
Implementation Notes
--------------------
**Hardware:**
* `Adafruit NeoPixels <https://www.adafruit.com/category/168>`_
* `Adafruit DotStars <https://www.adafruit.com/category/885>`_
**Software and Dependencies:**
* Adafruit CircuitPython firmware for the supported boards:
https://circuitpython.org/downloads
"""
from . import MS_PER_SECOND, monotonic_ms
from .color import calculate_intensity
def pulse_generator(period: float, animation_object, dotstar_pwm=False):
"""
Generates a sequence of colors for a pulse, based on the time period specified.
:param period: Pulse duration in seconds.
:param animation_object: An animation object to interact with.
:param dotstar_pwm: Whether to use the dostar per pixel PWM value for brightness control.
"""
period = int((period + (animation_object.breath * 2)) * MS_PER_SECOND)
half_breath = int(animation_object.breath * MS_PER_SECOND // 2)
half_period = period // 2
last_update = monotonic_ms()
cycle_position = 0
last_pos = 0
while True:
now = monotonic_ms()
time_since_last_draw = now - last_update
last_update = now
pos = cycle_position = (cycle_position + time_since_last_draw) % period
if pos < last_pos:
animation_object.cycle_complete = True
last_pos = pos
if pos > half_period:
pos = period - pos
if pos < half_breath:
intensity = animation_object.min_intensity
elif pos > (half_period - half_breath):
intensity = animation_object.max_intensity
else:
intensity = animation_object.min_intensity + (
((pos - half_breath) / (half_period - (half_breath * 2)))
* (animation_object.max_intensity - animation_object.min_intensity)
)
if dotstar_pwm:
fill_color = (
animation_object.color[0],
animation_object.color[1],
animation_object.color[2],
intensity,
)
yield fill_color
continue
yield calculate_intensity(animation_object.color, intensity)

View file

@ -27,12 +27,10 @@ Implementation Notes
"""
import random
from adafruit_led_animation.color import BLACK
from . import MS_PER_SECOND, monotonic_ms
__version__ = "0.0.0+auto.0"
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation.git"
@ -75,6 +73,7 @@ class AnimationSequence:
animations.animate()
"""
# pylint: disable=too-many-instance-attributes
def __init__(
self,
*members,
@ -83,12 +82,16 @@ class AnimationSequence:
random_order=False,
auto_reset=False,
advance_on_cycle_complete=False,
name=None,
name=None
):
if advance_interval and advance_on_cycle_complete:
raise ValueError("Cannot use both advance_interval and advance_on_cycle_complete.")
raise ValueError(
"Cannot use both advance_interval and advance_on_cycle_complete."
)
self._members = members
self._advance_interval = advance_interval * MS_PER_SECOND if advance_interval else None
self._advance_interval = (
advance_interval * MS_PER_SECOND if advance_interval else None
)
self._last_advance = monotonic_ms()
self._current = 0
self.auto_clear = auto_clear
@ -112,7 +115,7 @@ class AnimationSequence:
on_cycle_complete_supported = True
def __str__(self):
return f"<{self.__class__.__name__}: {self.name}>"
return "<%s: %s>" % (self.__class__.__name__, self.name)
def on_cycle_complete(self):
"""
@ -125,7 +128,7 @@ class AnimationSequence:
for callback in self._also_notify:
callback(self)
def _sequence_complete(self, animation):
def _sequence_complete(self, animation): # pylint: disable=unused-argument
if self.advance_on_cycle_complete:
self._advance()
@ -176,13 +179,6 @@ class AnimationSequence:
self.on_cycle_complete()
self.activate(current % len(self._members))
def previous(self):
"""
Jump to the previous animation.
"""
current = self._current - 1
self.activate(current % len(self._members))
def random(self):
"""
Jump to a random animation.

View file

@ -1,82 +0,0 @@
# SPDX-FileCopyrightText: 2020 Gamblor21
#
# SPDX-License-Identifier: MIT
"""
`adafruit_led_animation.timedsequence`
================================================================================
Animation timed sequence helper for CircuitPython helper library for LED animations.
* Author(s): Mark Komus
Implementation Notes
--------------------
**Hardware:**
* `Adafruit NeoPixels <https://www.adafruit.com/category/168>`_
* `Adafruit DotStars <https://www.adafruit.com/category/885>`_
**Software and Dependencies:**
* Adafruit CircuitPython firmware for the supported boards:
https://circuitpython.org/downloads
"""
from adafruit_led_animation.sequence import AnimationSequence
from . import MS_PER_SECOND
class TimedAnimationSequence(AnimationSequence):
"""
A sequence of Animations to run in succession, each animation running for an
individual amount of time.
:param members: The animation objects or groups followed by how long the animation
should run in seconds.
:param bool auto_clear: Clear the pixels between animations. If ``True``, the current animation
will be cleared from the pixels before the next one starts.
Defaults to ``False``.
:param bool random_order: Activate the animations in a random order. Defaults to ``False``.
:param bool auto_reset: Automatically call reset() on animations when changing animations.
.. code-block:: python
import board
import neopixel
from adafruit_led_animation.timedsequence import TimedAnimationSequence
import adafruit_led_animation.animation.comet as comet_animation
import adafruit_led_animation.animation.sparkle as sparkle_animation
import adafruit_led_animation.animation.blink as blink_animation
import adafruit_led_animation.color as color
strip_pixels = neopixel.NeoPixel(board.A1, 30, brightness=1, auto_write=False)
blink = blink_animation.Blink(strip_pixels, 0.2, color.RED)
comet = comet_animation.Comet(strip_pixels, 0.1, color.BLUE)
sparkle = sparkle_animation.Sparkle(strip_pixels, 0.05, color.GREEN)
animations = TimedAnimationSequence(blink, 5, comet, 3, sparkle, 7)
while True:
animations.animate()
"""
def __init__(self, *members, auto_clear=True, random_order=False, auto_reset=False, name=None):
self._animation_members = []
self._animation_timings = []
for x, item in enumerate(members):
if not x % 2:
self._animation_members.append(item)
else:
self._animation_timings.append(item)
super().__init__(
*self._animation_members,
auto_clear=auto_clear,
random_order=random_order,
auto_reset=auto_reset,
advance_on_cycle_complete=False,
name=name,
)
self._advance_interval = self._animation_timings[self._current] * MS_PER_SECOND
def activate(self, index):
super().activate(index)
self._advance_interval = self._animation_timings[self._current] * MS_PER_SECOND

View file

@ -4,9 +4,6 @@
.. If your library file(s) are nested in a directory (e.g. /adafruit_foo/foo.py)
.. use this format as the module name: "adafruit_foo.foo"
API Reference
#############
.. automodule:: adafruit_led_animation.animation
:members:

View file

@ -1,8 +1,9 @@
# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import datetime
import os
import sys
@ -15,7 +16,6 @@ sys.path.insert(0, os.path.abspath(".."))
# ones.
extensions = [
"sphinx.ext.autodoc",
"sphinxcontrib.jquery",
"sphinx.ext.intersphinx",
"sphinx.ext.napoleon",
"sphinx.ext.todo",
@ -25,12 +25,12 @@ extensions = [
# Uncomment the below if you use native CircuitPython modules such as
# digitalio, micropython and busio. List the modules you use. Without it, the
# autodoc module docs will fail to generate with a warning.
autodoc_mock_imports = ["rainbowio"]
autodoc_mock_imports = []
intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
"CircuitPython": ("https://docs.circuitpython.org/en/latest/", None),
"python": ("https://docs.python.org/3.4", None),
"CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None),
}
# Add any paths that contain templates here, relative to this directory.
@ -43,12 +43,7 @@ master_doc = "index"
# General information about the project.
project = "LED_Animation Library"
creation_year = "2020"
current_year = str(datetime.datetime.now().year)
year_duration = (
current_year if current_year == creation_year else creation_year + " - " + current_year
)
copyright = year_duration + " Kattni Rembor"
copyright = "2020 Kattni Rembor"
author = "Kattni Rembor"
# The version info for the project you're documenting, acts as replacement for
@ -65,7 +60,7 @@ release = "1.0"
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = "en"
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
@ -97,9 +92,19 @@ napoleon_numpy_docstring = False
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
import sphinx_rtd_theme
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
html_theme = "sphinx_rtd_theme"
if not on_rtd: # only import and set the theme if we're building docs locally
try:
import sphinx_rtd_theme
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
except:
html_theme = "default"
html_theme_path = ["."]
else:
html_theme_path = ["."]
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,

View file

@ -6,110 +6,3 @@ Ensure your device works with this simple test.
.. literalinclude:: ../examples/led_animation_simpletest.py
:caption: examples/led_animation_simpletest.py
:linenos:
Basic Animations
----------------
Demonstrates the basic animations.
.. literalinclude:: ../examples/led_animation_basic_animations.py
:caption: examples/led_animation_basic_animations.py
:linenos:
All Animations
----------------
Demonstrates the entire suite of animations.
.. literalinclude:: ../examples/led_animation_all_animations.py
:caption: examples/led_animation_all_animations.py
:linenos:
Pixel Map
---------
Demonstrates the pixel mapping feature.
.. literalinclude:: ../examples/led_animation_pixel_map.py
:caption: examples/led_animation_pixel_map.py
:linenos:
Animation Sequence
------------------
Demonstrates the animation sequence feature.
.. literalinclude:: ../examples/led_animation_sequence.py
:caption: examples/led_animation_sequence.py
:linenos:
Animation Group
---------------
Demonstrates the animation group feature.
.. literalinclude:: ../examples/led_animation_group.py
:caption: examples/led_animation_group.py
:linenos:
Blink
-----
Demonstrates the blink animation.
.. literalinclude:: ../examples/led_animation_blink.py
:caption: examples/led_animation_blink.py
:linenos:
Blink with a selcted background color
----------------------------------------
Demonstrates the blink animation with an user defined background color.
.. literalinclude:: ../examples/led_animation_blink_with_background.py
:caption: examples/led_animation_blink_with_background.py
:linenos:
Comet
-----
Demonstrates the comet animation.
.. literalinclude:: ../examples/led_animation_comet.py
:caption: examples/led_animation_comet.py
:linenos:
Chase
-----
Demonstrates the chase animation.
.. literalinclude:: ../examples/led_animation_chase.py
:caption: examples/led_animation_chase.py
:linenos:
Rainbow
-------
Demonstrates the rainbow animations.
.. literalinclude:: ../examples/led_animation_rainbow_animations.py
:caption: examples/led_animation_rainbow_animations.py
:linenos:
Sparkle
-------
Demonstrates the sparkle animations.
.. literalinclude:: ../examples/led_animation_sparkle_animations.py
:caption: examples/led_animation_sparkle_animations.py
:linenos:
Pacman
------
Demonstrates the pacman animation.
.. literalinclude:: ../examples/led_animation_pacman.py
:caption: examples/led_animation_pacman.py
:linenos:

View file

@ -20,25 +20,11 @@ Table of Contents
api
.. toctree::
:caption: Tutorials
CircuitPython LED Animations Learning Guide <https://learn.adafruit.com/circuitpython-led-animations>
.. toctree::
:caption: Related Products
Adafruit NeoPixel LEDs <https://www.adafruit.com/category/168>
Adafruit DotStar LEDs <https://www.adafruit.com/category/885>
.. toctree::
:caption: Other Links
Download from GitHub <https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation/releases/latest>
Download Library Bundle <https://circuitpython.org/libraries>
CircuitPython Reference Documentation <https://docs.circuitpython.org>
Download <https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation/releases/latest>
CircuitPython Reference Documentation <https://circuitpython.readthedocs.io>
CircuitPython Support Forum <https://forums.adafruit.com/viewforum.php?f=60>
Discord Chat <https://adafru.it/discord>
Adafruit Learning System <https://learn.adafruit.com>

View file

@ -1,7 +0,0 @@
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
sphinx
sphinxcontrib-jquery
sphinx-rtd-theme

View file

@ -9,25 +9,24 @@ a different form of NeoPixels.
This example does not work on SAMD21 (M0) boards.
"""
import board
import neopixel
from adafruit_led_animation.animation.blink import Blink
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.animation.colorcycle import ColorCycle
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.animation.customcolorchase import CustomColorChase
from adafruit_led_animation.animation.pulse import Pulse
from adafruit_led_animation.animation.rainbow import Rainbow
from adafruit_led_animation.animation.rainbowchase import RainbowChase
from adafruit_led_animation.animation.rainbowcomet import RainbowComet
from adafruit_led_animation.animation.rainbowsparkle import RainbowSparkle
from adafruit_led_animation.animation.solid import Solid
from adafruit_led_animation.animation.sparkle import Sparkle
from adafruit_led_animation.animation.sparklepulse import SparklePulse
from adafruit_led_animation.color import AMBER, JADE, MAGENTA, ORANGE, PURPLE, WHITE
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.animation.pulse import Pulse
from adafruit_led_animation.animation.sparkle import Sparkle
from adafruit_led_animation.animation.rainbowchase import RainbowChase
from adafruit_led_animation.animation.rainbowsparkle import RainbowSparkle
from adafruit_led_animation.animation.rainbowcomet import RainbowComet
from adafruit_led_animation.animation.solid import Solid
from adafruit_led_animation.animation.colorcycle import ColorCycle
from adafruit_led_animation.animation.rainbow import Rainbow
from adafruit_led_animation.animation.customcolorchase import CustomColorChase
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation.color import PURPLE, WHITE, AMBER, JADE, MAGENTA, ORANGE
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D6

View file

@ -9,27 +9,26 @@ a different form of NeoPixels.
This example may not work on SAMD21 (M0) boards.
"""
import board
import neopixel
from adafruit_led_animation.animation.blink import Blink
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.animation.colorcycle import ColorCycle
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.animation.pulse import Pulse
from adafruit_led_animation.animation.solid import Solid
from adafruit_led_animation.animation.colorcycle import ColorCycle
from adafruit_led_animation.animation.blink import Blink
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.animation.pulse import Pulse
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation.color import (
PURPLE,
WHITE,
AMBER,
JADE,
TEAL,
PINK,
MAGENTA,
ORANGE,
PINK,
PURPLE,
TEAL,
WHITE,
)
from adafruit_led_animation.sequence import AnimationSequence
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D6

View file

@ -10,7 +10,6 @@ using a different board or form of NeoPixels.
This example will run on SAMD21 (M0) Express boards (such as Circuit Playground Express or QT Py
Haxpress), but not on SAMD21 non-Express boards (such as QT Py or Trinket).
"""
import board
import neopixel

View file

@ -1,30 +0,0 @@
# SPDX-FileCopyrightText: 2025 Jose D. Montoya
# SPDX-License-Identifier: MIT
"""
This example blinks the LEDs purple with a yellow background at a 0.5 second interval.
For QT Py Haxpress and a NeoPixel strip. Update pixel_pin and pixel_num to match your wiring if
using a different board or form of NeoPixels.
This example will run on SAMD21 (M0) Express boards (such as Circuit Playground Express or QT Py
Haxpress), but not on SAMD21 non-Express boards (such as QT Py or Trinket).
"""
import board
import neopixel
from adafruit_led_animation.animation.blink import Blink
from adafruit_led_animation.color import PURPLE, YELLOW
# Update to match the pin connected to your NeoPixels
pixel_pin = board.A3
# Update to match the number of NeoPixels you have connected
pixel_num = 30
pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=0.5, auto_write=False)
blink = Blink(pixels, speed=0.5, color=PURPLE, background_color=YELLOW)
while True:
blink.animate()

View file

@ -11,7 +11,6 @@ using a different board or form of NeoPixels.
This example will run on SAMD21 (M0) Express boards (such as Circuit Playground Express or QT Py
Haxpress), but not on SAMD21 non-Express boards (such as QT Py or Trinket).
"""
import board
import neopixel

View file

@ -10,7 +10,6 @@ using a different board or form of NeoPixels.
This example will run on SAMD21 (M0) Express boards (such as Circuit Playground Express or QT Py
Haxpress), but not on SAMD21 non-Express boards (such as QT Py or Trinket).
"""
import board
import neopixel

View file

@ -9,16 +9,17 @@ a different form of NeoPixels.
This example may not work on SAMD21 (M0) boards.
"""
import board
import neopixel
from adafruit_led_animation.animation.customcolorchase import CustomColorChase
from adafruit_led_animation.sequence import AnimationSequence
# colorwheel only needed for rainbowchase example
from adafruit_led_animation.color import colorwheel
# Colors for customcolorchase examples
from adafruit_led_animation.color import BLUE, GREEN, PINK, RED, colorwheel
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation.color import PINK, GREEN, RED, BLUE
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D5
@ -26,11 +27,15 @@ pixel_pin = board.D5
pixel_num = 30
brightness = 0.3
pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=brightness, auto_write=False)
pixels = neopixel.NeoPixel(
pixel_pin, pixel_num, brightness=brightness, auto_write=False
)
# colors default to RAINBOW as defined in color.py
custom_color_chase_rainbow = CustomColorChase(pixels, speed=0.1, size=2, spacing=3)
custom_color_chase_rainbow_r = CustomColorChase(pixels, speed=0.1, size=3, spacing=3, reverse=True)
custom_color_chase_rainbow_r = CustomColorChase(
pixels, speed=0.1, size=3, spacing=3, reverse=True
)
# Example with same colors as RainbowChase
steps = 30

View file

@ -1,46 +0,0 @@
# SPDX-FileCopyrightText: 2021 Alec Delaney
# SPDX-License-Identifier: MIT
"""
This example uses AnimationsSequence along with a connected push button to cycle through
two animations
For NeoPixel FeatherWing. Update pixel_pin and pixel_num to match your wiring if using
a different form of NeoPixels.
"""
import time
import board
import neopixel
from digitalio import DigitalInOut, Direction, Pull
from adafruit_led_animation.animation.solid import Solid
from adafruit_led_animation.color import BLUE, RED
from adafruit_led_animation.sequence import AnimationSequence
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D6
# Update to match the number of NeoPixels you have connected
pixel_num = 32
# Update to matchpin connected to button that connect logic high when pushed
button_pin = board.D3
pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=0.5, auto_write=False)
button = DigitalInOut(button_pin)
button.direction = Direction.INPUT
button.pull = Pull.UP
solid_blue = Solid(pixels, color=BLUE)
solid_red = Solid(pixels, color=RED)
animation_sequence = AnimationSequence(solid_blue, solid_red, auto_clear=True)
while True:
animation_sequence.animate()
# Pressing the button pauses the animation permanently
if not button.value:
animation_sequence.next()
while button.value:
time.sleep(0.1) # Used for button debouncing

View file

@ -1,39 +0,0 @@
# SPDX-FileCopyrightText: 2021 Alec Delaney
# SPDX-License-Identifier: MIT
"""
This example uses Pulse animation along with a connected push button to freeze
the animation permanently when pressed
For NeoPixel FeatherWing. Update pixel_pin and pixel_num to match your wiring if using
a different form of NeoPixels.
"""
import board
import neopixel
from digitalio import DigitalInOut, Direction, Pull
from adafruit_led_animation.animation.pulse import Pulse
from adafruit_led_animation.color import RED
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D6
# Update to match the number of NeoPixels you have connected
pixel_num = 32
# Update to matchpin connected to button that connect logic high when pushed
button_pin = board.D3
pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=0.5, auto_write=False)
button = DigitalInOut(button_pin)
button.direction = Direction.INPUT
button.pull = Pull.UP
pulse_animation = Pulse(pixels, speed=0.1, period=1, color=RED)
while True:
pulse_animation.animate()
# Pressing the button pauses the animation permanently
if not button.value:
pulse_animation.freeze()

View file

@ -10,18 +10,19 @@ pixel objects such as the built-in NeoPixels on a Circuit Playground Bluefruit a
This example is written for Circuit Playground Bluefruit and a 30-pixel NeoPixel strip connected to
pad A1. It does not work on Circuit Playground Express.
"""
import board
import neopixel
from adafruit_circuitplayground import cp
from adafruit_led_animation import color
from adafruit_led_animation.animation.blink import Blink
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.group import AnimationGroup
from adafruit_led_animation.sequence import AnimationSequence
import adafruit_led_animation.color as color
strip_pixels = neopixel.NeoPixel(board.A1, 30, brightness=0.5, auto_write=False)
cp.pixels.brightness = 0.5

View file

@ -1,65 +0,0 @@
# SPDX-FileCopyrightText: 2022 Tim Cocks
#
# SPDX-License-Identifier: MIT
"""
This example animates a red, yellow, and green gradient comet that bounces
from end to end of the strip.
For QT Py Haxpress and a NeoPixel strip. Update pixel_pin and pixel_num to match your wiring if
using a different board or form of NeoPixels.
This example will run on SAMD21 (M0) Express boards (such as Circuit Playground Express or QT Py
Haxpress), but not on SAMD21 non-Express boards (such as QT Py or Trinket).
"""
import board
import neopixel
from adafruit_led_animation.animation.multicolor_comet import MulticolorComet
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D9
# Update to match the number of NeoPixels you have connected
pixel_num = 96
brightness = 0.02
pixels = neopixel.NeoPixel(
pixel_pin,
pixel_num,
brightness=brightness,
auto_write=True,
pixel_order=neopixel.RGB,
)
comet_colors = [
0xFF0000,
0xFD2000,
0xF93E00,
0xF45B00,
0xEC7500,
0xE28D00,
0xD5A200,
0xC6B500,
0xB5C600,
0xA2D500,
0x8DE200,
0x75EC00,
0x5BF400,
0x3EF900,
0x20FD00,
0x00FF00,
]
comet = MulticolorComet(
pixels,
colors=comet_colors,
speed=0.01,
tail_length=20,
bounce=True,
ring=False,
reverse=False,
)
while True:
comet.animate()

View file

@ -1,34 +0,0 @@
# SPDX-FileCopyrightText: 2025 Jose D. Montoya
# SPDX-License-Identifier: MIT
"""
This example animates a Pacman on a NeoPixel strip.
"""
import board
import neopixel
from adafruit_led_animation.animation.pacman import Pacman
from adafruit_led_animation.color import WHITE
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D6
# Update to match the number of NeoPixels you have connected
num_pixels = 50
# Create the NeoPixel object
ORDER = neopixel.GRB
pixels = neopixel.NeoPixel(
pixel_pin,
num_pixels,
brightness=0.5,
auto_write=False,
pixel_order=ORDER,
)
# Create the Pacman animation object
pacman = Pacman(pixels, speed=0.1, color=WHITE)
# Main loop
while True:
pacman.animate()

View file

@ -11,18 +11,17 @@ will need to alter the PixelMap values as well for this example to work.
This example does not work on SAMD21 (M0) boards.
"""
import board
import neopixel
from adafruit_led_animation import helper
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.animation.rainbow import Rainbow
from adafruit_led_animation.animation.rainbowchase import RainbowChase
from adafruit_led_animation.animation.rainbowcomet import RainbowComet
from adafruit_led_animation.color import AMBER, JADE, PURPLE
from adafruit_led_animation.animation.rainbowchase import RainbowChase
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.animation.rainbow import Rainbow
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation import helper
from adafruit_led_animation.color import PURPLE, JADE, AMBER
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D6
@ -38,11 +37,17 @@ pixel_wing_horizontal = helper.PixelMap.horizontal_lines(
pixels, 8, 4, helper.horizontal_strip_gridmap(8, alternating=False)
)
comet_h = Comet(pixel_wing_horizontal, speed=0.1, color=PURPLE, tail_length=3, bounce=True)
comet_h = Comet(
pixel_wing_horizontal, speed=0.1, color=PURPLE, tail_length=3, bounce=True
)
comet_v = Comet(pixel_wing_vertical, speed=0.1, color=AMBER, tail_length=6, bounce=True)
chase_h = Chase(pixel_wing_horizontal, speed=0.1, size=3, spacing=6, color=JADE)
rainbow_chase_v = RainbowChase(pixel_wing_vertical, speed=0.1, size=3, spacing=2, step=8)
rainbow_comet_v = RainbowComet(pixel_wing_vertical, speed=0.1, tail_length=7, bounce=True)
rainbow_chase_v = RainbowChase(
pixel_wing_vertical, speed=0.1, size=3, spacing=2, step=8
)
rainbow_comet_v = RainbowComet(
pixel_wing_vertical, speed=0.1, tail_length=7, bounce=True
)
rainbow_v = Rainbow(pixel_wing_vertical, speed=0.1, period=2)
rainbow_chase_h = RainbowChase(pixel_wing_horizontal, speed=0.1, size=3, spacing=3)

View file

@ -10,7 +10,6 @@ a different form of NeoPixels.
This example does not work on SAMD21 (M0) boards.
"""
import board
import neopixel

View file

@ -1,41 +0,0 @@
# SPDX-FileCopyrightText: 2021 Alec Delaney
# SPDX-License-Identifier: MIT
"""
This example uses Pulse animation along with a connected push button to start
the animation when pressed
For NeoPixel FeatherWing. Update pixel_pin and pixel_num to match your wiring if using
a different form of NeoPixels.
"""
import board
import neopixel
from digitalio import DigitalInOut, Direction, Pull
from adafruit_led_animation.animation.pulse import Pulse
from adafruit_led_animation.color import RED
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D6
# Update to match the number of NeoPixels you have connected
pixel_num = 32
# Update to matchpin connected to button that connect logic high when pushed
button_pin = board.D3
pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=0.5, auto_write=False)
button = DigitalInOut(button_pin)
button.direction = Direction.INPUT
button.pull = Pull.UP
# Create the animation and freeze it afterwards
pulse_animation = Pulse(pixels, speed=0.1, period=1, color=RED)
pulse_animation.freeze()
while True:
pulse_animation.animate()
# Pressing the button resumes (or in this case starts) the animation permanently
if not button.value:
pulse_animation.resume()

View file

@ -16,11 +16,9 @@ using a different board or form of NeoPixels.
This example will run on SAMD21 (M0) Express boards (such as Circuit Playground Express or QT Py
Haxpress), but not on SAMD21 non-Express boards (such as QT Py or Trinket).
"""
import time
import board
import microcontroller
import board
import neopixel
from adafruit_led_animation.animation.comet import Comet
@ -39,4 +37,4 @@ while True:
comet.animate()
if time.monotonic() > 3600: # After an hour passes, reset the board.
microcontroller.reset()
microcontroller.reset() # pylint: disable=no-member

View file

@ -8,15 +8,14 @@ interval.
For NeoPixel FeatherWing. Update pixel_pin and pixel_num to match your wiring if using
a different form of NeoPixels.
"""
import board
import neopixel
from adafruit_led_animation.animation.blink import Blink
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.color import AMBER, JADE, PURPLE
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation.color import PURPLE, AMBER, JADE
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D6

View file

@ -7,10 +7,8 @@ This simpletest example displays the Blink animation.
For NeoPixel FeatherWing. Update pixel_pin and pixel_num to match your wiring if using
a different form of NeoPixels.
"""
import board
import neopixel
from adafruit_led_animation.animation.blink import Blink
from adafruit_led_animation.color import RED

View file

@ -8,14 +8,13 @@ interval.
For NeoPixel FeatherWing. Update pixel_pin and pixel_num to match your wiring if using
a different form of NeoPixels.
"""
import board
import neopixel
from adafruit_led_animation.animation.sparkle import Sparkle
from adafruit_led_animation.animation.sparklepulse import SparklePulse
from adafruit_led_animation.color import AMBER, JADE
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation.color import AMBER, JADE
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D6

View file

@ -1,50 +0,0 @@
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries, karan bhatia
# SPDX-License-Identifier: MIT
"""
This example uses AnimationsSequence to display multiple animations in sequence, at a five second
interval.
For NeoPixel FeatherWing. Update pixel_pin and pixel_num to match your wiring if using
a different form of NeoPixels.
"""
import board
import neopixel
from adafruit_led_animation.animation.sparkle import Sparkle
from adafruit_led_animation.color import AQUA, JADE, PINK
from adafruit_led_animation.sequence import AnimationSequence
# Update to match the pin connected to your NeoPixels
pixel_pin = board.A1
# Update to match the number of NeoPixels you have connected
pixel_num = 64
# fmt: off
heart_mask = [ 1, 2, 5, 6,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
33, 34, 35, 36, 37, 38,
42, 43, 44, 45,
51, 52]
unheart_mask = [0, 3, 4, 7,
32, 39,
40, 41, 46, 47,
48, 49, 50, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63]
# fmt: on
pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=0.9, auto_write=False)
animations = AnimationSequence(
Sparkle(pixels, speed=0.05, color=JADE, num_sparkles=1, mask=unheart_mask),
Sparkle(pixels, speed=0.05, color=AQUA, num_sparkles=1),
Sparkle(pixels, speed=0.05, color=PINK, num_sparkles=1, mask=heart_mask),
advance_interval=5,
auto_clear=False,
)
while True:
animations.animate()

View file

@ -1,23 +0,0 @@
# SPDX-FileCopyrightText: 2020 Gamblor21
#
# SPDX-License-Identifier: MIT
"""
Example for TimedSequence
"""
import board
import neopixel
import adafruit_led_animation.animation.blink as blink_animation
import adafruit_led_animation.animation.comet as comet_animation
import adafruit_led_animation.animation.sparkle as sparkle_animation
from adafruit_led_animation import color
from adafruit_led_animation.timedsequence import TimedAnimationSequence
strip_pixels = neopixel.NeoPixel(board.D6, 32, brightness=0.1, auto_write=False)
blink = blink_animation.Blink(strip_pixels, 0.3, color.RED)
comet = comet_animation.Comet(strip_pixels, 0.1, color.BLUE)
sparkle = sparkle_animation.Sparkle(strip_pixels, 0.05, color.GREEN)
animations = TimedAnimationSequence(blink, 2, comet, 4, sparkle, 5)
while True:
animations.animate()

View file

@ -1,36 +0,0 @@
# SPDX-FileCopyrightText: 2023 Tim Cocks
#
# SPDX-License-Identifier: MIT
"""Volume Animation Example"""
import board
import neopixel
from audiomp3 import MP3Decoder
from adafruit_led_animation.animation import volume
try:
from audioio import AudioOut
except ImportError:
try:
from audiopwmio import PWMAudioOut as AudioOut
except ImportError:
pass # not always supported by every board!
# Fill in your own MP3 file or use the one from the learn guide:
# https://learn.adafruit.com/circuitpython-essentials/circuitpython-mp3-audio#installing-project-code-3067700
mp3file = "happy.mp3"
with open(mp3file, "rb") as mp3:
decoder = MP3Decoder(mp3)
audio = AudioOut(board.SPEAKER)
strip_pixels = neopixel.NeoPixel(board.D4, 30, brightness=0.1, auto_write=False)
volume_anim = volume.Volume(strip_pixels, 0.3, (0, 255, 0), decoder, 400)
while True:
audio.play(decoder)
print("playing", mp3file)
while audio.playing:
volume_anim.animate()

View file

@ -1,3 +0,0 @@
# SPDX-FileCopyrightText: 2022 Alec Delaney, for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense

View file

@ -1,48 +0,0 @@
# SPDX-FileCopyrightText: 2022 Alec Delaney for Adafruit Industries
#
# SPDX-License-Identifier: MIT
[build-system]
requires = [
"setuptools",
"wheel",
"setuptools-scm",
]
[project]
name = "adafruit-circuitpython-led-animation"
description = "CircuitPython helper for LED colors and animations."
version = "0.0.0+auto.0"
readme = "README.rst"
authors = [
{name = "Adafruit Industries", email = "circuitpython@adafruit.com"}
]
urls = {Homepage = "https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation"}
keywords = [
"adafruit",
"blinka",
"circuitpython",
"micropython",
"led",
"animation",
"led",
"colors",
"animations",
]
license = {text = "MIT"}
classifiers = [
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries",
"Topic :: Software Development :: Embedded Systems",
"Topic :: System :: Hardware",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
]
dynamic = ["dependencies", "optional-dependencies"]
[tool.setuptools]
packages = ["adafruit_led_animation"]
[tool.setuptools.dynamic]
dependencies = {file = ["requirements.txt"]}
optional-dependencies = {optional = {file = ["optional_requirements.txt"]}}

View file

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Alec Delaney, for Adafruit Industries
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense

108
ruff.toml
View file

@ -1,108 +0,0 @@
# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries
#
# SPDX-License-Identifier: MIT
target-version = "py38"
line-length = 100
[lint]
preview = true
select = ["I", "PL", "UP"]
extend-select = [
"D419", # empty-docstring
"E501", # line-too-long
"W291", # trailing-whitespace
"PLC0414", # useless-import-alias
"PLC2401", # non-ascii-name
"PLC2801", # unnecessary-dunder-call
"PLC3002", # unnecessary-direct-lambda-call
"E999", # syntax-error
"PLE0101", # return-in-init
"F706", # return-outside-function
"F704", # yield-outside-function
"PLE0116", # continue-in-finally
"PLE0117", # nonlocal-without-binding
"PLE0241", # duplicate-bases
"PLE0302", # unexpected-special-method-signature
"PLE0604", # invalid-all-object
"PLE0605", # invalid-all-format
"PLE0643", # potential-index-error
"PLE0704", # misplaced-bare-raise
"PLE1141", # dict-iter-missing-items
"PLE1142", # await-outside-async
"PLE1205", # logging-too-many-args
"PLE1206", # logging-too-few-args
"PLE1307", # bad-string-format-type
"PLE1310", # bad-str-strip-call
"PLE1507", # invalid-envvar-value
"PLE2502", # bidirectional-unicode
"PLE2510", # invalid-character-backspace
"PLE2512", # invalid-character-sub
"PLE2513", # invalid-character-esc
"PLE2514", # invalid-character-nul
"PLE2515", # invalid-character-zero-width-space
"PLR0124", # comparison-with-itself
"PLR0202", # no-classmethod-decorator
"PLR0203", # no-staticmethod-decorator
"UP004", # useless-object-inheritance
"PLR0206", # property-with-parameters
"PLR0904", # too-many-public-methods
"PLR0911", # too-many-return-statements
"PLR0912", # too-many-branches
"PLR0913", # too-many-arguments
"PLR0914", # too-many-locals
"PLR0915", # too-many-statements
"PLR0916", # too-many-boolean-expressions
"PLR1702", # too-many-nested-blocks
"PLR1704", # redefined-argument-from-local
"PLR1711", # useless-return
"C416", # unnecessary-comprehension
"PLR1733", # unnecessary-dict-index-lookup
"PLR1736", # unnecessary-list-index-lookup
# ruff reports this rule is unstable
#"PLR6301", # no-self-use
"PLW0108", # unnecessary-lambda
"PLW0120", # useless-else-on-loop
"PLW0127", # self-assigning-variable
"PLW0129", # assert-on-string-literal
"B033", # duplicate-value
"PLW0131", # named-expr-without-context
"PLW0245", # super-without-brackets
"PLW0406", # import-self
"PLW0602", # global-variable-not-assigned
"PLW0603", # global-statement
"PLW0604", # global-at-module-level
# fails on the try: import typing used by libraries
#"F401", # unused-import
"F841", # unused-variable
"E722", # bare-except
"PLW0711", # binary-op-exception
"PLW1501", # bad-open-mode
"PLW1508", # invalid-envvar-default
"PLW1509", # subprocess-popen-preexec-fn
"PLW2101", # useless-with-lock
"PLW3301", # nested-min-max
]
ignore = [
"PLR2004", # magic-value-comparison
"UP030", # format literals
"PLW1514", # unspecified-encoding
"PLR0913", # too-many-arguments
"PLR0915", # too-many-statements
"PLR0917", # too-many-positional-arguments
"PLR0904", # too-many-public-methods
"PLR0912", # too-many-branches
"PLR0916", # too-many-boolean-expressions
"PLR6301", # could-be-static no-self-use
"PLC0415", # import outside toplevel
"PLC2701", # private import
]
[format]
line-ending = "lf"

59
setup.py Normal file
View file

@ -0,0 +1,59 @@
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""A setuptools based setup module.
See:
https://packaging.python.org/en/latest/distributing.html
https://github.com/pypa/sampleproject
"""
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path
here = path.abspath(path.dirname(__file__))
# Get the long description from the README file
with open(path.join(here, "README.rst"), encoding="utf-8") as f:
long_description = f.read()
setup(
name="adafruit-circuitpython-led-animation",
use_scm_version=True,
setup_requires=["setuptools_scm"],
description="CircuitPython helper for LED colors and animations.",
long_description=long_description,
long_description_content_type="text/x-rst",
# The project's main homepage.
url="https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation",
# Author details
author="Adafruit Industries",
author_email="circuitpython@adafruit.com",
install_requires=[
"Adafruit-Blinka",
],
# Choose your license
license="MIT",
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries",
"Topic :: System :: Hardware",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
],
# What does your project relate to?
keywords="adafruit blinka circuitpython micropython led animation led colors animations",
# You can just specify the packages manually here if your project is
# simple. Or you can use find_packages().
# TODO: IF LIBRARY FILES ARE A PACKAGE FOLDER,
# CHANGE `py_modules=['...']` TO `packages=['...']`
packages=["adafruit_led_animation", "adafruit_led_animation.animation"],
)