Compare commits

..

No commits in common. "master" and "pi_bitbang_exception" have entirely different histories.

15 changed files with 342 additions and 518 deletions

View file

@ -1,57 +0,0 @@
name: Build CI
on: [pull_request, push]
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, black, & Sphinx
run: |
pip install pylint black==19.10b0 Sphinx sphinx-rtd-theme
- name: Library version
run: git describe --dirty --always --tags
- name: Check formatting
run: |
black --check --target-version=py35 .
- 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: Build docs
working-directory: docs
run: sphinx-build -E -W -b html . _build/html

View file

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

1
.gitignore vendored
View file

@ -4,6 +4,7 @@ __pycache__
_build
*.pyc
.env
build*
bundles
*.DS_Store
.eggs

View file

@ -18,7 +18,6 @@ ignore-patterns=
#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,
@ -51,8 +50,7 @@ confidence=
# --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
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
# 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
@ -119,8 +117,7 @@ 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
notes=FIXME,XXX,TODO
[TYPECHECK]
@ -203,7 +200,6 @@ 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.
@ -276,11 +272,9 @@ class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
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
@ -300,8 +294,7 @@ function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
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,_
good-names=r,g,b,i,j,k,n,ex,Run,_
# Include a hint for the correct naming format with invalid-name
include-naming-hint=no
@ -398,7 +391,6 @@ valid-metaclass-classmethod-first-arg=mcs
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
@ -423,7 +415,7 @@ max-returns=6
max-statements=50
# Minimum number of public methods for a class (see R0903).
min-public-methods=1
min-public-methods=2
[EXCEPTIONS]

32
.travis.yml Normal file
View file

