Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature analogin: submodule + update scheduling #1080

Merged
merged 3 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion docs/en/analogin.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ from kmk.modules.analogin import AnalogInputs, AnalogInput
analog = AnalogInputs(
inputs: list(AnalogInput),
evtmap=[[]],
update_interval: int = 10,
)
```

Expand All @@ -28,6 +29,13 @@ instead of keys.
It supports KMK's layer mechanism and `KC.TRNS` and `KC.NO`.
Any other keys have to be wrapped in `AnalogKey`, see below.

#### `update_interval`
The update interval limits how often new values are read from inputs; the value
unit is milliseconds and the default is set to 10ms.
In addition to limiting analog conversions, which can take a significant amount
of time if there's a lot of them, a fixed interval provides a more predictable
time base for repeating events.

### AnalogInput

A light wrapper around objects that implement CircuitPython's analogio
Expand Down Expand Up @@ -84,7 +92,7 @@ AE = AnalogEvent(
A "convenience" implementation of `AnalogEvent` that emits `Key` objects.

```python
from analogio import AnalogKey
from kmk.modules.analogin.keys import AnalogKey

AK = AnalogKey(
key: Key,
Expand All @@ -100,6 +108,7 @@ AK = AnalogKey(
import board
from analogio import AnalogIn
from kmk.modules.analogin import AnalogInput, AnalogInputs
from kmk.modules.analogin.keys import AnalogKey

analog = AnalogInputs(
[
Expand Down
42 changes: 22 additions & 20 deletions kmk/modules/analogin.py → kmk/modules/analogin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from kmk.keys import KC
from kmk.modules import Module
from kmk.scheduler import create_task
from kmk.utils import Debug

debug = Debug(__name__)
Expand Down Expand Up @@ -61,21 +62,37 @@ def update(self):


class AnalogInputs(Module):
def __init__(self, inputs, evtmap):
def __init__(self, inputs, evtmap, update_interval=10):
self._active = {}
self.inputs = inputs
self.evtmap = evtmap
self.update_interval = update_interval

def on_runtime_enable(self, keyboard):
def during_bootup(self, keyboard):
self.task = create_task(
lambda: self.update(keyboard),
period_ms=self.update_interval,
)

def before_matrix_scan(self, keyboard):
return

def on_runtime_disable(self, keyboard):
def after_matrix_scan(self, keyboard):
return

def during_bootup(self, keyboard):
def before_hid_send(self, keyboard):
return

def before_matrix_scan(self, keyboard):
def after_hid_send(self, keyboard):
return

def on_powersave_enable(self, keyboard):
return

def on_powersave_disable(self, keyboard):
return

def update(self, keyboard):
for idx, input in enumerate(self.inputs):
value = input.update()

Expand Down Expand Up @@ -114,18 +131,3 @@ def before_matrix_scan(self, keyboard):
except Exception as e:
if debug.enabled:
debug(type(e), ': ', e, ' in ', key.on_change)

def after_matrix_scan(self, keyboard):
return

def before_hid_send(self, keyboard):
return

def after_hid_send(self, keyboard):
return

def on_powersave_enable(self, keyboard):
return

def on_powersave_disable(self, keyboard):
return
20 changes: 20 additions & 0 deletions kmk/modules/analogin/keys.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from . import AnalogEvent


class AnalogKey(AnalogEvent):
def __init__(self, key, threshold=127):
self.key = key
self.threshold = threshold
self.pressed = False

def on_change(self, event, keyboard):
if event.value >= self.threshold and not self.pressed:
self.pressed = True
keyboard.pre_process_key(self.key, True)

elif event.value < self.threshold and self.pressed:
self.pressed = False
keyboard.pre_process_key(self.key, False)

def on_stop(self, event, keyboard):
pass