finished making Macropad OS 1.0

This commit is contained in:
Lucas
2022-05-07 19:11:52 -04:00
parent 3afba8d096
commit f627501436
9 changed files with 233 additions and 108 deletions
+1
View File
@@ -18,3 +18,4 @@ class Config(object):
def save(self): def save(self):
with open(self.save_file, "w") as f: with open(self.save_file, "w") as f:
json.dump(self.data, f) json.dump(self.data, f)
+7 -2
View File
@@ -4,7 +4,10 @@
"k2":["TWO"], "k2":["TWO"],
"k3":["THREE"], "k3":["THREE"],
"k4":["ONE"], "k4":["ONE"],
"k5":["TWO"], "k5":{
"keys":["TWO"],
"name":""
}
"k6":["THREE"], "k6":["THREE"],
"k7":["ONE"], "k7":["ONE"],
"k8":["TWO"], "k8":["TWO"],
@@ -12,4 +15,6 @@
"k10":["ONE"], "k10":["ONE"],
"k11":["TWO"], "k11":["TWO"],
"k12":["THREE"], "k12":["THREE"],
} }
example.k1.name
+160 -5
View File
@@ -1,20 +1,50 @@
import displayio import displayio
import terminalio
from adafruit_display_text import label
from adafruit_hid.keycode import Keycode
from .app_state import AppState, InvalidStateUpdateError from .app_state import AppState, InvalidStateUpdateError
DISPLAY = displayio.Group() DISPLAY = displayio.Group()
def convert_to_keynum(x, y):
return 3 * x + y
class App(object): class App(object):
def __init__(self, macropad, config): def __init__(self, macropad, config):
"""
:param macropad:
:param config:
"""
print("app created") print("app created")
self._key_lights = [(0, 0, 0) for _ in range(12)]
self._display_group = DISPLAY
self._title = "title"
self._layout = None
self._title_label = label.Label(
y=4,
font=terminalio.FONT,
color=0x0,
text=f"",
background_color=0xFFFFFF,
)
self._key_tones = [config.data["default_tone"] for _ in range(12)]
self._enabled_key_sounds = True
self._pressed_keys = []
self._key_pressed_callbacks = []
self._key_released_callbacks = []
self._encoder_changed_callbacks = []
self._encoder_state = 0
self.macropad = macropad self.macropad = macropad
self.config = config self.config = config
self.name = "app" self.name = "app"
self.state = AppState.STOPPED self.state = AppState.STOPPED
self.display_group = DISPLAY
def start(self): def start(self):
print("Start from base class ") print("Start from base class ")
@@ -40,7 +70,7 @@ class App(object):
self.state = AppState.RUNNING self.state = AppState.RUNNING
def _on_resume(self): def _on_resume(self):
pass self.add_displays_to_group()
def on_resume(self): def on_resume(self):
raise NotImplementedError("on_resume not implemented") raise NotImplementedError("on_resume not implemented")
@@ -59,14 +89,55 @@ class App(object):
self.macropad.mouse.release_all() self.macropad.mouse.release_all()
self.macropad.stop_tone() self.macropad.stop_tone()
self.macropad.pixels.show() self.macropad.pixels.show()
# self.macropad.display.refresh() self.remove_displays_from_group()
def on_pause(self): def on_pause(self):
raise NotImplementedError("on_pause not implemented") raise NotImplementedError("on_pause not implemented")
def loop(self): def loop(self):
# We'll fire you if you override this method.
self._on_loop()
self.on_loop()
def on_loop(self):
raise NotImplementedError("Not implemented") raise NotImplementedError("Not implemented")
def _on_loop(self):
self._update_lighting()
self._process_keys_pressed()
self._process_wheel_changes()
self.on_loop()
def _process_keys_pressed(self):
key_event = self.macropad.keys.events.get()
if key_event:
if key_event.key_number < 12:
if key_event.pressed:
self.macropad.stop_tone()
self.macropad.start_tone(self._key_tones[key_event.key_number])
self._pressed_keys.append(key_event.key_number)
if self._key_pressed_callbacks:
for callback in self._key_pressed_callbacks:
callback(key_event.key_number)
else:
self.macropad.stop_tone()
self._pressed_keys.remove(key_event.key_number)
if self._pressed_keys:
self.macropad.start_tone(self._key_tones[self._pressed_keys[0]])
if self._key_released_callbacks:
for callback in self._key_pressed_callbacks:
callback(key_event.key_number)
def _process_wheel_changes(self):
encoder = self.macropad.encoder
if self._encoder_state != encoder:
for callback in self._encoder_changed_callbacks:
if self._encoder_state > encoder:
callback(-1)
else:
callback(1)
self._encoder_state = encoder
def stop(self): def stop(self):
if self.state is not AppState.PAUSED: if self.state is not AppState.PAUSED:
raise InvalidStateUpdateError(f"Stop called but the current app state is {self.state}") raise InvalidStateUpdateError(f"Stop called but the current app state is {self.state}")
@@ -80,3 +151,87 @@ class App(object):
def on_stop(self): def on_stop(self):
raise NotImplementedError("on_stop not implemented.") raise NotImplementedError("on_stop not implemented.")
def _update_lighting(self):
for index, color in enumerate(self._key_lights):
self.macropad.pixels[index] = color
def add_displays_to_group(self):
self._display_group.append(self._title_label)
self._display_group.append(self._layout)
self.macropad.display.show(self._display_group)
def remove_displays_from_group(self):
self._display_group.remove(self._title_label)
self._display_group.remove(self._layout)
def set_color(self, x, y, color):
key_value = convert_to_keynum(x, y)
if key_value >= 12:
raise ValueError("color index out of range")
if len(color) != 3:
self._key_lights[key_value] = color
def set_colors(self, colors):
if len(colors) != 12:
raise ValueError("Colors must be passed in as a 12 len array")
for color in colors:
if len(color) != 3:
raise ValueError("Color format error - color must be length 3")
self._key_lights = colors
def get_colors(self):
return self._key_lights
def set_tone(self, keypad_num, tone):
if keypad_num >= 12:
raise ValueError("Tone index out of range")
if tone < 20 or tone > 20000:
raise ValueError("Tone format error - tone out of human hearing range (20 - 20000)")
self._key_tones[keypad_num] = tone
def set_tones(self, tones):
if len(tones) != 12:
raise ValueError("Tones must be passed in as a 12 len array")
for tone in tones:
if tone < 20 or tone > 20000:
raise ValueError("Tone format error - tone out of human hearing range (20 - 20000)")
self._key_tones = tones
def set_tone_status(self, enable):
self._enabled_key_sounds = enable
def get_tones(self):
return self._key_tones
def set_title(self, title):
"""
:string title: Title of your app - shown in the top bar.
:return: None
"""
if len(title) > 22:
# TODO: Update this to be able to scroll the display if too long?
raise ValueError("Title too long to be displayed on screen")
self._title = title
diff = int((22 - len(title)) / 2)
self._title_label.text = f"{''.join([' ' for _ in range(diff)])}{self._title}{''.join([' ' for _ in range(diff)])}"
def set_layout(self, layout):
"""
:displayio.Group layout:
:return:
"""
self._layout = layout
def register_on_key_pressed(self, function):
self._key_pressed_callbacks.append(function)
def register_on_key_released(self, function):
self._key_released_callbacks.append(function)
def register_on_encoder_changed(self, function):
self._encoder_changed_callbacks.append(function)
-1
View File
@@ -33,7 +33,6 @@ class AppRouter(object):
if self.current_app.state is AppState.PAUSED: if self.current_app.state is AppState.PAUSED:
print("Starting new app") print("Starting new app")
self.current_app.resume() self.current_app.resume()
print(time.monotonic_ns())
def start(self): def start(self):
self.current_app.start() self.current_app.start()
+2 -1
View File
@@ -1,2 +1,3 @@
from .light_patterns import * from .light_patterns import *
from .sound_patterns import * from .sound_patterns import *
from .helper_funcs import *
@@ -1,20 +1,20 @@
arrows_with_enter = [ arrows_with_enter = [
(0, 0, 0), (0, 0, 0), (0, 0, 0), [(0, 0, 0), (0, 0, 0), (0, 0, 0)],
(0, 0, 0), (0, 0, 100), (0, 0, 0), [(0, 0, 0), (0, 0, 100), (0, 0, 0)],
(0, 0, 100), (100, 0, 0), (0, 0, 100), [(0, 0, 100), (100, 0, 0), (0, 0, 100)],
(0, 0, 0), (0, 0, 100), (0, 0, 0) [(0, 0, 0), (0, 0, 100), (0, 0, 0)]
] ]
up_down_enter = [ up_down_enter = [
(0, 0, 0), (0, 0, 0), (0, 0, 0), [(0, 0, 0), (0, 0, 0), (0, 0, 0)],
(0, 0, 0), (0, 0, 100), (0, 0, 0), [(0, 0, 0), (0, 0, 100), (0, 0, 0)],
(0, 0, 0), (100, 0, 0), (0, 0, 0), [(0, 0, 0), (100, 0, 0), (0, 0, 0)],
(0, 0, 0), (0, 0, 100), (0, 0, 0) [(0, 0, 0), (0, 0, 100), (0, 0, 0)]
] ]
arrows_yes_no = [ arrows_yes_no = [
(0, 0, 0), (0, 0, 0), (0, 0, 0), [(0, 0, 0), (0, 0, 0), (0, 0, 0)],
(0, 0, 0), (0, 0, 100), (0, 0, 0), [(0, 0, 0), (0, 0, 100), (0, 0, 0)],
(0, 0, 0), (100, 0, 0), (0, 0, 0), [(0, 0, 0), (100, 0, 0), (0, 0, 0)],
(0, 100, 0), (0, 0, 100), (100, 0, 0) [(0, 100, 0), (0, 0, 100), (100, 0, 0)]
] ]
+31 -46
View File
@@ -18,74 +18,59 @@ class DebugApp(App):
def __init__(self, macropad, config, name): def __init__(self, macropad, config, name):
super().__init__(macropad, config) super().__init__(macropad, config)
self.name = name self.name = name
self.tones = [196, 220, 246, 262, 294, 330, 349, 392, 440, 494, 523, 587]
self.wheel_offset = 0 self.wheel_offset = 0
self.send_keyboard_inputs = 0
self.lit_keys = [False] * 12 self.lit_keys = [False] * 12
self.labels = [] self.labels = []
self.layout = GridLayout(x=0, y=9, width=128, height=54, grid_size=(4, 4), cell_padding=1) self.title = "Debug App!"
self.title = label.Label(
y=4,
font=terminalio.FONT,
color=0x0,
text=f" {self.name} MENU ",
background_color=0xFFFFFF,
)
def on_start(self): def on_start(self):
print("on start from the app!") print("on start from the app!")
self.lit_keys = [False] * 12 self.set_layout(GridLayout(x=0, y=9, width=128, height=54, grid_size=(4, 4), cell_padding=1))
self.macropad.display.show(self.display_group) self.set_title(self.title)
self.lit_keys = [True] * 12
for _ in range(12): for _ in range(12):
self.labels.append(label.Label(terminalio.FONT, text="")) self.labels.append(label.Label(terminalio.FONT, text=""))
for index in range(12): # for index in range(12):
x = index % 3 # x = index % 3
y = index // 3 # y = index // 3
self.layout.add_content(self.labels[index], grid_position=(x, y), cell_size=(1, 1)) # self.layout.add_content(self.labels[index], grid_position=(x, y), cell_size=(1, 1))
self.set_tone_status(True)
self.set_tones([196, 220, 246, 262, 294, 330, 349, 392, 440, 494, 523, 587])
self.register_on_key_pressed(self.process_keys_pressed_callback)
self.register_on_key_released(self.process_keys_released_callback)
self.register_on_encoder_changed(self.process_enbcoder_changed)
def on_resume(self): def on_resume(self):
print("resume from the debug app!") print("resume from the debug app!")
print(id(self.display_group))
print(self.display_group)
self.display_group.append(self.title)
self.display_group.append(self.layout)
self.macropad.display.show(self.display_group)
def on_pause(self): def on_pause(self):
print("Pausing") print("Pausing")
self.display_group.remove(self.title)
self.display_group.remove(self.layout)
def on_stop(self): def on_stop(self):
print("Stopping") print("Stopping")
def loop(self): def on_loop(self):
self.process_key_presses() self.update_key_colors()
self.light_keys()
self.light_keys()
def process_key_presses(self): def update_key_colors(self):
key_event = self.macropad.keys.events.get()
if key_event:
if key_event.pressed:
self.labels[key_event.key_number].text = "KEY{}".format(key_event.key_number)
print(self.macropad.keys)
self.lit_keys[key_event.key_number] = not self.lit_keys[key_event.key_number]
self.macropad.stop_tone()
self.macropad.start_tone(self.tones[key_event.key_number])
else:
self.labels[key_event.key_number].text = ""
self.macropad.stop_tone()
def light_keys(self):
self.wheel_offset += 1 self.wheel_offset += 1
colors = self.get_colors()
for pixel in range(12): for pixel in range(12):
if self.lit_keys[pixel]: if self.lit_keys[pixel]:
(r, g, b) = rgb_from_int(colorwheel((pixel / 12 * 256) + self.wheel_offset)) (r, g, b) = rgb_from_int(colorwheel((pixel / 12 * 256) + self.wheel_offset))
self.macropad.pixels[pixel] = (r * .1, g * .1, b * .1) colors[pixel] = (r, g, b)
else: else:
self.macropad.pixels[pixel] = 0 colors[pixel] = 0
self.set_colors(colors)
def process_keys_pressed_callback(self, keyevent):
print("PROCESS KEYS CALLBACK FROM DEBUG")
print(keyevent)
def process_keys_released_callback(self, keyevent):
print("PROCESS KEYS RELEASED CALLBACK FROM DEBUG")
print(keyevent)
def process_enbcoder_changed(self, keyevent):
print("PROCESS Encoder Changed Callback FROM DEBUG")
print(keyevent)
+20 -41
View File
@@ -1,5 +1,3 @@
import terminalio
from adafruit_display_text import label
from adafruit_displayio_layout.layouts.grid_layout import GridLayout from adafruit_displayio_layout.layouts.grid_layout import GridLayout
from .common import arrows_yes_no, arrows_with_enter, up_down_enter from .common import arrows_yes_no, arrows_with_enter, up_down_enter
@@ -12,59 +10,40 @@ class OptionsApp(App):
super().__init__(macropad, config) super().__init__(macropad, config)
self.send_keyboard_inputs = 0 self.send_keyboard_inputs = 0
self.labels = [] self.labels = []
self.layout = GridLayout(x=0, y=9, width=128, height=54, grid_size=(4, 4), cell_padding=1)
self.key_colors = arrows_yes_no self.key_colors = arrows_yes_no
self.possible_key_colors = [arrows_yes_no, arrows_with_enter, up_down_enter] self.possible_key_colors = [arrows_yes_no, arrows_with_enter, up_down_enter]
self.title = label.Label(
y=4,
font=terminalio.FONT,
color=0x0,
text=f" OPTIONS MENU ",
background_color=0xFFFFFF,
)
self.counter = 0 self.counter = 0
self.title = "Options"
def on_start(self): def on_start(self):
print("on start from the app!") print("on start from the options app!")
self.lit_keys = [False] * 4 self.set_title(self.title)
for _ in range(4): self.set_layout(GridLayout(x=0, y=9, width=128, height=54, grid_size=(4, 4), cell_padding=1))
self.labels.append(label.Label(terminalio.FONT, text=""))
for index in range(4):
x = 0
y = index
self.layout.add_content(self.labels[index], grid_position=(x, y), cell_size=(3, 1))
def on_resume(self): def on_resume(self):
print("resume from the options app!") print("resume from the options app!")
self.display_group.append(self.title)
self.display_group.append(self.layout)
self.macropad.display.show(self.display_group)
def on_pause(self): def on_pause(self):
print("Pausing") print("Pausing")
self.display_group.remove(self.title)
self.display_group.remove(self.layout)
def on_stop(self): def on_stop(self):
print("Stopping") print("Stopping")
def loop(self): def on_loop(self):
self.process_key_presses() pass
self.light_keys()
self.key_colors = self.possible_key_colors[self.counter % len(self.possible_key_colors)] def on_key_pressed(self, keyevent):
self.counter+=1 print("ON KEY PRESSED CALLBACK FROM OPTIONS")
print(keyevent)
def on_key_released(self, keyevent):
print("ON KEY RELEASED CALLBACK FROM OPTIONS")
print(keyevent)
def on_wheel_change(self, event):
print("ON WHEEL CHANGED CALLBACK")
print(event)
def process_key_presses(self):
key_event = self.macropad.keys.events.get()
if key_event:
if key_event.key_number < 12:
if key_event.pressed:
self.macropad.stop_tone()
self.macropad.start_tone(440)
else:
self.macropad.stop_tone()
def light_keys(self):
for pixel in range(12):
self.macropad.pixels[pixel] = self.key_colors[pixel]