Compare commits

...

164 commits
REUSE ... main

Author SHA1 Message Date
Dan Halbert
8af0570596
Merge pull request #129 from hberg32/patch-1
Fix initial offset calculation when reversed in chase.py
2025-07-31 16:57:08 -04:00
hberg32
9cb567f013
Fix initial offset calculation when reversed in chase.py
Found a bug in the chase animation when reverse is set to True which results in the animation being offset by the length of the size parameter.  You can observe this by setting up two animations of equal length on a single strip of pixels with the second one reversed.  The bars should appear to meet in the middle but don't.

Example:
pixels = neopixel.NeoPixel(board.A0, 22, auto_write=False, brightness = .5)
left_pixels = PixelSubset(pixels, 0, 11)
right_pixels = PixelSubset(pixels, 11, 22)
left_animation = Chase(
    left_pixels, speed=.5, color=CYAN, size=2, spacing=11
)

right_animation = Chase(
    right_pixels, speed=.5, color=CYAN, size=2, spacing=11, reverse=True
)

animations = AnimationSequence(
    AnimationGroup(
        left_animation,
        right_animation,
        sync=True
    ),
    auto_clear=True,
    auto_reset=True,
)

while True:
    animations.animate()
2025-07-31 16:41:58 -04:00
foamyguy
5d13d0966a update rtd.yml file
Signed-off-by: foamyguy <foamyguy@gmail.com>
2025-06-17 10:31:12 -05:00
foamyguy
c76c948175
Merge pull request #127 from adafruit/use_ruff
change to ruff
2025-05-16 11:39:00 -05:00
foamyguy
d06c5ca9df change to ruff 2025-05-16 16:29:36 +00:00
foamyguy
964b8dafe2
Merge pull request #125 from jposada202020/PacMan_animation
PacMan animation
2025-04-24 15:55:54 -05:00
foamyguy
78a74180d0 lower brightness in pacman example 2025-04-24 15:50:08 -05:00
foamyguy
37800fe313
Merge pull request #124 from jposada202020/blink-with-user-color-selected-background
Blink with user color selected background
2025-04-24 15:42:44 -05:00
jposada2020
a8e057cf93 adding pacman animation 2025-02-09 22:48:07 -05:00
jposada2020
bfdbe0078c adding Pacman Animation 2025-02-09 22:47:22 -05:00
jposada2020
34bcf3c535 formating 2025-02-05 17:10:48 -05:00
jposada2020
c7dc901791 Blink animation with a user selected background color 2025-02-05 17:02:54 -05:00
foamyguy
83b87ef867 add sphinx configuration to rtd.yaml
Signed-off-by: foamyguy <foamyguy@gmail.com>
2025-01-16 09:18:08 -06:00
foamyguy
908a031aa7
Merge pull request #123 from FoamyGuy/period_property_more_animations
add period property to pulse and sparklepulse, fix typo
2024-12-30 09:28:27 -06:00
foamyguy
0b66cc1c11 add period property to pulse and sparklepulse, fix typo 2024-12-20 17:56:28 -06:00
foamyguy
0d782f83ef
Merge pull request #122 from FoamyGuy/rainbowcommet_256_length_fix
rainbow commet fix for tail_length > 256
2024-12-18 12:45:02 -06:00
foamyguy
6ef0715b77 integer division 2024-12-16 14:47:32 -06:00
foamyguy
bac273b46d rainbow commet fix for tail_length > 256 2024-12-13 11:52:07 -06:00
foamyguy
bcdedb2303
Merge pull request #121 from FoamyGuy/rainbow_period_property
public property for rainbow.period
2024-12-13 11:28:40 -06:00
foamyguy
ee5301b938 format 2024-12-13 10:56:56 -06:00
foamyguy
7dc67c5c70 add docstring 2024-12-13 10:45:59 -06:00
foamyguy
5badc804f7 public property for rainbow.period 2024-12-13 10:36:07 -06:00
foamyguy
389e40119d remove deprecated get_html_theme_path() call
Signed-off-by: foamyguy <foamyguy@gmail.com>
2024-10-07 14:48:22 -05:00
Dan Halbert
8dda51a010
Merge pull request #120 from indomitableSwan/main
Fixes #76
2024-08-21 16:52:46 -04:00
indomitableSwan
3d91a78621 Move misplaced computation of wheel_index into the case for precompute_rainbow=True 2024-08-21 15:14:52 -04:00
Dan Halbert
576a094602
Merge pull request #119 from xsorifc28/main
fix(ISSUE-118): move pulse generator from helper to own file to reduce memory footprint when imported
2024-07-06 12:02:58 -04:00
Samed Ozdemir
ef3ab8ae2d fix: move pulse generator from helper to own file to reduce memory footprint when imported 2024-07-06 11:50:39 -04:00
foamyguy
251bcd13cf
Merge pull request #116 from tylerwinfield/main
Restores min_intensity and max_intensity for Pulse animation and smoother transition option
2024-01-28 18:42:19 -06:00
Tyler Winfield
786cd806fc Resolving build CI errors 2023-12-28 09:01:11 -06:00
Dan Halbert
35d8c011b8
Merge pull request #115 from tneish/horiz_animation
ColorCycle accepts start color
2023-12-27 16:43:47 -05:00
tneish
cba51fb34b
Update adafruit_led_animation/animation/colorcycle.py
Adding the new arg to the end will make any calls upward.compatible

