ledmatrix 0.1.0__tar.gz
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.
- ledmatrix-0.1.0/LICENSE +21 -0
- ledmatrix-0.1.0/MANIFEST.in +2 -0
- ledmatrix-0.1.0/PKG-INFO +287 -0
- ledmatrix-0.1.0/README.md +245 -0
- ledmatrix-0.1.0/pyproject.toml +69 -0
- ledmatrix-0.1.0/setup.cfg +4 -0
- ledmatrix-0.1.0/src/ledmatrix/__init__.py +33 -0
- ledmatrix-0.1.0/src/ledmatrix/async_device.py +64 -0
- ledmatrix-0.1.0/src/ledmatrix/canvas.py +208 -0
- ledmatrix-0.1.0/src/ledmatrix/cli/__init__.py +1 -0
- ledmatrix-0.1.0/src/ledmatrix/cli/main.py +250 -0
- ledmatrix-0.1.0/src/ledmatrix/data/50-framework-inputmodule.rules +3 -0
- ledmatrix-0.1.0/src/ledmatrix/data/__init__.py +1 -0
- ledmatrix-0.1.0/src/ledmatrix/device.py +367 -0
- ledmatrix-0.1.0/src/ledmatrix/dither.py +95 -0
- ledmatrix-0.1.0/src/ledmatrix/exceptions.py +41 -0
- ledmatrix-0.1.0/src/ledmatrix/font/__init__.py +5 -0
- ledmatrix-0.1.0/src/ledmatrix/font/bdf.py +112 -0
- ledmatrix-0.1.0/src/ledmatrix/font/data/3x5.bdf +946 -0
- ledmatrix-0.1.0/src/ledmatrix/font/data/5x7.bdf +1102 -0
- ledmatrix-0.1.0/src/ledmatrix/font/data/__init__.py +1 -0
- ledmatrix-0.1.0/src/ledmatrix/font/data/tom-thumb.bdf +1024 -0
- ledmatrix-0.1.0/src/ledmatrix/font/font.py +111 -0
- ledmatrix-0.1.0/src/ledmatrix/geometry.py +49 -0
- ledmatrix-0.1.0/src/ledmatrix/hotplug.py +75 -0
- ledmatrix-0.1.0/src/ledmatrix/image.py +56 -0
- ledmatrix-0.1.0/src/ledmatrix/logging.py +21 -0
- ledmatrix-0.1.0/src/ledmatrix/protocol/__init__.py +8 -0
- ledmatrix-0.1.0/src/ledmatrix/protocol/framework16.py +66 -0
- ledmatrix-0.1.0/src/ledmatrix/protocol/types.py +57 -0
- ledmatrix-0.1.0/src/ledmatrix/scheduler.py +67 -0
- ledmatrix-0.1.0/src/ledmatrix/shapes.py +36 -0
- ledmatrix-0.1.0/src/ledmatrix/transport/__init__.py +9 -0
- ledmatrix-0.1.0/src/ledmatrix/transport/base.py +30 -0
- ledmatrix-0.1.0/src/ledmatrix/transport/mock.py +47 -0
- ledmatrix-0.1.0/src/ledmatrix/transport/serial.py +102 -0
- ledmatrix-0.1.0/src/ledmatrix.egg-info/PKG-INFO +287 -0
- ledmatrix-0.1.0/src/ledmatrix.egg-info/SOURCES.txt +47 -0
- ledmatrix-0.1.0/src/ledmatrix.egg-info/dependency_links.txt +1 -0
- ledmatrix-0.1.0/src/ledmatrix.egg-info/entry_points.txt +2 -0
- ledmatrix-0.1.0/src/ledmatrix.egg-info/requires.txt +18 -0
- ledmatrix-0.1.0/src/ledmatrix.egg-info/top_level.txt +1 -0
- ledmatrix-0.1.0/tests/test_canvas.py +116 -0
- ledmatrix-0.1.0/tests/test_cli.py +44 -0
- ledmatrix-0.1.0/tests/test_device.py +59 -0
- ledmatrix-0.1.0/tests/test_dither.py +17 -0
- ledmatrix-0.1.0/tests/test_font.py +63 -0
- ledmatrix-0.1.0/tests/test_protocol.py +13 -0
- ledmatrix-0.1.0/tests/test_scheduler.py +21 -0
ledmatrix-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ledmatrix contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
ledmatrix-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ledmatrix
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A cross-platform Python SDK for the Framework 16 LED Matrix Input Module
|
|
5
|
+
Author: ledmatrix contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/jeffthepineapple/ledmatrix
|
|
8
|
+
Project-URL: Documentation, https://github.com/jeffthepineapple/ledmatrix#readme
|
|
9
|
+
Project-URL: Issues, https://github.com/jeffthepineapple/ledmatrix/issues
|
|
10
|
+
Project-URL: Repository, https://github.com/jeffthepineapple/ledmatrix
|
|
11
|
+
Keywords: framework,framework16,led,matrix,serial,hardware
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
23
|
+
Classifier: Topic :: System :: Hardware
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: pyserial>=3.5
|
|
28
|
+
Provides-Extra: image
|
|
29
|
+
Requires-Dist: Pillow>=9.0; extra == "image"
|
|
30
|
+
Provides-Extra: array
|
|
31
|
+
Requires-Dist: numpy>=1.21; extra == "array"
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-cov>=4.1; extra == "dev"
|
|
36
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
37
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
38
|
+
Provides-Extra: all
|
|
39
|
+
Requires-Dist: Pillow>=9.0; extra == "all"
|
|
40
|
+
Requires-Dist: numpy>=1.21; extra == "all"
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
|
|
43
|
+
# ledmatrix
|
|
44
|
+
|
|
45
|
+
`ledmatrix` is a Python SDK and command-line tool for the Framework 16 LED
|
|
46
|
+
Matrix Input Module. It provides a small drawing API, device discovery, frame
|
|
47
|
+
transport, image/text helpers, frame pacing, and diagnostics that can run with
|
|
48
|
+
or without hardware attached.
|
|
49
|
+
|
|
50
|
+
Current package status: `0.1.0`. The SDK has deterministic tests for protocol
|
|
51
|
+
encoding, canvas operations, fonts, dithering, scheduler behavior, device
|
|
52
|
+
helpers, and CLI behavior. Hardware-in-loop validation is still tracked
|
|
53
|
+
separately because it requires a physical Framework 16 LED Matrix Input Module.
|
|
54
|
+
|
|
55
|
+
## Features
|
|
56
|
+
|
|
57
|
+
- Canvas drawing for pixels, rectangles, lines, fills, inversion, and packed
|
|
58
|
+
frame output.
|
|
59
|
+
- Device discovery and synchronous or asynchronous device control.
|
|
60
|
+
- CLI commands for listing devices, showing pixels/rectangles/text/images,
|
|
61
|
+
brightness, raw packet inspection, and diagnostics.
|
|
62
|
+
- Optional image and array support through Pillow and NumPy.
|
|
63
|
+
- Font rendering with bundled bitmap fonts.
|
|
64
|
+
- Mock transport for examples, dry runs, and tests without LED hardware.
|
|
65
|
+
- Geometry helpers for the Framework 16 LED Matrix Input Module layout.
|
|
66
|
+
|
|
67
|
+
## Install
|
|
68
|
+
|
|
69
|
+
Install the base package:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install ledmatrix
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Install optional image and NumPy helpers:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install "ledmatrix[image]"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Install development tools from a checkout:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
python -m pip install -e ".[dev,image]"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Linux users may need udev rules before a non-root process can access the input
|
|
88
|
+
module. A packaged rule is included under `src/ledmatrix/data/`.
|
|
89
|
+
|
|
90
|
+
## Quick Start
|
|
91
|
+
|
|
92
|
+
Create a frame in memory:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from ledmatrix import Canvas
|
|
96
|
+
|
|
97
|
+
frame = Canvas()
|
|
98
|
+
frame.clear()
|
|
99
|
+
frame.set_pixel(0, 0, 255)
|
|
100
|
+
frame.fill_rect(2, 4, 5, 3, 180)
|
|
101
|
+
frame.draw_line(0, 33, 8, 0, 255)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Send a frame to the first discovered device:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from ledmatrix import Canvas, open_device
|
|
108
|
+
|
|
109
|
+
canvas = Canvas().clear()
|
|
110
|
+
canvas.fill_rect(1, 8, 7, 4, 200)
|
|
111
|
+
|
|
112
|
+
with open_device() as device:
|
|
113
|
+
device.show_frame(canvas)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Use explicit discovery if you want to choose a device:
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from ledmatrix import list_devices, open_device
|
|
120
|
+
|
|
121
|
+
devices = list_devices()
|
|
122
|
+
if not devices:
|
|
123
|
+
raise SystemExit("No LED Matrix Input Module found")
|
|
124
|
+
|
|
125
|
+
with open_device(devices[0].path) as device:
|
|
126
|
+
print(device.get_device_info())
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Drawing And Geometry
|
|
130
|
+
|
|
131
|
+
The default geometry is the Framework 16 LED Matrix Input Module: 9 columns by
|
|
132
|
+
34 rows. Coordinates are zero-based with `(0, 0)` at the top-left of the canvas.
|
|
133
|
+
Pixel values are grayscale integers from `0` to `255`.
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from ledmatrix import Canvas
|
|
137
|
+
|
|
138
|
+
canvas = Canvas()
|
|
139
|
+
canvas.clear()
|
|
140
|
+
canvas.set_pixel(8, 33, 255)
|
|
141
|
+
canvas.fill_rect(x=1, y=8, width=7, height=4, value=160)
|
|
142
|
+
canvas.invert_rect(x=2, y=9, width=2, height=2)
|
|
143
|
+
|
|
144
|
+
payload = canvas.to_bytes()
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Additional helpers include `draw_circle`, `draw_triangle`, `ImagePipeline`,
|
|
148
|
+
`normalize_dither`, and `dither`.
|
|
149
|
+
|
|
150
|
+
Per-pixel intensity is controlled by the pixel value in the frame:
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
canvas = Canvas().clear()
|
|
154
|
+
canvas.set_pixel(4, 17, 64) # dim pixel
|
|
155
|
+
canvas.set_pixel(5, 17, 255) # full-intensity pixel
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Device brightness is separate and applies globally to the module:
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
from ledmatrix import open_device
|
|
162
|
+
|
|
163
|
+
with open_device() as device:
|
|
164
|
+
device.set_brightness(50)
|
|
165
|
+
device.show_frame(canvas)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The CLI `pixel` command currently turns a coordinate on; use the Python API when
|
|
169
|
+
you need a specific per-pixel grayscale value.
|
|
170
|
+
|
|
171
|
+
## Text And Images
|
|
172
|
+
|
|
173
|
+
Text rendering uses bundled bitmap fonts:
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
from ledmatrix import Canvas
|
|
177
|
+
from ledmatrix.font import Font
|
|
178
|
+
|
|
179
|
+
canvas = Canvas().clear()
|
|
180
|
+
font = Font.load("3x5")
|
|
181
|
+
font.draw_text(canvas, 0, 0, "Hi")
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Image helpers are available when Pillow is installed:
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
from PIL import Image
|
|
188
|
+
from ledmatrix import ImagePipeline
|
|
189
|
+
|
|
190
|
+
image = Image.open("icon.png")
|
|
191
|
+
canvas = ImagePipeline(dither="bayer4x4").process(image)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Device API
|
|
195
|
+
|
|
196
|
+
The synchronous API is centered on `Device`:
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
from ledmatrix import Canvas, Device
|
|
200
|
+
|
|
201
|
+
with Device("/dev/ttyACM0") as device:
|
|
202
|
+
device.set_brightness(50)
|
|
203
|
+
device.show_frame(Canvas().clear().set_pixel(4, 17, 255))
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
The package also exports `AsyncDevice` for asyncio applications,
|
|
207
|
+
`FrameScheduler` for frame pacing, and exceptions such as
|
|
208
|
+
`DeviceNotFound`, `DeviceDisconnected`, and `ProtocolError`.
|
|
209
|
+
|
|
210
|
+
## CLI
|
|
211
|
+
|
|
212
|
+
The package installs a `ledmatrix` command:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
ledmatrix list
|
|
216
|
+
ledmatrix info
|
|
217
|
+
ledmatrix brightness 50
|
|
218
|
+
ledmatrix pixel 4 17
|
|
219
|
+
ledmatrix rect 1 8 7 4
|
|
220
|
+
ledmatrix clear
|
|
221
|
+
ledmatrix text "Hi"
|
|
222
|
+
ledmatrix image icon.png
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Diagnostics and hardware-free inspection:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
ledmatrix pixel 4 17 --dry-run
|
|
229
|
+
ledmatrix rect 1 8 7 4 --dry-run
|
|
230
|
+
ledmatrix raw 0x32 00 --dry-run
|
|
231
|
+
ledmatrix orientation-test
|
|
232
|
+
ledmatrix system
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Use `ledmatrix --help` and `ledmatrix <command> --help` for command-specific
|
|
236
|
+
arguments such as device paths, orientation, brightness, and dry-run options.
|
|
237
|
+
|
|
238
|
+
## Current Validation Status
|
|
239
|
+
|
|
240
|
+
Validated in the repository:
|
|
241
|
+
|
|
242
|
+
- Canvas bounds handling, drawing primitives, and packed frame conversion.
|
|
243
|
+
- Protocol message encoding for SDK commands.
|
|
244
|
+
- Device helper behavior with mock transports.
|
|
245
|
+
- Font loading/rendering and image dithering helpers.
|
|
246
|
+
- CLI command behavior in deterministic tests.
|
|
247
|
+
|
|
248
|
+
Known validation follow-up:
|
|
249
|
+
|
|
250
|
+
- Static analysis cleanup remains for the current checkout. The test suite
|
|
251
|
+
passes, but the virtualenv `mypy src` run reports existing serial-transport
|
|
252
|
+
typing issues.
|
|
253
|
+
|
|
254
|
+
Still requiring real hardware validation:
|
|
255
|
+
|
|
256
|
+
- End-to-end frame display on a physical Framework 16 LED Matrix Input Module.
|
|
257
|
+
- Brightness/power behavior against firmware.
|
|
258
|
+
- Orientation confirmation on the installed module.
|
|
259
|
+
- Host setup notes for platform-specific serial permissions.
|
|
260
|
+
|
|
261
|
+
See `BUILD_REPORT.md` and `docs/IMPLEMENTATION_NOTES.md` for the current
|
|
262
|
+
validation notes.
|
|
263
|
+
|
|
264
|
+
## Development
|
|
265
|
+
|
|
266
|
+
From a checkout:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
python -m pip install -e ".[dev,image]"
|
|
270
|
+
python -m pytest
|
|
271
|
+
ruff check src tests examples
|
|
272
|
+
mypy src
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Examples are in `examples/`:
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
python examples/mock_demo.py
|
|
279
|
+
python examples/snake_game.py --dry-run
|
|
280
|
+
python examples/snake_game.py --port /dev/ttyACM0
|
|
281
|
+
python examples/draw_primitives.py /dev/ttyACM0
|
|
282
|
+
python examples/text_marquee.py /dev/ttyACM0
|
|
283
|
+
python examples/hardware_smoketest.py /dev/ttyACM0
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
More detailed API and PyPI-facing documentation is available in `docs/API.md`
|
|
287
|
+
and `docs/PYPI_GUIDE.md`.
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# ledmatrix
|
|
2
|
+
|
|
3
|
+
`ledmatrix` is a Python SDK and command-line tool for the Framework 16 LED
|
|
4
|
+
Matrix Input Module. It provides a small drawing API, device discovery, frame
|
|
5
|
+
transport, image/text helpers, frame pacing, and diagnostics that can run with
|
|
6
|
+
or without hardware attached.
|
|
7
|
+
|
|
8
|
+
Current package status: `0.1.0`. The SDK has deterministic tests for protocol
|
|
9
|
+
encoding, canvas operations, fonts, dithering, scheduler behavior, device
|
|
10
|
+
helpers, and CLI behavior. Hardware-in-loop validation is still tracked
|
|
11
|
+
separately because it requires a physical Framework 16 LED Matrix Input Module.
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- Canvas drawing for pixels, rectangles, lines, fills, inversion, and packed
|
|
16
|
+
frame output.
|
|
17
|
+
- Device discovery and synchronous or asynchronous device control.
|
|
18
|
+
- CLI commands for listing devices, showing pixels/rectangles/text/images,
|
|
19
|
+
brightness, raw packet inspection, and diagnostics.
|
|
20
|
+
- Optional image and array support through Pillow and NumPy.
|
|
21
|
+
- Font rendering with bundled bitmap fonts.
|
|
22
|
+
- Mock transport for examples, dry runs, and tests without LED hardware.
|
|
23
|
+
- Geometry helpers for the Framework 16 LED Matrix Input Module layout.
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
Install the base package:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install ledmatrix
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Install optional image and NumPy helpers:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install "ledmatrix[image]"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Install development tools from a checkout:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
python -m pip install -e ".[dev,image]"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Linux users may need udev rules before a non-root process can access the input
|
|
46
|
+
module. A packaged rule is included under `src/ledmatrix/data/`.
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
50
|
+
Create a frame in memory:
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from ledmatrix import Canvas
|
|
54
|
+
|
|
55
|
+
frame = Canvas()
|
|
56
|
+
frame.clear()
|
|
57
|
+
frame.set_pixel(0, 0, 255)
|
|
58
|
+
frame.fill_rect(2, 4, 5, 3, 180)
|
|
59
|
+
frame.draw_line(0, 33, 8, 0, 255)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Send a frame to the first discovered device:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from ledmatrix import Canvas, open_device
|
|
66
|
+
|
|
67
|
+
canvas = Canvas().clear()
|
|
68
|
+
canvas.fill_rect(1, 8, 7, 4, 200)
|
|
69
|
+
|
|
70
|
+
with open_device() as device:
|
|
71
|
+
device.show_frame(canvas)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Use explicit discovery if you want to choose a device:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from ledmatrix import list_devices, open_device
|
|
78
|
+
|
|
79
|
+
devices = list_devices()
|
|
80
|
+
if not devices:
|
|
81
|
+
raise SystemExit("No LED Matrix Input Module found")
|
|
82
|
+
|
|
83
|
+
with open_device(devices[0].path) as device:
|
|
84
|
+
print(device.get_device_info())
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Drawing And Geometry
|
|
88
|
+
|
|
89
|
+
The default geometry is the Framework 16 LED Matrix Input Module: 9 columns by
|
|
90
|
+
34 rows. Coordinates are zero-based with `(0, 0)` at the top-left of the canvas.
|
|
91
|
+
Pixel values are grayscale integers from `0` to `255`.
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from ledmatrix import Canvas
|
|
95
|
+
|
|
96
|
+
canvas = Canvas()
|
|
97
|
+
canvas.clear()
|
|
98
|
+
canvas.set_pixel(8, 33, 255)
|
|
99
|
+
canvas.fill_rect(x=1, y=8, width=7, height=4, value=160)
|
|
100
|
+
canvas.invert_rect(x=2, y=9, width=2, height=2)
|
|
101
|
+
|
|
102
|
+
payload = canvas.to_bytes()
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Additional helpers include `draw_circle`, `draw_triangle`, `ImagePipeline`,
|
|
106
|
+
`normalize_dither`, and `dither`.
|
|
107
|
+
|
|
108
|
+
Per-pixel intensity is controlled by the pixel value in the frame:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
canvas = Canvas().clear()
|
|
112
|
+
canvas.set_pixel(4, 17, 64) # dim pixel
|
|
113
|
+
canvas.set_pixel(5, 17, 255) # full-intensity pixel
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Device brightness is separate and applies globally to the module:
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from ledmatrix import open_device
|
|
120
|
+
|
|
121
|
+
with open_device() as device:
|
|
122
|
+
device.set_brightness(50)
|
|
123
|
+
device.show_frame(canvas)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The CLI `pixel` command currently turns a coordinate on; use the Python API when
|
|
127
|
+
you need a specific per-pixel grayscale value.
|
|
128
|
+
|
|
129
|
+
## Text And Images
|
|
130
|
+
|
|
131
|
+
Text rendering uses bundled bitmap fonts:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from ledmatrix import Canvas
|
|
135
|
+
from ledmatrix.font import Font
|
|
136
|
+
|
|
137
|
+
canvas = Canvas().clear()
|
|
138
|
+
font = Font.load("3x5")
|
|
139
|
+
font.draw_text(canvas, 0, 0, "Hi")
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Image helpers are available when Pillow is installed:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from PIL import Image
|
|
146
|
+
from ledmatrix import ImagePipeline
|
|
147
|
+
|
|
148
|
+
image = Image.open("icon.png")
|
|
149
|
+
canvas = ImagePipeline(dither="bayer4x4").process(image)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Device API
|
|
153
|
+
|
|
154
|
+
The synchronous API is centered on `Device`:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from ledmatrix import Canvas, Device
|
|
158
|
+
|
|
159
|
+
with Device("/dev/ttyACM0") as device:
|
|
160
|
+
device.set_brightness(50)
|
|
161
|
+
device.show_frame(Canvas().clear().set_pixel(4, 17, 255))
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The package also exports `AsyncDevice` for asyncio applications,
|
|
165
|
+
`FrameScheduler` for frame pacing, and exceptions such as
|
|
166
|
+
`DeviceNotFound`, `DeviceDisconnected`, and `ProtocolError`.
|
|
167
|
+
|
|
168
|
+
## CLI
|
|
169
|
+
|
|
170
|
+
The package installs a `ledmatrix` command:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
ledmatrix list
|
|
174
|
+
ledmatrix info
|
|
175
|
+
ledmatrix brightness 50
|
|
176
|
+
ledmatrix pixel 4 17
|
|
177
|
+
ledmatrix rect 1 8 7 4
|
|
178
|
+
ledmatrix clear
|
|
179
|
+
ledmatrix text "Hi"
|
|
180
|
+
ledmatrix image icon.png
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Diagnostics and hardware-free inspection:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
ledmatrix pixel 4 17 --dry-run
|
|
187
|
+
ledmatrix rect 1 8 7 4 --dry-run
|
|
188
|
+
ledmatrix raw 0x32 00 --dry-run
|
|
189
|
+
ledmatrix orientation-test
|
|
190
|
+
ledmatrix system
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Use `ledmatrix --help` and `ledmatrix <command> --help` for command-specific
|
|
194
|
+
arguments such as device paths, orientation, brightness, and dry-run options.
|
|
195
|
+
|
|
196
|
+
## Current Validation Status
|
|
197
|
+
|
|
198
|
+
Validated in the repository:
|
|
199
|
+
|
|
200
|
+
- Canvas bounds handling, drawing primitives, and packed frame conversion.
|
|
201
|
+
- Protocol message encoding for SDK commands.
|
|
202
|
+
- Device helper behavior with mock transports.
|
|
203
|
+
- Font loading/rendering and image dithering helpers.
|
|
204
|
+
- CLI command behavior in deterministic tests.
|
|
205
|
+
|
|
206
|
+
Known validation follow-up:
|
|
207
|
+
|
|
208
|
+
- Static analysis cleanup remains for the current checkout. The test suite
|
|
209
|
+
passes, but the virtualenv `mypy src` run reports existing serial-transport
|
|
210
|
+
typing issues.
|
|
211
|
+
|
|
212
|
+
Still requiring real hardware validation:
|
|
213
|
+
|
|
214
|
+
- End-to-end frame display on a physical Framework 16 LED Matrix Input Module.
|
|
215
|
+
- Brightness/power behavior against firmware.
|
|
216
|
+
- Orientation confirmation on the installed module.
|
|
217
|
+
- Host setup notes for platform-specific serial permissions.
|
|
218
|
+
|
|
219
|
+
See `BUILD_REPORT.md` and `docs/IMPLEMENTATION_NOTES.md` for the current
|
|
220
|
+
validation notes.
|
|
221
|
+
|
|
222
|
+
## Development
|
|
223
|
+
|
|
224
|
+
From a checkout:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
python -m pip install -e ".[dev,image]"
|
|
228
|
+
python -m pytest
|
|
229
|
+
ruff check src tests examples
|
|
230
|
+
mypy src
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Examples are in `examples/`:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
python examples/mock_demo.py
|
|
237
|
+
python examples/snake_game.py --dry-run
|
|
238
|
+
python examples/snake_game.py --port /dev/ttyACM0
|
|
239
|
+
python examples/draw_primitives.py /dev/ttyACM0
|
|
240
|
+
python examples/text_marquee.py /dev/ttyACM0
|
|
241
|
+
python examples/hardware_smoketest.py /dev/ttyACM0
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
More detailed API and PyPI-facing documentation is available in `docs/API.md`
|
|
245
|
+
and `docs/PYPI_GUIDE.md`.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ledmatrix"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A cross-platform Python SDK for the Framework 16 LED Matrix Input Module"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [{name = "ledmatrix contributors"}]
|
|
13
|
+
keywords = ["framework", "framework16", "led", "matrix", "serial", "hardware"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
20
|
+
"Programming Language :: Python :: 3.9",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Topic :: Software Development :: Libraries",
|
|
26
|
+
"Topic :: System :: Hardware",
|
|
27
|
+
]
|
|
28
|
+
dependencies = ["pyserial>=3.5"]
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
image = ["Pillow>=9.0"]
|
|
32
|
+
array = ["numpy>=1.21"]
|
|
33
|
+
dev = ["build>=1.2", "pytest>=7.4", "pytest-cov>=4.1", "ruff>=0.6", "mypy>=1.10"]
|
|
34
|
+
all = ["Pillow>=9.0", "numpy>=1.21"]
|
|
35
|
+
|
|
36
|
+
[project.scripts]
|
|
37
|
+
ledmatrix = "ledmatrix.cli.main:main"
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://github.com/jeffthepineapple/ledmatrix"
|
|
41
|
+
Documentation = "https://github.com/jeffthepineapple/ledmatrix#readme"
|
|
42
|
+
Issues = "https://github.com/jeffthepineapple/ledmatrix/issues"
|
|
43
|
+
Repository = "https://github.com/jeffthepineapple/ledmatrix"
|
|
44
|
+
|
|
45
|
+
[tool.setuptools]
|
|
46
|
+
package-dir = {"" = "src"}
|
|
47
|
+
include-package-data = true
|
|
48
|
+
|
|
49
|
+
[tool.setuptools.packages.find]
|
|
50
|
+
where = ["src"]
|
|
51
|
+
|
|
52
|
+
[tool.setuptools.package-data]
|
|
53
|
+
ledmatrix = ["font/data/*.bdf", "data/*.rules"]
|
|
54
|
+
|
|
55
|
+
[tool.pytest.ini_options]
|
|
56
|
+
addopts = "-q"
|
|
57
|
+
testpaths = ["tests"]
|
|
58
|
+
|
|
59
|
+
[tool.ruff]
|
|
60
|
+
line-length = 100
|
|
61
|
+
target-version = "py39"
|
|
62
|
+
|
|
63
|
+
[tool.ruff.lint]
|
|
64
|
+
select = ["E", "F", "I", "B", "UP"]
|
|
65
|
+
|
|
66
|
+
[tool.mypy]
|
|
67
|
+
python_version = "3.9"
|
|
68
|
+
strict = true
|
|
69
|
+
warn_unused_ignores = true
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Framework 16 LED Matrix SDK."""
|
|
2
|
+
from .async_device import AsyncDevice
|
|
3
|
+
from .canvas import Canvas
|
|
4
|
+
from .device import Device, DeviceDetails, DeviceInfo, list_devices, open_device
|
|
5
|
+
from .dither import dither
|
|
6
|
+
from .exceptions import (
|
|
7
|
+
DeviceDisconnected,
|
|
8
|
+
DeviceError,
|
|
9
|
+
DeviceNotFound,
|
|
10
|
+
DeviceStalled,
|
|
11
|
+
ImageDependencyError,
|
|
12
|
+
LedMatrixError,
|
|
13
|
+
ProtocolError,
|
|
14
|
+
TransportError,
|
|
15
|
+
TransportUnavailable,
|
|
16
|
+
UnsupportedCapability,
|
|
17
|
+
)
|
|
18
|
+
from .geometry import FW16_LED_MATRIX, MatrixGeometry, PackingOrder
|
|
19
|
+
from .font import Font, draw_text_scrolling
|
|
20
|
+
from .hotplug import DeviceWatcher
|
|
21
|
+
from .image import ImagePipeline
|
|
22
|
+
from .protocol import Command, DeviceCapabilities, FirmwareVersion, Pattern
|
|
23
|
+
from .scheduler import FrameScheduler
|
|
24
|
+
|
|
25
|
+
__version__ = "0.1.0"
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"AsyncDevice", "Canvas", "Command", "Device", "DeviceCapabilities", "DeviceDetails", "DeviceDisconnected",
|
|
29
|
+
"DeviceError", "DeviceInfo", "DeviceNotFound", "DeviceStalled", "DeviceWatcher", "FW16_LED_MATRIX",
|
|
30
|
+
"FirmwareVersion", "Font", "FrameScheduler", "ImageDependencyError", "ImagePipeline", "LedMatrixError",
|
|
31
|
+
"MatrixGeometry", "PackingOrder", "Pattern", "ProtocolError", "TransportError", "TransportUnavailable",
|
|
32
|
+
"UnsupportedCapability", "__version__", "dither", "draw_text_scrolling", "list_devices", "open_device",
|
|
33
|
+
]
|