git.s-ol.nu hw/0x33.board/firmware / a97b5c6
update all board definitions s-ol a month ago
8 changed file(s) with 256 addition(s) and 50 deletion(s). Raw diff Collapse all Expand all
0 # import test
1 from hex33board import Keyboard
20 import config as board
31
4 k = Keyboard(board)
2 k = board.Keyboard(board)
53 k.run()
0 from hex33board.boards.r3_d4cf583 import *
0 from hex33board.boards.r4_5e4bf5c import *
1
12
23 dev_mode = False
34 simulator = False
5757 self.display = board.create_display(self, width=128, height=32, auto_refresh=False)
5858
5959 self.display.show(displayio.Group())
60 self._display_rotation = self.display.rotation
6061 self.display.refresh()
6162
6263 self.midi_usb = board.create_midi_usb(self)
204205 self.modes['base'].update_scale()
205206
206207 def on_flip(self, flip, last):
207 self.display.rotation = self.board.display_rotation + (180 if flip else 0)
208 self.display.rotation = self._display_rotation + (180 if flip else 0)
208209 self.flip = flip
209210
210211 for key in self.modes['base'].keys:
00 from __future__ import annotations
11
22 import board
3 import usb_midi
4 from busio import I2C, UART
5 from audiopwmio import PWMAudioOut
36 from digitalio import DigitalInOut, Pull
7 from displayio import I2CDisplay
8 from neopixel import NeoPixel
9 from adafruit_midi import MIDI
10 from adafruit_displayio_ssd1306 import SSD1306
11
412 from ..matrix import mapping_left_right
13 from .. import Keyboard
14
15
16 matrix_pins = (
17 [board.GP8, board.GP4, board.GP0, board.GP6, board.GP7, board.GP9],
18 [board.GP5, board.GP1, board.GP2, board.GP3, board.GP10],
19 )
20
21 pixels_pin = board.GP11
22 display_pins = {"sda": board.GP14, "scl": board.GP15}
23
24 midi_pins = {"tx": board.GP16, "rx": None}
25 audio_pins = {"left_channel": board.GP12, "right_channel": board.GP13}
26
527
628 class Matrix:
7 '''
29 """
830 A Scanner for Keyboard Matrices with Diodes in both directions.
931
1032 In a bidirectional matrix, each (col, row) crossing can be used twice -
3456 :param cols: A sequence of pins that are the columns for matrix A.
3557 :param rows: A sequence of pins that are the rows for matrix A.
3658 :param mapping: A coord_mapping generator function, see above.
37 '''
59 """
3860
3961 def __init__(self, cols, rows, mapping=mapping_left_right):
4062 self.len_cols = len(cols)
5173 unique_pins = {repr(c) for c in cols} | {repr(r) for r in rows}
5274 assert (
5375 len(unique_pins) == self.len_cols + self.len_rows
54 ), 'Cannot use a pin as both a column and row'
76 ), "Cannot use a pin as both a column and row"
5577 del unique_pins
5678
5779 # __class__.__name__ is used instead of isinstance as the MCP230xx lib
5981 # https://github.com/adafruit/Adafruit_CircuitPython_MCP230xx/blob/3f04abbd65ba5fa938fcb04b99e92ae48a8c9406/adafruit_mcp230xx/digital_inout.py#L33
6082
6183 self.cols = [
62 x if x.__class__.__name__ == 'DigitalInOut' else DigitalInOut(x)
84 x if x.__class__.__name__ == "DigitalInOut" else DigitalInOut(x)
6385 for x in cols
6486 ]
6587 self.rows = [
66 x if x.__class__.__name__ == 'DigitalInOut' else DigitalInOut(x)
88 x if x.__class__.__name__ == "DigitalInOut" else DigitalInOut(x)
6789 for x in rows
6890 ]
6991
109131
110132 opin.switch_to_input()
111133
112 matrix_pins = (
113 [board.GP8, board.GP4, board.GP0, board.GP6, board.GP7, board.GP9],
114 [board.GP5, board.GP1, board.GP2, board.GP3, board.GP10],
115 )
116134
117 pixels_pin = board.GP11
118 display_pins = { "sda": board.GP14, "scl": board.GP15 }
135 def create_matrix(board):
136 return Matrix(*matrix_pins)
119137
120 midi_pins = { "tx": board.GP16, "rx": None }
121 audio_pins = { "left_channel": board.GP12, "right_channel": board.GP13 }
122 i2c_pins = None
138
139 def create_pixels(board, **kwargs):
140 return NeoPixel(pixels_pin, 48 + 4, **kwargs)
141
142
143 def create_display(board, **kwargs):
144 i2c = I2C(**display_pins, frequency=1000000)
145 bus = I2CDisplay(i2c, device_address=0x3C)
146 return SSD1306(bus, rotation=180, **kwargs)
147
148
149 def create_midi_trs(board):
150 return MIDI(None, UART(**midi_pins, baudrate=31250))
151
152
153 def create_midi_usb(board):
154 midi_in = next(p for p in usb_midi.ports if isinstance(p, usb_midi.PortIn))
155 midi_out = next(p for p in usb_midi.ports if isinstance(p, usb_midi.PortOut))
156 return MIDI(midi_in, midi_out)
157
158
159 def create_i2c(board, **kwargs):
160 return None
161
162
163 def create_i2ctarget(board, **kwargs):
164 return None
165
166
167 def create_audio_out(board):
168 return PWMAudioOut(**audio_pins)
00 import board
1 import usb_midi
2 from busio import I2C, UART
3 from audiopwmio import PWMAudioOut
4 from displayio import I2CDisplay
5 from neopixel import NeoPixel
6 from adafruit_midi import MIDI
7 from adafruit_displayio_ssd1306 import SSD1306
18
29 from ..matrix import Matrix
10 from .. import Keyboard
311
412 matrix_pins = (
513 # cols
1927 )
2028
2129 pixels_pin = board.GP17
22 display_pins = { "sda": board.GP14, "scl": board.GP15 }
2330
24 midi_pins = { "tx": board.GP16, "rx": None }
25 audio_pins = { "left_channel": board.GP18, "right_channel": board.GP19 }
26 i2c_pins = { "sda": board.GP20, "scl": board.GP21 }
31 display_pins = {"sda": board.GP14, "scl": board.GP15}
32
33 midi_pins = {"tx": board.GP16, "rx": None}
34
35 sda = board.GP20
36 scl = board.GP21
37
38 audio_pins = {"left_channel": board.GP18, "right_channel": board.GP19}
39
40
41 def create_matrix(board):
42 return Matrix(*matrix_pins)
43
44
45 def create_pixels(board, **kwargs):
46 return NeoPixel(pixels_pin, 48 + 4, **kwargs)
47
48
49 def create_display(board, **kwargs):
50 i2c = I2C(**display_pins, frequency=1000000)
51 bus = I2CDisplay(i2c, device_address=0x3C)
52 return SSD1306(bus, rotation=180, **kwargs)
53
54
55 def create_midi_trs(board):
56 return MIDI(None, UART(**midi_pins, baudrate=31250))
57
58
59 def create_midi_usb(board):
60 midi_in = next(p for p in usb_midi.ports if isinstance(p, usb_midi.PortIn))
61 midi_out = next(p for p in usb_midi.ports if isinstance(p, usb_midi.PortOut))
62 return MIDI(midi_in, midi_out)
63
64
65 def create_i2c(board, **kwargs):
66 return I2C(sda=sda, scl=scl, **kwargs)
67
68
69 def create_i2ctarget(board, **kwargs):
70 from i2ctarget import I2CTarget
71
72 return I2CTarget(sda=sda, scl=scl, **kwargs)
73
74
75 def create_audio_out(board):
76 return PWMAudioOut(**audio_pins)
77 from adafruit_displayio_ssd1306 import SSD1306
88
99 from ..matrix import Matrix
10 from .. import Keyboard
1011
1112 matrix_pins = (
1213 # cols
2526 ],
2627 )
2728
29 pixels_pin = board.GP17
30
31 display_pins = {"sda": board.GP14, "scl": board.GP15}
32
33 midi_pins = {"tx": board.GP16, "rx": None}
34
35 sda = board.GP20
36 scl = board.GP21
37
38 audio_pins = {"left_channel": board.GP18, "right_channel": board.GP19}
39
2840
2941 def create_matrix(board):
3042 return Matrix(*matrix_pins)
3143
32 pixels_pin = board.GP17
44
3345 def create_pixels(board, **kwargs):
3446 return NeoPixel(pixels_pin, 48 + 4, **kwargs)
3547
36 display_pins = { "sda": board.GP14, "scl": board.GP15 }
37 display_rotation = 180
48
3849 def create_display(board, **kwargs):
3950 i2c = I2C(**display_pins, frequency=1000000)
4051 bus = I2CDisplay(i2c, device_address=0x3C)
41 return SSD1306(
42 bus, rotation=display_rotation, **kwargs
43 )
52 return SSD1306(bus, rotation=180, **kwargs)
4453
45 midi_pins = { "tx": board.GP16, "rx": None }
54
4655 def create_midi_trs(board):
4756 return MIDI(None, UART(**midi_pins, baudrate=31250))
57
58
4859 def create_midi_usb(board):
4960 midi_in = next(p for p in usb_midi.ports if isinstance(p, usb_midi.PortIn))
5061 midi_out = next(p for p in usb_midi.ports if isinstance(p, usb_midi.PortOut))
5162 return MIDI(midi_in, midi_out)
5263
53 audio_pins = { "left_channel": board.GP18, "right_channel": board.GP19 }
54 def create_audio_out(board):
55 return PWMAudioOut(**audio_pins)
5664
57 sda = board.GP20
58 scl = board.GP21
5965 def create_i2c(board, **kwargs):
6066 return I2C(sda=sda, scl=scl, **kwargs)
6167
68
6269 def create_i2ctarget(board, **kwargs):
6370 from i2ctarget import I2CTarget
71
6472 return I2CTarget(sda=sda, scl=scl, **kwargs)
73
74
75 def create_audio_out(board):
76 return PWMAudioOut(**audio_pins)
0 import board
1 import usb_midi
2 from busio import I2C, UART
3 from audiopwmio import PWMAudioOut
4 from displayio import I2CDisplay
5 from neopixel import NeoPixel
6 from adafruit_midi import MIDI
7 from adafruit_displayio_ssd1306 import SSD1306
8
9 from ..matrix import Matrix
10 from .. import Keyboard
11
12 matrix_pins = (
13 # cols
14 [board.GP9, board.GP4, board.GP0, board.GP6, board.GP7, board.GP8],
15 # rows
16 [
17 board.GP13,
18 board.GP12,
19 board.GP11,
20 board.GP10,
21 board.GP5,
22 board.GP1,
23 board.GP2,
24 board.GP3,
25 board.GP22,
26 ],
27 )
28
29 pixels_pin = board.GP17
30
31 display_pins = {"sda": board.GP14, "scl": board.GP15}
32
33 midi_pins = {"tx": board.GP16, "rx": None}
34
35 sda = board.GP20
36 scl = board.GP21
37
38 audio_pins = {"left_channel": board.GP18, "right_channel": board.GP19}
39
40
41 def create_matrix(board):
42 return Matrix(*matrix_pins)
43
44
45 def create_pixels(board, **kwargs):
46 return NeoPixel(pixels_pin, 48 + 4, **kwargs)
47
48
49 def create_display(board, **kwargs):
50 i2c = I2C(**display_pins, frequency=1000000)
51 bus = I2CDisplay(i2c, device_address=0x3C)
52 return SSD1306(bus, rotation=180, **kwargs)
53
54
55 def create_midi_trs(board):
56 return MIDI(None, UART(**midi_pins, baudrate=31250))
57
58
59 def create_midi_usb(board):
60 midi_in = next(p for p in usb_midi.ports if isinstance(p, usb_midi.PortIn))
61 midi_out = next(p for p in usb_midi.ports if isinstance(p, usb_midi.PortOut))
62 return MIDI(midi_in, midi_out)
63
64
65 def create_i2c(board, **kwargs):
66 return I2C(sda=sda, scl=scl, **kwargs)
67
68
69 def create_i2ctarget(board, **kwargs):
70 from i2ctarget import I2CTarget
71
72 return I2CTarget(sda=sda, scl=scl, **kwargs)
73
74
75 def create_audio_out(board):
76 return PWMAudioOut(**audio_pins)
2020 if rtmidi.API_UNIX_JACK in rtmidi.get_compiled_api():
2121 rtmidi_api = rtmidi.API_UNIX_JACK
2222
23
2324 class MIDI:
2425 def __init__(self, inp, out):
2526 self.inp = inp
4546 msg = self.inp.get_message()
4647 if msg:
4748 return MIDIMessage.from_message_bytes(msg[0], self.in_channel)[0]
49
4850
4951 def create_midi_usb(board):
5052 inp = rtmidi.MidiIn(rtmidi_api, "0x33.boad sim")
5456 inp.ignore_types(sysex=False)
5557 return MIDI(inp, out)
5658
59
5760 def create_midi_trs(board):
5861 out = rtmidi.MidiOut(rtmidi_api, "0x33.boad sim")
5962 out.open_virtual_port("TRS out")
6063 return MIDI(None, out)
6164
65
6266 def create_matrix(board):
6367 class DummyMatrix:
6468 def __init__(self, board):
7074
7175 msg = self.board.midi_usb.receive()
7276 while msg:
73 if isinstance(msg, SystemExclusive) and msg.manufacturer_id == b'\0s-':
77 if isinstance(msg, SystemExclusive) and msg.manufacturer_id == b"\0s-":
7478 key, state = msg.data
7579 yield key, state
7680
7882
7983 return DummyMatrix(board)
8084
85
8186 display_rotation = 0
87
88
8289 def create_display(board, **kwargs):
8390 class ScaledDisplay:
8491 def __init__(self, board, width, height, scale=1, **args):
8592 self.board = board
86 self.display = PyGameDisplay(width=width*scale, height=height*scale, **args)
93 self.display = PyGameDisplay(
94 width=width * scale, height=height * scale, **args
95 )
8796 self.group = displayio.Group(scale=scale)
8897 self.display.show(self.group)
8998
9099 def refresh(self):
91100 self.display.refresh()
92101
93 if not hasattr(self.board, 'svg_preview'):
102 if not hasattr(self.board, "svg_preview"):
94103 return
95104
96105 scale = self.group.scale
97 res = (self.display.width//scale, self.display.height//scale)
98 shot = self.display._buffer.convert('1').resize(res)
106 res = (self.display.width // scale, self.display.height // scale)
107 shot = self.display._buffer.convert("1").resize(res)
99108
100109 with BytesIO() as buf:
101 shot.save(buf, format='PNG')
110 shot.save(buf, format="PNG")
102111 data = b64encode(buf.getvalue())
103 self.board.svg_preview.set_oled('data:image/png;base64,' + data.decode())
112 self.board.svg_preview.set_oled(
113 "data:image/png;base64," + data.decode()
114 )
104115
105116 def show(self, group):
106117 while len(self.group):
108119 self.group.append(group)
109120
110121 return ScaledDisplay(board, scale=4, **kwargs)
122
111123
112124 def create_pixels(board, **kwargs):
113125 class DummyNeopixels:
120132 self.pixels[key] = value
121133
122134 def show(self):
135 if not hasattr(self.board, "svg_preview"):
136 return
137
123138 self.board.svg_preview.set_pixels(self.pixels)
124139
125140 def fill(self, value):
128143
129144 return DummyNeopixels(board)
130145
146
131147 def create_audio_out(board):
132148 pass
133149
150
134151 def create_i2c(board, **kwargs):
135152 pass
153
136154
137155 def create_i2ctarget(board, **kwargs):
138156 pass
142160 def __init__(self):
143161 super().__init__()
144162
145 self.template = ElementTree.parse('template.svg')
163 self.template = ElementTree.parse("template.svg")
146164 self.oled = self.template.find(".//*[@id='oled']")
147165 self.leds = self.template.findall(".//*[@class='btn']")
148166
159177 def set_pixels(self, pixels):
160178 for i, rgb in enumerate(pixels):
161179 if not isinstance(rgb, tuple):
162 rgb = (rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff)
163 hex = "#{0:02x}{1:02x}{2:02x}".format(*(int(128 + sqrt(x) * 127) for x in rgb))
164 self.leds[i].set('style', 'stroke:#000000;stroke-width:1;fill:' + hex)
180 rgb = (rgb >> 16, (rgb >> 8) & 0xFF, rgb & 0xFF)
181 hex = "#{0:02x}{1:02x}{2:02x}".format(
182 *(int(128 + sqrt(x) * 127) for x in rgb)
183 )
184 self.leds[i].set("style", "stroke:#000000;stroke-width:1;fill:" + hex)
165185
166186 def set_oled(self, data):
167 self.oled.set('{http://www.w3.org/1999/xlink}href', data)
187 self.oled.set("href", data)
168188
169189 def update(self):
170 data = ElementTree.tostring(self.template.getroot(), encoding='unicode')
171 self.widget.load(data.encode('utf-8'))
190 data = ElementTree.tostring(self.template.getroot(), encoding="unicode")
191 self.widget.load(data.encode("utf-8"))
192
172193
173194 class Worker(QObject):
174195 finished = pyqtSignal()
183204 finally:
184205 self.finished.emit()
185206
207
186208 class Keyboard(BaseKeyboard):
187209 def run(self):
188210 self.app = QApplication([])
201223 self.thread.start()
202224
203225 self.app.exec_()
204
205226
206227 def _run(self):
207228 i = 0