Co-authored-by: Dan Halbert <halbert@halwitz.org>
2023-12-27 22:40:48 +01:00
tneish
43aa654b4d cycle complete at start_color 2023-12-27 22:33:33 +01:00
Tyler Winfield
1293a471eb Corrected position calculation after introducing breath pauses 2023-12-20 11:47:39 -06:00
Tyler Winfield
72c6c68451 Variable type-o 2023-12-19 23:20:06 -06:00
Tyler Winfield
a855c3b99e Simplified comparison chain 2023-12-19 23:16:10 -06:00
Tyler Winfield
f16e519991 Corrected variable scoping 2023-12-19 23:04:12 -06:00
Tyler Winfield
fc1aefafca Adds min_intensity and max_intensity support back to Pulse animation. Introduces a 'breath' value (default 0) to give a duration to hold the minimum and maximum intensity during the animation for smoother changes in direction. 2023-12-19 22:01:30 -06:00
tneish
da467ce9b7 Fix pylint errors 2023-12-16 11:23:17 +01:00
tneish
cce709470f ColorCycle accepts start color 2023-12-16 11:15:27 +01:00
foamyguy
0f24be5dad unpin sphinx and add sphinx-rtd-theme to docs reqs
Signed-off-by: foamyguy <foamyguy@gmail.com>
2023-12-04 09:53:59 -06:00
foamyguy
5cd37ed2f5 "fix rtd theme
"
2023-09-18 16:24:07 -05:00
foamyguy
ed8e0bafe2
Merge pull request #67 from gamblor21/timed-animation
Timed animation
2023-08-06 20:04:40 -05:00
foamyguy
e23e57b421 reuse formatting. add examples for new functionality 2023-06-29 19:36:32 -05:00
foamyguy
fe11f17986 Merge branch 'main' into timed-animation 2023-06-29 18:59:01 -05:00
Tekktrik
66898580ac Update .pylintrc, fix jQuery for docs
Signed-off-by: Tekktrik <tekktrik@gmail.com>
2023-05-23 21:14:34 -04:00
Tekktrik
46f1be6bce Run pre-commit 2023-05-10 22:36:01 -04:00
Tekktrik
df79acd1a2 Update pre-commit hooks
Signed-off-by: Tekktrik <tekktrik@gmail.com>
2023-05-10 15:27:22 -04:00
Alec Delaney
7fd9f41ba1
Merge pull request #105 from FoamyGuy/multicolor_comet
adding multicolor comet animation
2023-02-27 09:56:10 -05:00
foamyguy
0629e1418e Merge branch 'main' into multicolor_comet
# Conflicts:
#	adafruit_led_animation/animation/comet.py
2023-02-24 17:26:50 -06:00
foamyguy
3aaa75efbf add star arg and docstring for name 2023-02-24 17:24:48 -06:00
jposada202020
b8538c64b7
Merge pull request #110 from tlyu/comet-doc
comet: add doc for `background_color`
2023-01-25 09:54:12 -05:00
Taylor Yu
38af7a0c39 comet: add doc for background_color
Add missing documentation for the recently-added `background_color`
parameter to `Comet`.

Signed-off-by: Taylor Yu <code@argon.blue>
2023-01-25 08:28:40 -06:00
Alec Delaney
b101ab80e8
Merge pull request #108 from tlyu/rainbowcomet-init
rainbowcomet: add missing arg initing base class
2023-01-23 19:49:06 -08:00
Scott Shawcroft
9215d0893f
Merge pull request #109 from tlyu/comet-doc
fix doc of `bounce`
2023-01-23 09:47:05 -08:00
Taylor Yu
a2c36c659a fix doc of bounce
Fix documentation of the default `bounce` value for `Comet` and
`RainbowComet`.

Signed-off-by: Taylor Yu <code@argon.blue>
2023-01-22 14:50:21 -06:00
Taylor Yu
58bc776678 rainbowcomet: add missing arg initing base class
In RainbowComet, the call to `super().__init__()` was missing the
`background_color` argument. This caused strange effects when
non-default arguments were passed.

For example, setting `reverse=True` resulted a red comet with a
tail length of 1, and setting `bounce=True` resulted in a reversed
rainbow comet.

