diff --git a/software/src/hwconfig_Rev1/hwconfig.py b/software/src/hwconfig_Rev1/hwconfig.py index 6ad9afc..5cffeed 100644 --- a/software/src/hwconfig_Rev1/hwconfig.py +++ b/software/src/hwconfig_Rev1/hwconfig.py @@ -30,10 +30,12 @@ RC522_SS = Pin.board.GP13 LED_DIN = Pin.board.GP16 # Buttons -BUTTON_VOLUP = Pin.board.GP17 -BUTTON_VOLDOWN = Pin.board.GP19 -BUTTON_NEXT = Pin.board.GP18 -BUTTON_POWER = Pin.board.GP21 +BUTTONS = [Pin.board.GP17, + Pin.board.GP18, + Pin.board.GP19, + Pin.board.GP20, + Pin.board.GP21, + ] # Power POWER_EN = Pin.board.GP22 diff --git a/software/src/hwconfig_breadboard/hwconfig.py b/software/src/hwconfig_breadboard/hwconfig.py index 12df6bb..4fc026d 100644 --- a/software/src/hwconfig_breadboard/hwconfig.py +++ b/software/src/hwconfig_breadboard/hwconfig.py @@ -29,10 +29,10 @@ RC522_SS = Pin.board.GP13 LED_DIN = Pin.board.GP16 # Buttons -BUTTON_VOLUP = Pin.board.GP17 -BUTTON_VOLDOWN = Pin.board.GP19 -BUTTON_NEXT = Pin.board.GP18 -BUTTON_POWER = None +BUTTONS = [Pin.board.GP17, + Pin.board.GP18, + Pin.board.GP19, + ] # Power POWER_EN = None diff --git a/software/src/main.py b/software/src/main.py index 17f0881..a02b9a1 100644 --- a/software/src/main.py +++ b/software/src/main.py @@ -89,9 +89,7 @@ def run(): # Setup app deps = app.Dependencies(mp3player=lambda the_app: MP3Player(audioctx, the_app), nfcreader=lambda the_app: Nfc(reader, the_app), - buttons=lambda the_app: Buttons(the_app, pin_volup=hwconfig.BUTTON_VOLUP, - pin_voldown=hwconfig.BUTTON_VOLDOWN, - pin_next=hwconfig.BUTTON_NEXT), + buttons=lambda the_app: Buttons(the_app, config, hwconfig), playlistdb=lambda _: playlistdb, hwconfig=lambda _: hwconfig, leds=lambda _: LedManager(np), @@ -124,5 +122,5 @@ def builddb(): if __name__ == '__main__': time.sleep(1) - if machine.Pin(hwconfig.BUTTON_VOLUP, machine.Pin.IN, machine.Pin.PULL_UP).value() != 0: + if machine.Pin(hwconfig.BUTTONS[0], machine.Pin.IN, machine.Pin.PULL_UP).value() != 0: run() diff --git a/software/src/utils/buttons.py b/software/src/utils/buttons.py index 140ffc6..a1f1c6e 100644 --- a/software/src/utils/buttons.py +++ b/software/src/utils/buttons.py @@ -17,14 +17,27 @@ if TYPE_CHECKING: class Buttons: - def __init__(self, cb: "ButtonCallback", pin_volup=17, pin_voldown=19, pin_next=18): - self.VOLUP = micropython.const(1) - self.VOLDOWN = micropython.const(2) - self.NEXT = micropython.const(3) + VOLUP = micropython.const(1) + VOLDOWN = micropython.const(2) + NEXT = micropython.const(3) + PREV = micropython.const(4) + PLAY_PAUSE = micropython.const(5) + KEYMAP = {VOLUP: 'VOLUP', + VOLDOWN: 'VOLDOWN', + NEXT: 'NEXT', + PREV: 'PREV', + PLAY_PAUSE: 'PLAY_PAUSE'} + + def __init__(self, cb: "ButtonCallback", config, hwconfig): + self.button_map = config.get_button_map() + self.hw_buttons = hwconfig.BUTTONS self.cb = cb - self.buttons = {machine.Pin(pin_volup, machine.Pin.IN, machine.Pin.PULL_UP): self.VOLUP, - machine.Pin(pin_voldown, machine.Pin.IN, machine.Pin.PULL_UP): self.VOLDOWN, - machine.Pin(pin_next, machine.Pin.IN, machine.Pin.PULL_UP): self.NEXT} + self.buttons = dict() + for key_id, key_name in self.KEYMAP.items(): + pin = self._get_pin(key_name) + if pin is None: + continue + self.buttons[pin] = key_id self.int_flag = asyncio.ThreadSafeFlag() self.pressed: list[int] = [] self.last: dict[int, int] = {} @@ -32,6 +45,17 @@ class Buttons: button.irq(handler=self._interrupt, trigger=machine.Pin.IRQ_FALLING | machine.Pin.IRQ_RISING) asyncio.create_task(self.task()) + def _get_pin(self, key): + key_id = self.button_map.get(key, None) + if key_id is None: + return None + if key_id < 0 or key_id >= len(self.hw_buttons): + return None + pin = self.hw_buttons[key_id] + if pin is not None: + pin.init(machine.Pin.IN, machine.Pin.PULL_UP) + return pin + def _interrupt(self, button): keycode = self.buttons[button] last = self.last.get(keycode, 0) diff --git a/software/src/utils/config.py b/software/src/utils/config.py index 56a52af..432c2b8 100644 --- a/software/src/utils/config.py +++ b/software/src/utils/config.py @@ -4,6 +4,10 @@ from errno import ENOENT import json import os +try: + from typing import TYPE_CHECKING, Mapping +except ImportError: + TYPE_CHECKING = False class Configuration: @@ -11,6 +15,13 @@ class Configuration: 'LED_COUNT': 1, 'IDLE_TIMEOUT_SECS': 60, 'TAG_TIMEOUT_SECS': 5, + 'BUTTON_MAP': { + 'PLAY_PAUSE': 4, + 'VOLUP': 0, + 'VOLDOWN': 2, + 'PREV': None, + 'NEXT': 1, + } } def __init__(self, config_path='/config.json'): @@ -49,11 +60,14 @@ class Configuration: def _get(self, key): return self.config.get(key, self.DEFAULT_CONFIG[key]) - def get_led_count(self): + def get_led_count(self) -> int: return self._get('LED_COUNT') - def get_idle_timeout(self): + def get_idle_timeout(self) -> int: return self._get('IDLE_TIMEOUT_SECS') - def get_tag_timeout(self): + def get_tag_timeout(self) -> int: return self._get('TAG_TIMEOUT_SECS') + + def get_button_map(self) -> Mapping[str, int | None]: + return self._get('BUTTON_MAP')