Skip to content

Commit 036fbf4

Browse files
committed
Hardware bring up
1 parent 64e5536 commit 036fbf4

File tree

2 files changed

+111
-57
lines changed

2 files changed

+111
-57
lines changed

adafruit_neotrellis/multitrellis.py

Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,70 +29,112 @@
2929
__version__ = "0.0.0-auto.0"
3030
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_neotrellis.git"
3131

32+
from typing import List, Dict, Tuple, Sequence
3233
from time import sleep
3334
from micropython import const
35+
from adafruit_neotrellis.neotrellis import NeoTrellis
3436
from adafruit_seesaw.keypad import KeyEvent
3537

36-
_NEO_TRELLIS_NUM_KEYS = const(16)
37-
38-
39-
def _key(xval):
40-
return int(int(xval / 4) * 8 + (xval % 4))
41-
42-
43-
def _seesaw_key(xval):
44-
return int(int(xval / 8) * 4 + (xval % 8))
45-
4638

4739
class MultiTrellis:
4840
"""Driver for multiple connected Adafruit NeoTrellis boards."""
4941

42+
_trelli: List[List[NeoTrellis]]
43+
_rows: int
44+
_cols: int
45+
_key_pads: List[List[NeoTrellis]]
46+
5047
def __init__(self, neotrellis_array):
5148
self._trelli = neotrellis_array
5249
self._rows = len(neotrellis_array)
5350
self._cols = len(neotrellis_array[0])
51+
col_size_sum = [0 for _ in range(self._cols)]
52+
row_size_sum = [0 for _ in range(self._rows)]
53+
for py in range(self._rows):
54+
for px in range(self._cols):
55+
assert len(self._trelli[py]) == self._cols
56+
57+
tr0 = self._trelli[0][px]
58+
tc0 = self._trelli[py][0]
59+
t = self._trelli[py][px]
60+
61+
# All columns must have similar shape
62+
assert t.height == tc0.height
63+
# All rows must have similar shape
64+
assert t.width == tr0.width
65+
66+
y_base = row_size_sum[py - 1] if py > 0 else 0
67+
x_base = col_size_sum[px - 1] if px > 0 else 0
68+
row_size_sum[py] = t.height + y_base
69+
col_size_sum[px] = t.width + x_base
70+
71+
t.x_base = x_base
72+
t.y_base = y_base
73+
74+
self._width = col_size_sum[self._cols - 1]
75+
self._height = row_size_sum[self._rows - 1]
76+
self._key_pads : List[List[NeoTrellis]] = [[None for _ in range(self._width)]
77+
for _ in range(self._height)]
78+
79+
for py in range(self._rows):
80+
for px in range(self._cols):
81+
t = self._trelli[py][px]
82+
for ky in range(t.height):
83+
for kx in range(t.width):
84+
x = t.x_base + kx
85+
y = t.y_base + ky
86+
self._key_pads[y][x] = t
87+
88+
@property
89+
def width(self):
90+
return self._width
91+
92+
@property
93+
def height(self):
94+
return self._height
95+
96+
@property
97+
def rows(self):
98+
return self._rowa
99+
100+
@property
101+
def cols(self):
102+
return self._cols
103+
104+
def __len__(self) -> int:
105+
return self._rows
106+
107+
def __getitem__(self, subscript: int) -> Sequence[NeoTrellis]:
108+
return self._trelli[subscript]
109+
110+
def get_key_pad(self, x: int, y: int) -> NeoTrellis:
111+
return self._key_pads[y][x]
54112

55113
def activate_key(self, x, y, edge, enable=True):
56114
"""Activate or deactivate a key on the trellis. x and y are the index
57115
of the key measured from the top lefthand corner. Edge specifies what
58116
edge to register an event on and can be NeoTrellis.EDGE_FALLING or
59117
NeoTrellis.EDGE_RISING. enable should be set to True if the event is
60118
to be enabled, or False if the event is to be disabled."""
61-
xkey = x % 4
62-
ykey = int(int(y % 4) * 4 / 4)
63-
self._trelli[int(y / 4)][int(x / 4)].activate_key(ykey * 4 + xkey, edge, enable)
119+
pad = self._key_pads[y][x]
120+
pad.activate_key(pad.key_index(x, y), enable)
64121

65122
def set_callback(self, x, y, function):
66123
"""Set a callback function for when an event for the key at index x, y
67124
(measured from the top lefthand corner) is detected."""
68-
xkey = x % 4
69-
ykey = int(int(y % 4) * 4 / 4)
70-
self._trelli[int(y / 4)][int(x / 4)].callbacks[ykey * 4 + xkey] = function
125+
pad = self._key_pads[y][x]
126+
pad.callbacks[pad.key_index(x, y)] = function
71127

72128
def color(self, x, y, color):
73129
"""Set the color of the pixel at index x, y measured from the top
74130
lefthand corner of the matrix"""
75-
xkey = x % 4
76-
ykey = int(int(y % 4) * 4 / 4)
77-
self._trelli[int(y / 4)][int(x / 4)].pixels[ykey * 4 + xkey] = color
131+
pad = self._key_pads[y][x]
132+
pad.pixels[pad.key_index(x, y)] = color
78133