Signed-off-by: Taylor Yu <code@argon.blue>
2023-01-22 14:38:02 -06:00
Alec Delaney
56728e3290 Add upload url to release action
Signed-off-by: Alec Delaney <89490472+tekktrik@users.noreply.github.com>
2023-01-19 23:58:31 -05:00
Mark
f2d7fd4eaa
Merge pull request #107 from priestbh/main
Update comet.py to include a background color
2023-01-05 19:29:46 -06:00
priestbh
85e4d6ee1b
Update comet.py 2022-12-30 14:52:01 -05:00
priestbh
bc0298b35a
Update comet.py to include a background color
Update comet.py to include a background color other than BLACK
2022-12-30 14:43:00 -05:00
foamyguy
9179e7c25a adding multicolor comet animation 2022-12-17 11:49:12 -06:00
Alec Delaney
5e3a68c793 Add .venv to .gitignore
Signed-off-by: Alec Delaney <89490472+tekktrik@users.noreply.github.com>
2022-11-30 19:39:23 -05:00
Alec Delaney
563f608f86
Merge pull request #103 from adafruit/optimizations
Optimizations
2022-11-12 14:50:36 -05:00
73d5f61c6e
Optimize comet draw
The big pay-off is avoiding enumerate(). Removing redundant
comparisons of _ring() and avoiding modulo operations help too.
2022-11-10 16:51:02 -06:00
914bb8060b
speed bar generation by not querying pixels
In a test this improved speed substantially, nearly doubling
the speed of the following test program
```python
pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=1, auto_write=False, pixel_order="RGB")
evens = helper.PixelMap(pixels, [(i,) for i in range(0, pixel_num, 2)], individual_pixels=True)
animation = RainbowChase(evens, 0, spacing=8)
t0 = adafruit_ticks.ticks_ms()
while True:
    for i in range(10):
        animation.animate(show=False)
    t1 = adafruit_ticks.ticks_ms()
    print(f"{10000/(t1-t0):.0f}fps")
    t0 = t1
```

Performance on Raspberry Pi Pico W:
Before: ~85fps
After: ~140fps

