Improved readability and finished renaming

This commit is contained in:
Steven Wilde 2022-05-15 19:42:12 -05:00 committed by xs5871
parent a6e5ee1c08
commit 8d0b835c9c
2 changed files with 52 additions and 46 deletions

View File

@ -18,27 +18,27 @@ keyboard.modules.append(DynamicSequences())
``` ```
## Keycodes ## Keycodes
|Key |Description | |Key |Description |
|----------------------------|---------------------------------------| |-------------------------------|---------------------------------------|
|`KC.RECORD_MACRO()` |Start recording into the current slot | |`KC.RECORD_SEQUENCE()` |Start recording into the current slot |
|`KC.PLAY_MACRO()` |Play the sequence in the current slot | |`KC.PLAY_SEQUENCE()` |Play the sequence in the current slot |
|`KC.STOP_MACRO()` |Stop recording, playing, or configuring| |`KC.STOP_SEQUENCE()` |Stop recording, playing, or configuring|
|`KC.SET_MACRO(x)` |Change to the sequence in slot `x` | |`KC.SET_SEQUENCE(x)` |Change to the sequence in slot `x` |
|`KC.SET_MACRO_REPETITIONS()`|Change to repepition config mode | |`KC.SET_SEQUENCE_REPETITIONS()`|Change to repepition config mode |
|`KC.SET_MACRO_INTERVAL()` |Change to interval config mode | |`KC.SET_SEQUENCE_INTERVAL()` |Change to interval config mode |
## Config ## Config
```python ```python
dynamicSequences = DynamicSequences( dynamicSequences = DynamicSequences(
slots=1, # The number of sequence slots to use slots=1, # The number of sequence slots to use
timeout=60000, # Maximum time to spend in record or config mode before stopping automatically, miliseconds timeout=60000, # Maximum time to spend in record or config mode before stopping automatically, milliseconds
key_interval=0, # Miliseconds between key events while playing key_interval=0, # Milliseconds between key events while playing
use_recorded_speed=False # Whether to play the sequence at the speed it was typed use_recorded_speed=False # Whether to play the sequence at the speed it was typed
) )
``` ```
## Sequence slots ## Sequence slots
You can configure multiple slots that each store a different sequence. You can change to a specific slot with `KC.SET_MACRO(x)`, where `x` is the sequence slot number (starting from `0`). Every keycode can take an optional number to change to a specific sequence slot before performing the action. For example `KC.PLAY_MACRO(2)` will play the sequence in slot `2`. If a slot is not specified, the current slot will be used. You can configure multiple slots that each store a different sequence. You can change to a specific slot with `KC.SET_SEQUENCE(x)`, where `x` is the sequence slot number (starting from `0`). Every keycode can take an optional number to change to a specific sequence slot before performing the action. For example `KC.PLAY_SEQUENCE(2)` will play the sequence in slot `2`. If a slot is not specified, the current slot will be used.
## Repeating sequences ## Repeating sequences
Sequences can be set to repeat automatically. The number of repetitions and the interval between repetitions can be set using `KC.SET_MACRO_REPETITIONS()` and `KC.SET_MACRO_INTERVAL()`. Using one of these keys will put the keyboard in sequence config mode. In this mode, keypresses will not be sent to the OS and you can use your number keys to type the number of repetitions or the interval time in seconds. This mode ends when you press `KC.ENTER`, `KC.STOP_MACRO()`, or automatically when the timeout is reached. Repeat settings are stored in the current slot. Sequences can be set to repeat automatically. The number of repetitions and the interval between repetitions can be set using `KC.SET_SEQUENCE_REPETITIONS()` and `KC.SET_SEQUENCE_INTERVAL()`. Using one of these keys will put the keyboard in sequence config mode. In this mode, keypresses will not be sent to the OS and you can use your number keys to type the number of repetitions or the interval time in seconds. This mode ends when you press `KC.ENTER`, `KC.STOP_SEQUENCE()`, or automatically when the timeout is reached. Repeat settings are stored in the current slot.

View File