79134
def sync(self):
80135
"""Read all trellis boards in the matrix and call any callbacks"""
81136
for _n in range(self._rows):
82137
for _m in range(self._cols):
83138

84139
_t = self._trelli[_n][_m]
85-
available = _t.count
86-
sleep(0.0005)
87-
if available > 0:
88-
available = available + 2
89-
buf = _t.read_keypad(available)
90-
for raw in buf:
91-
evt = KeyEvent(_seesaw_key((raw >> 2) & 0x3F), raw & 0x3)
92-
if (
93-
evt.number < _NEO_TRELLIS_NUM_KEYS
94-
and _t.callbacks[evt.number] is not None
95-
):
96-
y = int(evt.number / 4) + _n * 4
97-
x = int(evt.number % 4) + _m * 4
98-
_t.callbacks[evt.number](x, y, evt.edge)
140+
_t.sync()

adafruit_neotrellis/neotrellis.py

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@
4747
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_neotrellis.git"
4848

4949
from time import sleep
50+
from typing import List, Callable
5051
from micropython import const
51-
from adafruit_seesaw.keypad import Keypad, KeyEvent
52+
from adafruit_seesaw.keypad import Keypad, KeyEvent, SeesawKeyResponse, ResponseType
5253
from adafruit_seesaw.neopixel import NeoPixel
5354

5455
_NEO_TRELLIS_ADDR = const(0x2E)
@@ -59,21 +60,27 @@
5960
_NEO_TRELLIS_NUM_COLS = const(8)
6061
_NEO_TRELLIS_NUM_KEYS = const(64)
6162

62-
_NEO_TRELLIS_MAX_CALLBACKS = const(64)
63-
64-
65-
def _key(xval):
66-
return int(int(xval / 8) * 8 + (xval % 8))
67-
68-
69-
def _seesaw_key(xval):
70-
return int(int(xval / 8) * 8 + (xval % 8))
71-
7263
class NeoTrellis(Keypad):
7364
"""Driver for the Adafruit NeoTrellis."""
7465

75-
def __init__(self, i2c_bus, interrupt=False, addr=_NEO_TRELLIS_ADDR, drdy=None):
66+
width: int
67+
height: int
68+
x_base: int
69+
y_base: int
70+
interrupt_enabled: bool
71+
callbacks: List[Callable[[KeyEvent], None]]
72+
pixels: List[NeoPixel]
73+
74+
def __init__(self, i2c_bus, interrupt=False,
75+
addr=_NEO_TRELLIS_ADDR, drdy=None,
76+
width=_NEO_TRELLIS_NUM_COLS,
77+
height=_NEO_TRELLIS_NUM_ROWS,
78+
x_base = 0, y_base = 0):
7679
super().__init__(i2c_bus, addr, drdy)
80+
self.width = width
81+
self.height = height
82+
self.x_base = x_base
83+
self.y_base = y_base
7784
self.interrupt_enabled = interrupt
7885
self.callbacks = [None] * _NEO_TRELLIS_NUM_KEYS
7986
self.pixels = NeoPixel(self, _NEO_TRELLIS_NEOPIX_PIN, _NEO_TRELLIS_NUM_KEYS)
@@ -84,23 +91,28 @@ def activate_key(self, key, edge, enable=True):
8491
NeoTrellis.EDGE_FALLING or NeoTrellis.EDGE_RISING. enable should be set
8592
to True if the event is to be enabled, or False if the event is to be
8693
disabled."""
87-
self.set_event(_key(key), edge, enable)
94+
self.set_event(key, edge, enable)
95+
96+
def clear(self):
97+
self.pixels.fill((0, 0, 0))
8898

8999
def sync(self):
90100
"""read any events from the Trellis hardware and call associated
91101
callbacks"""
92102
available = self.count
93-
sleep(0.0005)
103+
sleep(0.0005) # FIXME: resolve
94104
if available > 0:
95-
# FIXME: used to read
96-
# available = available + 2
97-
# why??
98-
99105
buf = self.read_keypad(available)
100-
for response in buf:
101-
raw = response.data
102-
evt = KeyEvent(_seesaw_key((raw >> 2) & 0x3F), raw & 0x3)
103-
if (evt.number < _NEO_TRELLIS_NUM_KEYS and
104-
self.callbacks[evt.number] is not None):
105-
self.callbacks[evt.number](evt)
106+
for r in buf:
107+
if r.response_type == ResponseType.TYPE_KEY:
108+
(e, n) = r.data_edge_num()
109+
evt = KeyEvent(n, e)
110+
if (
111+
evt.number < _NEO_TRELLIS_NUM_KEYS
112+
and self.callbacks[evt.number] is not None
113+
):
114+
self.callbacks[evt.number](evt)
115+
116+
def key_index(self, x, y):
117+
return int((y - self.y_base) * self.width + (x - self.x_base))
106118

0 commit comments

Comments
 (0)