|
31 | 31 | import random
|
32 | 32 | import time
|
33 | 33 |
|
| 34 | +import keypad |
34 | 35 | from micropython import const
|
35 | 36 |
|
36 | 37 | try:
|
37 | 38 | from typing import Callable
|
38 |
| - |
39 |
| - from circuitpython_typing.io import ROValueIO |
40 | 39 | except ImportError:
|
41 | 40 | pass
|
42 | 41 |
|
43 | 42 |
|
44 |
| -class KeyState: |
45 |
| - """An enum-like class representing states used by :class:`Key` and :class:`Keyboard`.""" |
46 |
| - |
47 |
| - NONE: int = const(0) |
48 |
| - """Indicates that the key hasn't been activated in any way""" |
49 |
| - |
50 |
| - PRESS: int = const(1) |
51 |
| - """Indicates that the key has been pressed""" |
52 |
| - |
53 |
| - RELEASE: int = const(2) |
54 |
| - """Indicates that the key has been released""" |
55 |
| - |
56 |
| - |
57 |
| -class Key: |
58 |
| - """An abstract layer to interface with the :class:`Keyboard` class.""" |
59 |
| - |
60 |
| - def __init__(self): |
61 |
| - pass |
62 |
| - |
63 |
| - @property |
64 |
| - def state(self) -> int: |
65 |
| - """The current state as a constant value of :class:`KeyState`.""" |
66 |
| - return KeyState.NONE |
67 |
| - |
68 |
| - @property |
69 |
| - def velocity(self) -> float: |
70 |
| - """Get the current velocity (0.0-1.0).""" |
71 |
| - return 1.0 |
72 |
| - |
73 |
| - |
74 |
| -class DebouncerKey(Key): |
75 |
| - """An abstract layer to debouncer sensor input to use physical key objects with the |
76 |
| - :class:`Keyboard` class. The Adafruit-CircuitPython-Debouncer module must be installed to use |
77 |
| - this class, else a ImportError will be thrown upon instantiation. |
78 |
| -
|
79 |
| - :param io_or_predicate: The input pin or arbitrary predicate to debounce |
80 |
| - :int inverted: Whether or not to invert the state of the input. When invert is `False`, the |
81 |
| - signal is active-high. When it is `True`, the signal is active-low. |
82 |
| - """ |
83 |
| - |
84 |
| - def __init__(self, io_or_predicate: ROValueIO | Callable[[], bool], inverted: bool = False): |
85 |
| - from adafruit_debouncer import Debouncer |
86 |
| - |
87 |
| - self._debouncer = Debouncer(io_or_predicate) |
88 |
| - self._inverted = inverted |
89 |
| - |
90 |
| - inverted: bool = False |
91 |
| - """Whether or not the state is inverted. When invert is `False`, the signal is active-high. When |
92 |
| - it is `True`, the signal is active-low. |
93 |
| - """ |
94 |
| - |
95 |
| - @property |
96 |
| - def state(self) -> int: |
97 |
| - """The current state as a constant value of :class:`KeyState`. When accessed, the input pin |
98 |
| - or arbitraary predicate will be updated with basic debouncing. |
99 |
| - """ |
100 |
| - self._debouncer.update() |
101 |
| - if self._debouncer.rose: |
102 |
| - return KeyState.PRESS if not self._inverted else KeyState.RELEASE |
103 |
| - elif self._debouncer.fell: |
104 |
| - return KeyState.RELEASE if not self._inverted else KeyState.PRESS |
105 |
| - else: |
106 |
| - return KeyState.NONE |
107 |
| - |
108 |
| - |
109 | 43 | class Note:
|
110 | 44 | """Object which represents the parameters of a note. Contains note number, velocity, key number
|
111 | 45 | (if evoked by a :class:`Key` object), and timestamp of when the note was created.
|
@@ -766,7 +700,7 @@ class Keyboard:
|
766 | 700 |
|
767 | 701 | def __init__(
|
768 | 702 | self,
|
769 |
| - keys: tuple[Key] = [], |
| 703 | + keys: keypad = None, |
770 | 704 | max_voices: int = 1,
|
771 | 705 | root: int = 48,
|
772 | 706 | mode: int = KeyboardMode.HIGH,
|
@@ -799,11 +733,11 @@ def __init__(
|
799 | 733 | release(keynum, notenum):`.
|
800 | 734 | """
|
801 | 735 |
|
802 |
| - _keys: tuple[Key] = None |
| 736 | + _keys: keypad = None |
803 | 737 |
|
804 | 738 | @property
|
805 |
| - def keys(self) -> tuple[Key]: |
806 |
| - """The :class:`Key` objects which will be used to update the keyboard state.""" |
| 739 | + def keys(self) -> keypad: |
| 740 | + """The :class:`keypad.Keys` object which will be used to update the keyboard state.""" |
807 | 741 | return self._keys
|
808 | 742 |
|
809 | 743 | _arpeggiator: Arpeggiator = None
|
@@ -915,20 +849,19 @@ async def update(self, delay: float = 0.01) -> None:
|
915 | 849 | :param delay: The amount of time to sleep between polling in seconds.
|
916 | 850 | """
|
917 | 851 | while self._keys:
|
918 |
| - for i in range(len(self._keys)): |
919 |
| - state = self._keys[i].state |
920 |
| - if state == KeyState.NONE: |
921 |
| - continue |
922 |
| - notenum = self.root + i |
923 |
| - if state == KeyState.PRESS: |
924 |
| - velocity = self._keys[i].velocity |
925 |
| - self.append(notenum, velocity, i) |
| 852 | + while True: |
| 853 | + event = self._keys.events.get() |
| 854 | + if not event: |
| 855 | + break |
| 856 | + notenum = self.root + event.key_number |
| 857 | + if event.pressed: |
| 858 | + self.append(notenum, keynum=event.key_number) |
926 | 859 | if callable(self.on_key_press):
|
927 |
| - self.on_key_press(i, notenum, velocity) |
928 |
| - else: # KeyState.RELEASE |
| 860 | + self.on_key_press(event.key_number, notenum, 1.0) |
| 861 | + elif event.released: |
929 | 862 | self.remove(notenum)
|
930 | 863 | if callable(self.on_key_release):
|
931 |
| - self.on_key_release(i, notenum) |
| 864 | + self.on_key_release(event.key_number, notenum) |
932 | 865 | await asyncio.sleep(delay)
|
933 | 866 |
|
934 | 867 | def _update(self) -> None:
|
|
0 commit comments