This also happens to make it compatible with an in-process PR that adds
a fast PixelMap-like class to the core, but which doesn't support
getitem.
2022-11-10 16:48:35 -06:00
Kattni
16179eaadf
Merge pull request #102 from tekktrik/dev/fix-pylint-errors
Fix pylint errors
2022-11-08 15:02:32 -05:00
Alec Delaney
24319aac5d
Fix pylint errors 2022-11-07 20:34:04 -05:00
Alec Delaney
eaecdc3b1d Update .pylintrc for v2.15.5 2022-11-04 18:34:33 -04:00
Alec Delaney
c19e802c65 Fix release CI files 2022-11-04 09:12:45 -04:00
Alec Delaney
caf39ebe64 Update pylint to 2.15.5 2022-11-04 08:15:21 -04:00
Alec Delaney
5f27fa68c1 Updated pylint version to 2.13.0 2022-11-04 00:47:00 -04:00
Alec Delaney
a9525ef5b1 Switching to composite actions 2022-11-04 00:02:50 -04:00
foamyguy
795be500a6
Merge pull request #101 from arturo182/patch-1
sequence: Add a function to play the previous animation
2022-10-24 11:28:54 -05:00
Alec Delaney
2e97f14805 Use year duration range for copyright attribution 2022-08-23 17:26:22 -04:00
Alec Delaney
dbd925e734 Keep copyright up to date in documentation 2022-08-22 21:36:32 -04:00
arturo182
829cd1d7af
sequence: Add a function to play the previous animation 2022-08-22 15:35:27 +02:00
Dan Halbert
364226f3c5
Merge pull request #100 from vm0824/fix-short-circuit-group-animate
broke out animate() logic to guarantee each item calls animate
2022-08-17 10:57:40 -04:00
Alec Delaney
b328c7f751 Fix version strings in workflow files 2022-08-16 21:09:15 -04:00
Alec Delaney
4326d9e9dd Update version string 2022-08-16 18:09:15 -04:00
Vin Minichino
d9b877d8ba blacked 2022-08-09 15:33:56 -04:00
Alec Delaney
9feca42f6e Add setuptools-scm to build system requirements
Signed-off-by: Alec Delaney <tekktrik@gmail.com>
2022-08-09 13:43:42 -04:00
Vin Minichino
d02dde7622 cleanup comments 2022-08-09 13:38:12 -04:00
Vin Minichino
ba57e7a6e1 broke out animate() logic to guarantee each item calls animate without short circuit 2022-08-09 13:04:58 -04:00
Alec Delaney
fc16661ac8 Switched to pyproject.toml 2022-08-08 22:05:54 -04:00
evaherrada
6a91ce7cd0
Added Black formatting badge 2022-08-02 17:00:43 -04:00
evaherrada
fc62a1ea8d
Changed .env to .venv in README.rst 2022-07-22 13:58:54 -04:00
evaherrada
80ac0d063b
Removed duplicate-code from library pylint disable
Signed-off-by: evaherrada <eva.herrada@adafruit.com>
2022-06-21 17:28:18 -04:00
evaherrada
77e6ec8ff7
Added cp.org link to index.rst 2022-06-07 15:34:31 -04:00
Alec Delaney
c2ded5bd83 Set language to "en" for documentation
Signed-off-by: Alec Delaney <tekktrik@gmail.com>
2022-05-30 17:51:10 -04:00
Alec Delaney
88475e1b53 Switch to inclusive terminology
Signed-off-by: Alec Delaney <tekktrik@gmail.com>
2022-05-25 23:13:45 -04:00
Alec Delaney
47b37c9e51 Increase min lines similarity
Signed-off-by: Alec Delaney <tekktrik@gmail.com>
2022-05-25 19:29:43 -04:00
Alec Delaney
6e2e4aad21 Patch .pre-commit-config.yaml 2022-05-15 12:48:52 -04:00
foamyguy
2455652c97 change discord badge 2022-04-24 14:04:24 -05:00
evaherrada
03f6fbe3de
Patch: Replaced discord badge image 2022-04-22 15:58:50 -04:00
Eva Herrada
44d69b19b4
Update .gitignore 2022-04-21 18:52:46 -04:00
Alec Delaney
444c0841d7 "Reformatted per new black version" 2022-03-29 18:15:55 -04:00
Kattni Rembor
a84eb12d01 Update Black to latest.
Signed-off-by: Kattni Rembor <kattni@adafruit.com>
2022-03-28 18:11:11 -04:00
dherrada
59b02752f0 Fixed readthedocs build
Signed-off-by: dherrada <dylan.herrada@adafruit.com>
2022-02-15 11:56:59 -05:00
Limor "Ladyada" Fried
5c8d64deab
Merge pull request #94 from tekktrik/doc/add-pause-example
Add push button examples for pausing, resuming, and cycling animations
2022-02-11 17:38:03 -05:00
Alec Delaney
a50aea4029 Invert button logic
Per review, not all boards have pull down capability, so swapping the logic!
2022-02-11 10:35:11 -05:00
tekktrik
c203abdd7f
Post-patch cleanup
Added link for info on building library documentation
2022-02-10 12:25:29 -05:00
Alec Delaney
0fe08ed65f Swap import order for cycle example 2022-02-01 22:00:46 -05:00
Alec Delaney
d33a887bf4 Reformatted per pre-commit 2022-02-01 21:55:58 -05:00
Alec Delaney
376c9e1f8b Add examples for freezing, resuming, and cycling animations via push button 2022-02-01 21:52:48 -05:00
dherrada
7892d09962 Updated docs link, updated python docs link, updated setup.py 2022-01-24 16:46:16 -05:00
Dan Halbert
ef90c2e634
Merge pull request #93 from adafruit/dhalbert-blink-readme
Update README to use adafruit_led_animation.animation.blink
2022-01-10 23:47:26 -05:00
Dan Halbert
6fb700333b
Update README to use adafruit_led_animation.animation.blink 2022-01-10 23:07:11 -05:00
Dan Halbert
dd7381e834
Merge pull request #90 from kattni/specify-python
Remove specific Python, use 3.x
2021-12-21 11:22:15 -05:00
Kattni Rembor
e296e6f67a Remove specific Python, use 3.x 2021-12-21 11:17:31 -05:00
foamyguy
4b2cb10efc update rtd py version 2021-11-23 13:14:31 -06:00
Kattni
6f8987bea2
Merge pull request #89 from adafruit/patch
Pylint and RTD update patch, and other fixes
2021-11-11 16:19:23 -05:00
dherrada
9fde73f3dc Pylint and RTD update patch, and other fixes 2021-11-11 15:33:12 -05:00
dherrada
e86381a82c Updated readthedocs file
Signed-off-by: dherrada <dylan.herrada@adafruit.com>
2021-11-09 15:24:47 -05:00
dherrada
72c0bfb602 Disabled unspecified-encoding pylint check
Signed-off-by: dherrada <dylan.herrada@adafruit.com>
2021-11-05 15:15:54 -04:00
Kattni
2f1107a2a3
Merge pull request #88 from kattni/add-docs-link
Add guide and products to docs.
2021-11-03 18:01:18 -04:00
Kattni Rembor
8002ef12e3 Add details. 2021-11-03 17:38:13 -04:00
Kattni Rembor
fd78e6278d Update examples. 2021-11-03 17:34:12 -04:00
Kattni Rembor
e3f77376fd Add other examples. 2021-11-03 17:27:03 -04:00
Kattni Rembor
fc28f5088f Add guide and products to docs. 2021-11-03 17:13:27 -04:00
Kattni
a3f3a63f27
Merge pull request #87 from kattni/rtd-fix
Switch to docs/requirement.txt
2021-11-03 14:08:48 -04:00
Kattni Rembor
288a644348 Switch to docs/requirement.txt 2021-11-03 14:08:02 -04:00
Kattni Rembor
2a1d74c1cd Switch to docs/requirement.txt 2021-11-03 14:04:27 -04:00
Kattni
d609c42304
Merge pull request #86 from kattni/docs-fix
Pin Sphinx.
2021-11-03 13:49:20 -04:00
Kattni Rembor
d80fd9c3d4 Pin Sphinx. 2021-11-03 13:44:39 -04:00
Kattni
cab77e287d
Merge pull request #85 from kattni/docs-fix
Fix code block, force Sphinx update on RTD.
2021-11-03 13:38:35 -04:00
Kattni Rembor
f2e57d9c71 Fix code block, force Sphinx update on RTD. 2021-11-03 13:34:01 -04:00
Kattni
8d378fa2ed
Merge pull request #84 from rhooper/sparkle-mask
Move sparkle mask example to own file to make mergeable
2021-10-31 15:55:05 -04:00
Kattni
76d419afc6
Merge pull request #78 from plugowski/master
Fixed reverse mode for Comet / RainbowComet animation.
2021-10-31 15:52:26 -04:00
Rose Hooper
e09c87772d add copyright header 2021-10-31 15:18:17 -04:00
Rose Hooper
4d6c98ff0d Merge branch 'main' into sparkle-mask 2021-10-31 15:14:06 -04:00
Rose Hooper
ed7d09695e restore original example filename 2021-10-31 15:06:43 -04:00
Rose Hooper
016b97d873 Add original example back to examples. 2021-10-31 15:06:05 -04:00
Rose Hooper
8bdb9d4a29 copy sparkle mask example to separate file 2021-10-31 15:05:42 -04:00
Rose Hooper
43b256c51f temporarily rename sparkle example 2021-10-31 15:04:00 -04:00
foamyguy
e95ce187f0 add docs link to readme 2021-10-25 11:28:45 -05:00
Kattni
24b1897b1a
Merge pull request #82 from adafruit/rainbowio
Updating to use rainbowio.
2021-09-23 17:57:05 -04:00
Kattni Rembor
1f17980222 Sphinx. 2021-09-23 17:50:42 -04:00
Kattni Rembor
30226d4983 Updating to use rainbowio. 2021-09-23 17:44:52 -04:00
dherrada
100254a4db Moved default branch to main 2021-06-07 13:37:47 -04:00
dherrada
f90bbfe0ec Moved CI to Python 3.7
Signed-off-by: dherrada <dylan.herrada@adafruit.com>
2021-05-24 11:36:57 -04:00
dherrada
268e63ec58 Added help text and problem matcher
Signed-off-by: dherrada <dylan.herrada@adafruit.com>
2021-05-19 15:17:12 -04:00
dherrada
f345c3efcf Added pull request template
Signed-off-by: dherrada <dylan.herrada@adafruit.com>
2021-05-19 14:05:26 -04:00
Paweł Ługowski
78417f1568 Merge remote-tracking branch 'origin/master' 2021-05-18 12:02:21 +07:00
Paweł Ługowski
a18eb1134c pre-commit code reformat 2021-05-18 12:01:57 +07:00
Paweł Ługowski
50f73a532f pre-commit code reformat 2021-05-18 11:51:24 +07:00
Paweł Ługowski
da7484427c Fixed reverse mode for Comet / RainbowComet animation. 2021-05-03 10:49:41 +07:00
Dylan Herrada
312c0428e0
Moved to generator 2021-04-19 17:09:50 -04:00
dherrada
d8bec1ea82 "Increase duplicate code check threshold
"
2021-03-19 13:47:14 -04:00
dherrada
05f4e497a6 Re-added pylint install to build.yml
Signed-off-by: dherrada <dylan.herrada@adafruit.com>
2021-03-02 17:39:17 -05:00
dherrada
fddf73727b Removed pylint process from github workflow
Signed-off-by: dherrada <dylan.herrada@adafruit.com>
2021-03-02 17:15:05 -05:00
Kattni
b3378d7923
Merge pull request #75 from adafruit/REUSE
Ran pre-commit, added licenses
2021-02-22 10:57:33 -05:00
dherrada
a37a86f83c Hardcoded Black and REUSE versions
Signed-off-by: dherrada <dylan.herrada@adafruit.com>
2021-02-10 16:22:47 -05:00
karan bhatia
6869e4c128 more pylint changes 2020-11-25 11:19:16 -05:00
Karan Bhatia
0fea0a48f1 added black recommended change 2020-11-25 00:29:59 -05:00
karan bhatia
b5e93fd414 updated code based on pylint and PR feedback. 2020-11-24 13:29:37 -05:00
karan bhatia
c3b868b880 fixed formating issue identified by black and pylint 2020-11-23 14:35:05 -05:00
karan bhatia
5f56db76aa fixed a few issues, added heart example for sparkle animation 2020-11-22 09:47:23 -05:00
karan bhatia
f4a25f5a4f added mask array for sparkle animation 2020-11-20 14:44:07 -05:00
gamblor21
63ab8dae84 Fixed black error 2020-09-28 19:09:44 -05:00
gamblor21
27f313650b Fixed example code 2020-09-28 17:10:29 -05:00
gamblor21
766b226153 Initial commit 2020-09-28 17:08:26 -05:00
gamblor21
eb86bf0b4e Fixed errors from pylint and black 2020-09-28 16:32:30 -05:00
gamblor21
d12b7fb50b Added license and documentation 2020-09-28 16:03:36 -05:00
gamblor21
1190ffe244 Initial commit 2020-09-28 15:58:53 -05:00
70 changed files with 1638 additions and 945 deletions

