-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
158 lines (146 loc) · 6.62 KB
/
Copy pathmain.py
File metadata and controls
158 lines (146 loc) · 6.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
from uasyncio import sleep, run, create_task
from asyncio import Task
from umachine import Pin, UART
from neopixel import NeoPixel
from usys import stdin, print_exception
from uselect import poll, POLLIN
class NeopixelController:
def configure(
self,
config: "dict[int, tuple[tuple[int, dict[str, object]], ...]]",
character: str,
) -> None:
self.leds: list[NeoPixel] = []
self.start: list[int] = []
self.led_strip: list[int] = []
self.led_count: list[int] = []
self.tasks: "dict[int, list[tuple[str, None | Task[None]]]]" = {
pin: list(("", None) for _ in attributes) for pin, attributes in config.items()
}
self.modes: "dict[int, tuple[dict[str, object], ...]]" = {
pin: tuple(info[1] for info in attributes) for pin, attributes in config.items()
}
self.character: str = character
index: int = 0
for count, (pin, info) in enumerate(config.items()):
index = 0
self.leds.append(
NeoPixel(Pin(pin), sum(length for length, _ in info)))
for length, _ in info:
self.led_strip.append(count)
self.start.append(index)
self.led_count.append(length)
index += length
def choose_pattern(self) -> None:
for start_position, (pin, tasks) in enumerate(self.tasks.items()):
for count, task in enumerate(tasks):
if task[0] != self.character and self.modes[pin][count].get(self.character) != None:
if task[1] is not None:
try:
task[1].cancel()
except RuntimeError:
pass
self.tasks[pin][count] = (self.character, create_task(self.modes[pin][count][self.character](start_position + count))) # type: ignore
async def color_fade(
self,
strip: int,
colors: "tuple[tuple[int, int, int], ...]",
mix: int,
step_delay: float,
) -> None:
while True:
for count in range(len(colors)):
for fade_step in range(mix + 1):
intermediate_color = tuple(int((1 - fade_step / mix) * rgb_1 + fade_step / mix * rgb_2) for rgb_1, rgb_2 in zip(colors[count], colors[(count + 1) % len(colors)]))
for led in range(self.led_count[strip]):
self.leds[self.led_strip[strip]][self.start[strip] + led] = intermediate_color # type: ignore
self.leds[self.led_strip[strip]].write()
await sleep(step_delay)
async def static_color(
self,
strip: int,
color: "tuple[int, int, int]",
delay: int,
kill: bool,
kill_mode: str,
) -> None:
for led in range(self.led_count[strip]):
self.leds[self.led_strip[strip]][self.start[strip] + led] = color # type: ignore
self.leds[self.led_strip[strip]].write()
await sleep(delay)
if kill:
self.character = kill_mode
self.choose_pattern()
async def chasing(
self,
strip: int,
base_color: "tuple[int, int, int]",
chasing_color: "tuple[int, int, int]",
mix: int,
step_delay: float,
length: int,
speed: int,
) -> None:
intermediate_colors: "list[list[int]]" = [[int((1 - fade_step / mix) * rgb_1 + fade_step / mix * rgb_2) for rgb_1, rgb_2 in zip(base_color, chasing_color)] for fade_step in range(mix + 1)]
colors_length: int = len(intermediate_colors) - 1
position: float = 0
while True:
for led in range(self.led_count[strip]):
closest_position: float = abs(position - led)
distance: float = min(closest_position, self.led_count[strip] - closest_position)
equation: int = int(colors_length - colors_length / max(length / distance, 1)) if distance != 0 else 0
self.leds[self.led_strip[strip]][self.start[strip] + led] = intermediate_colors[equation] # type: ignore
position = position + 1 / mix if position < self.led_count[strip] else 0
self.leds[self.led_strip[strip]].write()
await sleep(step_delay / mix / speed)
async def set_mode(controller: NeopixelController) -> None:
uart = UART(0, 9600, parity=None, stop=1, bits=8, tx=Pin(0), rx=Pin(1), timeout=10)
select_poll: poll = poll()
select_poll.register(stdin, POLLIN)
while True:
if uart.any() > 0:
received_input = uart.read(1).decode("utf-8")
if received_input != "\n":
controller.character = received_input
if select_poll.poll(0):
received_input = stdin.read(1)
if received_input != "\n":
controller.character = received_input
controller.choose_pattern()
await sleep(0.1)
controller = NeopixelController()
controller.configure(
config={
9: (
(18, {
"D": lambda pin: controller.chasing(pin, (0, 0, 200), (200, 0, 200), 10, 0.01, 20, 50),
"X": lambda pin: controller.chasing(pin, (0, 0, 200), (200, 0, 200), 10, 0.01, 20, 50),
"E": lambda pin: controller.color_fade(pin, ((255, 0, 0), (0, 255, 0), (0, 0, 255)), 128, 0.01),
"P": lambda pin: controller.static_color(pin, (255, 165, 0), 0, False, ""),
"S": lambda pin: controller.static_color(pin, (0, 255, 0), 0, False, ""),
"C": lambda pin: controller.static_color(pin, (255, 0, 0), 0, False, ""),
"H": lambda pin: controller.static_color(pin, (255, 255, 255), 0, False, ""),
}),
),
10: (
(18, {
"D": lambda pin: controller.chasing(pin, (0, 0, 200), (200, 0, 200), 10, 0.01, 20, 50),
"X": lambda pin: controller.chasing(pin, (0, 0, 200), (200, 0, 200), 10, 0.01, 20, 50),
"E": lambda pin: controller.color_fade(pin, ((255, 0, 0), (0, 255, 0), (0, 0, 255)), 128, 0.01),
"P": lambda pin: controller.static_color(pin, (255, 165, 0), 0, False, ""),
"S": lambda pin: controller.static_color(pin, (0, 255, 0), 0, False, ""),
"C": lambda pin: controller.static_color(pin, (255, 0, 0), 0, False, ""),
"H": lambda pin: controller.static_color(pin, (255, 255, 255), 0, False, ""),
}),
),
},
character="D",
)
try:
run(set_mode(controller))
except Exception as e:
print_exception(e)
finally:
for led in controller.leds:
led.fill((0, 0, 0))
led.write()