from __future__ import annotations from adafruit_display_text import label from adafruit_display_shapes import rect from adafruit_ticks import ticks_ms, ticks_diff from .util import FONT_10, led_map from .core import Key, Note, Mode from .rgb import ColorScale class BaseMode(Mode): keys: list[Key] rgb: RGBEffect notes: dict[int, Note] notes_expiring: dict[int, Note] scale_label: label.Label notes_label: label.Label notes_dirty: bool def __init__(self, *args): super().__init__(*args) self.keys = [Key(self.keyboard, i) for i in range(48)] self.rgb = ColorScale(self.keyboard) self.notes = {} self.extra_notes = {} self.notes_expiring = {} self.notes_dirty = False self.scale_label = label.Label( FONT_10, text="", color=0xFFFFFF, anchor_point=(0, 0), anchored_position=(0, 0), ) self.notes_label = label.Label( FONT_10, text="", color=0xFFFFFF, anchor_point=(0, 0), anchored_position=(10, 12), ) self.group.append(self.scale_label) self.group.append(self.notes_label) self.group.append( label.Label( FONT_10, text="OCTVE", color=0xFFFFFF, anchor_point=(1, 0.5), anchored_position=(128, 16), label_direction="DWR", ) ) self.group.append( rect.Rect( x=118, y=0, width=1, height=32, fill=0xFFFFFF, ) ) if self.keyboard.board.dev_mode: self.color = (0.83, 1.0, 0.5) self.group.append( label.Label( FONT_10, text="DEV", color=0xFFFFFF, anchor_point=(0, 0), anchored_position=(0, 24), ) ) def update_scale(self): for key in self.keys: key.update_scale() self.rgb.prepare() self.scale_label.text = self.keyboard.scale.format() def tick(self, ticks_ms: int): for note in list(self.notes_expiring.values()): note.update_expiry(ticks_ms) self.rgb.tick(ticks_ms) def update_pixels(self, pixels: NeoPixel): pixels.fill(0) super().update_pixels(pixels) for i, key in enumerate(self.keys): pixels[led_map[key.i]] = self.rgb.get_color(i, key) if self.notes_dirty: active = [pitch for pitch in self.notes] active.sort() self.notes_label.text = " ".join( self.keyboard.scale.label(p) for p in active ) self.notes_dirty = False def key_event(self, i: int, pressed: bool) -> bool: if pressed: if i == Key.MENU_I: self.keyboard.mode = self.keyboard.modes["base_shift"] return False if i == Key.PREV_I: self.keyboard.layout.offset -= self.keyboard.scale.size self.update_scale() layout_offset = self.keyboard.settings.get("layout_offset") layout_offset.value -= self.keyboard.scale.size self.keyboard.settings.dispatch("layout_offset") return False if i == Key.NEXT_I: layout_offset = self.keyboard.settings.get("layout_offset") layout_offset.value += self.keyboard.scale.size self.keyboard.settings.dispatch("layout_offset") return False if i < len(self.keys): key = self.keys[i] if pressed: key.on_press() else: key.on_release() return pressed class BaseShiftMode(Mode): color = (0.1, 1.0, 0.5) scale_label: label.Label entered: int pressed_something: bool def __init__(self, *args): super().__init__(*args) self.scale_label = label.Label( FONT_10, text="", color=0xFFFFFF, anchor_point=(0, 0), anchored_position=(0, 0), ) self.group.append(self.scale_label) self.group.append( label.Label( FONT_10, text="choose root note", color=0xFFFFFF, anchor_point=(0, 0), anchored_position=(10, 12), ) ) self.group.append( label.Label( FONT_10, text="SCALE", color=0xFFFFFF, anchor_point=(1, 0.5), anchored_position=(128, 16), label_direction="DWR", ) ) self.group.append( rect.Rect( x=118, y=0, width=1, height=32, fill=0xFFFFFF, ) ) def enter(self): self.entered = ticks_ms() self.pressed_something = False self.update_display() super().enter() def update_display(self): base = self.keyboard.modes["base"] self.scale_label.text = base.scale_label.text def update_pixels(self, pixels: NeoPixel): base = self.keyboard.modes["base"] base.update_pixels(pixels) super().update_pixels(pixels) def key_event(self, i: int, pressed: bool) -> bool: base = self.keyboard.modes["base"] if not pressed and i == Key.MENU_I: held = ticks_diff(ticks_ms(), self.entered) if not self.pressed_something and held <= 300: # tap: enter menu self.keyboard.mode = self.keyboard.modes["menu"] return False self.keyboard.mode = base return False if not pressed: return False if i < len(base.keys): key = base.keys[i] self.keyboard.settings.get("scale_root").value = key.pitch self.keyboard.settings.dispatch("scale_root") self.pressed_something = True return False if i == Key.PREV_I: self.keyboard.settings.get("scale_name").press_prev() self.keyboard.settings.dispatch("scale_name") self.pressed_something = True return False if i == Key.NEXT_I: self.keyboard.settings.get("scale_name").press_next() self.keyboard.settings.dispatch("scale_name") self.pressed_something = True return False