micrOSDevToolKit 2.10.6__py3-none-any.whl → 2.13.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of micrOSDevToolKit might be problematic. Click here for more details.
- env/driver_cp210x/macOS_VCP_Driver/SiLabsUSBDriverDisk.dmg +0 -0
- env/driver_cp210x/macOS_VCP_Driver/macOS_VCP_Driver_Release_Notes.txt +17 -1
- micrOS/micropython/esp32c6-GENERIC-20250415-v1.25.0.bin +0 -0
- micrOS/micropython/esp32s3-4MBflash-20241129-v1.24.1.bin +0 -0
- micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +57 -61
- micrOS/source/Common.py +286 -91
- micrOS/source/Config.py +7 -7
- micrOS/source/Debug.py +50 -94
- micrOS/source/Espnow.py +7 -7
- micrOS/source/Files.py +23 -2
- micrOS/source/Hooks.py +62 -19
- micrOS/source/IO_esp32c6.py +16 -0
- micrOS/source/IO_esp32s3.py +37 -1
- micrOS/source/IO_m5stamp.py +35 -1
- micrOS/source/IO_qtpy.py +22 -17
- micrOS/source/IO_s3matrix.py +21 -0
- micrOS/source/IO_tinypico.py +38 -0
- micrOS/source/InterConnect.py +5 -5
- micrOS/source/Interrupts.py +2 -2
- micrOS/source/LM_VL53L0X.py +1 -1
- micrOS/source/LM_buzzer.py +6 -7
- micrOS/source/LM_cct.py +6 -5
- micrOS/source/LM_dashboard_be.py +2 -2
- micrOS/source/LM_dimmer.py +6 -5
- micrOS/source/LM_espnow.py +15 -10
- micrOS/source/LM_i2c.py +3 -2
- micrOS/source/LM_neoeffects.py +173 -230
- micrOS/source/LM_neomatrix.py +335 -0
- micrOS/source/LM_neopixel.py +10 -10
- micrOS/source/LM_pacman.py +40 -23
- micrOS/source/LM_qmi8658.py +204 -0
- micrOS/source/LM_rgb.py +6 -6
- micrOS/source/LM_roboarm.py +5 -4
- micrOS/source/LM_switch.py +6 -4
- micrOS/source/LM_tcs3472.py +75 -0
- micrOS/source/LM_telegram.py +5 -4
- micrOS/source/Logger.py +47 -33
- micrOS/source/Network.py +6 -6
- micrOS/source/Notify.py +2 -2
- micrOS/source/Scheduler.py +5 -5
- micrOS/source/Server.py +6 -6
- micrOS/source/Shell.py +4 -4
- micrOS/source/Tasks.py +20 -17
- micrOS/source/Time.py +12 -10
- micrOS/source/Types.py +2 -2
- micrOS/source/Web.py +20 -13
- micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Debug.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Server.cpython-312.pyc +0 -0
- micrOS/source/micrOS.py +10 -7
- micrOS/source/micrOSloader.py +6 -6
- micrOS/source/microIO.py +8 -6
- micrOS/source/urequests.py +4 -4
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/METADATA +24 -22
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/RECORD +142 -132
- toolkit/DevEnvCompile.py +20 -15
- toolkit/DevEnvOTA.py +29 -8
- toolkit/DevEnvUSB.py +52 -10
- toolkit/LM_to_compile.dat +1 -0
- toolkit/MicrOSDevEnv.py +10 -2
- toolkit/MicrosFiles.py +26 -0
- toolkit/dashboard_apps/NeoEffectsDemo.py +8 -15
- toolkit/dashboard_apps/QMI8685_GYRO.py +68 -0
- toolkit/dashboard_apps/_app_base.py +2 -2
- toolkit/dashboard_apps/_gyro_visualizer.py +78 -0
- toolkit/lib/LocalMachine.py +6 -1
- toolkit/lib/file_extensions.py +9 -3
- toolkit/micrOSlint.py +3 -1
- toolkit/simulator_lib/__pycache__/IO_darwin.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/machine.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/neopixel.cpython-312.pyc +0 -0
- toolkit/simulator_lib/machine.py +0 -1
- toolkit/simulator_lib/neopixel.py +3 -2
- toolkit/socketClient.py +3 -2
- toolkit/workspace/precompiled/Common.cpython-312.pyc +0 -0
- toolkit/workspace/precompiled/Common.mpy +0 -0
- toolkit/workspace/precompiled/Config.mpy +0 -0
- toolkit/workspace/precompiled/Debug.mpy +0 -0
- toolkit/workspace/precompiled/Espnow.mpy +0 -0
- toolkit/workspace/precompiled/Files.mpy +0 -0
- toolkit/workspace/precompiled/Hooks.mpy +0 -0
- toolkit/workspace/precompiled/IO_esp32c6.mpy +0 -0
- toolkit/workspace/precompiled/IO_esp32s3.mpy +0 -0
- toolkit/workspace/precompiled/IO_m5stamp.mpy +0 -0
- toolkit/workspace/precompiled/IO_qtpy.mpy +0 -0
- toolkit/workspace/precompiled/IO_s3matrix.mpy +0 -0
- toolkit/workspace/precompiled/IO_tinypico.mpy +0 -0
- toolkit/workspace/precompiled/InterConnect.mpy +0 -0
- toolkit/workspace/precompiled/Interrupts.mpy +0 -0
- toolkit/workspace/precompiled/LM_VL53L0X.py +1 -1
- toolkit/workspace/precompiled/LM_buzzer.mpy +0 -0
- toolkit/workspace/precompiled/LM_cct.mpy +0 -0
- toolkit/workspace/precompiled/LM_dashboard_be.py +2 -2
- toolkit/workspace/precompiled/LM_dimmer.mpy +0 -0
- toolkit/workspace/precompiled/LM_espnow.py +15 -10
- toolkit/workspace/precompiled/LM_i2c.py +3 -2
- toolkit/workspace/precompiled/LM_neoeffects.mpy +0 -0
- toolkit/workspace/precompiled/LM_neomatrix.mpy +0 -0
- toolkit/workspace/precompiled/LM_neopixel.mpy +0 -0
- toolkit/workspace/precompiled/LM_pacman.mpy +0 -0
- toolkit/workspace/precompiled/LM_qmi8658.py +204 -0
- toolkit/workspace/precompiled/LM_rgb.mpy +0 -0
- toolkit/workspace/precompiled/LM_roboarm.mpy +0 -0
- toolkit/workspace/precompiled/LM_switch.mpy +0 -0
- toolkit/workspace/precompiled/LM_tcs3472.py +75 -0
- toolkit/workspace/precompiled/LM_telegram.mpy +0 -0
- toolkit/workspace/precompiled/Logger.cpython-312.pyc +0 -0
- toolkit/workspace/precompiled/Logger.mpy +0 -0
- toolkit/workspace/precompiled/Network.mpy +0 -0
- toolkit/workspace/precompiled/Notify.mpy +0 -0
- toolkit/workspace/precompiled/Scheduler.mpy +0 -0
- toolkit/workspace/precompiled/Server.cpython-312.pyc +0 -0
- toolkit/workspace/precompiled/Server.mpy +0 -0
- toolkit/workspace/precompiled/Shell.mpy +0 -0
- toolkit/workspace/precompiled/Tasks.mpy +0 -0
- toolkit/workspace/precompiled/Time.mpy +0 -0
- toolkit/workspace/precompiled/Types.mpy +0 -0
- toolkit/workspace/precompiled/Web.mpy +0 -0
- toolkit/workspace/precompiled/micrOS.mpy +0 -0
- toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
- toolkit/workspace/precompiled/microIO.mpy +0 -0
- toolkit/workspace/precompiled/urequests.mpy +0 -0
- micrOS/micropython/esp32s3-20240105-v1.22.1.bin +0 -0
- micrOS/source/LM_catgame.py +0 -75
- micrOS/source/LM_demo.py +0 -97
- micrOS/source/LM_intercon.py +0 -60
- micrOS/source/LM_ph_sensor.py +0 -51
- toolkit/workspace/precompiled/LM_catgame.py +0 -75
- toolkit/workspace/precompiled/LM_demo.py +0 -97
- toolkit/workspace/precompiled/LM_intercon.mpy +0 -0
- toolkit/workspace/precompiled/LM_ph_sensor.py +0 -51
- /micrOS/micropython/{esp32s3-20241129-v1.24.1.bin → esp32s3-8MBflash-20241129-v1.24.1.bin} +0 -0
- /micrOS/source/{dashboard.html → web/dashboard.html} +0 -0
- /micrOS/source/{index.html → web/index.html} +0 -0
- /micrOS/source/{uapi.js → web/uapi.js} +0 -0
- /micrOS/source/{udashboard.js → web/udashboard.js} +0 -0
- /micrOS/source/{ustyle.css → web/ustyle.css} +0 -0
- /micrOS/source/{uwidgets.js → web/uwidgets.js} +0 -0
- /micrOS/source/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
- {microsdevtoolkit-2.10.6.data → microsdevtoolkit-2.13.0.data}/scripts/devToolKit.py +0 -0
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/WHEEL +0 -0
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/licenses/LICENSE +0 -0
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/top_level.txt +0 -0
- /toolkit/workspace/precompiled/{dashboard.html → web/dashboard.html} +0 -0
- /toolkit/workspace/precompiled/{index.html → web/index.html} +0 -0
- /toolkit/workspace/precompiled/{uapi.js → web/uapi.js} +0 -0
- /toolkit/workspace/precompiled/{udashboard.js → web/udashboard.js} +0 -0
- /toolkit/workspace/precompiled/{ustyle.css → web/ustyle.css} +0 -0
- /toolkit/workspace/precompiled/{uwidgets.js → web/uwidgets.js} +0 -0
- /toolkit/workspace/precompiled/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
from neopixel import NeoPixel
|
|
2
|
+
from machine import Pin
|
|
3
|
+
from utime import sleep_ms
|
|
4
|
+
|
|
5
|
+
from microIO import bind_pin
|
|
6
|
+
from Types import resolve
|
|
7
|
+
from Common import manage_task, AnimationPlayer
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class NeoPixelMatrix(AnimationPlayer):
|
|
11
|
+
INSTANCE = None
|
|
12
|
+
DEFAULT_COLOR = (100, 23, 0) # Default color for the matrix
|
|
13
|
+
|
|
14
|
+
def __init__(self, width: int = 8, height: int = 8, pin: int = 0):
|
|
15
|
+
super().__init__(tag="neomatrix")
|
|
16
|
+
self.width = width
|
|
17
|
+
self.height = height
|
|
18
|
+
self.num_pixels = width * height
|
|
19
|
+
self.pixels = NeoPixel(Pin(pin, Pin.OUT), self.num_pixels)
|
|
20
|
+
self._color_buffer = [(0, 0, 0)] * self.num_pixels # Store original RGB values
|
|
21
|
+
self._brightness = 0.25 # Brightness level, default 25%
|
|
22
|
+
NeoPixelMatrix.INSTANCE = self
|
|
23
|
+
|
|
24
|
+
def update(self, x:int, y:int, color:tuple[int, int, int]):
|
|
25
|
+
# Animation player will call this method to update pixels.
|
|
26
|
+
self.set_pixel(x, y, color)
|
|
27
|
+
|
|
28
|
+
def draw(self):
|
|
29
|
+
# Animation player will call this method to update the display.
|
|
30
|
+
self.pixels.write()
|
|
31
|
+
|
|
32
|
+
def clear(self):
|
|
33
|
+
# Animation player will call this method to clear the display.
|
|
34
|
+
for i in range(self.num_pixels):
|
|
35
|
+
# Write pixel buffer before write to ws2812
|
|
36
|
+
self.pixels[i] = (0, 0, 0)
|
|
37
|
+
# Send buffer to device
|
|
38
|
+
self.draw()
|
|
39
|
+
|
|
40
|
+
def _coord_to_index(self, x: int, y: int, zigzag:bool=True):
|
|
41
|
+
"""
|
|
42
|
+
Zigzag layout: even rows left-to-right, odd rows right-to-left
|
|
43
|
+
"""
|
|
44
|
+
if (zigzag is None or zigzag) and y % 2 == 0:
|
|
45
|
+
return y * self.width + x
|
|
46
|
+
return y * self.width + (self.width - 1 - x)
|
|
47
|
+
|
|
48
|
+
def _index_to_coord(self, index: int, zigzag:bool=True) -> tuple[int, int]:
|
|
49
|
+
"""
|
|
50
|
+
Converts a linear index to (x, y) coordinates.
|
|
51
|
+
Zigzag layout: even rows left-to-right, odd rows right-to-left.
|
|
52
|
+
"""
|
|
53
|
+
y = index // self.width
|
|
54
|
+
x = index % self.width
|
|
55
|
+
if (zigzag is None or zigzag) and y % 2 == 1:
|
|
56
|
+
x = self.width - 1 - x
|
|
57
|
+
return x, y
|
|
58
|
+
|
|
59
|
+
def _rgb_to_grb_with_br(self, color: tuple[int, int, int]):
|
|
60
|
+
"""
|
|
61
|
+
Converts RGB to GRB with brightness adjustment.
|
|
62
|
+
"""
|
|
63
|
+
def scale(val):
|
|
64
|
+
return max(0, min(255, int(val * self._brightness)))
|
|
65
|
+
|
|
66
|
+
return scale(color[1]), scale(color[0]), scale(color[2])
|
|
67
|
+
|
|
68
|
+
def set_pixel(self, x: int, y: int, color: tuple[int, int, int], zigzag:bool=True):
|
|
69
|
+
"""
|
|
70
|
+
Set pixel at (x, y) with RGB
|
|
71
|
+
"""
|
|
72
|
+
if 0 <= x < self.width and 0 <= y < self.height:
|
|
73
|
+
index = self._coord_to_index(x, y, zigzag=zigzag)
|
|
74
|
+
self._color_buffer[index] = color # store original RGB for brightness control
|
|
75
|
+
self.pixels[index] = self._rgb_to_grb_with_br(color)
|
|
76
|
+
|
|
77
|
+
def color(self, color: tuple[int, int, int]):
|
|
78
|
+
"""
|
|
79
|
+
Fill color OR Animation color change.
|
|
80
|
+
:param color: tuple[int, int, int] range: 0-255
|
|
81
|
+
:return: str
|
|
82
|
+
"""
|
|
83
|
+
r, g, b = max(0, min(color[0], 255)), max(0, min(color[1], 255)), max(0, min(color[2], 255))
|
|
84
|
+
color = (r, g, b)
|
|
85
|
+
NeoPixelMatrix.DEFAULT_COLOR = color
|
|
86
|
+
if manage_task(self._task_tag, "isbusy"):
|
|
87
|
+
return f"Set animation color to {color}"
|
|
88
|
+
for i in range(self.num_pixels):
|
|
89
|
+
self._color_buffer[i] = color
|
|
90
|
+
# Write pixel buffer before write to ws2812
|
|
91
|
+
self.pixels[i] = self._rgb_to_grb_with_br(color)
|
|
92
|
+
# Send buffer to device
|
|
93
|
+
self.draw()
|
|
94
|
+
return f"Set all pixels to {color}"
|
|
95
|
+
|
|
96
|
+
def brightness(self, br: int):
|
|
97
|
+
"""
|
|
98
|
+
Change the brightness of all pixels.
|
|
99
|
+
"""
|
|
100
|
+
br = max(0, min(br, 100)) # clamp brightness to 0–100%
|
|
101
|
+
self._brightness = br / 100.0
|
|
102
|
+
# Set color matrix brightness
|
|
103
|
+
for i, color in enumerate(self._color_buffer):
|
|
104
|
+
# Write pixel buffer before write to ws2812
|
|
105
|
+
self.pixels[i] = self._rgb_to_grb_with_br(color)
|
|
106
|
+
self.draw()
|
|
107
|
+
return f"Set brightness to {br}%"
|
|
108
|
+
|
|
109
|
+
def draw_colormap(self, bitmap:list):
|
|
110
|
+
"""
|
|
111
|
+
Draw a bitmap on the Neopixel
|
|
112
|
+
bitmap: [(x, y, (r, g, b)),
|
|
113
|
+
(x, y, (r, g, b)), ...]
|
|
114
|
+
"""
|
|
115
|
+
if len(bitmap) == 0:
|
|
116
|
+
self.clear()
|
|
117
|
+
return
|
|
118
|
+
for bm in bitmap:
|
|
119
|
+
x, y, color = bm
|
|
120
|
+
self.set_pixel(x, y, color, zigzag=False)
|
|
121
|
+
self.draw()
|
|
122
|
+
|
|
123
|
+
def export_colormap(self):
|
|
124
|
+
"""
|
|
125
|
+
Export the current screen as bitmap
|
|
126
|
+
"""
|
|
127
|
+
colormap = []
|
|
128
|
+
for i, color in enumerate(self._color_buffer):
|
|
129
|
+
x, y = self._index_to_coord(i, zigzag=False)
|
|
130
|
+
colormap.append((x, y, color))
|
|
131
|
+
return colormap
|
|
132
|
+
|
|
133
|
+
##########################################################################################################
|
|
134
|
+
##########################################################################################################
|
|
135
|
+
# --- Example usage with micrOS framework ---
|
|
136
|
+
|
|
137
|
+
def load(width=8, height=8):
|
|
138
|
+
"""
|
|
139
|
+
Load NeoPixelMatrix instance. If not already loaded
|
|
140
|
+
"""
|
|
141
|
+
if NeoPixelMatrix.INSTANCE is None:
|
|
142
|
+
NeoPixelMatrix(width=width, height=height, pin=bind_pin('neop'))
|
|
143
|
+
return NeoPixelMatrix.INSTANCE
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def pixel(x, y, color=None, show=True):
|
|
147
|
+
"""
|
|
148
|
+
Set pixel at (x,y) to RGB color.
|
|
149
|
+
"""
|
|
150
|
+
color = NeoPixelMatrix.DEFAULT_COLOR if color is None else color
|
|
151
|
+
matrix = load()
|
|
152
|
+
matrix.set_pixel(x, y, color)
|
|
153
|
+
if show:
|
|
154
|
+
matrix.draw()
|
|
155
|
+
return "Set and draw color"
|
|
156
|
+
return "Set color"
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def draw():
|
|
160
|
+
"""
|
|
161
|
+
Draw the current frame manually on the screen.
|
|
162
|
+
"""
|
|
163
|
+
load().draw()
|
|
164
|
+
return "Draw screen"
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def clear():
|
|
168
|
+
"""
|
|
169
|
+
Clear the screen.
|
|
170
|
+
"""
|
|
171
|
+
load().clear()
|
|
172
|
+
return "Clear screen"
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def color_fill(r: int, g: int, b: int):
|
|
176
|
+
"""
|
|
177
|
+
Fill the screen with a solid color.
|
|
178
|
+
OR
|
|
179
|
+
Change animation color (when possible)
|
|
180
|
+
"""
|
|
181
|
+
return load().color((r, g, b))
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def brightness(br: int):
|
|
185
|
+
"""
|
|
186
|
+
Change the brightness of the display. (0-100)
|
|
187
|
+
"""
|
|
188
|
+
return load().brightness(br)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def control(speed_ms=None, bt_draw:bool=None):
|
|
192
|
+
"""
|
|
193
|
+
Change the speed of frame generation for animations.
|
|
194
|
+
"""
|
|
195
|
+
data = load().control(play_speed_ms=speed_ms, bt_draw=bt_draw)
|
|
196
|
+
_speed_ms = data.get("player_speed", None)
|
|
197
|
+
return f"Control state: {data} (speed: {_speed_ms}ms)"
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def stop():
|
|
201
|
+
"""
|
|
202
|
+
Stop the current animation
|
|
203
|
+
"""
|
|
204
|
+
return load().stop()
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def draw_colormap(bitmap):
|
|
208
|
+
try:
|
|
209
|
+
load().draw_colormap(bitmap)
|
|
210
|
+
except Exception as e:
|
|
211
|
+
return str(e)
|
|
212
|
+
return "Done."
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def get_colormap():
|
|
216
|
+
return load().export_colormap()
|
|
217
|
+
|
|
218
|
+
# -----------------------------------------------------------------------------
|
|
219
|
+
# -----------------------------------------------------------------------------
|
|
220
|
+
|
|
221
|
+
def rainbow(speed_ms=0):
|
|
222
|
+
def effect_rainbow():
|
|
223
|
+
def hsv_to_rgb(h, s, v):
|
|
224
|
+
max_color = 150 #255
|
|
225
|
+
h = float(h)
|
|
226
|
+
s = float(s)
|
|
227
|
+
v = float(v)
|
|
228
|
+
i = int(h * 6.0)
|
|
229
|
+
f = (h * 6.0) - i
|
|
230
|
+
p = v * (1.0 - s)
|
|
231
|
+
q = v * (1.0 - s * f)
|
|
232
|
+
t = v * (1.0 - s * (1.0 - f))
|
|
233
|
+
i = i % 6
|
|
234
|
+
if i == 0:
|
|
235
|
+
r, g, b = v, t, p
|
|
236
|
+
elif i == 1:
|
|
237
|
+
r, g, b = q, v, p
|
|
238
|
+
elif i == 2:
|
|
239
|
+
r, g, b = p, v, t
|
|
240
|
+
elif i == 3:
|
|
241
|
+
r, g, b = p, q, v
|
|
242
|
+
elif i == 4:
|
|
243
|
+
r, g, b = t, p, v
|
|
244
|
+
elif i == 5:
|
|
245
|
+
r, g, b = v, p, q
|
|
246
|
+
return int(r * max_color), int(g * max_color), int(b * max_color)
|
|
247
|
+
|
|
248
|
+
width = 8
|
|
249
|
+
height = 8
|
|
250
|
+
total_frames = 64
|
|
251
|
+
|
|
252
|
+
for frame in range(total_frames):
|
|
253
|
+
for y in range(height):
|
|
254
|
+
for x in range(width):
|
|
255
|
+
index = y * width + x
|
|
256
|
+
hue = ((index + frame) % 64) / 64.0
|
|
257
|
+
r, g, b = hsv_to_rgb(hue, 1.0, 0.7)
|
|
258
|
+
yield x, y, (r, g, b)
|
|
259
|
+
|
|
260
|
+
return load().play(effect_rainbow, speed_ms=speed_ms, bt_draw=True, bt_size=8)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def snake(speed_ms:int=30, length:int=5):
|
|
264
|
+
def effect_snake():
|
|
265
|
+
clear_color = (0, 0, 0)
|
|
266
|
+
total_pixels = 8 * 8
|
|
267
|
+
total_steps = total_pixels + length # run just past the end to clear tail
|
|
268
|
+
|
|
269
|
+
for step in range(total_steps):
|
|
270
|
+
# 1) clear the tail pixel once the snake is longer than `length`
|
|
271
|
+
if step >= length:
|
|
272
|
+
tail_idx = step - length
|
|
273
|
+
tx, ty = tail_idx % 8, tail_idx // 8
|
|
274
|
+
yield tx, ty, clear_color
|
|
275
|
+
|
|
276
|
+
# 2) draw the snake segments with decreasing brightness
|
|
277
|
+
for i in range(length):
|
|
278
|
+
seg_idx = step - i
|
|
279
|
+
if 0 <= seg_idx < total_pixels:
|
|
280
|
+
x, y = seg_idx % 8, seg_idx // 8
|
|
281
|
+
br = 1.0 - (i / length) ** 0.6
|
|
282
|
+
r, g, b = NeoPixelMatrix.DEFAULT_COLOR
|
|
283
|
+
color = (int(r * br), int(g * br), int(b * br))
|
|
284
|
+
yield x, y, color
|
|
285
|
+
|
|
286
|
+
return load().play(effect_snake, speed_ms=speed_ms, bt_draw=False)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def cube(speed_ms=10):
|
|
290
|
+
def effect_cube(max_radius:int = 3):
|
|
291
|
+
"""
|
|
292
|
+
Generator yielding (x, y, color) for a centered 2×2 square ("cube")
|
|
293
|
+
that expands outward to `max_radius` then collapses back.
|
|
294
|
+
"""
|
|
295
|
+
width, height = 8, 8
|
|
296
|
+
# Center the 2×2 core in an 8×8 grid
|
|
297
|
+
cx, cy = width // 2 - 1, height // 2 - 1
|
|
298
|
+
|
|
299
|
+
# Expansion phase: radius 0 (2×2) up to max_radius
|
|
300
|
+
for r in range(0, max_radius + 1):
|
|
301
|
+
for dx in range(-r, r + 2):
|
|
302
|
+
for dy in range(-r, r + 2):
|
|
303
|
+
x, y = cx + dx, cy + dy
|
|
304
|
+
if 0 <= x < width and 0 <= y < height:
|
|
305
|
+
yield x, y, NeoPixelMatrix.DEFAULT_COLOR
|
|
306
|
+
# Clear matrix
|
|
307
|
+
try:
|
|
308
|
+
NeoPixelMatrix.INSTANCE.clear()
|
|
309
|
+
except:
|
|
310
|
+
pass
|
|
311
|
+
# Collapse phase: back down, skipping the largest to avoid duplicate
|
|
312
|
+
for r in range(max_radius - 1, -1, -1):
|
|
313
|
+
for dx in range(-r, r + 2):
|
|
314
|
+
for dy in range(-r, r + 2):
|
|
315
|
+
x, y = cx + dx, cy + dy
|
|
316
|
+
if 0 <= x < width and 0 <= y < height:
|
|
317
|
+
yield x, y, NeoPixelMatrix.DEFAULT_COLOR
|
|
318
|
+
|
|
319
|
+
return load().play(effect_cube, speed_ms=speed_ms, bt_draw=False)
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def help(widgets=False):
|
|
323
|
+
return resolve(('load width=8 height=8',
|
|
324
|
+
'pixel x y color=(10, 3, 0) show=True',
|
|
325
|
+
'BUTTON clear',
|
|
326
|
+
'COLOR color_fill r=<0-255-5> g=<0-255-5> b=<0-255-5>',
|
|
327
|
+
'SLIDER brightness br=<0-60-2>',
|
|
328
|
+
'BUTTON stop',
|
|
329
|
+
'BUTTON snake speed_ms=50 length=5',
|
|
330
|
+
'BUTTON rainbow',
|
|
331
|
+
'BUTTON cube speed_ms=10',
|
|
332
|
+
'SLIDER control speed_ms=<1-200-2> bt_draw=None',
|
|
333
|
+
'draw_colormap bitmap=[(0,0,(10,2,0)),(x,y,color),...]',
|
|
334
|
+
'get_colormap'
|
|
335
|
+
), widgets=widgets)
|
micrOS/source/LM_neopixel.py
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
from neopixel import NeoPixel
|
|
2
2
|
from machine import Pin
|
|
3
|
-
from sys import platform
|
|
4
3
|
from utime import sleep_ms
|
|
5
|
-
from Common import transition_gen, micro_task
|
|
4
|
+
from Common import transition_gen, micro_task, data_dir
|
|
6
5
|
from microIO import bind_pin, pinmap_search
|
|
7
6
|
from random import randint
|
|
8
7
|
from Types import resolve
|
|
@@ -19,6 +18,7 @@ class Data:
|
|
|
19
18
|
PERSISTENT_CACHE = False
|
|
20
19
|
RGB_TASK_TAG = "neopixel._tran"
|
|
21
20
|
TASK_STATE = False
|
|
21
|
+
FILE_CACHE = data_dir('neopixel.cache')
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
#########################################
|
|
@@ -40,7 +40,7 @@ def __init_NEOPIXEL(pin=None, n=24):
|
|
|
40
40
|
|
|
41
41
|
def __persistent_cache_manager(mode):
|
|
42
42
|
"""
|
|
43
|
-
|
|
43
|
+
File cache
|
|
44
44
|
modes:
|
|
45
45
|
r - recover, s - save
|
|
46
46
|
"""
|
|
@@ -48,12 +48,12 @@ def __persistent_cache_manager(mode):
|
|
|
48
48
|
return
|
|
49
49
|
if mode == 's':
|
|
50
50
|
# SAVE CACHE
|
|
51
|
-
with open(
|
|
51
|
+
with open(Data.FILE_CACHE, 'w') as f:
|
|
52
52
|
f.write(','.join([str(k) for k in Data.DCACHE]))
|
|
53
53
|
return
|
|
54
54
|
try:
|
|
55
55
|
# RESTORE CACHE
|
|
56
|
-
with open(
|
|
56
|
+
with open(Data.FILE_CACHE, 'r') as f:
|
|
57
57
|
Data.DCACHE = [float(data) for data in f.read().strip().split(',')]
|
|
58
58
|
except:
|
|
59
59
|
pass
|
|
@@ -77,7 +77,7 @@ def load(ledcnt=24, pin=None, cache=True):
|
|
|
77
77
|
Initiate NeoPixel RGB module
|
|
78
78
|
:param ledcnt: number of led segments
|
|
79
79
|
:param pin: optional number to overwrite default pin
|
|
80
|
-
:param cache: default True, store stages on disk + Load (.
|
|
80
|
+
:param cache: default True, store stages on disk + Load (.cache)
|
|
81
81
|
:return str: Cache state
|
|
82
82
|
"""
|
|
83
83
|
Data.PERSISTENT_CACHE = cache
|
|
@@ -182,13 +182,13 @@ def segment(r=None, g=None, b=None, s=0, cache=False, write=True):
|
|
|
182
182
|
:param g: green value 0-255
|
|
183
183
|
:param b: blue value 0-255
|
|
184
184
|
:param s: segment - index 0-ledcnt
|
|
185
|
-
:param cache: cache color (update .
|
|
185
|
+
:param cache: cache color (update .cache file)
|
|
186
186
|
:param write: send color buffer to neopixel (update LEDs)
|
|
187
187
|
:return dict: rgb status - states: R, G, B, S
|
|
188
188
|
"""
|
|
189
|
-
r = Data.DCACHE[0] if r is None else r
|
|
190
|
-
g = Data.DCACHE[1] if g is None else g
|
|
191
|
-
b = Data.DCACHE[2] if b is None else b
|
|
189
|
+
r = int(Data.DCACHE[0]) if r is None else r
|
|
190
|
+
g = int(Data.DCACHE[1]) if g is None else g
|
|
191
|
+
b = int(Data.DCACHE[2]) if b is None else b
|
|
192
192
|
neo_n = __init_NEOPIXEL().n
|
|
193
193
|
if s <= neo_n:
|
|
194
194
|
Data.NEOPIXEL_OBJ[s] = (r, g, b)
|
micrOS/source/LM_pacman.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from sys import modules
|
|
2
2
|
from Common import socket_stream
|
|
3
|
-
from Files import _is_module, list_fs, ilist_fs, remove_fs
|
|
3
|
+
from Files import _is_module, list_fs, ilist_fs, remove_fs, OSPath, path_join
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
#############################################
|
|
@@ -42,7 +42,7 @@ def rm(path, allow_dir=False):
|
|
|
42
42
|
def dirtree(path="/", raw=False):
|
|
43
43
|
"""Return only directories from a given path."""
|
|
44
44
|
path = path if path.endswith('/') else f"{path}/"
|
|
45
|
-
folders = [
|
|
45
|
+
folders = [path_join(path, item) for item in ilist_fs(path, type_filter='d')]
|
|
46
46
|
folder_contents = {folder:list_fs(folder) for folder in folders}
|
|
47
47
|
if raw:
|
|
48
48
|
return folder_contents
|
|
@@ -124,42 +124,57 @@ def moduls(unload=None):
|
|
|
124
124
|
|
|
125
125
|
|
|
126
126
|
@socket_stream
|
|
127
|
-
def cachedump(
|
|
127
|
+
def cachedump(delete=None, msgobj=None):
|
|
128
128
|
"""
|
|
129
|
-
Cache system persistent data storage files (.
|
|
130
|
-
:param
|
|
129
|
+
Cache system persistent data storage files (.cache)
|
|
130
|
+
:param delete: cache name to delete
|
|
131
131
|
"""
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
data_dir = OSPath.DATA
|
|
133
|
+
if delete is None:
|
|
134
|
+
# List cache files aka application cache
|
|
134
135
|
msg_buf = []
|
|
135
|
-
for
|
|
136
|
-
|
|
136
|
+
for cache in (c for c in ilist_fs(data_dir, type_filter='f') if c.endswith('.cache')):
|
|
137
|
+
_path = path_join(data_dir, cache)
|
|
138
|
+
with open(_path, 'r') as f:
|
|
137
139
|
if msgobj is None:
|
|
138
|
-
msg_buf.append(f'{
|
|
140
|
+
msg_buf.append(f'{_path}: {f.read()}')
|
|
139
141
|
else:
|
|
140
|
-
msgobj(f'{
|
|
142
|
+
msgobj(f'{_path}: {f.read()}')
|
|
141
143
|
return msg_buf if len(msg_buf) > 0 else ''
|
|
142
|
-
# Remove given
|
|
144
|
+
# Remove given cache file
|
|
143
145
|
try:
|
|
144
|
-
|
|
145
|
-
|
|
146
|
+
delete_cache = path_join(data_dir, f"{delete}.cache")
|
|
147
|
+
verdict = remove_fs(delete_cache)
|
|
148
|
+
return f'{delete_cache} delete done.: {verdict}'
|
|
146
149
|
except:
|
|
147
|
-
return f'{
|
|
150
|
+
return f'{delete}.cache not exists'
|
|
148
151
|
|
|
149
152
|
|
|
150
|
-
def
|
|
153
|
+
def datdump():
|
|
151
154
|
"""
|
|
152
155
|
Generic .dat file dump
|
|
153
|
-
- logged data from LMs, sensor
|
|
156
|
+
- logged data from LMs, sensor data, etc...
|
|
154
157
|
"""
|
|
155
|
-
|
|
156
|
-
dats = (f for f in ilist_fs(type_filter='f') if f.endswith('.dat'))
|
|
158
|
+
data_dir = OSPath.DATA
|
|
159
|
+
dats = (f for f in ilist_fs(data_dir, type_filter='f') if f.endswith('.dat'))
|
|
157
160
|
out = {}
|
|
158
161
|
for dat in dats:
|
|
159
|
-
with open(
|
|
162
|
+
with open(path_join(data_dir, dat), 'r') as f:
|
|
160
163
|
out[dat] = f.read()
|
|
161
164
|
return out
|
|
162
165
|
|
|
166
|
+
|
|
167
|
+
def makedir(path):
|
|
168
|
+
"""
|
|
169
|
+
Create directory command
|
|
170
|
+
"""
|
|
171
|
+
from uos import mkdir
|
|
172
|
+
try:
|
|
173
|
+
mkdir(path)
|
|
174
|
+
return f"{path} dir created."
|
|
175
|
+
except Exception as e:
|
|
176
|
+
return f"{path} failed to create: {e}"
|
|
177
|
+
|
|
163
178
|
#############################################
|
|
164
179
|
# Legacy features #
|
|
165
180
|
#############################################
|
|
@@ -220,9 +235,11 @@ def help(widgets=False):
|
|
|
220
235
|
"""
|
|
221
236
|
return ('listmods', 'delmod mod=<module>.py/.mpy or .js/.html/.css', 'del_duplicates',
|
|
222
237
|
'moduls unload="LM_rgb/None"',
|
|
223
|
-
'cachedump
|
|
224
|
-
'
|
|
238
|
+
'cachedump delete=None',
|
|
239
|
+
'datdump',
|
|
225
240
|
'download url="BxNxM/micrOS/master/toolkit/workspace/precompiled/LM_robustness.py"',
|
|
226
241
|
'micros_checksum',
|
|
227
242
|
'ls path="/" content="*/f/d" select="*/LM/IO"',
|
|
228
|
-
'rm <path>',
|
|
243
|
+
'rm <path>',
|
|
244
|
+
'dirtree path="/"',
|
|
245
|
+
'makedir <path>')
|