@@ -109,74 +109,41 @@ def __init__(self, rotation=0, midi_in_channel=1, midi_out_channel=1):
109
109
if rotation not in (0 , 90 , 180 , 270 ):
110
110
raise ValueError ("Only 90 degree rotations are supported." )
111
111
112
- # Define keys:
112
+ # Define LEDs:
113
+ self ._pixels = neopixel .NeoPixel (board .NEOPIXEL , 12 )
114
+ self ._led = digitalio .DigitalInOut (board .LED )
115
+ self ._led .switch_to_output ()
116
+
117
+ # Define key and pixel maps based on rotation:
118
+ self ._rotated_pixels = None
119
+ self ._key_pins = None
120
+
121
+ def _keys_and_pixels (order = None ):
122
+ """
123
+ Generate key and pixel maps based on a specified order.
124
+ :param order: The order of the keys and pixels.
125
+ """
126
+ if not order :
127
+ order = list (range (12 ))
128
+ self ._key_pins = [getattr (board , "KEY%d" % (num + 1 )) for num in order ]
129
+ self ._rotated_pixels = _PixelMapLite (self ._pixels , order = order )
130
+
113
131
if rotation == 0 :
114
- self ._key_pins = (
115
- board .KEY1 ,
116
- board .KEY2 ,
117
- board .KEY3 ,
118
- board .KEY4 ,
119
- board .KEY5 ,
120
- board .KEY6 ,
121
- board .KEY7 ,
122
- board .KEY8 ,
123
- board .KEY9 ,
124
- board .KEY10 ,
125
- board .KEY11 ,
126
- board .KEY12 ,
127
- )
132
+ _keys_and_pixels ()
128
133
129
134
if rotation == 90 :
130
- self ._key_pins = (
131
- board .KEY3 ,
132
- board .KEY6 ,
133
- board .KEY9 ,
134
- board .KEY12 ,
135
- board .KEY2 ,
136
- board .KEY5 ,
137
- board .KEY8 ,
138
- board .KEY11 ,
139
- board .KEY1 ,
140
- board .KEY4 ,
141
- board .KEY7 ,
142
- board .KEY10 ,
143
- )
135
+ _keys_and_pixels (order = (2 , 5 , 8 , 11 , 1 , 4 , 7 , 10 , 0 , 3 , 6 , 9 ))
144
136
145
137
if rotation == 180 :
146
- self ._key_pins = (
147
- board .KEY12 ,
148
- board .KEY11 ,
149
- board .KEY10 ,
150
- board .KEY9 ,
151
- board .KEY8 ,
152
- board .KEY7 ,
153
- board .KEY6 ,
154
- board .KEY5 ,
155
- board .KEY4 ,
156
- board .KEY3 ,
157
- board .KEY2 ,
158
- board .KEY1 ,
159
- )
138
+ _keys_and_pixels (order = (11 , 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 ))
160
139
161
140
if rotation == 270 :
162
- self ._key_pins = (
163
- board .KEY10 ,
164
- board .KEY7 ,
165
- board .KEY4 ,
166
- board .KEY1 ,
167
- board .KEY11 ,
168
- board .KEY8 ,
169
- board .KEY5 ,
170
- board .KEY2 ,
171
- board .KEY12 ,
172
- board .KEY9 ,
173
- board .KEY6 ,
174
- board .KEY3 ,
175
- )
141
+ _keys_and_pixels (order = (9 , 6 , 3 , 0 , 10 , 7 , 4 , 1 , 11 , 8 , 5 , 2 ))
176
142
143
+ # Define keys:
177
144
self ._keys = keypad .Keys (self ._key_pins , value_when_pressed = False , pull = True )
178
145
179
- # Define rotary encoder:
146
+ # Define rotary encoder and encoder switch :
180
147
self ._encoder = rotaryio .IncrementalEncoder (board .ROTA , board .ROTB )
181
148
self ._encoder_switch = digitalio .DigitalInOut (board .BUTTON )
182
149
self ._encoder_switch .switch_to_input (pull = digitalio .Pull .UP )
@@ -193,11 +160,6 @@ def __init__(self, rotation=0, midi_in_channel=1, midi_out_channel=1):
193
160
self ._sine_wave = None
194
161
self ._sine_wave_sample = None
195
162
196
- # Define LEDs:
197
- self ._pixels = neopixel .NeoPixel (board .NEOPIXEL , 12 , brightness = 0.5 )
198
- self ._led = digitalio .DigitalInOut (board .LED )
199
- self ._led .switch_to_output ()
200
-
201
163
# Define HID:
202
164
self ._keyboard = Keyboard (usb_hid .devices )
203
165
# This will need to be updated if we add more keyboard layouts. Currently there is only US.
@@ -280,7 +242,7 @@ def pixels(self):
280
242
macropad.pixels[0] = (255, 0, 0)
281
243
macropad.pixels[11] = (0, 0, 255)
282
244
"""
283
- return self ._pixels
245
+ return self ._rotated_pixels
284
246
285
247
@property
286
248
def red_led (self ):
@@ -908,3 +870,45 @@ def play_file(self, file_name):
908
870
while audio .playing :
909
871
pass
910
872
self ._speaker_enable .value = False
873
+
874
+
875
+ class _PixelMapLite :
876
+ """Generate a pixel map based on a specified order. Designed to work with a set of 12 pixels,
877
+ e.g. the MacroPad keypad LEDs.
878
+
879
+ :param pixels: The pixel object.
880
+ :param tuple order: The specified order of the pixels. Pixels are numbered 0-11. Defaults to
881
+ numerical order, ``0`` to ``11``.
882
+ """
883
+
884
+ def __init__ (self , pixels , order = (0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 )):
885
+ self ._pixels = pixels
886
+ self ._order = order
887
+ self ._num_pixels = len (self ._pixels )
888
+
889
+ # Copy methods from _pixels
890
+ for attr in dir (pixels ):
891
+ if not attr .startswith ("__" ) or attr in ("__enter__" , "__exit__" ):
892
+ setattr (self , attr , getattr (pixels , attr ))
893
+
894
+ def __setitem__ (self , index , val ):
895
+ if isinstance (index , slice ):
896
+ for val_i , in_i in enumerate (range (* index .indices (self ._num_pixels ))):
897
+ self ._pixels [in_i ] = self ._order [val_i ]
898
+ else :
899
+ self ._pixels [self ._order [index ]] = val
900
+
901
+ def __getitem__ (self , index ):
902
+ if isinstance (index , slice ):
903
+ return [
904
+ self ._pixels [self ._order [idx ]]
905
+ for idx in range (* index .indices (self ._num_pixels ))
906
+ ]
907
+ if index < 0 :
908
+ index += self ._num_pixels
909
+ if index >= self ._num_pixels or index < 0 :
910
+ raise IndexError
911
+ return self ._pixels [self ._order [index ]]
912
+
913
+ def __repr__ (self ):
914
+ return self ._pixels .__repr__ ()
0 commit comments