Cookiecutter the library and update to match NeoPixel API. (#1)
Cookiecutter the library and update to match NeoPixel API.
This commit is contained in:
parent
2619924e9a
commit
14205d83ea
11 changed files with 523 additions and 102 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
_build
|
||||
__pycache__
|
||||
74
CODE_OF_CONDUCT.md
Normal file
74
CODE_OF_CONDUCT.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at support@adafruit.com. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2016 Adafruit Industries
|
||||
Copyright (c) 2016, 2017 Adafruit Industries
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
# Adafruit_CircuitPython_DotStar
|
||||
Dotstarrin' away in CircuitPython land
|
||||
69
README.rst
Normal file
69
README.rst
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
|
||||
Adafruit CircuitPython DotStar
|
||||
==============================
|
||||
|
||||
.. image:: https://readthedocs.org/projects/adafruit-circuitpython-neopixel/badge/?version=latest
|
||||
:target: https://circuitpython.readthedocs.io/projects/neopixel/en/latest/
|
||||
:alt: Documentation Status
|
||||
|
||||
.. image :: https://badges.gitter.im/adafruit/circuitpython.svg
|
||||
:target: https://gitter.im/adafruit/circuitpython?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
|
||||
:alt: Gitter
|
||||
|
||||
.. image :: https://img.shields.io/discord/327254708534116352.svg
|
||||
:target: https://adafru.it/discord
|
||||
:alt: Discord
|
||||
|
||||
Higher level DotStar driver that presents the strip as a sequence. It is the
|
||||
same api as the `NeoPixel library <https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel>`_.
|
||||
|
||||
Colors are stored as tuples by default. However, you can also use int hex syntax
|
||||
to set values similar to colors on the web. For example, ``0x100000`` (``#100000``
|
||||
on the web) is equivalent to ``(0x10, 0, 0)``.
|
||||
|
||||
.. note:: The int hex API represents the brightness of the white pixel when
|
||||
present by setting the RGB channels to identical values. For example, full
|
||||
white is 0xffffff but is actually (0, 0, 0, 0xff) in the tuple syntax. Setting
|
||||
a pixel value with an int will use the white pixel if the RGB channels are
|
||||
identical. For full, independent, control of each color component use the
|
||||
tuple syntax.
|
||||
|
||||
Dependencies
|
||||
=============
|
||||
This driver depends on:
|
||||
|
||||
* `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_
|
||||
|
||||
Please ensure all dependencies are available on the CircuitPython filesystem.
|
||||
This is easily achieved by downloading
|
||||
`the Adafruit library and driver bundle <https://github.com/adafruit/Adafruit_CircuitPython_Bundle>`_.
|
||||
|
||||
Usage Example
|
||||
=============
|
||||
|
||||
This example demonstrates the library with the single built-in DotStar on the
|
||||
`Trinket M0 <https://www.adafruit.com/product/3500>`_ and
|
||||
`Gemma M0 <https://www.adafruit.com/product/3501>`_.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import board
|
||||
import adafruit_dotstar
|
||||
|
||||
pixels = adafruit_dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1)
|
||||
pixels[0] = (10, 0, 0)
|
||||
|
||||
Contributing
|
||||
============
|
||||
|
||||
Contributions are welcome! Please read our `Code of Conduct
|
||||
<https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel/blob/master/CODE_OF_CONDUCT.md>`_
|
||||
before contributing to help this project stay welcoming.
|
||||
|
||||
API Reference
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
api
|
||||
224
adafruit_dotstar.py
Executable file
224
adafruit_dotstar.py
Executable file
|
|
@ -0,0 +1,224 @@
|
|||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2016 Damien P. George (original Neopixel object)
|
||||
# Copyright (c) 2017 Ladyada
|
||||
# Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
"""
|
||||
`adafruit_dotstar` - DotStar strip driver
|
||||
====================================================
|
||||
|
||||
* Author(s): Damien P. George, Limor Fried & Scott Shawcroft
|
||||
"""
|
||||
import busio
|
||||
import digitalio
|
||||
import time
|
||||
|
||||
class DotStar:
|
||||
"""
|
||||
A sequence of dotstars.
|
||||
|
||||
:param ~microcontroller.Pin clock: The pin to output dotstar clock on.
|
||||
:param ~microcontroller.Pin data: The pin to output dotstar data on.
|
||||
:param int n: The number of dotstars in the chain
|
||||
:param float brightness: Brightness of the pixels between 0.0 and 1.0
|
||||
:param bool auto_write: True if the neopixels should immediately change when set. If False, `show` must be called explicitly.
|
||||
|
||||
|
||||
Example for Gemma M0:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import adafruit_dotstar
|
||||
import time
|
||||
from board import *
|
||||
|
||||
RED = 0x100000
|
||||
|
||||
with adafruit_dotstar.DotStar(APA102_SCK, APA102_MOSI, 1) as pixels:
|
||||
pixels[0] = RED
|
||||
time.sleep(2)
|
||||
"""
|
||||
|
||||
def __init__(self, clock, data, n, brightness=1.0, auto_write=True):
|
||||
self.spi = None
|
||||
try:
|
||||
self.spi = busio.SPI(clock, MOSI=data)
|
||||
while not self.spi.try_lock():
|
||||
pass
|
||||
self.spi.configure(baudrate=4000000)
|
||||
except ValueError:
|
||||
self.dpin = digitalio.DigitalInOut(data)
|
||||
self.cpin = digitalio.DigitalInOut(clock)
|
||||
self.dpin.direction = digitalio.Direction.OUTPUT
|
||||
self.cpin.direction = digitalio.Direction.OUTPUT
|
||||
self.cpin.value = False
|
||||
self.n = n
|
||||
self.start_header = 4
|
||||
# Supply one extra clock cycle for each two pixels in the strip.
|
||||
self.end_header = n // 16
|
||||
if n % 16 != 0:
|
||||
n += 1
|
||||
self.buf = bytearray(n * 4 + self.start_header + self.end_header)
|
||||
# Four empty bytes to start.
|
||||
for i in range(self.start_header):
|
||||
self.buf[i] = 0x00
|
||||
# Mark the beginnings of each pixel.
|
||||
for i in range(n):
|
||||
self.buf[self.start_header + 4 * i] = 0xff
|
||||
# 0xff bytes at the end.
|
||||
for i in range(self.end_header):
|
||||
self.buf[len(self.buf) - 1 - i] = 0xff
|
||||
self.brightness = brightness
|
||||
self.auto_write = auto_write
|
||||
|
||||
def deinit(self):
|
||||
"""Blank out the DotStars and release the resources."""
|
||||
self.auto_write = False
|
||||
for i in range(self.start_header, len(self.buf) - self.end_header):
|
||||
# Preserve the pixel markers.
|
||||
if i % 4 == 0:
|
||||
continue
|
||||
self.buf[i] = 0
|
||||
self.show()
|
||||
if self.spi:
|
||||
self.spi.deinit()
|
||||
else:
|
||||
self.dpin.deinit()
|
||||
self.cpin.deinit()
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exception_type, exception_value, traceback):
|
||||
self.deinit()
|
||||
|
||||
def __repr__(self):
|
||||
return "[" + ", ".join([str(x) for x in self]) + "]"
|
||||
|
||||
def _set_item(self, index, value):
|
||||
offset = index * 4 + self.start_header
|
||||
r = 0
|
||||
g = 0
|
||||
b = 0
|
||||
if type(value) == int:
|
||||
r = value >> 16
|
||||
g = (value >> 8) & 0xff
|
||||
b = value & 0xff
|
||||
else:
|
||||
r, g, b = value
|
||||
# Each pixel starts with 0xFF, then red/green/blue. Although the data
|
||||
# sheet suggests using a global brightness in the first byte, we don't
|
||||
# do that because it causes further issues with persistence of vision
|
||||
# projects.
|
||||
self.buf[offset] = 0xff
|
||||
self.buf[offset + 1] = b
|
||||
self.buf[offset + 2] = g
|
||||
self.buf[offset + 3] = r
|
||||
|
||||
def __setitem__(self, index, val):
|
||||
if isinstance(index, slice):
|
||||
start, stop, step = index.indices(len(self))
|
||||
length = stop - start
|
||||
if step != 0:
|
||||
length = math.ceil(length / step)
|
||||
if len(val) != length:
|
||||
raise ValueError("Slice and input sequence size do not match.")
|
||||
for val_i, in_i in enumerate(range(start, stop, step)):
|
||||
self._set_item(in_i, val[val_i])
|
||||
else:
|
||||
self._set_item(index, val)
|
||||
|
||||
if self.auto_write:
|
||||
self.show()
|
||||
|
||||
def __getitem__(self, index):
|
||||
if isinstance(index, slice):
|
||||
out = []
|
||||
for in_i in range(*index.indices(len(self.buf) // self.bpp)):
|
||||
out.append(tuple(self.buf[in_i * 4 + (3 - i) + self.start_header]
|
||||
for i in range(3)))
|
||||
return out
|
||||
if index < 0:
|
||||
index += len(self)
|
||||
if index >= self.n or index < 0:
|
||||
raise IndexError
|
||||
offset = index * 4
|
||||
return tuple(self.buf[offset + (3 - i) + self.start_header]
|
||||
for i in range(3))
|
||||
|
||||
def __len__(self):
|
||||
return self.n
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
"""Overall brightness of the pixel"""
|
||||
return self._brightness
|
||||
|
||||
@brightness.setter
|
||||
def brightness(self, brightness):
|
||||
self._brightness = min(max(brightness, 0.0), 1.0)
|
||||
|
||||
def fill(self, color):
|
||||
"""Colors all pixels the given ***color***."""
|
||||
auto_write = self.auto_write
|
||||
self.auto_write = False
|
||||
for i in range(len(self)):
|
||||
self[i] = color
|
||||
if auto_write:
|
||||
self.show()
|
||||
self.auto_write = auto_write
|
||||
|
||||
def ds_writebytes(self, buf):
|
||||
for b in buf:
|
||||
for i in range(8):
|
||||
self.cpin.value = True
|
||||
self.dpin.value = (b & 0x80)
|
||||
self.cpin.value = False
|
||||
b = b << 1
|
||||
|
||||
def show(self):
|
||||
"""Shows the new colors on the pixels themselves if they haven't already
|
||||
been autowritten.
|
||||
|
||||
The colors may or may not be showing after this function returns because
|
||||
it may be done asynchronously."""
|
||||
# Create a second output buffer if we need to compute brightness
|
||||
buf = self.buf
|
||||
if self.brightness < 0.99:
|
||||
buf = bytearray(n * bpp + 8)
|
||||
# Four empty bytes to start.
|
||||
for i in range(4):
|
||||
buf[i] = 0x00
|
||||
for i in range(4, len(self.buf) - 4):
|
||||
if i % 4 == 0:
|
||||
buf[i] = self.buf
|
||||
continue
|
||||
buf[i] = self.buf[i] * self._brightness
|
||||
# Four 0xff bytes at the end.
|
||||
for i in range(4):
|
||||
buf[len(self.buf) - 4 + i] = 0xff
|
||||
|
||||
if self.spi:
|
||||
self.spi.write(buf)
|
||||
else:
|
||||
self.ds_writebytes(buf)
|
||||
self.cpin.value = False
|
||||
5
api.rst
Normal file
5
api.rst
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
.. If you created a package, create one automodule per module in the package.
|
||||
|
||||
.. automodule:: adafruit_dotstar
|
||||
:members:
|
||||
145
conf.py
Normal file
145
conf.py
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.viewcode',
|
||||
]
|
||||
|
||||
autodoc_mock_imports = ["digitalio", "busio"]
|
||||
|
||||
intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),
|
||||
'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)}
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'README'
|
||||
|
||||
# General information about the project.
|
||||
project = u'Adafruit CircuitPython DotStar Library'
|
||||
copyright = u'2017 Scott Shawcroft, Limor Fried & Damien P. George'
|
||||
author = u'Scott Shawcroft, Limor Fried & Damien P. George'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = u'1.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = u'1.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# 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
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#
|
||||
default_role = "any"
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#
|
||||
add_function_parentheses = True
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# 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'
|
||||
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
try:
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
|
||||
except:
|
||||
html_theme = 'default'
|
||||
html_theme_path = ['.']
|
||||
else:
|
||||
html_theme_path = ['.']
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'AdafruitDotStarLibrarydoc'
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'AdafruitDotStarLibrary.tex', u'Adafruit DotStar Library Documentation',
|
||||
author, 'manual'),
|
||||
]
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'adafruitDotStarlibrary', u'Adafruit DotStar Library Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'AdafruitDotStarLibrary', u'Adafruit DotStar Library Documentation',
|
||||
author, 'AdafruitDotStarLibrary', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
99
dotstar.py
99
dotstar.py
|
|
@ -1,99 +0,0 @@
|
|||
# DotStar driver for CircuitPython
|
||||
# MIT license; Copyright (c) 2017 Ladyada & Damien George (original Neopixel object)
|
||||
|
||||
import digitalio
|
||||
import time
|
||||
|
||||
class DotStar:
|
||||
"""
|
||||
A sequence of dotstars.
|
||||
|
||||
:param ~microcontroller.Pin data: The pin to output dotstar data on.
|
||||
:param ~microcontroller.Pin clock: The pin to output dotstar clock on.
|
||||
:param int n: The number of dotstars in the chain
|
||||
:param int bpp: Bytes per pixel (usually 3 or 4)
|
||||
:param float brightness: Brightness of the pixels between 0.0 and 1.0
|
||||
|
||||
Example for Gemma M0:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import dotstar
|
||||
from board import *
|
||||
|
||||
RED = 0x100000
|
||||
|
||||
with dotstar.DotStar(APA102_MOSI, APA102_SCK, 1) as pixels:
|
||||
pixels[0] = RED
|
||||
pixels.show()
|
||||
"""
|
||||
|
||||
ORDER = (1, 0, 2, 3)
|
||||
def __init__(self, data, clock, n, bpp=3, brightness=1.0):
|
||||
self.dpin = digitalio.DigitalInOut(data)
|
||||
self.cpin = digitalio.DigitalInOut(clock)
|
||||
self.n = n
|
||||
self.bpp = bpp
|
||||
self.buf = bytearray(n * bpp)
|
||||
self.dpin.switch_to_output()
|
||||
self.cpin.switch_to_output()
|
||||
self.cpin.value = False
|
||||
self.brightness = brightness
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exception_type, exception_value, traceback):
|
||||
self.dpin.deinit()
|
||||
self.cpin.deinit()
|
||||
|
||||
def __setitem__(self, index, val):
|
||||
offset = index * self.bpp
|
||||
for i in range(self.bpp):
|
||||
self.buf[offset + self.ORDER[i]] = val[i]
|
||||
|
||||
def __getitem__(self, index):
|
||||
offset = index * self.bpp
|
||||
return tuple(self.buf[offset + self.ORDER[i]]
|
||||
for i in range(self.bpp))
|
||||
|
||||
def __len__(self):
|
||||
return self.n
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
return self._brightness
|
||||
|
||||
@brightness.setter
|
||||
def brightness(self, brightness):
|
||||
self._brightness = min(max(brightness, 0.0), 1.0)
|
||||
|
||||
def fill(self, color):
|
||||
for i in range(self.n):
|
||||
self[i] = color
|
||||
|
||||
def ds_writebytes(self, bytes):
|
||||
for b in bytes:
|
||||
for i in range(8):
|
||||
self.cpin.value = True
|
||||
self.dpin.value = (b & 0x80)
|
||||
self.cpin.value = False
|
||||
b = b << 1
|
||||
|
||||
def show(self):
|
||||
# Tell strip we're ready with many 0x00's
|
||||
self.ds_writebytes([0x00, 0x00, 0x00, 0x00])
|
||||
# Each pixel starts with 0xFF, then red/green/blue. Although the data
|
||||
# sheet suggests using a global brightness in the first byte, we don't
|
||||
# do that because it causes further issues with persistence of vision
|
||||
# projects.
|
||||
pixel = [0xFF, 0, 0, 0]
|
||||
for i in range(self.n):
|
||||
# scale each pixel by the brightness
|
||||
for x in range(3):
|
||||
pixel[x+1] = int(self.buf[i * self.bpp + x] * self._brightness)
|
||||
# write this pixel
|
||||
self.ds_writebytes(pixel)
|
||||
# Tell strip we're done with many 0xFF's
|
||||
self.ds_writebytes([0xFF, 0xFF, 0xFF, 0xFF])
|
||||
self.cpin.value = False
|
||||
2
readthedocs.yml
Normal file
2
readthedocs.yml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
requirements_file: requirements.txt
|
||||
|
||||
1
requirements.txt
Normal file
1
requirements.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
Loading…
Reference in a new issue