-
-
Save Gadgetoid/35b2cc87f3d07823bb82cdd3e7f12e6d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import atexit | |
import colorsys | |
from rpi_ws281x import __version__ as __rpi_ws281x__, PixelStrip, Color | |
__version__ = '2.2.3' | |
# LED strip configuration: | |
LED_COUNT = 96 # Number of LED pixels. | |
LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!). | |
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) | |
LED_DMA = 10 # DMA channel to use for generating signal | |
LED_BRIGHTNESS = 128 # Set to 0 for darkest and 255 for brightest | |
LED_CHANNEL = 0 # PWM channel | |
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) | |
LED_GAMMA = [ | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, | |
2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, | |
6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, | |
11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, | |
19, 19, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 27, 28, | |
29, 29, 30, 31, 31, 32, 33, 34, 34, 35, 36, 37, 37, 38, 39, 40, | |
40, 41, 42, 43, 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 54, | |
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, | |
71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 88, 89, | |
90, 91, 93, 94, 95, 96, 98, 99,100,102,103,104,106,107,109,110, | |
111,113,114,116,117,119,120,121,123,124,126,128,129,131,132,134, | |
135,137,138,140,142,143,145,146,148,150,151,153,155,157,158,160, | |
162,163,165,167,169,170,172,174,176,178,179,181,183,185,187,189, | |
191,193,194,196,198,200,202,204,206,208,210,212,214,216,218,220, | |
222,224,227,229,231,233,235,237,239,241,244,246,248,250,252,255] | |
ws2812 = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_GAMMA) | |
ws2812.begin() | |
""" | |
Store the rotation of UnicornHat, defaults to | |
0 which places 0,0 on the top left with the B+ | |
HDMI port facing downwards | |
""" | |
_rotation = 0 | |
_requested_rotation = 0 | |
_wx = 8 | |
_wy = 8 | |
_map = [] | |
_pixels = [(0,0,0) for x in range(64)] | |
""" | |
Store a map of pixel indexes for | |
translating x, y coordinates. | |
""" | |
MY_DISPLAY = [ | |
[95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72], | |
[48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71], | |
[47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24], | |
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23] | |
] | |
AUTO = None | |
def set_gamma(gamma): | |
ws2812.setGamma(gamma) | |
def disable_gamma(): | |
set_gamma(list(range(256))) | |
def set_layout(pixel_map = AUTO): | |
"""Set the layout to Unicorn HAT or Unicorn pHAT | |
Note: auto detection relies upon the HAT EEPROM. Your Unicorn HAT | |
must be connected before boot to successfully auto detect. | |
:param pixel_map: Choose the layout to set, can be either HAT, PHAT, PHAT_VERTICAL or AUTO | |
""" | |
global _map | |
if pixel_map is None: | |
pixel_map = MY_DISPLAY | |
_map = pixel_map | |
def get_shape(): | |
"""Returns the shape (width, height) of the display""" | |
global _map | |
return (len(_map), len(_map[0])) | |
def _clean_shutdown(): | |
"""Registered at exit to ensure ws2812 cleans up after itself | |
and all pixels are turned off. | |
""" | |
off() | |
def rotation(r=0): | |
"""Set the display rotation | |
:param r: Specify the rotation in degrees: 0, 90, 180 or 270 | |
""" | |
global _map | |
global _rotation | |
global _requested_rotation | |
if r in [0, 90, 180, 270]: | |
_requested_rotation=r | |
wx = len(_map) | |
wy = len(_map[0]) | |
if wx == wy: | |
_rotation = r | |
else: | |
if r in [0, 180]: | |
_map = PHAT | |
_rotation = r | |
else: | |
_map = PHAT_VERTICAL | |
_rotation = r-90 | |
return True | |
else: | |
raise ValueError('Rotation must be 0, 90, 180 or 270 degrees') | |
def get_rotation(): | |
"""Get the display rotation value | |
Returns an integer, either 0, 90, 180 or 270 | |
""" | |
return _requested_rotation | |
def brightness(b=0.2): | |
"""Set the display brightness between 0.0 and 1.0 | |
0.2 is highly recommended, UnicornHat can get painfully bright! | |
:param b: Brightness from 0.0 to 1.0 (default 0.2) | |
""" | |
if b > 1 or b < 0: | |
raise ValueError('Brightness must be between 0.0 and 1.0') | |
"""Absolute max brightness has been capped to 50%, do not change | |
this unless you know what you're doing. | |
UnicornHAT draws too much current above 50%.""" | |
brightness = int(b*128.0) | |
if brightness < 30: | |
print("Warning: Low brightness chosen, your UnicornHAT might not light up!") | |
ws2812.setBrightness(brightness) | |
def get_brightness(): | |
"""Get the display brightness value | |
Returns a float between 0.0 and 1.0 | |
""" | |
return round(ws2812.getBrightness()/128.0, 3) | |
def clear(): | |
"""Clear the buffer""" | |
for x in range(64): | |
ws2812.setPixelColorRGB(x, 0, 0, 0) | |
_pixels[x] = (0, 0, 0) | |
def off(): | |
"""Clear the buffer and immediately update UnicornHat | |
Turns off all pixels. | |
""" | |
clear() | |
show() | |
def get_index_from_xy(x, y): | |
"""Convert an x, y value to an index on the display | |
:param x: Horizontal position from 0 to 7 | |
:param y: Vertical position from 0 to 7 | |
""" | |
wy = len(_map) - 1 | |
wx = len(_map[0]) - 1 | |
y = (wy)-y | |
if _rotation == 180: | |
x, y = (wx)-x, (wy)-y | |
try: | |
index = _map[y][x] | |
except IndexError: | |
index = None | |
return index | |
def set_pixel_hsv(x, y, h, s=None, v=None): | |
"""Set a single pixel to a colour using HSV | |
:param x: Horizontal position from 0 to 7 | |
:param y: Veritcal position from 0 to 7 | |
:param h: Hue from 0.0 to 1.0 ( IE: degrees around hue wheel/360.0 ) | |
:param s: Saturation from 0.0 to 1.0 | |
:param v: Value (also known as brightness) from 0.0 to 1.0 | |
""" | |
if type(h) is tuple: | |
h, s, v = h | |
r, g, b = [int(n*255) for n in colorsys.hsv_to_rgb(h, s, v)] | |
set_pixel(x, y, r, g, b) | |
def set_pixel(x, y, r, g=None, b=None): | |
"""Set a single pixel to RGB colour | |
:param x: Horizontal position from 0 to 7 | |
:param y: Veritcal position from 0 to 7 | |
:param r: Amount of red from 0 to 255 | |
:param g: Amount of green from 0 to 255 | |
:param b: Amount of blue from 0 to 255 | |
""" | |
if type(r) is tuple: | |
r, g, b = r | |
index = get_index_from_xy(x, y) | |
if index is not None: | |
ws2812.setPixelColorRGB(index, r, g, b) | |
_pixels[index] = (r, g, b) | |
def get_pixel(x, y): | |
"""Get the RGB value of a single pixel | |
:param x: Horizontal position from 0 to 7 | |
:param y: Veritcal position from 0 to 7 | |
""" | |
index = get_index_from_xy(x, y) | |
if index is not None: | |
return _pixels[index] | |
def set_all(r, g=None, b=None): | |
"""Set all pixels to a specific colour""" | |
if type(r) is tuple: | |
r, g, b = r | |
shade_pixels(lambda x, y: (r, g, b)) | |
def shade_pixels(shader): | |
"""Set all pixels using a pixel shader style function | |
:param pixels: A function which accepts the x and y positions of a pixel and returns values r, g and b | |
For example, this would be synonymous to clear:: | |
set_pixels(lambda x, y: return 0,0,0) | |
Or perhaps we want to map red along the horizontal axis, and blue along the vertical:: | |
set_pixels(lambda x, y: return (x/7.0) * 255, 0, (y/7.0) * 255) | |
""" | |
width, height = get_shape() | |
for x in range(width): | |
for y in range(height): | |
r, g, b = shader(x, y) | |
set_pixel(x, y, r, g, b) | |
def set_pixels(pixels): | |
"""Set all pixels using an array of `get_shape()`""" | |
shade_pixels(lambda x, y: pixels[y][x]) | |
def get_pixels(): | |
"""Get the RGB value of all pixels in a 7x7x3 2d array of tuples""" | |
width, height = get_shape() | |
return [[get_pixel(x, y) for x in range(width)] for y in range(height)] | |
def show(): | |
"""Update UnicornHat with the contents of the display buffer""" | |
ws2812.show() | |
set_layout(MY_DISPLAY) | |
atexit.register(_clean_shutdown) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment