Removed ProS2 board files for now
This commit is contained in:
parent
4b1a7d812e
commit
819b5faa71
@ -1,198 +0,0 @@
|
|||||||
# 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
|
|
||||||
# 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
|
|
||||||
# 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 (for CircuitPython 5.0+ with _pixelbuf)
|
|
||||||
=================================================================================
|
|
||||||
|
|
||||||
* Author(s): Damien P. George, Limor Fried, Scott Shawcroft & Roy Hooper
|
|
||||||
"""
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# 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"""
|
|
||||||
|
|
||||||
|
|
||||||
class DotStar(_pixelbuf.PixelBuf):
|
|
||||||
"""
|
|
||||||
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 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
|
|
||||||
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.
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
.. 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
|
|
||||||
):
|
|
||||||
self._spi = None
|
|
||||||
try:
|
|
||||||
self._spi = busio.SPI(clock, MOSI=data)
|
|
||||||
while not self._spi.try_lock():
|
|
||||||
pass
|
|
||||||
self._spi.configure(baudrate=baudrate)
|
|
||||||
|
|
||||||
except (NotImplementedError, 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
|
|
||||||
|
|
||||||
# Supply one extra clock cycle for each two pixels in the strip.
|
|
||||||
trailer_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,
|
|
||||||
)
|
|
||||||
|
|
||||||
def deinit(self):
|
|
||||||
"""Blank out the DotStars and release the resources."""
|
|
||||||
self.fill(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]) + "]"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def n(self):
|
|
||||||
"""
|
|
||||||
The number of dotstars in the chain (read-only)
|
|
||||||
"""
|
|
||||||
return len(self)
|
|
||||||
|
|
||||||
def _transmit(self, buffer):
|
|
||||||
if self._spi:
|
|
||||||
self._spi.write(buffer)
|
|
||||||
else:
|
|
||||||
self._ds_writebytes(buffer)
|
|
||||||
|
|
||||||
def _ds_writebytes(self, buffer):
|
|
||||||
for b in buffer:
|
|
||||||
for _ in range(8):
|
|
||||||
self.dpin.value = b & 0x80
|
|
||||||
self.cpin.value = True
|
|
||||||
self.cpin.value = False
|
|
||||||
b = b << 1
|
|
||||||
self.cpin.value = False
|
|
@ -1,374 +0,0 @@
|
|||||||
# The MIT License (MIT)
|
|
||||||
#
|
|
||||||
# Based on the Adafruit NeoPixel and Adafruit Dotstar CircuitPython drivers.
|
|
||||||
# Copyright (c) 2019-2020 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
|
|
||||||
# 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_pypixelbuf` - A pure python implementation of _pixelbuf
|
|
||||||
=================================================================
|
|
||||||
This class is used when _pixelbuf is not available in CircuitPython. It is based on the work
|
|
||||||
in neopixel.py and adafruit_dotstar.py.
|
|
||||||
|
|
||||||
* Author(s): Damien P. George & Limor Fried & Scott Shawcroft & Roy Hooper
|
|
||||||
"""
|
|
||||||
|
|
||||||
DOTSTAR_LED_START_FULL_BRIGHT = 0xFF
|
|
||||||
DOTSTAR_LED_START = 0b11100000 # Three "1" bits, followed by 5 brightness bits
|
|
||||||
DOTSTAR_LED_BRIGHTNESS = 0b00011111
|
|
||||||
|
|
||||||
|
|
||||||
class PixelBuf: # pylint: disable=too-many-instance-attributes
|
|
||||||
"""
|
|
||||||
A sequence of RGB/RGBW pixels.
|
|
||||||
|
|
||||||
This is the pure python implementation of CircuitPython's _pixelbuf.
|
|
||||||
|
|
||||||
:param ~int n: Number of pixels
|
|
||||||
:param ~str byteorder: Byte order string constant (also sets bpp)
|
|
||||||
:param ~float brightness: Brightness (0 to 1.0, default 1.0)
|
|
||||||
:param ~bool auto_write: Whether to automatically write pixels (Default False)
|
|
||||||
:param bytes header: Sequence of bytes to always send before pixel values.
|
|
||||||
:param bytes trailer: Sequence of bytes to always send after pixel values.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__( # pylint: disable=too-many-locals,too-many-arguments
|
|
||||||
self,
|
|
||||||
n,
|
|
||||||
byteorder="BGR",
|
|
||||||
brightness=1.0,
|
|
||||||
auto_write=False,
|
|
||||||
header=None,
|
|
||||||
trailer=None,
|
|
||||||
):
|
|
||||||
|
|
||||||
bpp, byteorder_tuple, has_white, dotstar_mode = self.parse_byteorder(byteorder)
|
|
||||||
|
|
||||||
self.auto_write = False
|
|
||||||
|
|
||||||
effective_bpp = 4 if dotstar_mode else bpp
|
|
||||||
_bytes = effective_bpp * n
|
|
||||||
buf = bytearray(_bytes)
|
|
||||||
offset = 0
|
|
||||||
|
|
||||||
if header is not None:
|
|
||||||
if not isinstance(header, bytearray):
|
|
||||||
raise TypeError("header must be a bytearray")
|
|
||||||
buf = header + buf
|
|
||||||
offset = len(header)
|
|
||||||
|
|
||||||
if trailer is not None:
|
|
||||||
if not isinstance(trailer, bytearray):
|
|
||||||
raise TypeError("trailer must be a bytearray")
|
|
||||||
buf += trailer
|
|
||||||
|
|
||||||
self._pixels = n
|
|
||||||
self._bytes = _bytes
|
|
||||||
self._byteorder = byteorder_tuple
|
|
||||||
self._byteorder_string = byteorder
|
|
||||||
self._has_white = has_white
|
|
||||||
self._bpp = bpp
|
|
||||||
self._pre_brightness_buffer = None
|
|
||||||
self._post_brightness_buffer = buf
|
|
||||||
self._offset = offset
|
|
||||||
self._dotstar_mode = dotstar_mode
|
|
||||||
self._pixel_step = effective_bpp
|
|
||||||
|
|
||||||
if dotstar_mode:
|
|
||||||
self._byteorder_tuple = (
|
|
||||||
byteorder_tuple[0] + 1,
|
|
||||||
byteorder_tuple[1] + 1,
|
|
||||||
byteorder_tuple[2] + 1,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
# Initialize the buffer with the dotstar start bytes.
|
|
||||||
for i in range(self._offset, self._bytes + self._offset, 4):
|
|
||||||
self._post_brightness_buffer[i] = DOTSTAR_LED_START_FULL_BRIGHT
|
|
||||||
|
|
||||||
self._brightness = 1.0
|
|
||||||
self.brightness = brightness
|
|
||||||
|
|
||||||
self.auto_write = auto_write
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def parse_byteorder(byteorder):
|
|
||||||
"""
|
|
||||||
Parse a Byteorder string for validity and determine bpp, byte order, and
|
|
||||||
dostar brightness bits.
|
|
||||||
|
|
||||||
Byteorder strings may contain the following characters:
|
|
||||||
R - Red
|
|
||||||
G - Green
|
|
||||||
B - Blue
|
|
||||||
W - White
|
|
||||||
P - PWM (PWM Duty cycle for pixel - dotstars 0 - 1.0)
|
|
||||||
|
|
||||||
:param: ~str bpp: bpp string.
|
|
||||||
:return: ~tuple: bpp, byteorder, has_white, dotstar_mode
|
|
||||||
"""
|
|
||||||
bpp = len(byteorder)
|
|
||||||
dotstar_mode = False
|
|
||||||
has_white = False
|
|
||||||
|
|
||||||
if byteorder.strip("RGBWP") != "":
|
|
||||||
raise ValueError("Invalid Byteorder string")
|
|
||||||
|
|
||||||
try:
|
|
||||||
r = byteorder.index("R")
|
|
||||||
g = byteorder.index("G")
|
|
||||||
b = byteorder.index("B")
|
|
||||||
except ValueError:
|
|
||||||
raise ValueError("Invalid Byteorder string")
|
|
||||||
if "W" in byteorder:
|
|
||||||
w = byteorder.index("W")
|
|
||||||
byteorder = (r, g, b, w)
|
|
||||||
has_white = True
|
|
||||||
elif "P" in byteorder:
|
|
||||||
lum = byteorder.index("P")
|
|
||||||
byteorder = (r, g, b, lum)
|
|
||||||
dotstar_mode = True
|
|
||||||
else:
|
|
||||||
byteorder = (r, g, b)
|
|
||||||
|
|
||||||
return bpp, byteorder, has_white, dotstar_mode
|
|
||||||
|
|
||||||
@property
|
|
||||||
def bpp(self):
|
|
||||||
"""
|
|
||||||
The number of bytes per pixel in the buffer (read-only).
|
|
||||||
"""
|
|
||||||
return self._bpp
|
|
||||||
|
|
||||||
@property
|
|
||||||
def brightness(self):
|
|
||||||
"""
|
|
||||||
Float value between 0 and 1. Output brightness.
|
|
||||||
|
|
||||||
When brightness is less than 1.0, a second buffer will be used to store the color values
|
|
||||||
before they are adjusted for brightness.
|
|
||||||
"""
|
|
||||||
return self._brightness
|
|
||||||
|
|
||||||
@brightness.setter
|
|
||||||
def brightness(self, value):
|
|
||||||
value = min(max(value, 0.0), 1.0)
|
|
||||||
change = value - self._brightness
|
|
||||||
if -0.001 < change < 0.001:
|
|
||||||
return
|
|
||||||
|
|
||||||
self._brightness = value
|
|
||||||
|
|
||||||
if self._pre_brightness_buffer is None:
|
|
||||||
self._pre_brightness_buffer = bytearray(self._post_brightness_buffer)
|
|
||||||
|
|
||||||
# Adjust brightness of existing pixels
|
|
||||||
offset_check = self._offset % self._pixel_step
|
|
||||||
for i in range(self._offset, self._bytes + self._offset):
|
|
||||||
# Don't adjust per-pixel luminance bytes in dotstar mode
|
|
||||||
if self._dotstar_mode and (i % 4 != offset_check):
|
|
||||||
continue
|
|
||||||
self._post_brightness_buffer[i] = int(
|
|
||||||
self._pre_brightness_buffer[i] * self._brightness
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.auto_write:
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def byteorder(self):
|
|
||||||
"""
|
|
||||||
ByteOrder string for the buffer (read-only)
|
|
||||||
"""
|
|
||||||
return self._byteorder_string
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
"""
|
|
||||||
Number of pixels.
|
|
||||||
"""
|
|
||||||
return self._pixels
|
|
||||||
|
|
||||||
def show(self):
|
|
||||||
"""
|
|
||||||
Call the associated write function to display the pixels
|
|
||||||
"""
|
|
||||||
return self._transmit(self._post_brightness_buffer)
|
|
||||||
|
|
||||||
def fill(self, color):
|
|
||||||
"""
|
|
||||||
Fills the given pixelbuf with the given color.
|
|
||||||
:param pixelbuf: A pixel object.
|
|
||||||
:param color: Color to set.
|
|
||||||
"""
|
|
||||||
r, g, b, w = self._parse_color(color)
|
|
||||||
for i in range(self._pixels):
|
|
||||||
self._set_item(i, r, g, b, w)
|
|
||||||
if self.auto_write:
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
def _parse_color(self, value):
|
|
||||||
r = 0
|
|
||||||
g = 0
|
|
||||||
b = 0
|
|
||||||
w = 0
|
|
||||||
if isinstance(value, int):
|
|
||||||
r = value >> 16
|
|
||||||
g = (value >> 8) & 0xFF
|
|
||||||
b = value & 0xFF
|
|
||||||
w = 0
|
|
||||||
|
|
||||||
if self._dotstar_mode:
|
|
||||||
w = 1.0
|
|
||||||
else:
|
|
||||||
if len(value) < 3 or len(value) > 4:
|
|
||||||
raise ValueError(
|
|
||||||
"Expected tuple of length {}, got {}".format(self._bpp, len(value))
|
|
||||||
)
|
|
||||||
if len(value) == self._bpp:
|
|
||||||
if self._bpp == 3:
|
|
||||||
r, g, b = value
|
|
||||||
else:
|
|
||||||
r, g, b, w = value
|
|
||||||
elif len(value) == 3:
|
|
||||||
r, g, b = value
|
|
||||||
if self._dotstar_mode:
|
|
||||||
w = 1.0
|
|
||||||
|
|
||||||
if self._bpp == 4:
|
|
||||||
if self._dotstar_mode:
|
|
||||||
# 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
|
|
||||||
w = (int(w * 31) & 0b00011111) | DOTSTAR_LED_START
|
|
||||||
elif (
|
|
||||||
self._has_white
|
|
||||||
and (isinstance(value, int) or len(value) == 3)
|
|
||||||
and r == g
|
|
||||||
and g == b
|
|
||||||
):
|
|
||||||
# If all components are the same and we have a white pixel then use it
|
|
||||||
# instead of the individual components when all 4 values aren't explicitly given.
|
|
||||||
w = r
|
|
||||||
r = 0
|
|
||||||
g = 0
|
|
||||||
b = 0
|
|
||||||
|
|
||||||
return (r, g, b, w)
|
|
||||||
|
|
||||||
def _set_item(
|
|
||||||
self, index, r, g, b, w
|
|
||||||
): # pylint: disable=too-many-locals,too-many-branches,too-many-arguments
|
|
||||||
if index < 0:
|
|
||||||
index += len(self)
|
|
||||||
if index >= self._pixels or index < 0:
|
|
||||||
raise IndexError
|
|
||||||
offset = self._offset + (index * self._bpp)
|
|
||||||
|
|
||||||
if self._pre_brightness_buffer is not None:
|
|
||||||
if self._bpp == 4:
|
|
||||||
self._pre_brightness_buffer[offset + self._byteorder[3]] = w
|
|
||||||
self._pre_brightness_buffer[offset + self._byteorder[0]] = r
|
|
||||||
self._pre_brightness_buffer[offset + self._byteorder[1]] = g
|
|
||||||
self._pre_brightness_buffer[offset + self._byteorder[2]] = b
|
|
||||||
|
|
||||||
if self._bpp == 4:
|
|
||||||
# Only apply brightness if w is actually white (aka not DotStar.)
|
|
||||||
if not self._dotstar_mode:
|
|
||||||
w = int(w * self._brightness)
|
|
||||||
self._post_brightness_buffer[offset + self._byteorder[3]] = w
|
|
||||||
|
|
||||||
self._post_brightness_buffer[offset + self._byteorder[0]] = int(
|
|
||||||
r * self._brightness
|
|
||||||
)
|
|
||||||
self._post_brightness_buffer[offset + self._byteorder[1]] = int(
|
|
||||||
g * self._brightness
|
|
||||||
)
|
|
||||||
self._post_brightness_buffer[offset + self._byteorder[2]] = int(
|
|
||||||
b * self._brightness
|
|
||||||
)
|
|
||||||
|
|
||||||
def __setitem__(self, index, val):
|
|
||||||
if isinstance(index, slice):
|
|
||||||
start, stop, step = index.indices(self._pixels)
|
|
||||||
for val_i, in_i in enumerate(range(start, stop, step)):
|
|
||||||
r, g, b, w = self._parse_color(val[val_i])
|
|
||||||
self._set_item(in_i, r, g, b, w)
|
|
||||||
else:
|
|
||||||
r, g, b, w = self._parse_color(val)
|
|
||||||
self._set_item(index, r, g, b, w)
|
|
||||||
|
|
||||||
if self.auto_write:
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
def _getitem(self, index):
|
|
||||||
start = self._offset + (index * self._bpp)
|
|
||||||
buffer = (
|
|
||||||
self._pre_brightness_buffer
|
|
||||||
if self._pre_brightness_buffer is not None
|
|
||||||
else self._post_brightness_buffer
|
|
||||||
)
|
|
||||||
value = [
|
|
||||||
buffer[start + self._byteorder[0]],
|
|
||||||
buffer[start + self._byteorder[1]],
|
|
||||||
buffer[start + self._byteorder[2]],
|
|
||||||
]
|
|
||||||
if self._has_white:
|
|
||||||
value.append(buffer[start + self._byteorder[3]])
|
|
||||||
elif self._dotstar_mode:
|
|
||||||
value.append(
|
|
||||||
(buffer[start + self._byteorder[3]] & DOTSTAR_LED_BRIGHTNESS) / 31.0
|
|
||||||
)
|
|
||||||
return value
|
|
||||||
|
|
||||||
def __getitem__(self, index):
|
|
||||||
if isinstance(index, slice):
|
|
||||||
out = []
|
|
||||||
for in_i in range(
|
|
||||||
*index.indices(len(self._post_brightness_buffer) // self._bpp)
|
|
||||||
):
|
|
||||||
out.append(self._getitem(in_i))
|
|
||||||
return out
|
|
||||||
if index < 0:
|
|
||||||
index += len(self)
|
|
||||||
if index >= self._pixels or index < 0:
|
|
||||||
raise IndexError
|
|
||||||
return self._getitem(index)
|
|
||||||
|
|
||||||
def _transmit(self, buffer):
|
|
||||||
raise NotImplementedError("Must be subclassed")
|
|
||||||
|
|
||||||
|
|
||||||
def wheel(pos):
|
|
||||||
"""
|
|
||||||
Helper to create a colorwheel.
|
|
||||||
|
|
||||||
:param pos: int 0-255 of color value to return
|
|
||||||
:return: tuple of RGB values
|
|
||||||
"""
|
|
||||||
# Input a value 0 to 255 to get a color value.
|
|
||||||
# The colours are a transition r - g - b - back to r.
|
|
||||||
if pos < 0 or pos > 255:
|
|
||||||
return 0, 0, 0
|
|
||||||
if pos < 85:
|
|
||||||
return 255 - pos * 3, pos * 3, 0
|
|
||||||
if pos < 170:
|
|
||||||
pos -= 85
|
|
||||||
return 0, 255 - pos * 3, pos * 3
|
|
||||||
pos -= 170
|
|
||||||
return pos * 3, 0, 255 - pos * 3
|
|
@ -1,311 +0,0 @@
|
|||||||
# The MIT License (MIT)
|
|
||||||
#
|
|
||||||
# Copyright (c) 2019 ladyada 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_requests`
|
|
||||||
================================================================================
|
|
||||||
|
|
||||||
A requests-like library for web interfacing
|
|
||||||
|
|
||||||
|
|
||||||
* Author(s): ladyada, Paul Sokolovsky
|
|
||||||
|
|
||||||
Implementation Notes
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Adapted from https://github.com/micropython/micropython-lib/tree/master/urequests
|
|
||||||
|
|
||||||
micropython-lib consists of multiple modules from different sources and
|
|
||||||
authors. Each module comes under its own licensing terms. Short name of
|
|
||||||
a license can be found in a file within a module directory (usually
|
|
||||||
metadata.txt or setup.py). Complete text of each license used is provided
|
|
||||||
at https://github.com/micropython/micropython-lib/blob/master/LICENSE
|
|
||||||
|
|
||||||
author='Paul Sokolovsky'
|
|
||||||
license='MIT'
|
|
||||||
|
|
||||||
**Software and Dependencies:**
|
|
||||||
|
|
||||||
* Adafruit CircuitPython firmware for the supported boards:
|
|
||||||
https://github.com/adafruit/circuitpython/releases
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import gc
|
|
||||||
|
|
||||||
__version__ = "0.0.0-auto.0"
|
|
||||||
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Requests.git"
|
|
||||||
|
|
||||||
_the_interface = None # pylint: disable=invalid-name
|
|
||||||
_the_sock = None # pylint: disable=invalid-name
|
|
||||||
|
|
||||||
|
|
||||||
def set_socket(sock, iface=None):
|
|
||||||
"""Helper to set the global socket and optionally set the global network interface.
|
|
||||||
:param sock: socket object.
|
|
||||||
:param iface: internet interface object
|
|
||||||
|
|
||||||
"""
|
|
||||||
global _the_sock # pylint: disable=invalid-name, global-statement
|
|
||||||
_the_sock = sock
|
|
||||||
if iface:
|
|
||||||
global _the_interface # pylint: disable=invalid-name, global-statement
|
|
||||||
_the_interface = iface
|
|
||||||
_the_sock.set_interface(iface)
|
|
||||||
|
|
||||||
|
|
||||||
class Response:
|
|
||||||
"""The response from a request, contains all the headers/content"""
|
|
||||||
|
|
||||||
encoding = None
|
|
||||||
|
|
||||||
def __init__(self, sock):
|
|
||||||
self.socket = sock
|
|
||||||
self.encoding = "utf-8"
|
|
||||||
self._cached = None
|
|
||||||
self.status_code = None
|
|
||||||
self.reason = None
|
|
||||||
self._read_so_far = 0
|
|
||||||
self.headers = {}
|
|
||||||
|
|
||||||
def __enter__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_value, traceback):
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
"""Close, delete and collect the response data"""
|
|
||||||
if self.socket:
|
|
||||||
self.socket.close()
|
|
||||||
del self.socket
|
|
||||||
del self._cached
|
|
||||||
gc.collect()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def content(self):
|
|
||||||
"""The HTTP content direct from the socket, as bytes"""
|
|
||||||
# print(self.headers)
|
|
||||||
try:
|
|
||||||
content_length = int(self.headers["content-length"])
|
|
||||||
except KeyError:
|
|
||||||
content_length = 0
|
|
||||||
# print("Content length:", content_length)
|
|
||||||
if self._cached is None:
|
|
||||||
try:
|
|
||||||
self._cached = self.socket.recv(content_length)
|
|
||||||
finally:
|
|
||||||
self.socket.close()
|
|
||||||
self.socket = None
|
|
||||||
# print("Buffer length:", len(self._cached))
|
|
||||||
return self._cached
|
|
||||||
|
|
||||||
@property
|
|
||||||
def text(self):
|
|
||||||
"""The HTTP content, encoded into a string according to the HTTP
|
|
||||||
header encoding"""
|
|
||||||
return str(self.content, self.encoding)
|
|
||||||
|
|
||||||
def json(self):
|
|
||||||
"""The HTTP content, parsed into a json dictionary"""
|
|
||||||
# pylint: disable=import-outside-toplevel
|
|
||||||
try:
|
|
||||||
import json as json_module
|
|
||||||
except ImportError:
|
|
||||||
import ujson as json_module
|
|
||||||
return json_module.loads(self.content)
|
|
||||||
|
|
||||||
def iter_content(self, chunk_size=1, decode_unicode=False):
|
|
||||||
"""An iterator that will stream data by only reading 'chunk_size'
|
|
||||||
bytes and yielding them, when we can't buffer the whole datastream"""
|
|
||||||
if decode_unicode:
|
|
||||||
raise NotImplementedError("Unicode not supported")
|
|
||||||
|
|
||||||
while True:
|
|
||||||
chunk = self.socket.recv(chunk_size)
|
|
||||||
if chunk:
|
|
||||||
yield chunk
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-many-branches, too-many-statements, unused-argument, too-many-arguments, too-many-locals
|
|
||||||
def request(method, url, data=None, json=None, headers=None, stream=False, timeout=1):
|
|
||||||
"""Perform an HTTP request to the given url which we will parse to determine
|
|
||||||
whether to use SSL ('https://') or not. We can also send some provided 'data'
|
|
||||||
or a json dictionary which we will stringify. 'headers' is optional HTTP headers
|
|
||||||
sent along. 'stream' will determine if we buffer everything, or whether to only
|
|
||||||
read only when requested
|
|
||||||
"""
|
|
||||||
global _the_interface # pylint: disable=global-statement, invalid-name
|
|
||||||
global _the_sock # pylint: disable=global-statement, invalid-name
|
|
||||||
|
|
||||||
if not headers:
|
|
||||||
headers = {}
|
|
||||||
|
|
||||||
try:
|
|
||||||
proto, dummy, host, path = url.split("/", 3)
|
|
||||||
# replace spaces in path
|
|
||||||
path = path.replace(" ", "%20")
|
|
||||||
except ValueError:
|
|
||||||
proto, dummy, host = url.split("/", 2)
|
|
||||||
path = ""
|
|
||||||
if proto == "http:":
|
|
||||||
port = 80
|
|
||||||
elif proto == "https:":
|
|
||||||
port = 443
|
|
||||||
else:
|
|
||||||
raise ValueError("Unsupported protocol: " + proto)
|
|
||||||
|
|
||||||
if ":" in host:
|
|
||||||
host, port = host.split(":", 1)
|
|
||||||
port = int(port)
|
|
||||||
|
|
||||||
addr_info = _the_sock.getaddrinfo(host, port, 0, _the_sock.SOCK_STREAM)[0]
|
|
||||||
sock = _the_sock.socket(addr_info[0], addr_info[1], addr_info[2])
|
|
||||||
resp = Response(sock) # our response
|
|
||||||
|
|
||||||
sock.settimeout(timeout) # socket read timeout
|
|
||||||
|
|
||||||
try:
|
|
||||||
if proto == "https:":
|
|
||||||
conntype = _the_interface.TLS_MODE
|
|
||||||
sock.connect(
|
|
||||||
(host, port), conntype
|
|
||||||
) # for SSL we need to know the host name
|
|
||||||
else:
|
|
||||||
conntype = _the_interface.TCP_MODE
|
|
||||||
sock.connect(addr_info[-1], conntype)
|
|
||||||
sock.send(
|
|
||||||
b"%s /%s HTTP/1.0\r\n" % (bytes(method, "utf-8"), bytes(path, "utf-8"))
|
|
||||||
)
|
|
||||||
if "Host" not in headers:
|
|
||||||
sock.send(b"Host: %s\r\n" % bytes(host, "utf-8"))
|
|
||||||
if "User-Agent" not in headers:
|
|
||||||
sock.send(b"User-Agent: Adafruit CircuitPython\r\n")
|
|
||||||
# Iterate over keys to avoid tuple alloc
|
|
||||||
for k in headers:
|
|
||||||
sock.send(k.encode())
|
|
||||||
sock.send(b": ")
|
|
||||||
sock.send(headers[k].encode())
|
|
||||||
sock.send(b"\r\n")
|
|
||||||
if json is not None:
|
|
||||||
assert data is None
|
|
||||||
# pylint: disable=import-outside-toplevel
|
|
||||||
try:
|
|
||||||
import json as json_module
|
|
||||||
except ImportError:
|
|
||||||
import ujson as json_module
|
|
||||||
# pylint: enable=import-outside-toplevel
|
|
||||||
data = json_module.dumps(json)
|
|
||||||
sock.send(b"Content-Type: application/json\r\n")
|
|
||||||
if data:
|
|
||||||
if isinstance(data, dict):
|
|
||||||
sock.send(b"Content-Type: application/x-www-form-urlencoded\r\n")
|
|
||||||
_post_data = ""
|
|
||||||
for k in data:
|
|
||||||
_post_data = "{}&{}={}".format(_post_data, k, data[k])
|
|
||||||
data = _post_data[1:]
|
|
||||||
sock.send(b"Content-Length: %d\r\n" % len(data))
|
|
||||||
sock.send(b"\r\n")
|
|
||||||
if data:
|
|
||||||
if isinstance(data, bytearray):
|
|
||||||
sock.send(bytes(data))
|
|
||||||
else:
|
|
||||||
sock.send(bytes(data, "utf-8"))
|
|
||||||
|
|
||||||
line = sock.readline()
|
|
||||||
# print(line)
|
|
||||||
line = line.split(None, 2)
|
|
||||||
status = int(line[1])
|
|
||||||
reason = ""
|
|
||||||
if len(line) > 2:
|
|
||||||
reason = line[2].rstrip()
|
|
||||||
resp.headers = parse_headers(sock)
|
|
||||||
if resp.headers.get("transfer-encoding"):
|
|
||||||
if "chunked" in resp.headers.get("transfer-encoding"):
|
|
||||||
raise ValueError("Unsupported " + resp.headers.get("transfer-encoding"))
|
|
||||||
elif resp.headers.get("location") and not 200 <= status <= 299:
|
|
||||||
raise NotImplementedError("Redirects not yet supported")
|
|
||||||
|
|
||||||
except:
|
|
||||||
sock.close()
|
|
||||||
raise
|
|
||||||
|
|
||||||
resp.status_code = status
|
|
||||||
resp.reason = reason
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
def parse_headers(sock):
|
|
||||||
"""
|
|
||||||
Parses the header portion of an HTTP request/response from the socket.
|
|
||||||
Expects first line of HTTP request/response to have been read already
|
|
||||||
return: header dictionary
|
|
||||||
rtype: Dict
|
|
||||||
"""
|
|
||||||
headers = {}
|
|
||||||
while True:
|
|
||||||
line = sock.readline()
|
|
||||||
if not line or line == b"\r\n":
|
|
||||||
break
|
|
||||||
|
|
||||||
# print("**line: ", line)
|
|
||||||
splits = line.split(b": ", 1)
|
|
||||||
title = splits[0]
|
|
||||||
content = ""
|
|
||||||
if len(splits) > 1:
|
|
||||||
content = splits[1]
|
|
||||||
if title and content:
|
|
||||||
title = str(title.lower(), "utf-8")
|
|
||||||
content = str(content, "utf-8")
|
|
||||||
headers[title] = content
|
|
||||||
return headers
|
|
||||||
|
|
||||||
|
|
||||||
def head(url, **kw):
|
|
||||||
"""Send HTTP HEAD request"""
|
|
||||||
return request("HEAD", url, **kw)
|
|
||||||
|
|
||||||
|
|
||||||
def get(url, **kw):
|
|
||||||
"""Send HTTP GET request"""
|
|
||||||
return request("GET", url, **kw)
|
|
||||||
|
|
||||||
|
|
||||||
def post(url, **kw):
|
|
||||||
"""Send HTTP POST request"""
|
|
||||||
return request("POST", url, **kw)
|
|
||||||
|
|
||||||
|
|
||||||
def put(url, **kw):
|
|
||||||
"""Send HTTP PUT request"""
|
|
||||||
return request("PUT", url, **kw)
|
|
||||||
|
|
||||||
|
|
||||||
def patch(url, **kw):
|
|
||||||
"""Send HTTP PATCH request"""
|
|
||||||
return request("PATCH", url, **kw)
|
|
||||||
|
|
||||||
|
|
||||||
def delete(url, **kw):
|
|
||||||
"""Send HTTP DELETE request"""
|
|
||||||
return request("DELETE", url, **kw)
|
|
@ -1,47 +0,0 @@
|
|||||||
# FeatherS2 Helper Library
|
|
||||||
# 2020 Seon Rozenblum, Unexpected Maker
|
|
||||||
#
|
|
||||||
# Project home:
|
|
||||||
# https://feathers2.io
|
|
||||||
#
|
|
||||||
|
|
||||||
# Import required libraries
|
|
||||||
import time
|
|
||||||
import board
|
|
||||||
from digitalio import DigitalInOut, Direction, Pull
|
|
||||||
|
|
||||||
|
|
||||||
# Helper functions
|
|
||||||
|
|
||||||
def enable_LDO2(state):
|
|
||||||
"""Set the power for the second on-board LDO to allow no current draw when not needed."""
|
|
||||||
|
|
||||||
# Grab a reference to the LDO2 IO (21 in this case)
|
|
||||||
ldo2 = DigitalInOut(board.LDO2)
|
|
||||||
ldo2.direction = Direction.OUTPUT
|
|
||||||
|
|
||||||
# Set the LDO2 power pin on / off
|
|
||||||
ldo2.value = state
|
|
||||||
|
|
||||||
# A small delay to let the IO change state
|
|
||||||
time.sleep(0.035)
|
|
||||||
|
|
||||||
|
|
||||||
# Dotstar rainbow colour wheel
|
|
||||||
def dotstar_color_wheel(wheel_pos):
|
|
||||||
"""Color wheel to allow for cycling through the rainbow of RGB colors."""
|
|
||||||
wheel_pos = wheel_pos % 255
|
|
||||||
|
|
||||||
if wheel_pos < 85:
|
|
||||||
return 255 - wheel_pos * 3, 0, wheel_pos * 3
|
|
||||||
elif wheel_pos < 170:
|
|
||||||
wheel_pos -= 85
|
|
||||||
return 0, wheel_pos * 3, 255 - wheel_pos * 3
|
|
||||||
else:
|
|
||||||
wheel_pos -= 170
|
|
||||||
return wheel_pos * 3, 255 - wheel_pos * 3, 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Disable LDO2 by default
|
|
||||||
enable_LDO2(False)
|
|
@ -45,12 +45,12 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
|
|||||||
{ MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO43) },
|
{ MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO43) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) },
|
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) },
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO8) },
|
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO8) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO8) },
|
{ MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO8) },
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO9) },
|
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO9) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO9) },
|
{ MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO9) },
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) },
|
{ MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) },
|
||||||
@ -82,10 +82,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
|
|||||||
{ MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO11) },
|
{ MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO11) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO11) },
|
{ MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO11) },
|
||||||
|
|
||||||
// { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, // MTDO
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_GPIO40) }, // MTDO
|
{ MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_GPIO40) }, // MTDO
|
||||||
|
|
||||||
// { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_GPIO45) },
|
{ MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_GPIO45) },
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,198 +0,0 @@
|
|||||||
# 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
|
|
||||||
# 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
|
|
||||||
# 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 (for CircuitPython 5.0+ with _pixelbuf)
|
|
||||||
=================================================================================
|
|
||||||
|
|
||||||
* Author(s): Damien P. George, Limor Fried, Scott Shawcroft & Roy Hooper
|
|
||||||
"""
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# 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"""
|
|
||||||
|
|
||||||
|
|
||||||
class DotStar(_pixelbuf.PixelBuf):
|
|
||||||
"""
|
|
||||||
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 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
|
|
||||||
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.
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
.. 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
|
|
||||||
):
|
|
||||||
self._spi = None
|
|
||||||
try:
|
|
||||||
self._spi = busio.SPI(clock, MOSI=data)
|
|
||||||
while not self._spi.try_lock():
|
|
||||||
pass
|
|
||||||
self._spi.configure(baudrate=baudrate)
|
|
||||||
|
|
||||||
except (NotImplementedError, 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
|
|
||||||
|
|
||||||
# Supply one extra clock cycle for each two pixels in the strip.
|
|
||||||
trailer_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,
|
|
||||||
)
|
|
||||||
|
|
||||||
def deinit(self):
|
|
||||||
"""Blank out the DotStars and release the resources."""
|
|
||||||
self.fill(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]) + "]"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def n(self):
|
|
||||||
"""
|
|
||||||
The number of dotstars in the chain (read-only)
|
|
||||||
"""
|
|
||||||
return len(self)
|
|
||||||
|
|
||||||
def _transmit(self, buffer):
|
|
||||||
if self._spi:
|
|
||||||
self._spi.write(buffer)
|
|
||||||
else:
|
|
||||||
self._ds_writebytes(buffer)
|
|
||||||
|
|
||||||
def _ds_writebytes(self, buffer):
|
|
||||||
for b in buffer:
|
|
||||||
for _ in range(8):
|
|
||||||
self.dpin.value = b & 0x80
|
|
||||||
self.cpin.value = True
|
|
||||||
self.cpin.value = False
|
|
||||||
b = b << 1
|
|
||||||
self.cpin.value = False
|
|
@ -1,374 +0,0 @@
|
|||||||
# The MIT License (MIT)
|
|
||||||
#
|
|
||||||
# Based on the Adafruit NeoPixel and Adafruit Dotstar CircuitPython drivers.
|
|
||||||
# Copyright (c) 2019-2020 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
|
|
||||||
# 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_pypixelbuf` - A pure python implementation of _pixelbuf
|
|
||||||
=================================================================
|
|
||||||
This class is used when _pixelbuf is not available in CircuitPython. It is based on the work
|
|
||||||
in neopixel.py and adafruit_dotstar.py.
|
|
||||||
|
|
||||||
* Author(s): Damien P. George & Limor Fried & Scott Shawcroft & Roy Hooper
|
|
||||||
"""
|
|
||||||
|
|
||||||
DOTSTAR_LED_START_FULL_BRIGHT = 0xFF
|
|
||||||
DOTSTAR_LED_START = 0b11100000 # Three "1" bits, followed by 5 brightness bits
|
|
||||||
DOTSTAR_LED_BRIGHTNESS = 0b00011111
|
|
||||||
|
|
||||||
|
|
||||||
class PixelBuf: # pylint: disable=too-many-instance-attributes
|
|
||||||
"""
|
|
||||||
A sequence of RGB/RGBW pixels.
|
|
||||||
|
|
||||||
This is the pure python implementation of CircuitPython's _pixelbuf.
|
|
||||||
|
|
||||||
:param ~int n: Number of pixels
|
|
||||||
:param ~str byteorder: Byte order string constant (also sets bpp)
|
|
||||||
:param ~float brightness: Brightness (0 to 1.0, default 1.0)
|
|
||||||
:param ~bool auto_write: Whether to automatically write pixels (Default False)
|
|
||||||
:param bytes header: Sequence of bytes to always send before pixel values.
|
|
||||||
:param bytes trailer: Sequence of bytes to always send after pixel values.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__( # pylint: disable=too-many-locals,too-many-arguments
|
|
||||||
self,
|
|
||||||
n,
|
|
||||||
byteorder="BGR",
|
|
||||||
brightness=1.0,
|
|
||||||
auto_write=False,
|
|
||||||
header=None,
|
|
||||||
trailer=None,
|
|
||||||
):
|
|
||||||
|
|
||||||
bpp, byteorder_tuple, has_white, dotstar_mode = self.parse_byteorder(byteorder)
|
|
||||||
|
|
||||||
self.auto_write = False
|
|
||||||
|
|
||||||
effective_bpp = 4 if dotstar_mode else bpp
|
|
||||||
_bytes = effective_bpp * n
|
|
||||||
buf = bytearray(_bytes)
|
|
||||||
offset = 0
|
|
||||||
|
|
||||||
if header is not None:
|
|
||||||
if not isinstance(header, bytearray):
|
|
||||||
raise TypeError("header must be a bytearray")
|
|
||||||
buf = header + buf
|
|
||||||
offset = len(header)
|
|
||||||
|
|
||||||
if trailer is not None:
|
|
||||||
if not isinstance(trailer, bytearray):
|
|
||||||
raise TypeError("trailer must be a bytearray")
|
|
||||||
buf += trailer
|
|
||||||
|
|
||||||
self._pixels = n
|
|
||||||
self._bytes = _bytes
|
|
||||||
self._byteorder = byteorder_tuple
|
|
||||||
self._byteorder_string = byteorder
|
|
||||||
self._has_white = has_white
|
|
||||||
self._bpp = bpp
|
|
||||||
self._pre_brightness_buffer = None
|
|
||||||
self._post_brightness_buffer = buf
|
|
||||||
self._offset = offset
|
|
||||||
self._dotstar_mode = dotstar_mode
|
|
||||||
self._pixel_step = effective_bpp
|
|
||||||
|
|
||||||
if dotstar_mode:
|
|
||||||
self._byteorder_tuple = (
|
|
||||||
byteorder_tuple[0] + 1,
|
|
||||||
byteorder_tuple[1] + 1,
|
|
||||||
byteorder_tuple[2] + 1,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
# Initialize the buffer with the dotstar start bytes.
|
|
||||||
for i in range(self._offset, self._bytes + self._offset, 4):
|
|
||||||
self._post_brightness_buffer[i] = DOTSTAR_LED_START_FULL_BRIGHT
|
|
||||||
|
|
||||||
self._brightness = 1.0
|
|
||||||
self.brightness = brightness
|
|
||||||
|
|
||||||
self.auto_write = auto_write
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def parse_byteorder(byteorder):
|
|
||||||
"""
|
|
||||||
Parse a Byteorder string for validity and determine bpp, byte order, and
|
|
||||||
dostar brightness bits.
|
|
||||||
|
|
||||||
Byteorder strings may contain the following characters:
|
|
||||||
R - Red
|
|
||||||
G - Green
|
|
||||||
B - Blue
|
|
||||||
W - White
|
|
||||||
P - PWM (PWM Duty cycle for pixel - dotstars 0 - 1.0)
|
|
||||||
|
|
||||||
:param: ~str bpp: bpp string.
|
|
||||||
:return: ~tuple: bpp, byteorder, has_white, dotstar_mode
|
|
||||||
"""
|
|
||||||
bpp = len(byteorder)
|
|
||||||
dotstar_mode = False
|
|
||||||
has_white = False
|
|
||||||
|
|
||||||
if byteorder.strip("RGBWP") != "":
|
|
||||||
raise ValueError("Invalid Byteorder string")
|
|
||||||
|
|
||||||
try:
|
|
||||||
r = byteorder.index("R")
|
|
||||||
g = byteorder.index("G")
|
|
||||||
b = byteorder.index("B")
|
|
||||||
except ValueError:
|
|
||||||
raise ValueError("Invalid Byteorder string")
|
|
||||||
if "W" in byteorder:
|
|
||||||
w = byteorder.index("W")
|
|
||||||
byteorder = (r, g, b, w)
|
|
||||||
has_white = True
|
|
||||||
elif "P" in byteorder:
|
|
||||||
lum = byteorder.index("P")
|
|
||||||
byteorder = (r, g, b, lum)
|
|
||||||
dotstar_mode = True
|
|
||||||
else:
|
|
||||||
byteorder = (r, g, b)
|
|
||||||
|
|
||||||
return bpp, byteorder, has_white, dotstar_mode
|
|
||||||
|
|
||||||
@property
|
|
||||||
def bpp(self):
|
|
||||||
"""
|
|
||||||
The number of bytes per pixel in the buffer (read-only).
|
|
||||||
"""
|
|
||||||
return self._bpp
|
|
||||||
|
|
||||||
@property
|
|
||||||
def brightness(self):
|
|
||||||
"""
|
|
||||||
Float value between 0 and 1. Output brightness.
|
|
||||||
|
|
||||||
When brightness is less than 1.0, a second buffer will be used to store the color values
|
|
||||||
before they are adjusted for brightness.
|
|
||||||
"""
|
|
||||||
return self._brightness
|
|
||||||
|
|
||||||
@brightness.setter
|
|
||||||
def brightness(self, value):
|
|
||||||
value = min(max(value, 0.0), 1.0)
|
|
||||||
change = value - self._brightness
|
|
||||||
if -0.001 < change < 0.001:
|
|
||||||
return
|
|
||||||
|
|
||||||
self._brightness = value
|
|
||||||
|
|
||||||
if self._pre_brightness_buffer is None:
|
|
||||||
self._pre_brightness_buffer = bytearray(self._post_brightness_buffer)
|
|
||||||
|
|
||||||
# Adjust brightness of existing pixels
|
|
||||||
offset_check = self._offset % self._pixel_step
|
|
||||||
for i in range(self._offset, self._bytes + self._offset):
|
|
||||||
# Don't adjust per-pixel luminance bytes in dotstar mode
|
|
||||||
if self._dotstar_mode and (i % 4 != offset_check):
|
|
||||||
continue
|
|
||||||
self._post_brightness_buffer[i] = int(
|
|
||||||
self._pre_brightness_buffer[i] * self._brightness
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.auto_write:
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def byteorder(self):
|
|
||||||
"""
|
|
||||||
ByteOrder string for the buffer (read-only)
|
|
||||||
"""
|
|
||||||
return self._byteorder_string
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
"""
|
|
||||||
Number of pixels.
|
|
||||||
"""
|
|
||||||
return self._pixels
|
|
||||||
|
|
||||||
def show(self):
|
|
||||||
"""
|
|
||||||
Call the associated write function to display the pixels
|
|
||||||
"""
|
|
||||||
return self._transmit(self._post_brightness_buffer)
|
|
||||||
|
|
||||||
def fill(self, color):
|
|
||||||
"""
|
|
||||||
Fills the given pixelbuf with the given color.
|
|
||||||
:param pixelbuf: A pixel object.
|
|
||||||
:param color: Color to set.
|
|
||||||
"""
|
|
||||||
r, g, b, w = self._parse_color(color)
|
|
||||||
for i in range(self._pixels):
|
|
||||||
self._set_item(i, r, g, b, w)
|
|
||||||
if self.auto_write:
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
def _parse_color(self, value):
|
|
||||||
r = 0
|
|
||||||
g = 0
|
|
||||||
b = 0
|
|
||||||
w = 0
|
|
||||||
if isinstance(value, int):
|
|
||||||
r = value >> 16
|
|
||||||
g = (value >> 8) & 0xFF
|
|
||||||
b = value & 0xFF
|
|
||||||
w = 0
|
|
||||||
|
|
||||||
if self._dotstar_mode:
|
|
||||||
w = 1.0
|
|
||||||
else:
|
|
||||||
if len(value) < 3 or len(value) > 4:
|
|
||||||
raise ValueError(
|
|
||||||
"Expected tuple of length {}, got {}".format(self._bpp, len(value))
|
|
||||||
)
|
|
||||||
if len(value) == self._bpp:
|
|
||||||
if self._bpp == 3:
|
|
||||||
r, g, b = value
|
|
||||||
else:
|
|
||||||
r, g, b, w = value
|
|
||||||
elif len(value) == 3:
|
|
||||||
r, g, b = value
|
|
||||||
if self._dotstar_mode:
|
|
||||||
w = 1.0
|
|
||||||
|
|
||||||
if self._bpp == 4:
|
|
||||||
if self._dotstar_mode:
|
|
||||||
# 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
|
|
||||||
w = (int(w * 31) & 0b00011111) | DOTSTAR_LED_START
|
|
||||||
elif (
|
|
||||||
self._has_white
|
|
||||||
and (isinstance(value, int) or len(value) == 3)
|
|
||||||
and r == g
|
|
||||||
and g == b
|
|
||||||
):
|
|
||||||
# If all components are the same and we have a white pixel then use it
|
|
||||||
# instead of the individual components when all 4 values aren't explicitly given.
|
|
||||||
w = r
|
|
||||||
r = 0
|
|
||||||
g = 0
|
|
||||||
b = 0
|
|
||||||
|
|
||||||
return (r, g, b, w)
|
|
||||||
|
|
||||||
def _set_item(
|
|
||||||
self, index, r, g, b, w
|
|
||||||
): # pylint: disable=too-many-locals,too-many-branches,too-many-arguments
|
|
||||||
if index < 0:
|
|
||||||
index += len(self)
|
|
||||||
if index >= self._pixels or index < 0:
|
|
||||||
raise IndexError
|
|
||||||
offset = self._offset + (index * self._bpp)
|
|
||||||
|
|
||||||
if self._pre_brightness_buffer is not None:
|
|
||||||
if self._bpp == 4:
|
|
||||||
self._pre_brightness_buffer[offset + self._byteorder[3]] = w
|
|
||||||
self._pre_brightness_buffer[offset + self._byteorder[0]] = r
|
|
||||||
self._pre_brightness_buffer[offset + self._byteorder[1]] = g
|
|
||||||
self._pre_brightness_buffer[offset + self._byteorder[2]] = b
|
|
||||||
|
|
||||||
if self._bpp == 4:
|
|
||||||
# Only apply brightness if w is actually white (aka not DotStar.)
|
|
||||||
if not self._dotstar_mode:
|
|
||||||
w = int(w * self._brightness)
|
|
||||||
self._post_brightness_buffer[offset + self._byteorder[3]] = w
|
|
||||||
|
|
||||||
self._post_brightness_buffer[offset + self._byteorder[0]] = int(
|
|
||||||
r * self._brightness
|
|
||||||
)
|
|
||||||
self._post_brightness_buffer[offset + self._byteorder[1]] = int(
|
|
||||||
g * self._brightness
|
|
||||||
)
|
|
||||||
self._post_brightness_buffer[offset + self._byteorder[2]] = int(
|
|
||||||
b * self._brightness
|
|
||||||
)
|
|
||||||
|
|
||||||
def __setitem__(self, index, val):
|
|
||||||
if isinstance(index, slice):
|
|
||||||
start, stop, step = index.indices(self._pixels)
|
|
||||||
for val_i, in_i in enumerate(range(start, stop, step)):
|
|
||||||
r, g, b, w = self._parse_color(val[val_i])
|
|
||||||
self._set_item(in_i, r, g, b, w)
|
|
||||||
else:
|
|
||||||
r, g, b, w = self._parse_color(val)
|
|
||||||
self._set_item(index, r, g, b, w)
|
|
||||||
|
|
||||||
if self.auto_write:
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
def _getitem(self, index):
|
|
||||||
start = self._offset + (index * self._bpp)
|
|
||||||
buffer = (
|
|
||||||
self._pre_brightness_buffer
|
|
||||||
if self._pre_brightness_buffer is not None
|
|
||||||
else self._post_brightness_buffer
|
|
||||||
)
|
|
||||||
value = [
|
|
||||||
buffer[start + self._byteorder[0]],
|
|
||||||
buffer[start + self._byteorder[1]],
|
|
||||||
buffer[start + self._byteorder[2]],
|
|
||||||
]
|
|
||||||
if self._has_white:
|
|
||||||
value.append(buffer[start + self._byteorder[3]])
|
|
||||||
elif self._dotstar_mode:
|
|
||||||
value.append(
|
|
||||||
(buffer[start + self._byteorder[3]] & DOTSTAR_LED_BRIGHTNESS) / 31.0
|
|
||||||
)
|
|
||||||
return value
|
|
||||||
|
|
||||||
def __getitem__(self, index):
|
|
||||||
if isinstance(index, slice):
|
|
||||||
out = []
|
|
||||||
for in_i in range(
|
|
||||||
*index.indices(len(self._post_brightness_buffer) // self._bpp)
|
|
||||||
):
|
|
||||||
out.append(self._getitem(in_i))
|
|
||||||
return out
|
|
||||||
if index < 0:
|
|
||||||
index += len(self)
|
|
||||||
if index >= self._pixels or index < 0:
|
|
||||||
raise IndexError
|
|
||||||
return self._getitem(index)
|
|
||||||
|
|
||||||
def _transmit(self, buffer):
|
|
||||||
raise NotImplementedError("Must be subclassed")
|
|
||||||
|
|
||||||
|
|
||||||
def wheel(pos):
|
|
||||||
"""
|
|
||||||
Helper to create a colorwheel.
|
|
||||||
|
|
||||||
:param pos: int 0-255 of color value to return
|
|
||||||
:return: tuple of RGB values
|
|
||||||
"""
|
|
||||||
# Input a value 0 to 255 to get a color value.
|
|
||||||
# The colours are a transition r - g - b - back to r.
|
|
||||||
if pos < 0 or pos > 255:
|
|
||||||
return 0, 0, 0
|
|
||||||
if pos < 85:
|
|
||||||
return 255 - pos * 3, pos * 3, 0
|
|
||||||
if pos < 170:
|
|
||||||
pos -= 85
|
|
||||||
return 0, 255 - pos * 3, pos * 3
|
|
||||||
pos -= 170
|
|
||||||
return pos * 3, 0, 255 - pos * 3
|
|
@ -1,47 +0,0 @@
|
|||||||
# FeatherS2 Helper Library
|
|
||||||
# 2020 Seon Rozenblum, Unexpected Maker
|
|
||||||
#
|
|
||||||
# Project home:
|
|
||||||
# https://feathers2.io
|
|
||||||
#
|
|
||||||
|
|
||||||
# Import required libraries
|
|
||||||
import time
|
|
||||||
import board
|
|
||||||
from digitalio import DigitalInOut, Direction, Pull
|
|
||||||
|
|
||||||
|
|
||||||
# Helper functions
|
|
||||||
|
|
||||||
def enable_LDO2(state):
|
|
||||||
"""Set the power for the second on-board LDO to allow no current draw when not needed."""
|
|
||||||
|
|
||||||
# Grab a reference to the LDO2 IO (21 in this case)
|
|
||||||
ldo2 = DigitalInOut(board.LDO2)
|
|
||||||
ldo2.direction = Direction.OUTPUT
|
|
||||||
|
|
||||||
# Set the LDO2 power pin on / off
|
|
||||||
ldo2.value = state
|
|
||||||
|
|
||||||
# A small delay to let the IO change state
|
|
||||||
time.sleep(0.035)
|
|
||||||
|
|
||||||
|
|
||||||
# Dotstar rainbow colour wheel
|
|
||||||
def dotstar_color_wheel(wheel_pos):
|
|
||||||
"""Color wheel to allow for cycling through the rainbow of RGB colors."""
|
|
||||||
wheel_pos = wheel_pos % 255
|
|
||||||
|
|
||||||
if wheel_pos < 85:
|
|
||||||
return 255 - wheel_pos * 3, 0, wheel_pos * 3
|
|
||||||
elif wheel_pos < 170:
|
|
||||||
wheel_pos -= 85
|
|
||||||
return 0, wheel_pos * 3, 255 - wheel_pos * 3
|
|
||||||
else:
|
|
||||||
wheel_pos -= 170
|
|
||||||
return wheel_pos * 3, 255 - wheel_pos * 3, 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Disable LDO2 by default
|
|
||||||
enable_LDO2(False)
|
|
@ -30,11 +30,9 @@
|
|||||||
#define MICROPY_HW_MCU_NAME "ESP32S2"
|
#define MICROPY_HW_MCU_NAME "ESP32S2"
|
||||||
|
|
||||||
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)
|
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)
|
||||||
|
#define BOARD_USER_SAFE_MODE_ACTION translate("pressing boot button at start up.\n")
|
||||||
#define BOARD_USER_SAFE_MODE_ACTION "pressing boot button at start up.\n"
|
|
||||||
|
|
||||||
#define AUTORESET_DELAY_MS 500
|
#define AUTORESET_DELAY_MS 500
|
||||||
|
|
||||||
// Doesn't work with this on.
|
#define MICROPY_HW_APA102_MOSI (&pin_GPIO40)
|
||||||
// #define MICROPY_HW_APA102_MOSI (&pin_GPIO44)
|
#define MICROPY_HW_APA102_SCK (&pin_GPIO45)
|
||||||
// #define MICROPY_HW_APA102_SCK (&pin_GPIO45)
|
|
@ -1,198 +0,0 @@
|
|||||||
# 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
|
|
||||||
# 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
|
|
||||||
# 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 (for CircuitPython 5.0+ with _pixelbuf)
|
|
||||||
=================================================================================
|
|
||||||
|
|
||||||
* Author(s): Damien P. George, Limor Fried, Scott Shawcroft & Roy Hooper
|
|
||||||
"""
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# 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"""
|
|
||||||
|
|
||||||
|
|
||||||
class DotStar(_pixelbuf.PixelBuf):
|
|
||||||
"""
|
|
||||||
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 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
|
|
||||||
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.
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
.. 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
|
|
||||||
):
|
|
||||||
self._spi = None
|
|
||||||
try:
|
|
||||||
self._spi = busio.SPI(clock, MOSI=data)
|
|
||||||
while not self._spi.try_lock():
|
|
||||||
pass
|
|
||||||
self._spi.configure(baudrate=baudrate)
|
|
||||||
|
|
||||||
except (NotImplementedError, 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
|
|
||||||
|
|
||||||
# Supply one extra clock cycle for each two pixels in the strip.
|
|
||||||
trailer_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,
|
|
||||||
)
|
|
||||||
|
|
||||||
def deinit(self):
|
|
||||||
"""Blank out the DotStars and release the resources."""
|
|
||||||
self.fill(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]) + "]"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def n(self):
|
|
||||||
"""
|
|
||||||
The number of dotstars in the chain (read-only)
|
|
||||||
"""
|
|
||||||
return len(self)
|
|
||||||
|
|
||||||
def _transmit(self, buffer):
|
|
||||||
if self._spi:
|
|
||||||
self._spi.write(buffer)
|
|
||||||
else:
|
|
||||||
self._ds_writebytes(buffer)
|
|
||||||
|
|
||||||
def _ds_writebytes(self, buffer):
|
|
||||||
for b in buffer:
|
|
||||||
for _ in range(8):
|
|
||||||
self.dpin.value = b & 0x80
|
|
||||||
self.cpin.value = True
|
|
||||||
self.cpin.value = False
|
|
||||||
b = b << 1
|
|
||||||
self.cpin.value = False
|
|
@ -1,374 +0,0 @@
|
|||||||
# The MIT License (MIT)
|
|
||||||
#
|
|
||||||
# Based on the Adafruit NeoPixel and Adafruit Dotstar CircuitPython drivers.
|
|
||||||
# Copyright (c) 2019-2020 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
|
|
||||||
# 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_pypixelbuf` - A pure python implementation of _pixelbuf
|
|
||||||
=================================================================
|
|
||||||
This class is used when _pixelbuf is not available in CircuitPython. It is based on the work
|
|
||||||
in neopixel.py and adafruit_dotstar.py.
|
|
||||||
|
|
||||||
* Author(s): Damien P. George & Limor Fried & Scott Shawcroft & Roy Hooper
|
|
||||||
"""
|
|
||||||
|
|
||||||
DOTSTAR_LED_START_FULL_BRIGHT = 0xFF
|
|
||||||
DOTSTAR_LED_START = 0b11100000 # Three "1" bits, followed by 5 brightness bits
|
|
||||||
DOTSTAR_LED_BRIGHTNESS = 0b00011111
|
|
||||||
|
|
||||||
|
|
||||||
class PixelBuf: # pylint: disable=too-many-instance-attributes
|
|
||||||
"""
|
|
||||||
A sequence of RGB/RGBW pixels.
|
|
||||||
|
|
||||||
This is the pure python implementation of CircuitPython's _pixelbuf.
|
|
||||||
|
|
||||||
:param ~int n: Number of pixels
|
|
||||||
:param ~str byteorder: Byte order string constant (also sets bpp)
|
|
||||||
:param ~float brightness: Brightness (0 to 1.0, default 1.0)
|
|
||||||
:param ~bool auto_write: Whether to automatically write pixels (Default False)
|
|
||||||
:param bytes header: Sequence of bytes to always send before pixel values.
|
|
||||||
:param bytes trailer: Sequence of bytes to always send after pixel values.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__( # pylint: disable=too-many-locals,too-many-arguments
|
|
||||||
self,
|
|
||||||
n,
|
|
||||||
byteorder="BGR",
|
|
||||||
brightness=1.0,
|
|
||||||
auto_write=False,
|
|
||||||
header=None,
|
|
||||||
trailer=None,
|
|
||||||
):
|
|
||||||
|
|
||||||
bpp, byteorder_tuple, has_white, dotstar_mode = self.parse_byteorder(byteorder)
|
|
||||||
|
|
||||||
self.auto_write = False
|
|
||||||
|
|
||||||
effective_bpp = 4 if dotstar_mode else bpp
|
|
||||||
_bytes = effective_bpp * n
|
|
||||||
buf = bytearray(_bytes)
|
|
||||||
offset = 0
|
|
||||||
|
|
||||||
if header is not None:
|
|
||||||
if not isinstance(header, bytearray):
|
|
||||||
raise TypeError("header must be a bytearray")
|
|
||||||
buf = header + buf
|
|
||||||
offset = len(header)
|
|
||||||
|
|
||||||
if trailer is not None:
|
|
||||||
if not isinstance(trailer, bytearray):
|
|
||||||
raise TypeError("trailer must be a bytearray")
|
|
||||||
buf += trailer
|
|
||||||
|
|
||||||
self._pixels = n
|
|
||||||
self._bytes = _bytes
|
|
||||||
self._byteorder = byteorder_tuple
|
|
||||||
self._byteorder_string = byteorder
|
|
||||||
self._has_white = has_white
|
|
||||||
self._bpp = bpp
|
|
||||||
self._pre_brightness_buffer = None
|
|
||||||
self._post_brightness_buffer = buf
|
|
||||||
self._offset = offset
|
|
||||||
self._dotstar_mode = dotstar_mode
|
|
||||||
self._pixel_step = effective_bpp
|
|
||||||
|
|
||||||
if dotstar_mode:
|
|
||||||
self._byteorder_tuple = (
|
|
||||||
byteorder_tuple[0] + 1,
|
|
||||||
byteorder_tuple[1] + 1,
|
|
||||||
byteorder_tuple[2] + 1,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
# Initialize the buffer with the dotstar start bytes.
|
|
||||||
for i in range(self._offset, self._bytes + self._offset, 4):
|
|
||||||
self._post_brightness_buffer[i] = DOTSTAR_LED_START_FULL_BRIGHT
|
|
||||||
|
|
||||||
self._brightness = 1.0
|
|
||||||
self.brightness = brightness
|
|
||||||
|
|
||||||
self.auto_write = auto_write
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def parse_byteorder(byteorder):
|
|
||||||
"""
|
|
||||||
Parse a Byteorder string for validity and determine bpp, byte order, and
|
|
||||||
dostar brightness bits.
|
|
||||||
|
|
||||||
Byteorder strings may contain the following characters:
|
|
||||||
R - Red
|
|
||||||
G - Green
|
|
||||||
B - Blue
|
|
||||||
W - White
|
|
||||||
P - PWM (PWM Duty cycle for pixel - dotstars 0 - 1.0)
|
|
||||||
|
|
||||||
:param: ~str bpp: bpp string.
|
|
||||||
:return: ~tuple: bpp, byteorder, has_white, dotstar_mode
|
|
||||||
"""
|
|
||||||
bpp = len(byteorder)
|
|
||||||
dotstar_mode = False
|
|
||||||
has_white = False
|
|
||||||
|
|
||||||
if byteorder.strip("RGBWP") != "":
|
|
||||||
raise ValueError("Invalid Byteorder string")
|
|
||||||
|
|
||||||
try:
|
|
||||||
r = byteorder.index("R")
|
|
||||||
g = byteorder.index("G")
|
|
||||||
b = byteorder.index("B")
|
|
||||||
except ValueError:
|
|
||||||
raise ValueError("Invalid Byteorder string")
|
|
||||||
if "W" in byteorder:
|
|
||||||
w = byteorder.index("W")
|
|
||||||
byteorder = (r, g, b, w)
|
|
||||||
has_white = True
|
|
||||||
elif "P" in byteorder:
|
|
||||||
lum = byteorder.index("P")
|
|
||||||
byteorder = (r, g, b, lum)
|
|
||||||
dotstar_mode = True
|
|
||||||
else:
|
|
||||||
byteorder = (r, g, b)
|
|
||||||
|
|
||||||
return bpp, byteorder, has_white, dotstar_mode
|
|
||||||
|
|
||||||
@property
|
|
||||||
def bpp(self):
|
|
||||||
"""
|
|
||||||
The number of bytes per pixel in the buffer (read-only).
|
|
||||||
"""
|
|
||||||
return self._bpp
|
|
||||||
|
|
||||||
@property
|
|
||||||
def brightness(self):
|
|
||||||
"""
|
|
||||||
Float value between 0 and 1. Output brightness.
|
|
||||||
|
|
||||||
When brightness is less than 1.0, a second buffer will be used to store the color values
|
|
||||||
before they are adjusted for brightness.
|
|
||||||
"""
|
|
||||||
return self._brightness
|
|
||||||
|
|
||||||
@brightness.setter
|
|
||||||
def brightness(self, value):
|
|
||||||
value = min(max(value, 0.0), 1.0)
|
|
||||||
change = value - self._brightness
|
|
||||||
if -0.001 < change < 0.001:
|
|
||||||
return
|
|
||||||
|
|
||||||
self._brightness = value
|
|
||||||
|
|
||||||
if self._pre_brightness_buffer is None:
|
|
||||||
self._pre_brightness_buffer = bytearray(self._post_brightness_buffer)
|
|
||||||
|
|
||||||
# Adjust brightness of existing pixels
|
|
||||||
offset_check = self._offset % self._pixel_step
|
|
||||||
for i in range(self._offset, self._bytes + self._offset):
|
|
||||||
# Don't adjust per-pixel luminance bytes in dotstar mode
|
|
||||||
if self._dotstar_mode and (i % 4 != offset_check):
|
|
||||||
continue
|
|
||||||
self._post_brightness_buffer[i] = int(
|
|
||||||
self._pre_brightness_buffer[i] * self._brightness
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.auto_write:
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def byteorder(self):
|
|
||||||
"""
|
|
||||||
ByteOrder string for the buffer (read-only)
|
|
||||||
"""
|
|
||||||
return self._byteorder_string
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
"""
|
|
||||||
Number of pixels.
|
|
||||||
"""
|
|
||||||
return self._pixels
|
|
||||||
|
|
||||||
def show(self):
|
|
||||||
"""
|
|
||||||
Call the associated write function to display the pixels
|
|
||||||
"""
|
|
||||||
return self._transmit(self._post_brightness_buffer)
|
|
||||||
|
|
||||||
def fill(self, color):
|
|
||||||
"""
|
|
||||||
Fills the given pixelbuf with the given color.
|
|
||||||
:param pixelbuf: A pixel object.
|
|
||||||
:param color: Color to set.
|
|
||||||
"""
|
|
||||||
r, g, b, w = self._parse_color(color)
|
|
||||||
for i in range(self._pixels):
|
|
||||||
self._set_item(i, r, g, b, w)
|
|
||||||
if self.auto_write:
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
def _parse_color(self, value):
|
|
||||||
r = 0
|
|
||||||
g = 0
|
|
||||||
b = 0
|
|
||||||
w = 0
|
|
||||||
if isinstance(value, int):
|
|
||||||
r = value >> 16
|
|
||||||
g = (value >> 8) & 0xFF
|
|
||||||
b = value & 0xFF
|
|
||||||
w = 0
|
|
||||||
|
|
||||||
if self._dotstar_mode:
|
|
||||||
w = 1.0
|
|
||||||
else:
|
|
||||||
if len(value) < 3 or len(value) > 4:
|
|
||||||
raise ValueError(
|
|
||||||
"Expected tuple of length {}, got {}".format(self._bpp, len(value))
|
|
||||||
)
|
|
||||||
if len(value) == self._bpp:
|
|
||||||
if self._bpp == 3:
|
|
||||||
r, g, b = value
|
|
||||||
else:
|
|
||||||
r, g, b, w = value
|
|
||||||
elif len(value) == 3:
|
|
||||||
r, g, b = value
|
|
||||||
if self._dotstar_mode:
|
|
||||||
w = 1.0
|
|
||||||
|
|
||||||
if self._bpp == 4:
|
|
||||||
if self._dotstar_mode:
|
|
||||||
# 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
|
|
||||||
w = (int(w * 31) & 0b00011111) | DOTSTAR_LED_START
|
|
||||||
elif (
|
|
||||||
self._has_white
|
|
||||||
and (isinstance(value, int) or len(value) == 3)
|
|
||||||
and r == g
|
|
||||||
and g == b
|
|
||||||
):
|
|
||||||
# If all components are the same and we have a white pixel then use it
|
|
||||||
# instead of the individual components when all 4 values aren't explicitly given.
|
|
||||||
w = r
|
|
||||||
r = 0
|
|
||||||
g = 0
|
|
||||||
b = 0
|
|
||||||
|
|
||||||
return (r, g, b, w)
|
|
||||||
|
|
||||||
def _set_item(
|
|
||||||
self, index, r, g, b, w
|
|
||||||
): # pylint: disable=too-many-locals,too-many-branches,too-many-arguments
|
|
||||||
if index < 0:
|
|
||||||
index += len(self)
|
|
||||||
if index >= self._pixels or index < 0:
|
|
||||||
raise IndexError
|
|
||||||
offset = self._offset + (index * self._bpp)
|
|
||||||
|
|
||||||
if self._pre_brightness_buffer is not None:
|
|
||||||
if self._bpp == 4:
|
|
||||||
self._pre_brightness_buffer[offset + self._byteorder[3]] = w
|
|
||||||
self._pre_brightness_buffer[offset + self._byteorder[0]] = r
|
|
||||||
self._pre_brightness_buffer[offset + self._byteorder[1]] = g
|
|
||||||
self._pre_brightness_buffer[offset + self._byteorder[2]] = b
|
|
||||||
|
|
||||||
if self._bpp == 4:
|
|
||||||
# Only apply brightness if w is actually white (aka not DotStar.)
|
|
||||||
if not self._dotstar_mode:
|
|
||||||
w = int(w * self._brightness)
|
|
||||||
self._post_brightness_buffer[offset + self._byteorder[3]] = w
|
|
||||||
|
|
||||||
self._post_brightness_buffer[offset + self._byteorder[0]] = int(
|
|
||||||
r * self._brightness
|
|
||||||
)
|
|
||||||
self._post_brightness_buffer[offset + self._byteorder[1]] = int(
|
|
||||||
g * self._brightness
|
|
||||||
)
|
|
||||||
self._post_brightness_buffer[offset + self._byteorder[2]] = int(
|
|
||||||
b * self._brightness
|
|
||||||
)
|
|
||||||
|
|
||||||
def __setitem__(self, index, val):
|
|
||||||
if isinstance(index, slice):
|
|
||||||
start, stop, step = index.indices(self._pixels)
|
|
||||||
for val_i, in_i in enumerate(range(start, stop, step)):
|
|
||||||
r, g, b, w = self._parse_color(val[val_i])
|
|
||||||
self._set_item(in_i, r, g, b, w)
|
|
||||||
else:
|
|
||||||
r, g, b, w = self._parse_color(val)
|
|
||||||
self._set_item(index, r, g, b, w)
|
|
||||||
|
|
||||||
if self.auto_write:
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
def _getitem(self, index):
|
|
||||||
start = self._offset + (index * self._bpp)
|
|
||||||
buffer = (
|
|
||||||
self._pre_brightness_buffer
|
|
||||||
if self._pre_brightness_buffer is not None
|
|
||||||
else self._post_brightness_buffer
|
|
||||||
)
|
|
||||||
value = [
|
|
||||||
buffer[start + self._byteorder[0]],
|
|
||||||
buffer[start + self._byteorder[1]],
|
|
||||||
buffer[start + self._byteorder[2]],
|
|
||||||
]
|
|
||||||
if self._has_white:
|
|
||||||
value.append(buffer[start + self._byteorder[3]])
|
|
||||||
elif self._dotstar_mode:
|
|
||||||
value.append(
|
|
||||||
(buffer[start + self._byteorder[3]] & DOTSTAR_LED_BRIGHTNESS) / 31.0
|
|
||||||
)
|
|
||||||
return value
|
|
||||||
|
|
||||||
def __getitem__(self, index):
|
|
||||||
if isinstance(index, slice):
|
|
||||||
out = []
|
|
||||||
for in_i in range(
|
|
||||||
*index.indices(len(self._post_brightness_buffer) // self._bpp)
|
|
||||||
):
|
|
||||||
out.append(self._getitem(in_i))
|
|
||||||
return out
|
|
||||||
if index < 0:
|
|
||||||
index += len(self)
|
|
||||||
if index >= self._pixels or index < 0:
|
|
||||||
raise IndexError
|
|
||||||
return self._getitem(index)
|
|
||||||
|
|
||||||
def _transmit(self, buffer):
|
|
||||||
raise NotImplementedError("Must be subclassed")
|
|
||||||
|
|
||||||
|
|
||||||
def wheel(pos):
|
|
||||||
"""
|
|
||||||
Helper to create a colorwheel.
|
|
||||||
|
|
||||||
:param pos: int 0-255 of color value to return
|
|
||||||
:return: tuple of RGB values
|
|
||||||
"""
|
|
||||||
# Input a value 0 to 255 to get a color value.
|
|
||||||
# The colours are a transition r - g - b - back to r.
|
|
||||||
if pos < 0 or pos > 255:
|
|
||||||
return 0, 0, 0
|
|
||||||
if pos < 85:
|
|
||||||
return 255 - pos * 3, pos * 3, 0
|
|
||||||
if pos < 170:
|
|
||||||
pos -= 85
|
|
||||||
return 0, 255 - pos * 3, pos * 3
|
|
||||||
pos -= 170
|
|
||||||
return pos * 3, 0, 255 - pos * 3
|
|
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
|
||||||
*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2020 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "boards/board.h"
|
|
||||||
#include "mpconfigboard.h"
|
|
||||||
#include "shared-bindings/microcontroller/Pin.h"
|
|
||||||
|
|
||||||
void board_init(void) {
|
|
||||||
// USB
|
|
||||||
common_hal_never_reset_pin(&pin_GPIO19);
|
|
||||||
common_hal_never_reset_pin(&pin_GPIO20);
|
|
||||||
|
|
||||||
// Debug UART
|
|
||||||
common_hal_never_reset_pin(&pin_GPIO43);
|
|
||||||
common_hal_never_reset_pin(&pin_GPIO44);
|
|
||||||
|
|
||||||
// SPI Flash and RAM
|
|
||||||
common_hal_never_reset_pin(&pin_GPIO26);
|
|
||||||
common_hal_never_reset_pin(&pin_GPIO27);
|
|
||||||
common_hal_never_reset_pin(&pin_GPIO28);
|
|
||||||
common_hal_never_reset_pin(&pin_GPIO29);
|
|
||||||
common_hal_never_reset_pin(&pin_GPIO30);
|
|
||||||
common_hal_never_reset_pin(&pin_GPIO31);
|
|
||||||
common_hal_never_reset_pin(&pin_GPIO32);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool board_requests_safe_mode(void) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset_board(void) {
|
|
||||||
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the MicroPython project, http://micropython.org/
|
|
||||||
*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2019 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//Micropython setup
|
|
||||||
|
|
||||||
#define MICROPY_HW_BOARD_NAME "ProS2"
|
|
||||||
#define MICROPY_HW_MCU_NAME "ESP32S2"
|
|
||||||
|
|
||||||
#define AUTORESET_DELAY_MS 500
|
|
||||||
|
|
||||||
#define MICROPY_HW_APA102_MOSI (&pin_GPIO40)
|
|
||||||
#define MICROPY_HW_APA102_SCK (&pin_GPIO45)
|
|
@ -1,21 +0,0 @@
|
|||||||
USB_VID = 0x239A
|
|
||||||
USB_PID = 0x80AA
|
|
||||||
USB_PRODUCT = "ProS2"
|
|
||||||
USB_MANUFACTURER = "UnexpectedMaker"
|
|
||||||
USB_DEVICES = "CDC,MSC,HID"
|
|
||||||
|
|
||||||
INTERNAL_FLASH_FILESYSTEM = 1
|
|
||||||
LONGINT_IMPL = MPZ
|
|
||||||
|
|
||||||
# The default queue depth of 16 overflows on release builds,
|
|
||||||
# so increase it to 32.
|
|
||||||
CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32
|
|
||||||
|
|
||||||
CIRCUITPY_ESP_FLASH_MODE=qio
|
|
||||||
CIRCUITPY_ESP_FLASH_FREQ=40m
|
|
||||||
CIRCUITPY_ESP_FLASH_SIZE=16MB
|
|
||||||
|
|
||||||
CIRCUITPY_BITBANG_APA102 = 1
|
|
||||||
|
|
||||||
# Include these Python libraries in firmware.
|
|
||||||
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DotStar
|
|
@ -1,58 +0,0 @@
|
|||||||
#include "shared-bindings/board/__init__.h"
|
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO17) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO17) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO18) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO18) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO4) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO4) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO12) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO12) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO6) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO6) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO5) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D19), MP_ROM_PTR(&pin_GPIO5) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO36) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D25), MP_ROM_PTR(&pin_GPIO36) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO35) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D24), MP_ROM_PTR(&pin_GPIO35) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO37) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_GPIO37) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO44) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO43) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO8) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO9) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO1) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO3) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO7) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO8) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO9) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO10) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO11) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_GPIO40) }, // MTDO
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_GPIO45) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_LDO2), MP_ROM_PTR(&pin_GPIO21) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_VBAT_SENSE), MP_ROM_PTR(&pin_GPIO14) },
|
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
|
|
||||||
};
|
|
||||||
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
|
|
@ -1,63 +0,0 @@
|
|||||||
# Pros2 Helper Library
|
|
||||||
# 2020 Seon Rozenblum, Unexpected Maker
|
|
||||||
#
|
|
||||||
# Project home:
|
|
||||||
# https://pros2.io
|
|
||||||
#
|
|
||||||
|
|
||||||
# Import required libraries
|
|
||||||
import time
|
|
||||||
import board
|
|
||||||
from digitalio import DigitalInOut, Direction, Pull
|
|
||||||
from analogio import AnalogIn
|
|
||||||
|
|
||||||
|
|
||||||
# Helper functions
|
|
||||||
|
|
||||||
def enable_LDO2(state):
|
|
||||||
"""Set the power for the second on-board LDO to allow no current draw when not needed."""
|
|
||||||
|
|
||||||
# Grab a reference to the LDO2 IO (21 in this case)
|
|
||||||
ldo2 = DigitalInOut(board.LDO2)
|
|
||||||
ldo2.direction = Direction.OUTPUT
|
|
||||||
|
|
||||||
# Set the LDO2 power pin on / off
|
|
||||||
ldo2.value = state
|
|
||||||
|
|
||||||
# A small delay to let the IO change state
|
|
||||||
time.sleep(0.035)
|
|
||||||
|
|
||||||
|
|
||||||
# Dotstar rainbow colour wheel
|
|
||||||
def dotstar_color_wheel(wheel_pos):
|
|
||||||
"""Color wheel to allow for cycling through the rainbow of RGB colors."""
|
|
||||||
wheel_pos = wheel_pos % 255
|
|
||||||
|
|
||||||
if wheel_pos < 85:
|
|
||||||
return 255 - wheel_pos * 3, 0, wheel_pos * 3
|
|
||||||
elif wheel_pos < 170:
|
|
||||||
wheel_pos -= 85
|
|
||||||
return 0, wheel_pos * 3, 255 - wheel_pos * 3
|
|
||||||
else:
|
|
||||||
wheel_pos -= 170
|
|
||||||
return wheel_pos * 3, 255 - wheel_pos * 3, 0
|
|
||||||
|
|
||||||
|
|
||||||
# Get a *rough* estimate of the current battery voltage
|
|
||||||
# If the battery is not present, the charge IC will still report it's trying to charge at X voltage
|
|
||||||
# so it will still show a voltage.
|
|
||||||
def get_battery_voltage():
|
|
||||||
"""
|
|
||||||
Returns the current battery voltage. If no battery is connected, returns 3.7V
|
|
||||||
This is an approximation only, but useful to detect of the charge state of the battery is getting low.
|
|
||||||
"""
|
|
||||||
adc = AnalogIn(board.VBAT_SENSE)
|
|
||||||
|
|
||||||
measured_vbat = adc.value # Read the value
|
|
||||||
measured_vbat /= 4095 # divide by 4095 as we are using the default ADC voltage range of 0-1V
|
|
||||||
measured_vbat *= 3.7 # Multiply by 3.7V, our reference voltage
|
|
||||||
return measured_vbat
|
|
||||||
|
|
||||||
|
|
||||||
# Disable LDO2 by default
|
|
||||||
enable_LDO2(False)
|
|
@ -1,35 +0,0 @@
|
|||||||
CONFIG_ESP32S2_SPIRAM_SUPPORT=y
|
|
||||||
|
|
||||||
#
|
|
||||||
# SPI RAM config
|
|
||||||
#
|
|
||||||
# CONFIG_SPIRAM_TYPE_AUTO is not set
|
|
||||||
# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set
|
|
||||||
# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set
|
|
||||||
CONFIG_SPIRAM_TYPE_ESPPSRAM64=y
|
|
||||||
CONFIG_SPIRAM_SIZE=8388608
|
|
||||||
|
|
||||||
#
|
|
||||||
# PSRAM clock and cs IO for ESP32S2
|
|
||||||
#
|
|
||||||
CONFIG_DEFAULT_PSRAM_CLK_IO=30
|
|
||||||
CONFIG_DEFAULT_PSRAM_CS_IO=26
|
|
||||||
# end of PSRAM clock and cs IO for ESP32S2
|
|
||||||
|
|
||||||
CONFIG_SPIRAM_SPIWP_SD3_PIN=28
|
|
||||||
# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set
|
|
||||||
# CONFIG_SPIRAM_RODATA is not set
|
|
||||||
# CONFIG_SPIRAM_USE_AHB_DBUS3 is not set
|
|
||||||
# CONFIG_SPIRAM_SPEED_80M is not set
|
|
||||||
CONFIG_SPIRAM_SPEED_40M=y
|
|
||||||
# CONFIG_SPIRAM_SPEED_26M is not set
|
|
||||||
# CONFIG_SPIRAM_SPEED_20M is not set
|
|
||||||
CONFIG_SPIRAM=y
|
|
||||||
CONFIG_SPIRAM_BOOT_INIT=y
|
|
||||||
# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set
|
|
||||||
CONFIG_SPIRAM_USE_MEMMAP=y
|
|
||||||
# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set
|
|
||||||
# CONFIG_SPIRAM_USE_MALLOC is not set
|
|
||||||
CONFIG_SPIRAM_MEMTEST=y
|
|
||||||
# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set
|
|
||||||
# end of SPI RAM config
|
|
Loading…
x
Reference in New Issue
Block a user