@ -0,0 +1,32 @@
dist: trusty
sudo: false
language: python
python:
- '3.6'
cache:
pip: true
deploy:
- provider: releases
api_key: "$GITHUB_TOKEN"
file_glob: true
file: "$TRAVIS_BUILD_DIR/bundles/*"
skip_cleanup: true
overwrite: true
on:
tags: true
- provider: pypi
user: adafruit-travis
on:
tags: true
password:
secure: uLzy5y4iRH61pHF6yRKKii+JmWHLu8VDrSHsrHz3ofRTCr6EPEnvj+8kpo7QHTDAsc4ylg0S7PB2nmIS5LJ9tTJw2w8bAK+7BV2sdcabuZbzKh+CNb2SwFBX6LxzwxLBNyfVPOh5Zd+Tk04EePUGC/aIuSQ0UiEDbuUEA5FGHtj3czjMOZs1VkGt3dTZjlnkDimJtUDDvaYzGQp4cy2+hc/m4J2a7KgNkSbKJ4PCfiU2K6tnGPbz1q28oYYHfdWHcEP1Dy9JrA3dtXiudmDAVb4S2viTQdaUddZ1sOkRdri2Q93vVOVMdG0x1sCmn5IYDTw6FIInyL+2Rt9TjqgdH4WT94gYJof79nTBTDcGvYhxOybC0+16uZcfCjx5HKLTry38Du81vUEEBGXl8M+rH3p5wZpUr21q933jR18yNlkai9IGtQIR0xgUl2wi+dzxD/XHNCM7DdRB/oCo7pUurw/s5XVi4lhnoByK39H9aA/cZmlwCaUdYc04ADK9WSaHVUDr6/A6Gjp3LykVBVUzrdpyozKFXDdvW2Q8KaA3XyTcfKO92e0EihAr6dJdcYp1STUck4wNQLBefqAVVEUUeTruFTyVoIu5P0b1qMtK69dxAzVJpJ64l8hETZ8kLH3YkG1ergg5pYHPs8KNxhIcG8DfFNyccpjuP1uMwm4F6EY=
install:
- pip install -r requirements.txt
- pip install pylint circuitpython-build-tools Sphinx sphinx-rtd-theme
- pip install --force-reinstall pylint==1.9.2
script:
- pylint adafruit_dotstar.py
- ([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name examples/*.py)
- circuitpython-build-bundles --filename_prefix adafruit-circuitpython-dotstar --library_location
.
- cd docs && sphinx-build -E -W -b html . _build/html && cd ..

View file

@ -34,15 +34,13 @@ Examples of unacceptable behavior by participants include:
* Excessive or unwelcome helping; answering outside the scope of the question
asked
* Trolling, insulting/derogatory comments, and personal or political attacks
* Promoting or spreading disinformation, lies, or conspiracy theories against
a person, group, organisation, project, or community
* 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
The goal of the standards and moderation guidelines outlined here is to build
and maintain a respectful community. We ask that you dont just aim to be
and maintain a respectful community. We ask that you dont just aim to be
"technically unimpeachable", but rather try to be your best self.
We value many things beyond technical expertise, including collaboration and
@ -74,10 +72,10 @@ You may report in the following ways:
In any situation, you may send an email to <support@adafruit.com>.
On the Adafruit Discord, you may send an open message from any channel
to all Community Moderators by tagging @community moderators. You may
also send an open message from any channel, or a direct message to
@kattni#1507, @tannewt#4653, @Dan Halbert#1614, @cater#2442,
@sommersoft#0222, @Mr. Certainly#0472 or @Andon#8175.
to all Community Helpers by tagging @community helpers. You may also send an
open message from any channel, or a direct message to @kattni#1507,
@tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or
@Andon#8175.
Email and direct message reports will be kept confidential.
@ -85,7 +83,7 @@ In situations on Discord where the issue is particularly egregious, possibly
illegal, requires immediate action, or violates the Discord terms of service,
you should also report the message directly to Discord.
These are the steps for upholding our communitys standards of conduct.
These are the steps for upholding our communitys standards of conduct.
1. Any member of the community may report any situation that violates the
Adafruit Community Code of Conduct. All reports will be reviewed and
@ -126,4 +124,4 @@ For other projects adopting the Adafruit Community Code of
Conduct, please contact the maintainers of those projects for enforcement.
If you wish to use this code of conduct for your own project, consider
explicitly mentioning your moderation policy or making a copy with your
own moderation policy so as to avoid confusion.
own moderation policy so as to avoid confusion.

View file

@ -10,8 +10,8 @@ Adafruit CircuitPython DotStar
:target: https://adafru.it/discord
:alt: Discord
.. image:: https://github.com/adafruit/Adafruit_CircuitPython_DotStar/workflows/Build%20CI/badge.svg
:target: https://github.com/adafruit/Adafruit_CircuitPython_DotStar/actions/
.. image:: https://travis-ci.org/adafruit/Adafruit_CircuitPython_DotStar.svg?branch=master
:target: https://travis-ci.org/adafruit/Adafruit_CircuitPython_DotStar
:alt: Build Status
Higher level DotStar driver that presents the strip as a sequence. It is the
@ -26,7 +26,7 @@ It should be a float. For example, (0xFF,0,0, 1.0) is the brightest red possible
.. 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 (0xff, 0xff, 0xff) in the tuple syntax.
white is 0xffffff but is actually (0xff, 0xff, 0xff) in the tuple syntax.
Dependencies
=============
@ -38,31 +38,6 @@ 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>`_.
Installing from PyPI
====================
On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
PyPI <https://pypi.org/project/adafruit-circuitpython-dotstar/>`_. To install for current user:
.. code-block:: shell
pip3 install adafruit-circuitpython-dotstar
To install system-wide (this may be required in some cases):
.. code-block:: shell
sudo pip3 install adafruit-circuitpython-dotstar
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
pip3 install adafruit-circuitpython-dotstar
Usage Example
=============
@ -85,7 +60,49 @@ 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.
Documentation
=============
Building locally
================
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>`_.
To build this library locally you'll need to install the
`circuitpython-build-tools <https://github.com/adafruit/circuitpython-build-tools>`_ package.
.. code-block:: shell
python3 -m venv .env
source .env/bin/activate
pip install circuitpython-build-tools
Once installed, make sure you are in the virtual environment:
.. code-block:: shell
source .env/bin/activate
Then run the build:
.. code-block:: shell
circuitpython-build-bundles --filename_prefix adafruit-circuitpython-dotstar --library_location .
Sphinx documentation
-----------------------
Sphinx is used to build the documentation based on rST files and comments in the code. First,
install dependencies (feel free to reuse the virtual environment from above):
.. code-block:: shell
python3 -m venv .env
source .env/bin/activate
pip install Sphinx sphinx-rtd-theme
Now, once you have the virtual environment activated:
.. code-block:: shell
cd docs
sphinx-build -E -W -b html . _build/html
This will output the documentation to ``docs/_build/html``. Open the index.html in your browser to
view them. It will also (due to -W) error out on any warning like Travis will. This is a good way to
locally verify it will pass.

View file

@ -3,7 +3,6 @@
# Copyright (c) 2016 Damien P. George (original Neopixel object)
# Copyright (c) 2017 Ladyada
# Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
# Copyright (c) 2019 Roy Hooper
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@ -24,46 +23,30 @@
# THE SOFTWARE.
"""
`adafruit_dotstar` - DotStar strip driver (for CircuitPython 5.0+ with _pixelbuf)
=================================================================================
`adafruit_dotstar` - DotStar strip driver
====================================================
* Author(s): Damien P. George, Limor Fried, Scott Shawcroft & Roy Hooper
* Author(s): Damien P. George, Limor Fried & Scott Shawcroft
"""
# pylint: disable=ungrouped-imports
import sys
import busio
import digitalio
if sys.implementation.version[0] < 5:
import adafruit_pypixelbuf as _pixelbuf
else:
try:
import _pixelbuf
except ImportError:
import adafruit_pypixelbuf as _pixelbuf
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DotStar.git"
START_HEADER_SIZE = 4
LED_START = 0b11100000 # Three "1" bits, followed by 5 brightness bits
# Pixel color order constants
RBG = "PRBG"
"""Red Blue Green"""
RGB = "PRGB"
"""Red Green Blue"""
GRB = "PGRB"
"""Green Red Blue"""
GBR = "PGBR"
"""Green Blue Red"""
BRG = "PBRG"
"""Blue Red Green"""
BGR = "PBGR"
"""Blue Green Red"""
RGB = (0, 1, 2)
RBG = (0, 2, 1)
GRB = (1, 0, 2)
GBR = (1, 2, 0)
BRG = (2, 0, 1)
BGR = (2, 1, 0)
class DotStar(_pixelbuf.PixelBuf):
class DotStar:
"""
A sequence of dotstars.
@ -73,13 +56,10 @@ class DotStar(_pixelbuf.PixelBuf):
:param float brightness: Brightness of the pixels between 0.0 and 1.0
:param bool auto_write: True if the dotstars should immediately change when
set. If False, `show` must be called explicitly.
:param str pixel_order: Set the pixel order on the strip - different
:param tuple pixel_order: Set the pixel order on the strip - different
strips implement this differently. If you send red, and it looks blue
or green on the strip, modify this! It should be one of the values above.
:param int baudrate: Desired clock rate if using hardware SPI (ignored if
using 'soft' SPI). This is only a recommendation; the actual clock
rate may be slightly different depending on what the system hardware
can provide.
or green on the strip, modify this! It should be one of the values above
Example for Gemma M0:
@ -94,41 +74,15 @@ class DotStar(_pixelbuf.PixelBuf):
with adafruit_dotstar.DotStar(APA102_SCK, APA102_MOSI, 1) as pixels:
pixels[0] = RED
time.sleep(2)
.. py:method:: DotStar.show()
Shows the new colors on the dotstars 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.
.. py:method:: DotStar.fill(color)
Colors all dotstars the given ***color***.
.. py:attribute:: brightness
Overall brightness of all dotstars (0 to 1.0)
"""
def __init__(
self,
clock,
data,
n,
*,
brightness=1.0,
auto_write=True,
pixel_order=BGR,
baudrate=4000000
):
def __init__(self, clock, data, n, *, brightness=1.0, auto_write=True, pixel_order=BGR):
self._spi = None
try:
self._spi = busio.SPI(clock, MOSI=data)
while not self._spi.try_lock():
pass
self._spi.configure(baudrate=baudrate)
self._spi.configure(baudrate=4000000)
except (NotImplementedError, ValueError):
self.dpin = digitalio.DigitalInOut(data)
@ -136,29 +90,36 @@ class DotStar(_pixelbuf.PixelBuf):
self.dpin.direction = digitalio.Direction.OUTPUT
self.cpin.direction = digitalio.Direction.OUTPUT
self.cpin.value = False
self._n = n
# Supply one extra clock cycle for each two pixels in the strip.
trailer_size = n // 16
self.end_header_size = n // 16
if n % 16 != 0:
trailer_size += 1
# Four empty bytes for the header.
header = bytearray(START_HEADER_SIZE)
# 0xff bytes for the trailer.
trailer = bytearray(b"\xff") * trailer_size
super().__init__(
n,
byteorder=pixel_order,
brightness=brightness,
auto_write=auto_write,
header=header,
trailer=trailer,
)
self.end_header_size += 1
self._buf = bytearray(n * 4 + START_HEADER_SIZE + self.end_header_size)
self.end_header_index = len(self._buf) - self.end_header_size
self.pixel_order = pixel_order
# Four empty bytes to start.
for i in range(START_HEADER_SIZE):
self._buf[i] = 0x00
# Mark the beginnings of each pixel.
for i in range(START_HEADER_SIZE, self.end_header_index, 4):
self._buf[i] = 0xff
# 0xff bytes at the end.
for i in range(self.end_header_index, len(self._buf)):
self._buf[i] = 0xff
self._brightness = 1.0
# Set auto_write to False temporarily so brightness setter does _not_
# call show() while in __init__.
self.auto_write = False
self.brightness = brightness
self.auto_write = auto_write
def deinit(self):
"""Blank out the DotStars and release the resources."""
self.fill(0)
self.auto_write = False
for i in range(START_HEADER_SIZE, self.end_header_index):
if i % 4 != 0:
self._buf[i] = 0
self.show()
if self._spi:
self._spi.deinit()
@ -175,24 +136,131 @@ class DotStar(_pixelbuf.PixelBuf):
def __repr__(self):
return "[" + ", ".join([str(x) for x in self]) + "]"
@property
def n(self):
def _set_item(self, index, value):
"""
The number of dotstars in the chain (read-only)
"""
return len(self)
value can be one of three things:
a (r,g,b) list/tuple
a (r,g,b, brightness) list/tuple
a single, longer int that contains RGB values, like 0xFFFFFF
brightness, if specified should be a float 0-1
def _transmit(self, buffer):
if self._spi:
self._spi.write(buffer)
Set a pixel value. You can set per-pixel brightness here, if it's not passed it
will use the max value for pixel brightness value, which is a good default.
Important notes about the per-pixel brightness - it's accomplished by
PWMing the entire output of the LED, and that PWM is at a much
slower clock than the rest of the LEDs. This can cause problems in
Persistence of Vision Applications
"""
offset = index * 4 + START_HEADER_SIZE
rgb = value
if isinstance(value, int):
rgb = (value >> 16, (value >> 8) & 0xff, value & 0xff)
if len(rgb) == 4:
brightness = value[3]
# Ignore value[3] below.
else:
self._ds_writebytes(buffer)
brightness = 1
def _ds_writebytes(self, buffer):
for b in buffer:
# LED startframe is three "1" bits, followed by 5 brightness bits
# then 8 bits for each of R, G, and B. The order of those 3 are configurable and
# vary based on hardware
# same as math.ceil(brightness * 31) & 0b00011111
# Idea from https://www.codeproject.com/Tips/700780/Fast-floor-ceiling-functions
brightness_byte = 32 - int(32 - brightness * 31) & 0b00011111
self._buf[offset] = brightness_byte | LED_START
self._buf[offset + 1] = rgb[self.pixel_order[0]]
self._buf[offset + 2] = rgb[self.pixel_order[1]]
self._buf[offset + 3] = rgb[self.pixel_order[2]]
def __setitem__(self, index, val):
if isinstance(index, slice):
start, stop, step = index.indices(self._n)
length = stop - start
if step != 0:
# same as math.ceil(length / step)
# Idea from https://fizzbuzzer.com/implement-a-ceil-function/
length = (length + step - 1) // 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(self._n)):
out.append(
tuple(self._buf[in_i * 4 + (3 - i) + START_HEADER_SIZE] 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) + START_HEADER_SIZE]
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)
if self.auto_write:
self.show()
def fill(self, color):
"""Colors all pixels the given ***color***."""
auto_write = self.auto_write
self.auto_write = False
for i in range(self._n):
self[i] = color
if auto_write:
self.show()
self.auto_write = auto_write
def _ds_writebytes(self, buf):
for b in buf:
for _ in range(8):
self.dpin.value = b & 0x80
self.cpin.value = True
self.dpin.value = (b & 0x80)
self.cpin.value = False
b = b << 1
self.cpin.value = False
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 < 1.0:
buf = bytearray(self._buf)
# Four empty bytes to start.
for i in range(START_HEADER_SIZE):
buf[i] = 0x00
for i in range(START_HEADER_SIZE, self.end_header_index):
buf[i] = self._buf[i] if i % 4 == 0 else int(self._buf[i] * self._brightness)
# Four 0xff bytes at the end.
for i in range(self.end_header_index, len(buf)):
buf[i] = 0xff
if self._spi:
self._spi.write(buf)
else:
self._ds_writebytes(buf)
self.cpin.value = False

View file

@ -2,8 +2,7 @@
import os
import sys
sys.path.insert(0, os.path.abspath(".."))
sys.path.insert(0, os.path.abspath('..'))
# -- General configuration ------------------------------------------------
@ -11,39 +10,37 @@ sys.path.insert(0, os.path.abspath(".."))
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.viewcode",
'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),
}
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"]
templates_path = ['_templates']
source_suffix = ".rst"
source_suffix = '.rst'
# The master toctree document.
master_doc = "index"
master_doc = 'index'
# General information about the project.
project = "Adafruit CircuitPython DotStar Library"
copyright = "2017 Scott Shawcroft, Limor Fried & Damien P. George"
author = "Scott Shawcroft, Limor Fried & Damien P. George"
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 = "1.0"
version = u'1.0'
# The full version, including alpha/beta/rc tags.
release = "1.0"
release = u'1.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@ -55,7 +52,7 @@ 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", ".env", "CODE_OF_CONDUCT.md"]
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.env', 'CODE_OF_CONDUCT.md']
# The reST default role (used for this markup: `text`) to use for all
# documents.
@ -67,7 +64,7 @@ default_role = "any"
add_function_parentheses = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"
pygments_style = 'sphinx'
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
@ -81,62 +78,59 @@ todo_emit_warnings = True
# 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"
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(), "."]
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
except:
html_theme = "default"
html_theme_path = ["."]
html_theme = 'default'
html_theme_path = ['.']
else:
html_theme_path = ["."]
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"]
html_static_path = ['_static']
# The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#
html_favicon = "_static/favicon.ico"
html_favicon = '_static/favicon.ico'
# Output file base name for HTML help builder.
htmlhelp_basename = "AdafruitDotStarLibrarydoc"
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',
# 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",
"Adafruit DotStar Library Documentation",
author,
"manual",
),
(master_doc, 'AdafruitDotStarLibrary.tex', u'Adafruit DotStar Library Documentation',
author, 'manual'),
]
# -- Options for manual page output ---------------------------------------
@ -144,13 +138,8 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(
master_doc,
"adafruitDotStarlibrary",
"Adafruit DotStar Library Documentation",
[author],
1,
)
(master_doc, 'adafruitDotStarlibrary', u'Adafruit DotStar Library Documentation',
[author], 1)
]
# -- Options for Texinfo output -------------------------------------------
@ -159,13 +148,7 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(
master_doc,
"AdafruitDotStarLibrary",
"Adafruit DotStar Library Documentation",
author,
"AdafruitDotStarLibrary",
"One line description of project.",
"Miscellaneous",
),
(master_doc, 'AdafruitDotStarLibrary', u'Adafruit DotStar Library Documentation',
author, 'AdafruitDotStarLibrary', 'One line description of project.',
'Miscellaneous'),
]

View file

@ -1,61 +0,0 @@
#!/usr/bin/python3
# Light-painting example for Adafruit DotStar RGB LED strip.
# Loads image, displays column-at-a-time on LEDs at a reasonable
# speed for long exposure photography.
# See dotstar_simpletest.py for a much simpler example script.
# See dotstar_image_pov.py for a faster persistence-of-vision example.
import time
import board
from PIL import Image
import adafruit_dotstar as dotstar
NUMPIXELS = 30 # Number of LEDs in strip
FILENAME = "hello.png" # Image file to load
# First two arguments in strip declaration identify the clock and data pins
# (here we're using the hardware SPI pins). Last argument identifies the
# color order -- older DotStar strips use GBR instead of BRG.
DOTS = dotstar.DotStar(
board.SCK,
board.MOSI,
NUMPIXELS,
brightness=0.25,
auto_write=False,
pixel_order=dotstar.BGR,
)
# Load image in RGB format and get dimensions:
print("Loading...")
IMG = Image.open(FILENAME).convert("RGB")
PIXELS = IMG.load()
WIDTH = IMG.size[0]
HEIGHT = IMG.size[1]
print("%dx%d pixels" % IMG.size)
if HEIGHT > NUMPIXELS:
HEIGHT = NUMPIXELS
# Calculate gamma correction table, makes mid-range colors look 'right':
GAMMA = bytearray(256)
for i in range(256):
GAMMA[i] = int(pow(float(i) / 255.0, 2.7) * 255.0 + 0.5)
print("Displaying...")
while True: # Loop forever
for x in range(WIDTH): # For each column of image...
for y in range(HEIGHT): # For each pixel in column...
value = PIXELS[x, y] # Read pixel in image
DOTS[y] = ( # Set pixel #y in strip
GAMMA[value[0]], # Gamma-corrected red
GAMMA[value[1]], # Gamma-corrected green
GAMMA[value[2]], # Gamma-corrected blue
)
DOTS.show() # Refresh LED strip
time.sleep(0.01) # Pause 1/100 sec.
DOTS.fill(0) # Clear strip and pause 1/4 sec.
DOTS.show()
time.sleep(0.25)

View file

@ -1,71 +0,0 @@
#!/usr/bin/python3
# Persistence-of-vision (POV) example for Adafruit DotStar RGB LED strip.
# Loads image, displays column-at-a-time on LEDs at very high speed,
# suitable for naked-eye illusions.
# See dotstar_simpletest.py for a much simpler example script.
# See dotstar_image_paint.py for a slightly simpler light painting example.
# This code accesses some elements of the dotstar object directly rather
# than through function calls or setters/getters...this is poor form as it
# could break easily with future library changes, but is the only way right
# now to do the POV as quickly as possible.
# May require installing separate libraries.
import board
from PIL import Image
import adafruit_dotstar as dotstar
NUMPIXELS = 30 # Length of DotStar strip
FILENAME = "hello.png" # Image file to load
ORDER = dotstar.BGR # Change to GBR for older DotStar strips
# First two arguments in strip declaration identify the clock and data pins
# (here we're using the hardware SPI pins).
DOTS = dotstar.DotStar(
board.SCK,
board.MOSI,
NUMPIXELS,
auto_write=False,
brightness=1.0,
pixel_order=ORDER,
)
# Load image in RGB format and get dimensions:
print("Loading...")
IMG = Image.open(FILENAME).convert("RGB")
PIXELS = IMG.load()
WIDTH = IMG.size[0]
HEIGHT = IMG.size[1]
print("%dx%d pixels" % IMG.size)
if HEIGHT > NUMPIXELS:
HEIGHT = NUMPIXELS
# Calculate gamma correction table, makes mid-range colors look 'right':
GAMMA = bytearray(256)
brightness = 0.25
for i in range(256):
GAMMA[i] = int(pow(float(i) / 255.0, 2.7) * brightness * 255.0 + 0.5)
# Allocate list of lists, one for each column of image.
print("Allocating...")
COLUMN = [0 for x in range(WIDTH)]
for x in range(WIDTH):
COLUMN[x] = [[0, 0, 0, 0] for _ in range(HEIGHT)]
# Convert entire RGB image into columnxrow 2D list.
print("Converting...")
for x in range(WIDTH): # For each column of image
for y in range(HEIGHT): # For each pixel in column
value = PIXELS[x, y] # Read RGB pixel in image
COLUMN[x][y][0] = GAMMA[value[0]] # Gamma-corrected R
COLUMN[x][y][1] = GAMMA[value[1]] # Gamma-corrected G
COLUMN[x][y][2] = GAMMA[value[2]] # Gamma-corrected B
COLUMN[x][y][3] = 1.0 # Brightness
print("Displaying...")
while True: # Loop forever
for x in range(WIDTH): # For each column of image...
DOTS[0 : DOTS.n] = COLUMN[x] # Copy column to DotStar buffer
DOTS.show() # Send data to strip

View file

@ -3,27 +3,27 @@ import random
import board
import adafruit_dotstar as dotstar
# On-board DotStar for boards including Gemma, Trinket, and ItsyBitsy
# One pixel connected internally on a GEMMA M0
# pylint: disable=no-member
dots = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
# Using a DotStar Digital LED Strip with 30 LEDs connected to hardware SPI
# dots = dotstar.DotStar(board.SCK, board.MOSI, 30, brightness=0.2)
# With a Dotstar Digital LEB Strip with 30 lights
#dots = dotstar.DotStar(board.SCK, board.MOSI, 30, brightness=0.2)
# Using a DotStar Digital LED Strip with 30 LEDs connected to digital pins
# dots = dotstar.DotStar(board.D6, board.D5, 30, brightness=0.2)
######################### HELPERS ##############################
# HELPERS
# a random color 0 -> 192
# a random color 0 -> 224
def random_color():
return random.randrange(0, 7) * 32
# MAIN LOOP
######################### MAIN LOOP ##############################
n_dots = len(dots)
while True:
# Fill each dot with a random color
#fill each dot with a random color
for dot in range(n_dots):
dots[dot] = (random_color(), random_color(), random_color())
time.sleep(0.25)
# show all dots in strip
dots.show()
time.sleep(.25)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

View file

@ -1,3 +1,2 @@
Adafruit-Blinka
adafruit-circuitpython-busdevice
adafruit-circuitpython-pypixelbuf>=2.0.0

View file

@ -7,7 +7,6 @@ https://github.com/pypa/sampleproject
# Always prefer setuptools over distutils
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path
@ -15,42 +14,47 @@ 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:
with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
long_description = f.read()
setup(
name="adafruit-circuitpython-dotstar",
name='adafruit-circuitpython-dotstar',
use_scm_version=True,
setup_requires=["setuptools_scm"],
description="CircuitPython library for DotStar LEDs.",
setup_requires=['setuptools_scm'],
description='CircuitPython library for DotStar LEDs.',
long_description=long_description,
long_description_content_type="text/x-rst",
long_description_content_type='text/x-rst',
# The project's main homepage.
url="https://github.com/adafruit/Adafruit_CircuitPython_DotStar",
url='https://github.com/adafruit/Adafruit_CircuitPython_DotStar',
# Author details
author="Adafruit Industries",
author_email="circuitpython@adafruit.com",
install_requires=[
"Adafruit-Blinka",
"adafruit-circuitpython-busdevice",
"adafruit-circuitpython-pypixelbuf>=2.0.0",
],
author='Adafruit Industries',
author_email='circuitpython@adafruit.com',
install_requires=['Adafruit-Blinka', 'adafruit-circuitpython-busdevice'],
# Choose your license
license="MIT",
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",
'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 dotstar leds rgb spi addressable hardware micropython circuitpython",
keywords='adafruit dotstar leds rgb spi addressable hardware micropython circuitpython',
# You can just specify the packages manually here if your project is
# simple. Or you can use find_packages().
py_modules=["adafruit_dotstar"],
)
py_modules=['adafruit_dotstar'],
)