11
.gitattributes vendored Normal file
View file

@ -0,0 +1,11 @@
# 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

@ -0,0 +1,13 @@
# 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,68 +10,5 @@ jobs:
test:
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 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/*
- name: Run Build CI workflow
uses: adafruit/workflows-circuitpython-libs/build@main

19
.github/workflows/failure-help-text.yml vendored Normal file
View file

@ -0,0 +1,19 @@
# 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

View file

@ -1,85 +0,0 @@
# 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/*

19
.github/workflows/release_gh.yml vendored Normal file
View file

@ -0,0 +1,19 @@
# 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 }}

19
.github/workflows/release_pypi.yml vendored Normal file
View file

@ -0,0 +1,19 @@
# 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,9 +1,48 @@
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-FileCopyrightText: 2022 Kattni Rembor, written for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
# SPDX-License-Identifier: MIT
# 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__
_build
*.pyc
# Sphinx build-specific files
_build
# This file results from running `pip -e install .` in a local repository
*.egg-info
# Virtual environment-specific files
.env
bundles
.venv
# MacOS-specific files
*.DS_Store
# IDE-specific files
.idea
.vscode
*~

View file

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

437
.pylintrc
View file

@ -1,437 +0,0 @@
# 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

22
.readthedocs.yaml Normal file
View file

@ -0,0 +1,22 @@
# 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

View file

@ -1,7 +0,0 @@
# 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://circuitpython.readthedocs.io/projects/led-animation/en/latest/
:target: https://docs.circuitpython.org/projects/led-animation/en/latest/
:alt: Documentation Status
.. image:: https://img.shields.io/discord/327254708534116352.svg
.. image:: https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_Bundle/main/badges/adafruit_discord.svg
:target: https://adafru.it/discord
:alt: Discord
@ -13,6 +13,10 @@ 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
@ -46,8 +50,8 @@ To install in a virtual environment in your current project:
.. code-block:: shell
mkdir project-name && cd project-name
python3 -m venv .env
source .env/bin/activate
python3 -m venv .venv
source .venv/bin/activate
pip3 install adafruit-circuitpython-led-animation
Usage Example
@ -57,7 +61,7 @@ Usage Example
import board
import neopixel
from adafruit_led_animation.animation import Blink
from adafruit_led_animation.animation.blink import Blink
import adafruit_led_animation.color as color
# Works on Circuit Playground Express and Bluefruit.
@ -72,11 +76,18 @@ 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/master/CODE_OF_CONDUCT.md>`_
<https://github.com/apatt/CircuitPython_LED_Animation/blob/main/CODE_OF_CONDUCT.md>`_
before contributing to help this project stay welcoming.
Building locally
@ -90,15 +101,15 @@ To build this library locally you'll need to install the
.. code-block:: shell
python3 -m venv .env
source .env/bin/activate
python3 -m venv .venv
source .venv/bin/activate
pip install circuitpython-build-tools
Once installed, make sure you are in the virtual environment:
.. code-block:: shell
source .env/bin/activate
source .venv/bin/activate
Then run the build:
@ -114,8 +125,8 @@ install dependencies (feel free to reuse the virtual environment from above):
.. code-block:: shell
python3 -m venv .env
source .env/bin/activate
python3 -m venv .venv
source .venv/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): # pylint: disable=missing-docstring
def const(value):
return value
@ -27,7 +27,6 @@ try:
"""
return monotonic_ns() // NANOS_PER_MS
except (ImportError, NotImplementedError):
import time

View file

@ -25,20 +25,19 @@ 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
@ -61,7 +60,7 @@ class Animation:
"""Number of animation cycles completed."""
def __str__(self):
return "<%s: %s>" % (self.__class__.__name__, self.name)
return f"<{self.__class__.__name__}: {self.name}>"
def animate(self, show=True):
"""

View file

@ -37,10 +37,14 @@ 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, name=None):
super().__init__(pixel_object, speed, [color, BLACK], name=name)
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 _set_color(self, color):
self.colors = [color, BLACK]
self.colors = [color, self._background_color]

View file

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

View file

@ -38,12 +38,14 @@ 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):
def __init__(self, pixel_object, speed, colors=RAINBOW, name=None, start_color=0):
self.colors = colors
super().__init__(pixel_object, speed, colors[0], name=name)
self._generator = self._color_generator()
self.start_color = start_color
super().__init__(pixel_object, speed, colors[start_color], name=name)
self._generator = self._color_generator(start_color)
next(self._generator)
on_cycle_complete_supported = True
@ -52,17 +54,17 @@ class ColorCycle(Animation):
self.pixel_object.fill(self.color)
next(self._generator)
def _color_generator(self):
index = 0
def _color_generator(self, start_color):
index = start_color
while True:
self._color = self.colors[index]
yield
index = (index + 1) % len(self.colors)
if index == 0:
if index == start_color:
self.cycle_complete = True
def reset(self):
"""
Resets to the first color.
"""
self._generator = self._color_generator()
self._generator = self._color_generator(self.start_color)

View file

@ -37,20 +37,24 @@ 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 ``True``.
: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 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,
@ -61,13 +65,14 @@ 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
@ -82,44 +87,79 @@ class Comet(Animation):
on_cycle_complete_supported = True
def _set_color(self, color):
self._comet_colors = [BLACK]
self._comet_colors = [self._background_color]
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
self.pixel_object[draw_at] = color
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._tail_start += self._direction
if self._tail_start < self._left_side or self._tail_start >= self._right_side:
if self._tail_start < self._left_side or (
self._tail_start >= self._right_side and not self._reverse
):
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()
if self.reverse == self._initial_reverse and self.draw_count > 0:
self.cycle_complete = True
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,7 +43,6 @@ class CustomColorChase(Chase):
:param reverse: Reverse direction of movement.
"""
# pylint: disable=too-many-arguments
def __init__(
self,
pixel_object,

View file

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

View file

@ -0,0 +1,114 @@
# 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

@ -0,0 +1,126 @@
# 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,12 +37,27 @@ 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.
"""
# pylint: disable=too-many-arguments
def __init__(self, pixel_object, speed, color, period=5, name=None):
def __init__(
self,
pixel_object,
speed,
color,
period=5,
breath=0,
min_intensity=0,
max_intensity=1,
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()
@ -56,11 +71,21 @@ 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.helper import ( # pylint: disable=import-outside-toplevel
dotstar = len(self.pixel_object[0]) == 4 and isinstance(self.pixel_object[0][-1], float)
from adafruit_led_animation.pulse_generator import (
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,10 +46,7 @@ class Rainbow(Animation):
(default True).
"""
# pylint: disable=too-many-arguments
def __init__(
self, pixel_object, speed, period=5, step=1, name=None, precompute_rainbow=True
):
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
@ -85,9 +82,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)
@ -107,13 +104,9 @@ 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)
@ -123,3 +116,15 @@ 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.color import colorwheel
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.color import colorwheel
class RainbowChase(Chase):
@ -40,10 +40,9 @@ 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 colorwheel, BLACK, calculate_intensity
from adafruit_led_animation.color import BLACK, calculate_intensity, colorwheel
class RainbowComet(Comet):
@ -40,13 +40,12 @@ 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 ``True``.
:param bool bounce: Comet will bounce back and forth. Defaults to ``False``.
: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,
@ -60,13 +59,11 @@ class RainbowComet(Comet):
ring=False,
):
if step == 0:
self._colorwheel_step = int(256 / tail_length)
self._colorwheel_step = max(256 // tail_length, 1)
else:
self._colorwheel_step = step
self._colorwheel_offset = colorwheel_offset
super().__init__(
pixel_object, speed, 0, tail_length, reverse, bounce, name, ring
)
super().__init__(pixel_object, speed, 0, 0, tail_length, reverse, bounce, name, ring)
def _set_color(self, color):
self._comet_colors = [BLACK]
@ -75,8 +72,7 @@ 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,6 +26,7 @@ Implementation Notes
"""
import random
from adafruit_led_animation.animation.rainbow import Rainbow
@ -45,7 +46,6 @@ class RainbowSparkle(Rainbow):
(default True).
"""
# pylint: disable=too-many-arguments
def __init__(
self,
pixel_object,
@ -91,10 +91,7 @@ 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,9 +26,10 @@ 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"
@ -40,12 +41,18 @@ 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
"""
# pylint: disable=too-many-arguments
def __init__(self, pixel_object, speed, color, num_sparkles=1, name=None):
def __init__(self, pixel_object, speed, color, num_sparkles=1, name=None, mask=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
@ -66,11 +73,13 @@ 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 = [
random.randint(0, (len(self.pixel_object) - 1))
for _ in range(self._num_sparkles)
]
self._pixels = [self._random_in_mask() for _ in range(self._num_sparkles)]
for pixel in self._pixels:
self.pixel_object[pixel] = self._sparkle_color
@ -78,4 +87,5 @@ class Sparkle(Animation):
self.show()
for pixel in self._pixels:
self.pixel_object[pixel % self._num_pixels] = self._half_color
self.pixel_object[(pixel + 1) % self._num_pixels] = self._dim_color
if (pixel + 1) % self._num_pixels in self._mask:
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.helper import pulse_generator
from adafruit_led_animation.pulse_generator 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,3 +71,19 @@ 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

@ -0,0 +1,111 @@
# 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,6 +23,10 @@ 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)
@ -70,29 +74,6 @@ 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,7 +154,6 @@ 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::
.. code-block:: python
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 "<AnimationGroup %s: %s>" % (self.__class__.__name__, self.name)
return f"<AnimationGroup {self.__class__.__name__}: {self.name}>"
def _group_done(self, animation): # pylint: disable=unused-argument
def _group_done(self, animation):
self.on_cycle_complete()
def on_cycle_complete(self):
@ -152,7 +152,11 @@ class AnimationGroup:
member.show()
return result
return any([item.animate(show) for item in self._members])
ret = False
for item in self._members:
if item.animate(show):
ret = True
return ret
@property
def color(self):

View file

@ -27,9 +27,6 @@ Implementation Notes
import math
from . import MS_PER_SECOND, monotonic_ms
from .color import calculate_intensity
class PixelMap:
"""
@ -168,7 +165,6 @@ 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):
@ -313,39 +309,3 @@ 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

@ -0,0 +1,74 @@
# 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,10 +27,12 @@ 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"
@ -73,7 +75,6 @@ class AnimationSequence:
animations.animate()
"""
# pylint: disable=too-many-instance-attributes
def __init__(
self,
*members,
@ -82,16 +83,12 @@ 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
@ -115,7 +112,7 @@ class AnimationSequence:
on_cycle_complete_supported = True
def __str__(self):
return "<%s: %s>" % (self.__class__.__name__, self.name)
return f"<{self.__class__.__name__}: {self.name}>"
def on_cycle_complete(self):
"""
@ -128,7 +125,7 @@ class AnimationSequence:
for callback in self._also_notify:
callback(self)
def _sequence_complete(self, animation): # pylint: disable=unused-argument
def _sequence_complete(self, animation):
if self.advance_on_cycle_complete:
self._advance()
@ -179,6 +176,13 @@ 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

@ -0,0 +1,82 @@
# 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,6 +4,9 @@
.. 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,9 +1,8 @@
# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import datetime
import os
import sys
@ -16,6 +15,7 @@ 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 = []
autodoc_mock_imports = ["rainbowio"]
intersphinx_mapping = {
"python": ("https://docs.python.org/3.4", None),
"CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None),
"python": ("https://docs.python.org/3", None),
"CircuitPython": ("https://docs.circuitpython.org/en/latest/", None),
}
# Add any paths that contain templates here, relative to this directory.
@ -43,7 +43,12 @@ master_doc = "index"
# General information about the project.
project = "LED_Animation Library"
copyright = "2020 Kattni Rembor"
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"
author = "Kattni Rembor"
# The version info for the project you're documenting, acts as replacement for
@ -60,7 +65,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 = None
language = "en"
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
@ -92,19 +97,9 @@ napoleon_numpy_docstring = False
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
import 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 = ["."]
html_theme = "sphinx_rtd_theme"
# 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,3 +6,110 @@ 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,11 +20,25 @@ 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 <https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation/releases/latest>
CircuitPython Reference Documentation <https://circuitpython.readthedocs.io>
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>
CircuitPython Support Forum <https://forums.adafruit.com/viewforum.php?f=60>
Discord Chat <https://adafru.it/discord>
Adafruit Learning System <https://learn.adafruit.com>

7
docs/requirements.txt Normal file
View file

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

View file

@ -9,24 +9,25 @@ 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.sparklepulse import SparklePulse
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.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.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,26 +9,27 @@ a different form of NeoPixels.
This example may not work on SAMD21 (M0) boards.
"""
import board
import neopixel
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.colorcycle import ColorCycle
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.animation.pulse import Pulse
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation.animation.solid import Solid
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,6 +10,7 @@ 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

@ -0,0 +1,30 @@
# 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,6 +11,7 @@ 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,6 +10,7 @@ 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,17 +9,16 @@ 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 PINK, GREEN, RED, BLUE
from adafruit_led_animation.color import BLUE, GREEN, PINK, RED, colorwheel
from adafruit_led_animation.sequence import AnimationSequence
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D5
@ -27,15 +26,11 @@ 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

@ -0,0 +1,46 @@
# 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

@ -0,0 +1,39 @@
# 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,19 +10,18 @@ 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.comet import Comet
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.animation.comet import Comet
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

@ -0,0 +1,65 @@
# 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

@ -0,0 +1,34 @@
# 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,17 +11,18 @@ 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.animation.comet import Comet
from adafruit_led_animation.animation.rainbowcomet import RainbowComet
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
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.sequence import AnimationSequence
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D6
@ -37,17 +38,11 @@ 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,6 +10,7 @@ a different form of NeoPixels.
This example does not work on SAMD21 (M0) boards.
"""
import board
import neopixel

View file

@ -0,0 +1,41 @@
# 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,9 +16,11 @@ 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 microcontroller
import board
import microcontroller
import neopixel
from adafruit_led_animation.animation.comet import Comet
@ -37,4 +39,4 @@ while True:
comet.animate()
if time.monotonic() > 3600: # After an hour passes, reset the board.
microcontroller.reset() # pylint: disable=no-member
microcontroller.reset()

View file

@ -8,14 +8,15 @@ 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.comet import Comet
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.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,8 +7,10 @@ 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,13 +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.sparkle import Sparkle
from adafruit_led_animation.animation.sparklepulse import SparklePulse
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation.color import AMBER, JADE
from adafruit_led_animation.sequence import AnimationSequence
# Update to match the pin connected to your NeoPixels
pixel_pin = board.D6

View file

@ -0,0 +1,50 @@
# 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

@ -0,0 +1,23 @@
# 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

@ -0,0 +1,36 @@
# 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

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

48
pyproject.toml Normal file
View file

@ -0,0 +1,48 @@
# 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: 2021 ladyada for Adafruit Industries
# SPDX-FileCopyrightText: 2022 Alec Delaney, for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense

108
ruff.toml Normal file
View file

@ -0,0 +1,108 @@
# 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"

View file

@ -1,59 +0,0 @@
# 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"],
)