update all board definitions
s-ol
a month ago
0 | # import test | |
1 | from hex33board import Keyboard | |
2 | 0 | import config as board |
3 | 1 | |
4 | k = Keyboard(board) | |
2 | k = board.Keyboard(board) | |
5 | 3 | k.run() |
0 | from hex33board.boards.r3_d4cf583 import * | |
0 | from hex33board.boards.r4_5e4bf5c import * | |
1 | ||
1 | 2 | |
2 | 3 | dev_mode = False |
3 | 4 | simulator = False |
57 | 57 | self.display = board.create_display(self, width=128, height=32, auto_refresh=False) |
58 | 58 | |
59 | 59 | self.display.show(displayio.Group()) |
60 | self._display_rotation = self.display.rotation | |
60 | 61 | self.display.refresh() |
61 | 62 | |
62 | 63 | self.midi_usb = board.create_midi_usb(self) |
204 | 205 | self.modes['base'].update_scale() |
205 | 206 | |
206 | 207 | 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) | |
208 | 209 | self.flip = flip |
209 | 210 | |
210 | 211 | for key in self.modes['base'].keys: |
0 | 0 | from __future__ import annotations |
1 | 1 | |
2 | 2 | import board |
3 | import usb_midi | |
4 | from busio import I2C, UART | |
5 | from audiopwmio import PWMAudioOut | |
3 | 6 | 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 | ||
4 | 12 | 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 | ||
5 | 27 | |
6 | 28 | class Matrix: |
7 | ''' | |
29 | """ | |
8 | 30 | A Scanner for Keyboard Matrices with Diodes in both directions. |
9 | 31 | |
10 | 32 | In a bidirectional matrix, each (col, row) crossing can be used twice - |
34 | 56 | :param cols: A sequence of pins that are the columns for matrix A. |
35 | 57 | :param rows: A sequence of pins that are the rows for matrix A. |
36 | 58 | :param mapping: A coord_mapping generator function, see above. |
37 | ''' | |
59 | """ | |
38 | 60 | |
39 | 61 | def __init__(self, cols, rows, mapping=mapping_left_right): |
40 | 62 | self.len_cols = len(cols) |
51 | 73 | unique_pins = {repr(c) for c in cols} | {repr(r) for r in rows} |
52 | 74 | assert ( |
53 | 75 | 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" | |
55 | 77 | del unique_pins |
56 | 78 | |
57 | 79 | # __class__.__name__ is used instead of isinstance as the MCP230xx lib |
59 | 81 | # https://github.com/adafruit/Adafruit_CircuitPython_MCP230xx/blob/3f04abbd65ba5fa938fcb04b99e92ae48a8c9406/adafruit_mcp230xx/digital_inout.py#L33 |
60 | 82 | |
61 | 83 | self.cols = [ |
62 | x if x.__class__.__name__ == 'DigitalInOut' else DigitalInOut(x) | |
84 | x if x.__class__.__name__ == "DigitalInOut" else DigitalInOut(x) | |
63 | 85 | for x in cols |
64 | 86 | ] |
65 | 87 | self.rows = [ |
66 | x if x.__class__.__name__ == 'DigitalInOut' else DigitalInOut(x) | |
88 | x if x.__class__.__name__ == "DigitalInOut" else DigitalInOut(x) | |
67 | 89 | for x in rows |
68 | 90 | ] |
69 | 91 | |
109 | 131 | |
110 | 132 | opin.switch_to_input() |
111 | 133 | |
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 | ) | |
116 | 134 | |
117 | pixels_pin = board.GP11 | |
118 | display_pins = { "sda": board.GP14, "scl": board.GP15 } | |
135 | def create_matrix(board): | |
136 | return Matrix(*matrix_pins) | |
119 | 137 | |
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) |
0 | 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 | |
1 | 8 | |
2 | 9 | from ..matrix import Matrix |
10 | from .. import Keyboard | |
3 | 11 | |
4 | 12 | matrix_pins = ( |
5 | 13 | # cols |
19 | 27 | ) |
20 | 28 | |
21 | 29 | pixels_pin = board.GP17 |
22 | display_pins = { "sda": board.GP14, "scl": board.GP15 } | |
23 | 30 | |
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) |
7 | 7 | from adafruit_displayio_ssd1306 import SSD1306 |
8 | 8 | |
9 | 9 | from ..matrix import Matrix |
10 | from .. import Keyboard | |
10 | 11 | |
11 | 12 | matrix_pins = ( |
12 | 13 | # cols |
25 | 26 | ], |
26 | 27 | ) |
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 | ||
28 | 40 | |
29 | 41 | def create_matrix(board): |
30 | 42 | return Matrix(*matrix_pins) |
31 | 43 | |
32 | pixels_pin = board.GP17 | |
44 | ||
33 | 45 | def create_pixels(board, **kwargs): |
34 | 46 | return NeoPixel(pixels_pin, 48 + 4, **kwargs) |
35 | 47 | |
36 | display_pins = { "sda": board.GP14, "scl": board.GP15 } | |
37 | display_rotation = 180 | |
48 | ||
38 | 49 | def create_display(board, **kwargs): |
39 | 50 | i2c = I2C(**display_pins, frequency=1000000) |
40 | 51 | bus = I2CDisplay(i2c, device_address=0x3C) |
41 | return SSD1306( | |
42 | bus, rotation=display_rotation, **kwargs | |
43 | ) | |
52 | return SSD1306(bus, rotation=180, **kwargs) | |
44 | 53 | |
45 | midi_pins = { "tx": board.GP16, "rx": None } | |
54 | ||
46 | 55 | def create_midi_trs(board): |
47 | 56 | return MIDI(None, UART(**midi_pins, baudrate=31250)) |
57 | ||
58 | ||
48 | 59 | def create_midi_usb(board): |
49 | 60 | midi_in = next(p for p in usb_midi.ports if isinstance(p, usb_midi.PortIn)) |
50 | 61 | midi_out = next(p for p in usb_midi.ports if isinstance(p, usb_midi.PortOut)) |
51 | 62 | return MIDI(midi_in, midi_out) |
52 | 63 | |
53 | audio_pins = { "left_channel": board.GP18, "right_channel": board.GP19 } | |
54 | def create_audio_out(board): | |
55 | return PWMAudioOut(**audio_pins) | |
56 | 64 | |
57 | sda = board.GP20 | |
58 | scl = board.GP21 | |
59 | 65 | def create_i2c(board, **kwargs): |
60 | 66 | return I2C(sda=sda, scl=scl, **kwargs) |
61 | 67 | |
68 | ||
62 | 69 | def create_i2ctarget(board, **kwargs): |
63 | 70 | from i2ctarget import I2CTarget |
71 | ||
64 | 72 | 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) |
20 | 20 | if rtmidi.API_UNIX_JACK in rtmidi.get_compiled_api(): |
21 | 21 | rtmidi_api = rtmidi.API_UNIX_JACK |
22 | 22 | |
23 | ||
23 | 24 | class MIDI: |
24 | 25 | def __init__(self, inp, out): |
25 | 26 | self.inp = inp |
45 | 46 | msg = self.inp.get_message() |
46 | 47 | if msg: |
47 | 48 | return MIDIMessage.from_message_bytes(msg[0], self.in_channel)[0] |
49 | ||
48 | 50 | |
49 | 51 | def create_midi_usb(board): |
50 | 52 | inp = rtmidi.MidiIn(rtmidi_api, "0x33.boad sim") |
54 | 56 | inp.ignore_types(sysex=False) |
55 | 57 | return MIDI(inp, out) |
56 | 58 | |
59 | ||
57 | 60 | def create_midi_trs(board): |
58 | 61 | out = rtmidi.MidiOut(rtmidi_api, "0x33.boad sim") |
59 | 62 | out.open_virtual_port("TRS out") |
60 | 63 | return MIDI(None, out) |
61 | 64 | |
65 | ||
62 | 66 | def create_matrix(board): |
63 | 67 | class DummyMatrix: |
64 | 68 | def __init__(self, board): |
70 | 74 | |
71 | 75 | msg = self.board.midi_usb.receive() |
72 | 76 | while msg: |
73 | if isinstance(msg, SystemExclusive) and msg.manufacturer_id == b'\0s-': | |
77 | if isinstance(msg, SystemExclusive) and msg.manufacturer_id == b"\0s-": | |
74 | 78 | key, state = msg.data |
75 | 79 | yield key, state |
76 | 80 | |
78 | 82 | |
79 | 83 | return DummyMatrix(board) |
80 | 84 | |
85 | ||
81 | 86 | display_rotation = 0 |
87 | ||
88 | ||
82 | 89 | def create_display(board, **kwargs): |
83 | 90 | class ScaledDisplay: |
84 | 91 | def __init__(self, board, width, height, scale=1, **args): |
85 | 92 | 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 | ) | |
87 | 96 | self.group = displayio.Group(scale=scale) |
88 | 97 | self.display.show(self.group) |
89 | 98 | |
90 | 99 | def refresh(self): |
91 | 100 | self.display.refresh() |
92 | 101 | |
93 | if not hasattr(self.board, 'svg_preview'): | |
102 | if not hasattr(self.board, "svg_preview"): | |
94 | 103 | return |
95 | 104 | |
96 | 105 | 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) | |
99 | 108 | |
100 | 109 | with BytesIO() as buf: |
101 | shot.save(buf, format='PNG') | |
110 | shot.save(buf, format="PNG") | |
102 | 111 | 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 | ) | |
104 | 115 | |
105 | 116 | def show(self, group): |
106 | 117 | while len(self.group): |
108 | 119 | self.group.append(group) |
109 | 120 | |
110 | 121 | return ScaledDisplay(board, scale=4, **kwargs) |
122 | ||
111 | 123 | |
112 | 124 | def create_pixels(board, **kwargs): |
113 | 125 | class DummyNeopixels: |
120 | 132 | self.pixels[key] = value |
121 | 133 | |
122 | 134 | def show(self): |
135 | if not hasattr(self.board, "svg_preview"): | |
136 | return | |
137 | ||
123 | 138 | self.board.svg_preview.set_pixels(self.pixels) |
124 | 139 | |
125 | 140 | def fill(self, value): |
128 | 143 | |
129 | 144 | return DummyNeopixels(board) |
130 | 145 | |
146 | ||
131 | 147 | def create_audio_out(board): |
132 | 148 | pass |
133 | 149 | |
150 | ||
134 | 151 | def create_i2c(board, **kwargs): |
135 | 152 | pass |
153 | ||
136 | 154 | |
137 | 155 | def create_i2ctarget(board, **kwargs): |
138 | 156 | pass |
142 | 160 | def __init__(self): |
143 | 161 | super().__init__() |
144 | 162 | |
145 | self.template = ElementTree.parse('template.svg') | |
163 | self.template = ElementTree.parse("template.svg") | |
146 | 164 | self.oled = self.template.find(".//*[@id='oled']") |
147 | 165 | self.leds = self.template.findall(".//*[@class='btn']") |
148 | 166 | |
159 | 177 | def set_pixels(self, pixels): |
160 | 178 | for i, rgb in enumerate(pixels): |
161 | 179 | 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) | |
165 | 185 | |
166 | 186 | def set_oled(self, data): |
167 | self.oled.set('{http://www.w3.org/1999/xlink}href', data) | |
187 | self.oled.set("href", data) | |
168 | 188 | |
169 | 189 | 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 | ||
172 | 193 | |
173 | 194 | class Worker(QObject): |
174 | 195 | finished = pyqtSignal() |
183 | 204 | finally: |
184 | 205 | self.finished.emit() |
185 | 206 | |
207 | ||
186 | 208 | class Keyboard(BaseKeyboard): |
187 | 209 | def run(self): |
188 | 210 | self.app = QApplication([]) |
201 | 223 | self.thread.start() |
202 | 224 | |
203 | 225 | self.app.exec_() |
204 | ||
205 | 226 | |
206 | 227 | def _run(self): |
207 | 228 | i = 0 |