feat: Make button mapping configurable
- Remove Pin to button mapping from hwconfig, replace with a simple list of Pins to which buttons are attached - Add BUTTON_MAP to config.json which maps indices in the HW button list to button names - Update utils.Buttons to use the button map to connect the correct pins to the matching key codes Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
This commit is contained in:
@@ -30,10 +30,12 @@ RC522_SS = Pin.board.GP13
|
|||||||
LED_DIN = Pin.board.GP16
|
LED_DIN = Pin.board.GP16
|
||||||
|
|
||||||
# Buttons
|
# Buttons
|
||||||
BUTTON_VOLUP = Pin.board.GP17
|
BUTTONS = [Pin.board.GP17,
|
||||||
BUTTON_VOLDOWN = Pin.board.GP19
|
Pin.board.GP18,
|
||||||
BUTTON_NEXT = Pin.board.GP18
|
Pin.board.GP19,
|
||||||
BUTTON_POWER = Pin.board.GP21
|
Pin.board.GP20,
|
||||||
|
Pin.board.GP21,
|
||||||
|
]
|
||||||
|
|
||||||
# Power
|
# Power
|
||||||
POWER_EN = Pin.board.GP22
|
POWER_EN = Pin.board.GP22
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ RC522_SS = Pin.board.GP13
|
|||||||
LED_DIN = Pin.board.GP16
|
LED_DIN = Pin.board.GP16
|
||||||
|
|
||||||
# Buttons
|
# Buttons
|
||||||
BUTTON_VOLUP = Pin.board.GP17
|
BUTTONS = [Pin.board.GP17,
|
||||||
BUTTON_VOLDOWN = Pin.board.GP19
|
Pin.board.GP18,
|
||||||
BUTTON_NEXT = Pin.board.GP18
|
Pin.board.GP19,
|
||||||
BUTTON_POWER = None
|
]
|
||||||
|
|
||||||
# Power
|
# Power
|
||||||
POWER_EN = None
|
POWER_EN = None
|
||||||
|
|||||||
@@ -89,9 +89,7 @@ def run():
|
|||||||
# Setup app
|
# Setup app
|
||||||
deps = app.Dependencies(mp3player=lambda the_app: MP3Player(audioctx, the_app),
|
deps = app.Dependencies(mp3player=lambda the_app: MP3Player(audioctx, the_app),
|
||||||
nfcreader=lambda the_app: Nfc(reader, the_app),
|
nfcreader=lambda the_app: Nfc(reader, the_app),
|
||||||
buttons=lambda the_app: Buttons(the_app, pin_volup=hwconfig.BUTTON_VOLUP,
|
buttons=lambda the_app: Buttons(the_app, config, hwconfig),
|
||||||
pin_voldown=hwconfig.BUTTON_VOLDOWN,
|
|
||||||
pin_next=hwconfig.BUTTON_NEXT),
|
|
||||||
playlistdb=lambda _: playlistdb,
|
playlistdb=lambda _: playlistdb,
|
||||||
hwconfig=lambda _: hwconfig,
|
hwconfig=lambda _: hwconfig,
|
||||||
leds=lambda _: LedManager(np),
|
leds=lambda _: LedManager(np),
|
||||||
@@ -124,5 +122,5 @@ def builddb():
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
time.sleep(1)
|
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()
|
run()
|
||||||
|
|||||||
@@ -17,14 +17,27 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
|
|
||||||
class Buttons:
|
class Buttons:
|
||||||
def __init__(self, cb: "ButtonCallback", pin_volup=17, pin_voldown=19, pin_next=18):
|
VOLUP = micropython.const(1)
|
||||||
self.VOLUP = micropython.const(1)
|
VOLDOWN = micropython.const(2)
|
||||||
self.VOLDOWN = micropython.const(2)
|
NEXT = micropython.const(3)
|
||||||
self.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.cb = cb
|
||||||
self.buttons = {machine.Pin(pin_volup, machine.Pin.IN, machine.Pin.PULL_UP): self.VOLUP,
|
self.buttons = dict()
|
||||||
machine.Pin(pin_voldown, machine.Pin.IN, machine.Pin.PULL_UP): self.VOLDOWN,
|
for key_id, key_name in self.KEYMAP.items():
|
||||||
machine.Pin(pin_next, machine.Pin.IN, machine.Pin.PULL_UP): self.NEXT}
|
pin = self._get_pin(key_name)
|
||||||
|
if pin is None:
|
||||||
|
continue
|
||||||
|
self.buttons[pin] = key_id
|
||||||
self.int_flag = asyncio.ThreadSafeFlag()
|
self.int_flag = asyncio.ThreadSafeFlag()
|
||||||
self.pressed: list[int] = []
|
self.pressed: list[int] = []
|
||||||
self.last: dict[int, 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)
|
button.irq(handler=self._interrupt, trigger=machine.Pin.IRQ_FALLING | machine.Pin.IRQ_RISING)
|
||||||
asyncio.create_task(self.task())
|
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):
|
def _interrupt(self, button):
|
||||||
keycode = self.buttons[button]
|
keycode = self.buttons[button]
|
||||||
last = self.last.get(keycode, 0)
|
last = self.last.get(keycode, 0)
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
from errno import ENOENT
|
from errno import ENOENT
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
try:
|
||||||
|
from typing import TYPE_CHECKING, Mapping
|
||||||
|
except ImportError:
|
||||||
|
TYPE_CHECKING = False
|
||||||
|
|
||||||
|
|
||||||
class Configuration:
|
class Configuration:
|
||||||
@@ -11,6 +15,13 @@ class Configuration:
|
|||||||
'LED_COUNT': 1,
|
'LED_COUNT': 1,
|
||||||
'IDLE_TIMEOUT_SECS': 60,
|
'IDLE_TIMEOUT_SECS': 60,
|
||||||
'TAG_TIMEOUT_SECS': 5,
|
'TAG_TIMEOUT_SECS': 5,
|
||||||
|
'BUTTON_MAP': {
|
||||||
|
'PLAY_PAUSE': 4,
|
||||||
|
'VOLUP': 0,
|
||||||
|
'VOLDOWN': 2,
|
||||||
|
'PREV': None,
|
||||||
|
'NEXT': 1,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, config_path='/config.json'):
|
def __init__(self, config_path='/config.json'):
|
||||||
@@ -49,11 +60,14 @@ class Configuration:
|
|||||||
def _get(self, key):
|
def _get(self, key):
|
||||||
return self.config.get(key, self.DEFAULT_CONFIG[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')
|
return self._get('LED_COUNT')
|
||||||
|
|
||||||
def get_idle_timeout(self):
|
def get_idle_timeout(self) -> int:
|
||||||
return self._get('IDLE_TIMEOUT_SECS')
|
return self._get('IDLE_TIMEOUT_SECS')
|
||||||
|
|
||||||
def get_tag_timeout(self):
|
def get_tag_timeout(self) -> int:
|
||||||
return self._get('TAG_TIMEOUT_SECS')
|
return self._get('TAG_TIMEOUT_SECS')
|
||||||
|
|
||||||
|
def get_button_map(self) -> Mapping[str, int | None]:
|
||||||
|
return self._get('BUTTON_MAP')
|
||||||
|
|||||||
Reference in New Issue
Block a user