summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kconfig8
-rw-r--r--boards/native_posix.overlay5
-rw-r--r--boards/shields/petejohanson_handwire/keymaps/default/keymap.overlay2
-rw-r--r--include/dt-bindings/zmk/keys.h28
-rw-r--r--include/zmk/endpoints.h1
-rw-r--r--include/zmk/hid.h4
-rw-r--r--include/zmk/keys.h6
-rw-r--r--include/zmk/kscan-mock.h2
-rw-r--r--prj.conf1
-rw-r--r--src/endpoints.c34
-rw-r--r--src/handlers.c59
-rw-r--r--src/hid.c12
-rw-r--r--src/kscan.c4
-rw-r--r--src/kscan_mock.c6
14 files changed, 135 insertions, 37 deletions
diff --git a/Kconfig b/Kconfig
index d778b64..264c451 100644
--- a/Kconfig
+++ b/Kconfig
@@ -25,6 +25,14 @@ config ZMK_KSCAN_MOCK_DRIVER
bool "Enable mock kscan driver to simulate key presses"
default n
+menu "ZMK Actions"
+
+config ZMK_ACTION_MOD_TAP
+ bool "Enable the Mod-Tap Action"
+ default true
+
+endmenu
+
module = ZMK
module-str = zmk
source "subsys/logging/Kconfig.template.log_config"
diff --git a/boards/native_posix.overlay b/boards/native_posix.overlay
index cd71191..1d692d4 100644
--- a/boards/native_posix.overlay
+++ b/boards/native_posix.overlay
@@ -13,7 +13,8 @@
rows = <2>;
columns = <2>;
- events = <ZMK_MOCK_PRESS(0,0,800) ZMK_MOCK_RELEASE(0,0,800)>;
+ events = <ZMK_MOCK_PRESS(0,1,300) ZMK_MOCK_PRESS(0,0,300) ZMK_MOCK_RELEASE(0,0,300) ZMK_MOCK_RELEASE(0,1,300)>;
+ // events = <ZMK_MOCK_PRESS(0,0,800) ZMK_MOCK_RELEASE(0,0,800) ZMK_MOCK_PRESS(0,1,800) ZMK_MOCK_RELEASE(0,1,800)>;
};
keymap0: keymap {
@@ -29,7 +30,7 @@
label = "DEFAULT";
keys =
<
- KC_A KC_B
+ KC_A MT(MOD_LSFT, KC_B)
KC_C KC_D
>;
};
diff --git a/boards/shields/petejohanson_handwire/keymaps/default/keymap.overlay b/boards/shields/petejohanson_handwire/keymaps/default/keymap.overlay
index ccc4230..863e034 100644
--- a/boards/shields/petejohanson_handwire/keymaps/default/keymap.overlay
+++ b/boards/shields/petejohanson_handwire/keymaps/default/keymap.overlay
@@ -18,7 +18,7 @@
label = "DEFAULT";
keys =
<
- KC_A KC_B
+ KC_A MT(MOD_LSFT, KC_B)
CC_RAIS CC_LOWR
>;
};
diff --git a/include/dt-bindings/zmk/keys.h b/include/dt-bindings/zmk/keys.h
index 5a2d97a..c266de0 100644
--- a/include/dt-bindings/zmk/keys.h
+++ b/include/dt-bindings/zmk/keys.h
@@ -74,11 +74,23 @@
#define ZC_CSTM(n) (0xFF + n)
-#define MOD_LCTL 0x00
-#define MOD_LSFT 0x01
-#define MOD_LALT 0x02
-#define MOD_LGUI 0x03
-#define MOD_RCTL 0x04
-#define MOD_RSFT 0x05
-#define MOD_RALT 0x06
-#define MOD_RGUI 0x07 \ No newline at end of file
+#define MOD_LCTL (1 << 0x00)
+#define MOD_LSFT (1 << 0x01)
+#define MOD_LALT (1 << 0x02)
+#define MOD_LGUI (1 << 0x03)
+#define MOD_RCTL (1 << 0x04)
+#define MOD_RSFT (1 << 0x05)
+#define MOD_RALT (1 << 0x06)
+#define MOD_RGUI (1 << 0x07)
+
+#define ZK_ACTION(k) (k >> 24)
+#define _ACTION(a) (a << 24)
+#define _ACTION_MODS(m) (m << 16)
+#define ZK_KEY(a) (a & 0xFFFF)
+#define ZK_MODS(a) ((a >> 16) & 0xFF)
+
+#define ZMK_ACTION_KEY 0x01
+#define ZMK_ACTION_MOD_TAP 0x01
+#define ZMK_ACTION_ONE_SHOT 0x02
+
+#define MT(mods, kc) (_ACTION(ZMK_ACTION_MOD_TAP) + _ACTION_MODS(mods) + kc)
diff --git a/include/zmk/endpoints.h b/include/zmk/endpoints.h
index 42734aa..666f00d 100644
--- a/include/zmk/endpoints.h
+++ b/include/zmk/endpoints.h
@@ -3,4 +3,5 @@
#include <zmk/keys.h>
int zmk_endpoints_init();
+int zmk_endpoints_send_report();
int zmk_endpoints_send_key_event(struct zmk_key_event key_event);
diff --git a/include/zmk/hid.h b/include/zmk/hid.h
index 8fbcf4f..3767b78 100644
--- a/include/zmk/hid.h
+++ b/include/zmk/hid.h
@@ -97,12 +97,14 @@ static const u8_t zmk_hid_report_desc[] = {
struct zmk_hid_report
{
- u8_t modifiers;
+ zmk_mod_flags modifiers;
u8_t keys[13];
} __packed;
int zmk_hid_register_mod(zmk_mod modifier);
int zmk_hid_unregister_mod(zmk_mod modifier);
+int zmk_hid_register_mods(zmk_mod_flags modifiers);
+int zmk_hid_unregister_mods(zmk_mod_flags modifiers);
int zmk_hid_press_key(zmk_key key);
int zmk_hid_release_key(zmk_key key);
diff --git a/include/zmk/keys.h b/include/zmk/keys.h
index be05784..6966bba 100644
--- a/include/zmk/keys.h
+++ b/include/zmk/keys.h
@@ -3,11 +3,15 @@
#include <zephyr.h>
#include <dt-bindings/zmk/keys.h>
-typedef u64_t zmk_key;
+typedef u32_t zmk_key;
+typedef u8_t zmk_action;
typedef u8_t zmk_mod;
+typedef u8_t zmk_mod_flags;
struct zmk_key_event
{
+ u32_t column;
+ u32_t row;
zmk_key key;
bool pressed;
}; \ No newline at end of file
diff --git a/include/zmk/kscan-mock.h b/include/zmk/kscan-mock.h
index b19cafb..d481899 100644
--- a/include/zmk/kscan-mock.h
+++ b/include/zmk/kscan-mock.h
@@ -1,6 +1,6 @@
#pragma once
-#define ZMK_MOCK_IS_PRESS(v) (v & (0x01 << 31))
+#define ZMK_MOCK_IS_PRESS(v) ((v & (0x01 << 31)) != 0)
#define ZMK_MOCK_PRESS(row, col, msec) (row + (col << 8) + (msec << 16) + (0x01 << 31))
#define ZMK_MOCK_RELEASE(row, col, msec) (row + (col << 8) + (msec << 16))
#define ZMK_MOCK_ROW(v) (v & 0xFF)
diff --git a/prj.conf b/prj.conf
index 5e0c8bb..863e502 100644
--- a/prj.conf
+++ b/prj.conf
@@ -5,6 +5,7 @@ CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_HID=y
CONFIG_USB_DEVICE_PRODUCT="ZMK Firmware"
CONFIG_ZMK_BLE=y
+CONFIG_ZMK_ACTION_MOD_TAP=y
# HID GATT notifications sent this way are *not* picked up by Linux, and possibly others.
CONFIG_BT_GATT_NOTIFY_MULTIPLE=n
CONFIG_BT_DEVICE_NAME="ZMK Keyboard"
diff --git a/src/endpoints.c b/src/endpoints.c
index 5e9fcdf..668380a 100644
--- a/src/endpoints.c
+++ b/src/endpoints.c
@@ -33,24 +33,10 @@ int zmk_endpoints_init()
return 0;
}
-int zmk_endpoints_send_key_event(struct zmk_key_event key_event)
+int zmk_endpoints_send_report()
{
- struct zmk_hid_report *report;
int err;
-
- LOG_DBG("key %lld, state %d\n", key_event.key, key_event.pressed);
-
-
- if (key_event.pressed)
- {
- zmk_hid_press_key(key_event.key);
- }
- else
- {
- zmk_hid_release_key(key_event.key);
- }
-
- report = zmk_hid_get_report();
+ struct zmk_hid_report *report = zmk_hid_get_report();
// if (zmk_usb_hid_send_report(report) != 0)
// {
@@ -67,3 +53,19 @@ int zmk_endpoints_send_key_event(struct zmk_key_event key_event)
return 0;
}
+
+int zmk_endpoints_send_key_event(struct zmk_key_event key_event)
+{
+ LOG_DBG("key %d, state %d\n", key_event.key, key_event.pressed);
+
+ if (key_event.pressed)
+ {
+ zmk_hid_press_key(key_event.key);
+ }
+ else
+ {
+ zmk_hid_release_key(key_event.key);
+ }
+
+ return zmk_endpoints_send_report();
+}
diff --git a/src/handlers.c b/src/handlers.c
index b73c92c..ff969b1 100644
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -2,20 +2,79 @@
#include <zmk/ble.h>
#include <zmk/handlers.h>
#include <zmk/endpoints.h>
+#include <zmk/hid.h>
+#include <zmk/matrix.h>
+
+#ifdef CONFIG_ZMK_ACTION_MOD_TAP
+u16_t action_effect_pending = 0;
+#endif
__attribute__((weak)) bool zmk_handle_key_user(struct zmk_key_event *key_event)
{
return true;
};
+bool zmk_handle_action(zmk_action action, struct zmk_key_event *key_event)
+{
+ zmk_mod mods = ZK_MODS(key_event->key);
+ u8_t flattened_index = (key_event->row * ZMK_MATRIX_COLS) + key_event->column;
+ switch (action)
+ {
+#ifdef CONFIG_ZMK_ACTION_MOD_TAP
+ case ZMK_ACTION_MOD_TAP:
+ if (key_event->pressed)
+ {
+ WRITE_BIT(action_effect_pending, flattened_index, true);
+ zmk_hid_register_mods(mods);
+ }
+ else
+ {
+ zmk_hid_unregister_mods(mods);
+ if (action_effect_pending & BIT(flattened_index))
+ {
+ struct zmk_key_event non_mod_event =
+ {
+ .row = key_event->row,
+ .column = key_event->column,
+ .key = ZK_KEY(key_event->key),
+ .pressed = true};
+
+ zmk_handle_key(non_mod_event);
+ non_mod_event.pressed = false;
+ zmk_handle_key(non_mod_event);
+ }
+ else
+ {
+ // Since not sending a keycode, at least send the report w/ the mod removed
+ zmk_endpoints_send_report();
+ }
+ }
+ break;
+#endif
+ }
+ return false;
+};
+
void zmk_handle_key(struct zmk_key_event key_event)
{
+ zmk_action action = ZK_ACTION(key_event.key);
+
if (!zmk_handle_key_user(&key_event))
{
return;
}
+ if (action && !zmk_handle_action(action, &key_event))
+ {
+ return;
+ }
+
+#ifdef CONFIG_ZMK_ACTION_MOD_TAP
+ action_effect_pending = 0;
+#endif
+
#ifdef CONFIG_ZMK_BLE
+ /* Used for intercepting key presses when doing passkey verification */
if (!zmk_ble_handle_key_user(&key_event))
{
return;
diff --git a/src/hid.c b/src/hid.c
index 51f92a7..5e87b59 100644
--- a/src/hid.c
+++ b/src/hid.c
@@ -21,6 +21,18 @@ int zmk_hid_unregister_mod(zmk_mod modifier)
_TOGGLE_MOD(modifier, false);
}
+int zmk_hid_register_mods(zmk_mod_flags modifiers)
+{
+ report.modifiers |= modifiers;
+ printk("After register mods %d have %d\n", modifiers, report.modifiers);
+}
+
+int zmk_hid_unregister_mods(zmk_mod_flags modifiers)
+{
+ report.modifiers &= ~modifiers;
+ printk("After unregister mods %d have %d\n", modifiers, report.modifiers);
+}
+
#define KEY_OFFSET 0x02
#define MAX_KEYS 6
diff --git a/src/kscan.c b/src/kscan.c
index 83e8ca6..1f54a14 100644
--- a/src/kscan.c
+++ b/src/kscan.c
@@ -50,9 +50,9 @@ void zmk_kscan_process_msgq(struct k_work *item)
{
bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED);
zmk_key key = zmk_keymap_keycode_from_position(ev.row, ev.column);
- struct zmk_key_event kev = (struct zmk_key_event){.key = key, .pressed = pressed};
+ struct zmk_key_event kev = (struct zmk_key_event){.row = ev.row, .column = ev.column, .key = key, .pressed = pressed};
- LOG_DBG("Row: %d, col: %d, key: %lld, pressed: %s\n", ev.row, ev.column, key, (pressed ? "true" : "false"));
+ LOG_DBG("Row: %d, col: %d, key: %d, pressed: %s\n", ev.row, ev.column, key, (pressed ? "true" : "false"));
zmk_handle_key(kev);
}
}
diff --git a/src/kscan_mock.c b/src/kscan_mock.c
index 09a0161..a214335 100644
--- a/src/kscan_mock.c
+++ b/src/kscan_mock.c
@@ -68,7 +68,7 @@ static void kscan_mock_work_handler(struct k_work *work)
struct kscan_mock_config *cfg = data->dev->config_info;
u32_t ev = cfg->events[data->event_index++];
- LOG_DBG("Triggering ev %d\n", ev);
+ LOG_DBG("ev %u row %d column %d state %d\n", ev, ZMK_MOCK_ROW(ev), ZMK_MOCK_COL(ev), ZMK_MOCK_IS_PRESS(ev));
data->callback(data->dev, ZMK_MOCK_ROW(ev), ZMK_MOCK_COL(ev), ZMK_MOCK_IS_PRESS(ev));
kscan_mock_schedule_next_event(data->dev);
}
@@ -93,10 +93,6 @@ static int kscan_mock_init(struct device *dev)
struct kscan_mock_data *data = dev->driver_data;
const struct kscan_mock_config *cfg = dev->config_info;
- printk("Init first event: %d\n", cfg->events[0]);
-
- int err;
-
data->dev = dev;
k_delayed_work_init(&data->work, kscan_mock_work_handler);