From 80d601aad426ce6b54fcb6f0395fc3d45c07001e Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 5 Sep 2017 16:49:15 -0700 Subject: [PATCH 1/3] Cookiecutter the library and update to match NeoPixel API. --- .gitignore | 2 + CODE_OF_CONDUCT.md | 74 +++++++++++++++ LICENSE | 2 +- README.md | 2 - README.rst | 69 ++++++++++++++ adafruit_dotstar.py | 213 ++++++++++++++++++++++++++++++++++++++++++++ api.rst | 5 ++ conf.py | 145 ++++++++++++++++++++++++++++++ dotstar.py | 99 -------------------- readthedocs.yml | 2 + requirements.txt | 1 + 11 files changed, 512 insertions(+), 102 deletions(-) create mode 100644 .gitignore create mode 100644 CODE_OF_CONDUCT.md delete mode 100644 README.md create mode 100644 README.rst create mode 100644 adafruit_dotstar.py create mode 100644 api.rst create mode 100644 conf.py delete mode 100644 dotstar.py create mode 100644 readthedocs.yml create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b42b1e2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +_build +__pycache__ diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..1617586 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -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/ diff --git a/LICENSE b/LICENSE index 19a9cd8..dc836b6 100644 --- a/LICENSE +++ b/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 diff --git a/README.md b/README.md deleted file mode 100644 index 753a462..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Adafruit_CircuitPython_DotStar -Dotstarrin' away in CircuitPython land diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..3264c92 --- /dev/null +++ b/README.rst @@ -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 `_. + +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 `_ + +Please ensure all dependencies are available on the CircuitPython filesystem. +This is easily achieved by downloading +`the Adafruit library and driver bundle `_. + +Usage Example +============= + +This example demonstrates the library with the single built-in DotStar on the +`Trinket M0 `_ and +`Gemma M0 `_. + +.. 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 +`_ +before contributing to help this project stay welcoming. + +API Reference +============= + +.. toctree:: + :maxdepth: 2 + + api diff --git a/adafruit_dotstar.py b/adafruit_dotstar.py new file mode 100644 index 0000000..cffd57f --- /dev/null +++ b/adafruit_dotstar.py @@ -0,0 +1,213 @@ +# 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 dotstar + import time + from board import * + + RED = 0x100000 + + with 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.buf = bytearray(n * 4 + 8) + # Four empty bytes to start. + for i in range(4): + self.buf[i] = 0x00 + # Four 0xff bytes at the end. + for i in range(4): + self.buf[len(self.buf) - 4 + 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(4, len(self.buf) - 4): + 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 + 4 + 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) + 4] + 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) + 4] + 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 diff --git a/api.rst b/api.rst new file mode 100644 index 0000000..3fd45ab --- /dev/null +++ b/api.rst @@ -0,0 +1,5 @@ + +.. If you created a package, create one automodule per module in the package. + +.. automodule:: adafruit_dotstar + :members: diff --git a/conf.py b/conf.py new file mode 100644 index 0000000..acf376b --- /dev/null +++ b/conf.py @@ -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'), +] diff --git a/dotstar.py b/dotstar.py deleted file mode 100644 index 0dd75d8..0000000 --- a/dotstar.py +++ /dev/null @@ -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 diff --git a/readthedocs.yml b/readthedocs.yml new file mode 100644 index 0000000..a3a16c1 --- /dev/null +++ b/readthedocs.yml @@ -0,0 +1,2 @@ +requirements_file: requirements.txt + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ + From 736d6158b377d7655786054f8970f54c53d2ff87 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 6 Sep 2017 11:55:40 -0700 Subject: [PATCH 2/3] Fix up the deinit code. --- adafruit_dotstar.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) mode change 100644 => 100755 adafruit_dotstar.py diff --git a/adafruit_dotstar.py b/adafruit_dotstar.py old mode 100644 new mode 100755 index cffd57f..d456185 --- a/adafruit_dotstar.py +++ b/adafruit_dotstar.py @@ -72,20 +72,31 @@ def __init__(self, clock, data, n, brightness=1.0, auto_write=True): self.cpin.direction = digitalio.Direction.OUTPUT self.cpin.value = False self.n = n - self.buf = bytearray(n * 4 + 8) + 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(4): + for i in range(self.start_header): self.buf[i] = 0x00 - # Four 0xff bytes at the end. - for i in range(4): - self.buf[len(self.buf) - 4 + i] = 0xff + # 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(4, len(self.buf) - 4): + 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: @@ -104,7 +115,7 @@ def __repr__(self): return "[" + ", ".join([str(x) for x in self]) + "]" def _set_item(self, index, value): - offset = index * 4 + 4 + offset = index * 4 + self.start_header r = 0 g = 0 b = 0 @@ -143,7 +154,7 @@ 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) + 4] + out.append(tuple(self.buf[in_i * 4 + (3 - i) + self.start_header] for i in range(3))) return out if index < 0: @@ -151,7 +162,7 @@ def __getitem__(self, index): if index >= self.n or index < 0: raise IndexError offset = index * 4 - return tuple(self.buf[offset + (3 - i) + 4] + return tuple(self.buf[offset + (3 - i) + self.start_header] for i in range(3)) def __len__(self): From 16819de69fc3afa8d2371faa9906279068f1711f Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 6 Sep 2017 11:57:53 -0700 Subject: [PATCH 3/3] Update example. --- adafruit_dotstar.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_dotstar.py b/adafruit_dotstar.py index d456185..53c20f5 100755 --- a/adafruit_dotstar.py +++ b/adafruit_dotstar.py @@ -47,13 +47,13 @@ class DotStar: .. code-block:: python - import dotstar + import adafruit_dotstar import time from board import * RED = 0x100000 - with dotstar.DotStar(APA102_SCK, APA102_MOSI, 1) as pixels: + with adafruit_dotstar.DotStar(APA102_SCK, APA102_MOSI, 1) as pixels: pixels[0] = RED time.sleep(2) """