Improved readability and finished renaming
This commit is contained in:
parent
a6e5ee1c08
commit
8d0b835c9c
@ -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.
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user