Updated UM boards
This commit is contained in:
parent
2bb44f6c4d
commit
a2a0aa058f
198
ports/esp32s2/boards/unexpectedmaker_feathers2/adafruit_dotstar.py
Executable file
198
ports/esp32s2/boards/unexpectedmaker_feathers2/adafruit_dotstar.py
Executable file
@ -0,0 +1,198 @@
|
|||||||
|
# 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
|
374
ports/esp32s2/boards/unexpectedmaker_feathers2/adafruit_pypixelbuf.py
Executable file
374
ports/esp32s2/boards/unexpectedmaker_feathers2/adafruit_pypixelbuf.py
Executable file
@ -0,0 +1,374 @@
|
|||||||
|
# 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
|
311
ports/esp32s2/boards/unexpectedmaker_feathers2/adafruit_requests.py
Executable file
311
ports/esp32s2/boards/unexpectedmaker_feathers2/adafruit_requests.py
Executable file
@ -0,0 +1,311 @@
|
|||||||
|
# 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)
|
47
ports/esp32s2/boards/unexpectedmaker_feathers2/feathers2.py
Normal file
47
ports/esp32s2/boards/unexpectedmaker_feathers2/feathers2.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# 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)
|
@ -35,6 +35,5 @@
|
|||||||
|
|
||||||
#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)
|
|
||||||
|
@ -16,3 +16,7 @@ CIRCUITPY_ESP_FLASH_FREQ=40m
|
|||||||
CIRCUITPY_ESP_FLASH_SIZE=16MB
|
CIRCUITPY_ESP_FLASH_SIZE=16MB
|
||||||
|
|
||||||
CIRCUITPY_BITBANG_APA102 = 1
|
CIRCUITPY_BITBANG_APA102 = 1
|
||||||
|
|
||||||
|
# Include these Python libraries in firmware.
|
||||||
|
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DotStar
|
||||||
|
|
||||||
|
@ -1,55 +1,103 @@
|
|||||||
#include "shared-bindings/board/__init__.h"
|
#include "shared-bindings/board/__init__.h"
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
|
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO17) },
|
{ 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_D14), MP_ROM_PTR(&pin_GPIO17) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO18) },
|
{ 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_D15), MP_ROM_PTR(&pin_GPIO18) },
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO14) },
|
{ MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO14) },
|
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO13) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO13) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO12) },
|
{ 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_D17), MP_ROM_PTR(&pin_GPIO12) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO6) },
|
{ 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_D18), MP_ROM_PTR(&pin_GPIO6) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO5) },
|
{ 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_D19), MP_ROM_PTR(&pin_GPIO5) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO36) },
|
{ 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_D25), MP_ROM_PTR(&pin_GPIO36) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO35) },
|
{ 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_D24), MP_ROM_PTR(&pin_GPIO35) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO37) },
|
{ 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_D23), MP_ROM_PTR(&pin_GPIO37) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO44) },
|
{ 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_RX), MP_ROM_PTR(&pin_GPIO44) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) },
|
||||||
{ 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) },
|
||||||
|
|
||||||
// Moving to 9 and 8
|
{ MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO38) },
|
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO8) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO33) },
|
|
||||||
{ 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_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_GPIO44) }, // MTDO
|
{ 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_D11), MP_ROM_PTR(&pin_GPIO9) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO0) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO1) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_A10), MP_ROM_PTR(&pin_GPIO1) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO3) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_GPIO3) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO7) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_GPIO7) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_D20), MP_ROM_PTR(&pin_GPIO33) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO38) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO10) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO10) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO11), 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_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_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) },
|
||||||
|
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_LDO2), MP_ROM_PTR(&pin_GPIO21) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO13) },
|
{ MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO13) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_AMB), MP_ROM_PTR(&pin_GPIO4) },
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
|
{ 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_SPI), MP_ROM_PTR(&board_spi_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
|
||||||
|
198
ports/esp32s2/boards/unexpectedmaker_feathers2_prerelease/adafruit_dotstar.py
Executable file
198
ports/esp32s2/boards/unexpectedmaker_feathers2_prerelease/adafruit_dotstar.py
Executable file
@ -0,0 +1,198 @@
|
|||||||
|
# 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
|
374
ports/esp32s2/boards/unexpectedmaker_feathers2_prerelease/adafruit_pypixelbuf.py
Executable file
374
ports/esp32s2/boards/unexpectedmaker_feathers2_prerelease/adafruit_pypixelbuf.py
Executable file
@ -0,0 +1,374 @@
|
|||||||
|
# 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
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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) {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
# 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)
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* 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 "FeatherS2"
|
||||||
|
#define MICROPY_HW_MCU_NAME "ESP32S2"
|
||||||
|
|
||||||
|
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)
|
||||||
|
|
||||||
|
#define BOARD_USER_SAFE_MODE_ACTION "pressing boot button at start up.\n"
|
||||||
|
|
||||||
|
#define AUTORESET_DELAY_MS 500
|
||||||
|
|
||||||
|
// Doesn't work with this on.
|
||||||
|
// #define MICROPY_HW_APA102_MOSI (&pin_GPIO44)
|
||||||
|
// #define MICROPY_HW_APA102_SCK (&pin_GPIO45)
|
@ -0,0 +1,21 @@
|
|||||||
|
USB_VID = 0x239A
|
||||||
|
USB_PID = 0x80AC
|
||||||
|
USB_PRODUCT = "FeatherS2"
|
||||||
|
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
|
@ -0,0 +1,56 @@
|
|||||||
|
#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_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) },
|
||||||
|
|
||||||
|
// Moving to 9 and 8
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO38) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO33) },
|
||||||
|
{ 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_LED), MP_ROM_PTR(&pin_GPIO13) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_AMB), MP_ROM_PTR(&pin_GPIO4) },
|
||||||
|
|
||||||
|
{ 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);
|
@ -0,0 +1,35 @@
|
|||||||
|
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
|
198
ports/esp32s2/boards/unexpectedmaker_pros2/adafruit_dotstar.py
Executable file
198
ports/esp32s2/boards/unexpectedmaker_pros2/adafruit_dotstar.py
Executable file
@ -0,0 +1,198 @@
|
|||||||
|
# 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
|
374
ports/esp32s2/boards/unexpectedmaker_pros2/adafruit_pypixelbuf.py
Executable file
374
ports/esp32s2/boards/unexpectedmaker_pros2/adafruit_pypixelbuf.py
Executable file
@ -0,0 +1,374 @@
|
|||||||
|
# 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
|
56
ports/esp32s2/boards/unexpectedmaker_pros2/board.c
Normal file
56
ports/esp32s2/boards/unexpectedmaker_pros2/board.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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) {
|
||||||
|
|
||||||
|
}
|
35
ports/esp32s2/boards/unexpectedmaker_pros2/mpconfigboard.h
Normal file
35
ports/esp32s2/boards/unexpectedmaker_pros2/mpconfigboard.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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)
|
21
ports/esp32s2/boards/unexpectedmaker_pros2/mpconfigboard.mk
Normal file
21
ports/esp32s2/boards/unexpectedmaker_pros2/mpconfigboard.mk
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
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
|
58
ports/esp32s2/boards/unexpectedmaker_pros2/pins.c
Normal file
58
ports/esp32s2/boards/unexpectedmaker_pros2/pins.c
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#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);
|
63
ports/esp32s2/boards/unexpectedmaker_pros2/pros2.py
Normal file
63
ports/esp32s2/boards/unexpectedmaker_pros2/pros2.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# 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)
|
35
ports/esp32s2/boards/unexpectedmaker_pros2/sdkconfig
Normal file
35
ports/esp32s2/boards/unexpectedmaker_pros2/sdkconfig
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
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…
Reference in New Issue
Block a user