|
|
|
@ -1,11 +1,14 @@
|
|
|
|
|
import array
|
|
|
|
|
import random
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
|
|
import asynced
|
|
|
|
|
import iptime
|
|
|
|
|
import machine
|
|
|
|
|
|
|
|
|
|
from neopixel_write import neopixel_write
|
|
|
|
|
import board
|
|
|
|
|
import machine
|
|
|
|
|
import neopixel
|
|
|
|
|
import random
|
|
|
|
|
|
|
|
|
|
RANGES = {
|
|
|
|
|
'dude': 0,
|
|
|
|
@ -40,6 +43,13 @@ RANGES = {
|
|
|
|
|
'its': 99,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CIEL8 = (0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9,
|
|
|
|
|
10, 11, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 28,
|
|
|
|
|
30, 31, 33, 35, 37, 39, 40, 42, 44, 46, 49, 51, 53, 55, 57, 60, 63,
|
|
|
|
|
66, 68, 71, 74, 77, 80, 83, 86, 90, 93, 96, 100, 103, 107, 111, 115,
|
|
|
|
|
118, 122, 127, 131, 136, 140, 144, 149, 153, 158, 163, 168, 173, 179,
|
|
|
|
|
184, 189, 195, 200, 206, 212, 218, 224, 230, 236, 242, 249, 255)
|
|
|
|
|
|
|
|
|
|
MINUTES = ('oclock', 'FIVE past', 'TEN past', 'QUARTER past', 'TWENTY past',
|
|
|
|
|
'TWENTYFIVE past', 'HALF past', 'TWENTYFIVE to', 'TWENTY to',
|
|
|
|
|
'QUARTER to', 'TEN to', 'FIVE to')
|
|
|
|
@ -72,10 +82,11 @@ def to_rgb(i, colour) -> tuple:
|
|
|
|
|
|
|
|
|
|
class Frame:
|
|
|
|
|
Max = 255
|
|
|
|
|
Zeros = tuple([0] * (11 * 10))
|
|
|
|
|
|
|
|
|
|
def __init__(self, n: int = 11 * 10, pixels: list = None):
|
|
|
|
|
if pixels is None:
|
|
|
|
|
pixels = [0] * n
|
|
|
|
|
pixels = list(self.Zeros)
|
|
|
|
|
self.pixels = pixels
|
|
|
|
|
|
|
|
|
|
def set(self, idx: int) -> Frame:
|
|
|
|
@ -91,6 +102,20 @@ class Frame:
|
|
|
|
|
return Frame(pixels=[x * num // den for x in self.pixels])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@micropython.native
|
|
|
|
|
def merge(f1: Frame, f2: Frame, num1: int, num2: int, den: int) -> Frame:
|
|
|
|
|
m = Frame.Max
|
|
|
|
|
p1 = f1.pixels
|
|
|
|
|
p2 = f2.pixels
|
|
|
|
|
o = array.array('H', Frame.Zeros)
|
|
|
|
|
for i in range(len(p1)):
|
|
|
|
|
k = (p1[i] * num1 + p2[i] * num2) // den
|
|
|
|
|
if k >= m:
|
|
|
|
|
k = m
|
|
|
|
|
o[i] = k
|
|
|
|
|
return Frame(pixels=o)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def render(words: list) -> Frame:
|
|
|
|
|
f = Frame()
|
|
|
|
|
for word in words:
|
|
|
|
@ -109,12 +134,17 @@ def prefix() -> tuple:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def show(f: Frame, n):
|
|
|
|
|
for i, p in enumerate(f.pixels):
|
|
|
|
|
n[i] = to_rgb(p, COLOUR)
|
|
|
|
|
n.show()
|
|
|
|
|
p = f.pixels
|
|
|
|
|
buf = bytearray(len(p) * 3)
|
|
|
|
|
r, g, b = COLOUR
|
|
|
|
|
i = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DT = 0.1
|
|
|
|
|
for c in p:
|
|
|
|
|
buf[i + 1] = (r * c) >> 8
|
|
|
|
|
buf[i + 0] = (g * c) >> 8
|
|
|
|
|
buf[i + 2] = (b * c) >> 8
|
|
|
|
|
i += 3
|
|
|
|
|
neopixel_write(n.pin, buf)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def scan() -> generator:
|
|
|
|
@ -125,9 +155,16 @@ def scan() -> generator:
|
|
|
|
|
f = f.muldiv(80, 100)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def intensity(num: int, den: int) -> int:
|
|
|
|
|
idx = num * len(CIEL8) // den
|
|
|
|
|
if idx >= len(CIEL8):
|
|
|
|
|
return 255
|
|
|
|
|
return CIEL8[idx]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def run() -> generator:
|
|
|
|
|
words = None
|
|
|
|
|
steps = int(2.0 / DT)
|
|
|
|
|
fade = 2000
|
|
|
|
|
secs = iptime.day_sec()
|
|
|
|
|
|
|
|
|
|
# Flash until time is synced.
|
|
|
|
@ -146,8 +183,9 @@ def run() -> generator:
|
|
|
|
|
yield from asynced.delay(1)
|
|
|
|
|
continue
|
|
|
|
|
dest = render(prefix() + nxt)
|
|
|
|
|
for i in range(steps):
|
|
|
|
|
yield src.muldiv(steps - i, steps) + dest.muldiv(i, steps)
|
|
|
|
|
for at in asynced.wait(fade):
|
|
|
|
|
yield merge(src, dest, intensity(fade - at, fade),
|
|
|
|
|
intensity(at, fade), 255)
|
|
|
|
|
words = nxt
|
|
|
|
|
src = dest
|
|
|
|
|
|
|
|
|
@ -163,29 +201,19 @@ def blink() -> generator:
|
|
|
|
|
|
|
|
|
|
def bench() -> generator:
|
|
|
|
|
yield None
|
|
|
|
|
i = 10
|
|
|
|
|
i = 30
|
|
|
|
|
while True:
|
|
|
|
|
start = time.monotonic()
|
|
|
|
|
yield from range(i)
|
|
|
|
|
elapsed = time.monotonic() - start
|
|
|
|
|
print('%d in %.3f %.3f/1' % (i, elapsed, elapsed / i))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test():
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
num = 11 * 10
|
|
|
|
|
n = neopixel.NeoPixel(board.GPIO2, num, brightness=0.4, auto_write=False)
|
|
|
|
|
while True:
|
|
|
|
|
for words in ITS:
|
|
|
|
|
f = render([words])
|
|
|
|
|
show(f, n)
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
print('%d in %.3f %.3f/1 %.1f FPS' % (i, elapsed, elapsed / i,
|
|
|
|
|
i / elapsed))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
num = 11 * 10
|
|
|
|
|
n = neopixel.NeoPixel(board.GPIO2, num, brightness=1, auto_write=False)
|
|
|
|
|
routines = (run(), blink(), asynced.fps(DT), bench())
|
|
|
|
|
routines = (run(), blink(), asynced.fps(30), bench())
|
|
|
|
|
while True:
|
|
|
|
|
for r in routines:
|
|
|
|
|
f = next(r)
|
|
|
|
|