summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSébastien Dailly <sebastien@dailly.me>2023-08-13 10:45:56 +0200
committerSébastien Dailly <sebastien@dailly.me>2023-08-13 10:46:58 +0200
commit6716fbc7a1ec5d14887d54b7d0286a149d15d46a (patch)
tree4b79c10ce838142ae9ac41222fd73d99aeba5228
parent7357e1f9671cbaef34fc934ce52b78f25c74f34e (diff)
Added a sleep function in the keyboard
-rw-r--r--src/code.py39
-rw-r--r--src/skeleton.py15
-rw-r--r--src/sleep_mode.py57
-rw-r--r--src/ticks.py4
4 files changed, 100 insertions, 15 deletions
diff --git a/src/code.py b/src/code.py
index 813574a..ad634ad 100644
--- a/src/code.py
+++ b/src/code.py
@@ -28,6 +28,7 @@ from supervisor import runtime
from actions import Action
import skeleton
import menu
+from sleep_mode import Power
# CONFIGURABLES ------------------------
@@ -43,6 +44,8 @@ macropad = MacroPad()
macropad.display.auto_refresh = False
macropad.pixels.auto_write = False
+power = Power(macropad)
+
Action().set_macropad(macropad)
# Load all the macro key setups from .py files in MACRO_FOLDER
@@ -76,6 +79,7 @@ if not apps:
app_index = 0
+
def run_application(app):
# Read encoder position. If it's changed, declare it as a button.
position = app.macropad.encoder
@@ -91,32 +95,41 @@ def run_application(app):
event = app.macropad.keys.events.get()
if not event:
app.tick()
+ power.tick()
return # No key events
key_number = event.key_number
pressed = event.pressed
+ power.execute_action(key_number, pressed or False)
return app.execute_action(key_number, pressed or False)
def switch_layout(configuration):
global app
app = skeleton.Handler(macropad, configuration)
+ power.set_configuration(configuration)
app.start()
def search_and_switch(layout):
- found_application = False
for local_app in apps:
if local_app.title == layout and app is not local_app:
- found_application = True
switch_layout(local_app)
break
+def stack(layout):
+ for configuration in apps:
+ if configuration.title == layout and app is not configuration:
+ app.stack(configuration)
+ app.start()
+ break
+
def send_layout(_any):
if usb_cdc.data.connected:
usb_cdc.data.write(bytes("%s\n" % app.name, "utf-8"))
actions = {
"layout" : search_and_switch,
+ "stack" : stack,
"get_layout" : send_layout,
}
@@ -128,13 +141,18 @@ while True:
# First read from the serial
# If we have an application name from the command line, switch to this app.
- if usb_cdc.data.connected and usb_cdc.data.in_waiting != 0:
- line = usb_cdc.data.read(usb_cdc.data.in_waiting).strip()
- commands = json.loads(line)
- for command in commands:
- for key, value in command.items():
- actions[key](value)
- continue
+ if usb_cdc.data.connected:
+ while usb_cdc.data.in_waiting != 0:
+ line = usb_cdc.data.readline(usb_cdc.data.in_waiting).strip()
+ try:
+ commands = json.loads(line)
+ for command in commands:
+ for key, value in command.items():
+ actions[key](value)
+ continue
+ except ValueError:
+ print(line)
+ pass
# Handle encoder button. If state has changed, and if there's a
# corresponding macro, set up variables to act on this just like
@@ -152,7 +170,8 @@ while True:
if configuration is None: continue
switch_layout(configuration)
break
- send_layout(None)
+ if configuration.is_layout:
+ send_layout(None)
run_application(app)
continue
diff --git a/src/skeleton.py b/src/skeleton.py
index 8497d34..1e4a03a 100644
--- a/src/skeleton.py
+++ b/src/skeleton.py
@@ -42,6 +42,9 @@ class Configuration(object):
# Set the application available in the menu by default
self.visible = True
+
+ self.is_layout = True
+
self.Action = namedtuple("Action", ("name", "callback", "color"))
self.title = title
self.keys = {
@@ -88,10 +91,16 @@ class Handler(object):
9 : None, 10 : None, 11 : None,
}
- self.options = configuration.group
+ self.stack(configuration)
+ def stack(self, configuration):
+ """ Add a new configuration on top of an existing one
+ """
+ self.group = displayio.Group()
self.name = configuration.title
+ self.options = configuration.group
+
for index, value in configuration.keys.items():
if value is None:
continue
@@ -112,6 +121,7 @@ class Handler(object):
self._update_tick()
self.macropad.pixels.show()
+
def _update_tick(self):
self.next_tick = ticks.add(
ticks_ms(),
@@ -162,8 +172,7 @@ class Handler(object):
self.macropad.consumer_control.release()
self.macropad.mouse.release_all()
self.macropad.stop_tone()
- for key in range(12):
- self._set_color(key, False)
+ self.macropad.pixels.fill((0, 0, 0))
self.macropad.pixels.show()
self.macropad.display.refresh()
diff --git a/src/sleep_mode.py b/src/sleep_mode.py
new file mode 100644
index 0000000..9c56c24
--- /dev/null
+++ b/src/sleep_mode.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# The firmware I’m using does not have the function display_sleep available. So
+# I’m sending the raw code directly.
+#
+# https://docs.circuitpython.org/projects/macropad/en/latest/api.html#adafruit_macropad.MacroPad.display_sleep
+#
+
+timeout = 15 * 60 * 1000
+from supervisor import ticks_ms
+import ticks
+
+class Power(object):
+
+ def __init__(self, macropad):
+ self.macropad = macropad
+ self.last_update = ticks_ms()
+ self.configuration = None
+ self.sleep = False
+ self.macropad.display.brightness = 0
+ self.macropad.display.bus.send(0xAF, b"")
+
+ def start(self):
+ self.last_update = ticks_ms()
+ self._wake()
+
+ def set_configuration(self, configuration):
+ self.configuration = configuration
+ self.start()
+
+ def _sleep(self):
+ if self.sleep:
+ return
+ self.sleep = True
+ self.macropad.pixels.fill((0, 0, 0))
+ self.macropad.pixels.show()
+ self.macropad.display.bus.send(0xAE, b"")
+
+ def _wake(self):
+ if not self.sleep:
+ return
+ self.sleep = False
+ #self.macropad.display_sleep = False
+ for index, value in self.configuration.keys.items():
+ if value is None or index >= 12:
+ continue
+ self.macropad.pixels[index] = value.color
+ self.macropad.pixels.show()
+ self.macropad.display.bus.send(0xAF, b"")
+
+ def tick(self):
+ if ticks.diff(ticks_ms(), self.last_update) > timeout:
+ self._sleep()
+
+ def execute_action(self, key, pressed):
+ self.start()
diff --git a/src/ticks.py b/src/ticks.py
index ba6831a..1f7e943 100644
--- a/src/ticks.py
+++ b/src/ticks.py
@@ -10,7 +10,7 @@ def add(ticks, delta):
"Add a delta to a base number of ticks, performing wraparound at 2**29ms."
return (ticks + delta) % _TICKS_PERIOD
-def ticks_diff(ticks1, ticks2):
+def diff(ticks1, ticks2):
"Compute the signed difference between two ticks values, assuming that they are within 2**28 ticks"
diff = (ticks1 - ticks2) & _TICKS_MAX
diff = ((diff + _TICKS_HALFPERIOD) & _TICKS_MAX) - _TICKS_HALFPERIOD
@@ -18,4 +18,4 @@ def ticks_diff(ticks1, ticks2):
def less(ticks):
"Return true iff ticks1 is less than ticks2, assuming that they are within 2**28 ticks"
- return ticks_diff(ticks_ms(), ticks) < 0
+ return diff(ticks_ms(), ticks) < 0