@ -1,12 +1,14 @@
from micropython import const from micropython import const
from supervisor import ticks_ms from supervisor import ticks_ms
from collections import namedtuple
from kmk.keys import KC, make_argumented_key from kmk.keys import KC, make_argumented_key
from kmk.kmktime import check_deadline, ticks_diff from kmk.kmktime import check_deadline, ticks_diff
from kmk.modules import Module from kmk.modules import Module
class DMMeta: class DSMeta:
def __init__(self, sequence_select=None): def __init__(self, sequence_select=None):
self.sequence_select = sequence_select self.sequence_select = sequence_select
@ -22,12 +24,14 @@ class SequenceStatus:
# Keycodes for number keys # Keycodes for number keys
_numbers = range(KC.N1.code, KC.N0.code + 1) _numbers = range(KC.N1.code, KC.N0.code + 1)
SequenceFrame = namedtuple('SequenceFrame', ['keys_pressed', 'timestamp'])
class Sequence: class Sequence:
def __init__(self): def __init__(self):
self.repetitions = 1 self.repetitions = 1
self.interval = 0 self.interval = 0
self.sequence_data = [(set(), 0), (set(), 0), (set(), 0)] self.sequence_data = [SequenceFrame(set(), 0) for i in range(3)]
class DynamicSequences(Module): class DynamicSequences(Module):
@ -49,31 +53,31 @@ class DynamicSequences(Module):
# Create keycodes # Create keycodes
make_argumented_key( make_argumented_key(
validator=DMMeta, names=('RECORD_MACRO',), on_press=self._record_sequence validator=DSMeta, names=('RECORD_SEQUENCE',), on_press=self._record_sequence
) )
make_argumented_key( make_argumented_key(
validator=DMMeta, names=('PLAY_MACRO',), on_press=self._play_sequence validator=DSMeta, names=('PLAY_SEQUENCE',), on_press=self._play_sequence
) )
make_argumented_key( make_argumented_key(
validator=DMMeta, validator=DSMeta,
names=( names=(
'SET_MACRO', 'SET_SEQUENCE',
'STOP_MACRO', 'STOP_SEQUENCE',
), ),
on_press=self._stop_sequence, on_press=self._stop_sequence,
) )
make_argumented_key( make_argumented_key(
validator=DMMeta, validator=DSMeta,
names=('SET_MACRO_REPETITIONS',), names=('SET_SEQUENCE_REPETITIONS',),
on_press=self._set_sequence_repetitions, on_press=self._set_sequence_repetitions,
) )
make_argumented_key( make_argumented_key(
validator=DMMeta, validator=DSMeta,
names=('SET_MACRO_INTERVAL',), names=('SET_SEQUENCE_INTERVAL',),
on_press=self._set_sequence_interval, on_press=self._set_sequence_interval,
) )
@ -81,7 +85,7 @@ class DynamicSequences(Module):
self._stop_sequence(key, keyboard) self._stop_sequence(key, keyboard)
self.status = SequenceStatus.RECORDING self.status = SequenceStatus.RECORDING
self.start_time = ticks_ms() self.start_time = ticks_ms()
self.current_slot.sequence_data = [(set(), 0)] self.current_slot.sequence_data = [SequenceFrame(set(), 0)]
self.index = 0 self.index = 0
def _play_sequence(self, key, keyboard, *args, **kwargs): def _play_sequence(self, key, keyboard, *args, **kwargs):
@ -119,19 +123,21 @@ class DynamicSequences(Module):
# Add the current keypress state to the sequence # Add the current keypress state to the sequence
def record_frame(self, keys_pressed): def record_frame(self, keys_pressed):
if self.current_slot.sequence_data[self.index][0] != keys_pressed: if self.current_slot.sequence_data[self.index].keys_pressed != keys_pressed:
self.index += 1 self.index += 1
# Recorded speed # Recorded speed
if self.use_recorded_speed: if self.use_recorded_speed:
self.current_slot.sequence_data.append( self.current_slot.sequence_data.append(
(keys_pressed.copy(), ticks_diff(ticks_ms(), self.start_time)) SequenceFrame(
keys_pressed.copy(), ticks_diff(ticks_ms(), self.start_time)
)
) )
# Constant speed # Constant speed
else: else:
self.current_slot.sequence_data.append( self.current_slot.sequence_data.append(
(keys_pressed.copy(), self.index * self.key_interval) SequenceFrame(keys_pressed.copy(), self.index * self.key_interval)
) )
if not check_deadline(ticks_ms(), self.start_time, self.timeout): if not check_deadline(ticks_ms(), self.start_time, self.timeout):
@ -141,15 +147,15 @@ class DynamicSequences(Module):
def stop_recording(self): def stop_recording(self):
# Clear the remaining keys # Clear the remaining keys
self.current_slot.sequence_data.append( self.current_slot.sequence_data.append(
(set(), self.current_slot.sequence_data[-1][1] + 20) SequenceFrame(set(), self.current_slot.sequence_data[-1].timestamp + 20)
) )
# Wait for the specified interval # Wait for the specified interval
prev_timestamp = self.current_slot.sequence_data[-1].timestamp
self.current_slot.sequence_data.append( self.current_slot.sequence_data.append(
( SequenceFrame(
set(), set(),
self.current_slot.sequence_data[-1][1] prev_timestamp + self.current_slot.interval * 1000,
+ self.current_slot.interval * 1000,
) )
) )
@ -158,16 +164,17 @@ class DynamicSequences(Module):
def play_frame(self, keyboard): def play_frame(self, keyboard):
# Send the keypresses at this point in the sequence # Send the keypresses at this point in the sequence
if not check_deadline( if not check_deadline(
ticks_ms(), self.start_time, self.current_slot.sequence_data[self.index][1] ticks_ms(),
self.start_time,
self.current_slot.sequence_data[self.index].timestamp,
): ):
if self.index: if self.index:
for key in self.current_slot.sequence_data[self.index - 1][ prev = self.current_slot.sequence_data[self.index - 1].keys_pressed
0 cur = self.current_slot.sequence_data[self.index].keys_pressed
].difference(self.current_slot.sequence_data[self.index][0]):
for key in prev.difference(cur):
keyboard.remove_key(key) keyboard.remove_key(key)
for key in self.current_slot.sequence_data[self.index][0].difference( for key in cur.difference(prev):
self.current_slot.sequence_data[self.index - 1][0]
):
keyboard.add_key(key) keyboard.add_key(key)
self.index += 1 self.index += 1
@ -183,15 +190,13 @@ class DynamicSequences(Module):
def config_mode(self, keyboard): def config_mode(self, keyboard):
for key in keyboard.keys_pressed.difference(self.last_config_frame): for key in keyboard.keys_pressed.difference(self.last_config_frame):
if key.code in _numbers: if key.code in _numbers:
digit = (key.code - KC.N1.code + 1) % 10
if self.status == SequenceStatus.SET_REPEPITIONS: if self.status == SequenceStatus.SET_REPEPITIONS:
self.current_slot.repetitions = ( self.current_slot.repetitions = (
self.current_slot.repetitions * 10 self.current_slot.repetitions * 10 + digit
+ ((key.code - KC.N1.code + 1) % 10)
) )
elif self.status == SequenceStatus.SET_INTERVAL: elif self.status == SequenceStatus.SET_INTERVAL:
self.current_slot.interval = self.current_slot.interval * 10 + ( self.current_slot.interval = self.current_slot.interval * 10 + digit
(key.code - KC.N1.code + 1) % 10
)
elif key.code == KC.ENTER.code: elif key.code == KC.ENTER.code:
self.stop_config() self.stop_config()
@ -204,9 +209,10 @@ class DynamicSequences(Module):
# Finish configuring repetitions # Finish configuring repetitions
def stop_config(self): def stop_config(self):
self.current_slot.sequence_data[-1] = ( self.current_slot.sequence_data[-1] = SequenceFrame(
self.current_slot.sequence_data[-1][0], self.current_slot.sequence_data[-1].keys_pressed,
self.current_slot.sequence_data[-2][1] + self.current_slot.interval * 1000, self.current_slot.sequence_data[-2].timestamp
+ self.current_slot.interval * 1000,
) )
self.current_slot.repetitions = max(self.current_slot.repetitions, 1) self.current_slot.repetitions = max(self.current_slot.repetitions, 1)
self.status = SequenceStatus.STOPPED self.status = SequenceStatus.STOPPED