From 7e659851c80bf2819554d93ad9971f56aa5b225b Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Sat, 20 Jun 2020 17:54:52 -0400
Subject: [PATCH] Refactor matrix transform, positions pervasively

* Do mapping to positions right in kscan handler, and then
  surface positions throughout the API.
---
 app/CMakeLists.txt                     |  1 +
 app/boards/shields/kyria/kyria.overlay | 39 ++++++++++++++++++++++++++
 app/include/zmk/events.h               |  4 +--
 app/include/zmk/keymap.h               |  2 +-
 app/include/zmk/matrix_transform.h     |  3 ++
 app/src/behaviors/behavior_keymap.c    |  8 +++---
 app/src/events.c                       |  8 +++---
 app/src/keymap.c                       | 35 ++++-------------------
 app/src/kscan.c                        | 16 ++++-------
 app/src/matrix_transform.c             | 30 ++++++++++++++++++++
 10 files changed, 95 insertions(+), 51 deletions(-)
 create mode 100644 app/include/zmk/matrix_transform.h
 create mode 100644 app/src/matrix_transform.c

diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 6f4217aa..ff534fe2 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -28,6 +28,7 @@ endif()
 # find_package(Zephyr) which defines the target.
 target_include_directories(app PRIVATE include)
 target_sources(app PRIVATE src/kscan.c)
+target_sources(app PRIVATE src/matrix_transform.c)
 target_sources(app PRIVATE src/events.c)
 target_sources(app PRIVATE src/keymap.c)
 target_sources(app PRIVATE src/hid.c)
diff --git a/app/boards/shields/kyria/kyria.overlay b/app/boards/shields/kyria/kyria.overlay
index af4e591c..4140fcfc 100644
--- a/app/boards/shields/kyria/kyria.overlay
+++ b/app/boards/shields/kyria/kyria.overlay
@@ -4,9 +4,20 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/matrix-transform.h>
+#include <behaviors/keymap.dtsi>
+#include <behaviors/hid.dtsi>
+
 / {
 	chosen {
 		zmk,kscan = &kscan0;
+		zmk,matrix_transform = &default_transform;
+		zmk,global_bindings = &bindings;
+	};
+
+	bindings: global_bindings {
+		compatible = "zmk,global-bindings";
+		bindings = <&keymap_behavior &hid_behavior>;
 	};
 
 	kscan0: kscan_comp {
@@ -28,6 +39,34 @@
 		};
 	};
 
+	default_transform: keymap_transform_0 {
+		compatible = "zmk,matrix-transform";
+// | MX6  | MX5  | MX4  | MX3  | MX2  | MX1  |                               | MX1  | MX2  | MX3  | MX4  | MX5  | MX6  |
+// | MX12 | MX11 | MX10 | MX9  | MX8  | MX7  |                               | MX7  | MX8  | MX9  | MX10 | MX11 | MX12 |
+// | MX20 | MX19 | MX18 | MX17 | MX16 | MX15 | MX14 | MX13 |   | MX13 | MX14 | MX15 | MX16 | MX17 | MX18 | MX19 | MX20 |
+//                    | MX25 | MX24 | MX23 | MX22 | MX21 |       | MX21 | MX22 | MX23 | MX24 | MX25 |
+		map = <
+RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5)                                 RC(0,10) RC(0,11) RC(0,12) RC(0,13) RC(0,14) RC(0,15)
+RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5)                                 RC(1,10) RC(1,11) RC(1,12) RC(1,13) RC(1,14) RC(1,15)
+RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,13) RC(2,14) RC(2,15)
+                        RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11) RC(3,12)
+		>;
+	};
+
+// | MX5  | MX4  | MX3  | MX2  | MX1  |                               | MX1  | MX2  | MX3  | MX4  | MX5  |
+// | MX11 | MX10 | MX9  | MX8  | MX7  |                               | MX7  | MX8  | MX9  | MX10 | MX11 |
+// | MX19 | MX18 | MX17 | MX16 | MX15 | MX14 | MX13 |   | MX13 | MX14 | MX15 | MX16 | MX17 | MX18 | MX19 |
+//             | MX25 | MX24 | MX23 | MX22 | MX21 |       | MX21 | MX22 | MX23 | MX24 | MX25 |
+	five_column_transform: keymap_transform_1 {
+		compatible = "zmk,matrix-transform";
+		map = <
+RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4)                                 RC(0,9) RC(0,10) RC(0,11) RC(0,12) RC(0,13)
+RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4)                                 RC(1,9) RC(1,10) RC(1,11) RC(1,12) RC(1,13)
+RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,13)
+                RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11)
+		>;
+	};
+
 	kscan_left: kscan_left {
 		compatible = "gpio-kscan";
 		label = "KSCAN_LEFT";
diff --git a/app/include/zmk/events.h b/app/include/zmk/events.h
index 9314b9d0..ac4815a9 100644
--- a/app/include/zmk/events.h
+++ b/app/include/zmk/events.h
@@ -1,7 +1,7 @@
 #pragma once
 
-int zmk_events_position_pressed(u32_t row, u32_t column);
-int zmk_events_position_released(u32_t row, u32_t column);
+int zmk_events_position_pressed(u32_t position);
+int zmk_events_position_released(u32_t position);
 int zmk_events_keycode_pressed(u32_t keycode);
 int zmk_events_keycode_released(u32_t keycode);
 int zmk_events_mod_pressed(u32_t modifier);
diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h
index 7866cd57..cf38904a 100644
--- a/app/include/zmk/keymap.h
+++ b/app/include/zmk/keymap.h
@@ -11,4 +11,4 @@
 bool zmk_keymap_layer_activate(u8_t layer);
 bool zmk_keymap_layer_deactivate(u8_t layer);
 
-int zmk_keymap_position_state_changed(u32_t row, u32_t column, bool pressed);
+int zmk_keymap_position_state_changed(u32_t position, bool pressed);
diff --git a/app/include/zmk/matrix_transform.h b/app/include/zmk/matrix_transform.h
new file mode 100644
index 00000000..e9e969a4
--- /dev/null
+++ b/app/include/zmk/matrix_transform.h
@@ -0,0 +1,3 @@
+#pragma once
+
+u32_t zmk_matrix_transform_row_column_to_position(u32_t row, u32_t column);
\ No newline at end of file
diff --git a/app/src/behaviors/behavior_keymap.c b/app/src/behaviors/behavior_keymap.c
index 48f85473..9369b404 100644
--- a/app/src/behaviors/behavior_keymap.c
+++ b/app/src/behaviors/behavior_keymap.c
@@ -23,14 +23,14 @@ static int behavior_keymap_init(struct device *dev)
 	return 0;
 };
 
-static int on_position_pressed(struct device *dev, u32_t row, u32_t column)
+static int on_position_pressed(struct device *dev, u32_t position, u32_t _)
 {
-  return zmk_keymap_position_state_changed(row, column, true);
+  return zmk_keymap_position_state_changed(position, true);
 }
 
-static int on_position_released(struct device *dev, u32_t row, u32_t column)
+static int on_position_released(struct device *dev, u32_t position, u32_t _)
 {
-  return zmk_keymap_position_state_changed(row, column, false);
+  return zmk_keymap_position_state_changed(position, false);
 }
 
 static const struct behavior_driver_api behavior_keymap_driver_api = {
diff --git a/app/src/events.c b/app/src/events.c
index c3e8d841..73c0e291 100644
--- a/app/src/events.c
+++ b/app/src/events.c
@@ -17,22 +17,22 @@
 static const struct zmk_behavior_binding bindings[] =
     { UTIL_LISTIFY(BINDING_COUNT, BINDING_GEN, 0) };
 
-int zmk_events_position_pressed(u32_t row, u32_t column)
+int zmk_events_position_pressed(u32_t position)
 {
     for (int i = 0; i < BINDING_COUNT; i++) {
         const struct zmk_behavior_binding *b = &bindings[i];
         struct device *dev = device_get_binding(b->behavior_dev);
-        behavior_position_pressed(dev, row, column);
+        behavior_position_pressed(dev, position, 0);
     }
     return 0;
 };
 
-int zmk_events_position_released(u32_t row, u32_t column)
+int zmk_events_position_released(u32_t position)
 {
     for (int i = 0; i < BINDING_COUNT; i++) {
         const struct zmk_behavior_binding *b = &bindings[i];
         struct device *dev = device_get_binding(b->behavior_dev);
-        behavior_position_released(dev, row, column);
+        behavior_position_released(dev, position, 0);
     }
     return 0;
 }
diff --git a/app/src/keymap.c b/app/src/keymap.c
index 386de81f..6ee61ec3 100644
--- a/app/src/keymap.c
+++ b/app/src/keymap.c
@@ -4,42 +4,22 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 #include <zmk/keymap.h>
 #include <dt-bindings/zmk/matrix-transform.h>
 #include <drivers/behavior.h>
+#include <zmk/behavior.h>
 #include <sys/util.h>
 
 static u32_t zmk_keymap_layer_state = 0;
 static u8_t zmk_keymap_layer_default = 0;
 
-struct zmk_behavior_binding {
-	char *behavior_dev;
-	u32_t param1;
-	u32_t param2;
-};
-
 #define ZMK_KEYMAP_NODE DT_CHOSEN(zmk_keymap)
 #define ZMK_KEYMAP_LAYERS_LEN DT_PROP_LEN(ZMK_KEYMAP_NODE, layers)
 
 #define LAYER_NODE(l) DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, l)
 
-#define BINDING_FOR_IDX(layer,idx) \
+#define _TRANSFORM_ENTRY(idx, layer) \
 	{ .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, layer), bindings, idx)), \
 	  .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(LAYER_NODE(layer), bindings, idx, param1), (0), (DT_PHA_BY_IDX(LAYER_NODE(layer), bindings, idx, param1))), \
 	  .param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(LAYER_NODE(layer), bindings, idx, param2), (0), (DT_PHA_BY_IDX(LAYER_NODE(layer), bindings, idx, param2))), \
-	}
-
-#if DT_NODE_HAS_PROP(ZMK_KEYMAP_NODE, transform)
-#define ZMK_KEYMAP_TRANSFORM_NODE DT_PHANDLE(ZMK_KEYMAP_NODE, transform)
-#define ZMK_KEYMAP_LEN DT_PROP_LEN(ZMK_KEYMAP_TRANSFORM_NODE, map)
-
-#define _TRANSFORM_ENTRY(i, l) \
-	[(KT_ROW(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i)) * ZMK_MATRIX_COLS) + KT_COL(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i))] = BINDING_FOR_IDX(l,i),
-
-#else
-
-#define ZMK_KEYMAP_LEN DT_PROP_LEN(ZMK_KEYMAP_NODE, bindings)
-#define _TRANSFORM_ENTRY(i, l) \
-	BINDING_FOR_IDX(l,i),
-
-#endif
+	},
 
 #define TRANSFORMED_LAYER(idx) \
   { UTIL_LISTIFY(DT_PROP_LEN(DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, idx), bindings), _TRANSFORM_ENTRY, idx) }
@@ -77,8 +57,6 @@ static struct zmk_behavior_binding zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_MATRIX_
 #endif
 };
 
-// #else
-
 #define SET_LAYER_STATE(layer, state)                \
 	if (layer >= 32)                                 \
 	{                                                \
@@ -97,18 +75,17 @@ bool zmk_keymap_layer_deactivate(u8_t layer)
 	SET_LAYER_STATE(layer, false);
 };
 
-int zmk_keymap_position_state_changed(u32_t row, u32_t column, bool pressed)
+int zmk_keymap_position_state_changed(u32_t position, bool pressed)
 {
 	for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--)
 	{
 		if ((zmk_keymap_layer_state & BIT(layer)) == BIT(layer) || layer == zmk_keymap_layer_default)
 		{
-			u8_t key_index = (row * ZMK_MATRIX_COLS) + column;
-			struct zmk_behavior_binding *binding = &zmk_keymap[layer][key_index];
+			struct zmk_behavior_binding *binding = &zmk_keymap[layer][position];
 			struct device *behavior;
 			int ret;
 
-			LOG_DBG("key index: %d, binding name: %s", key_index, binding->behavior_dev);
+			LOG_DBG("position: %d, binding name: %s", position, binding->behavior_dev);
 
 			behavior = device_get_binding(binding->behavior_dev);
 			if (pressed) {
diff --git a/app/src/kscan.c b/app/src/kscan.c
index 781824df..29a60199 100644
--- a/app/src/kscan.c
+++ b/app/src/kscan.c
@@ -11,8 +11,8 @@
 
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 
+#include <zmk/matrix_transform.h>
 #include <zmk/events.h>
-#include <zmk/handlers.h>
 
 #define ZMK_KSCAN_EVENT_STATE_PRESSED 0
 #define ZMK_KSCAN_EVENT_STATE_RELEASED 1
@@ -49,19 +49,13 @@ void zmk_kscan_process_msgq(struct k_work *item)
 	while (k_msgq_get(&zmk_kscan_msgq, &ev, K_NO_WAIT) == 0)
 	{
 		bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED);
+		u32_t position = zmk_matrix_transform_row_column_to_position(ev.row, ev.column);
+		LOG_DBG("Row: %d, col: %d, position: %d, pressed: %s\n", ev.row, ev.column, position, (pressed ? "true" : "false"));
 		if (pressed) {
-			LOG_DBG("PRESSING");
-			zmk_events_position_pressed(ev.row, ev.column);
+			zmk_events_position_pressed(position);
 		} else {
-			LOG_DBG("RELEASSING");
-			zmk_events_position_released(ev.row, ev.column);
+			zmk_events_position_released(position);
 		}
-		// zmk_keymap_position_state_changed(ev.row, ev.column, pressed);
-		// zmk_key key = zmk_keymap_keycode_from_position(ev.row, ev.column);
-		// 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: %d, pressed: %s\n", ev.row, ev.column, key, (pressed ? "true" : "false"));
-		// zmk_handle_key(kev);
 	}
 }
 
diff --git a/app/src/matrix_transform.c b/app/src/matrix_transform.c
new file mode 100644
index 00000000..7e8b481e
--- /dev/null
+++ b/app/src/matrix_transform.c
@@ -0,0 +1,30 @@
+
+#include <zephyr.h>
+#include <zmk/matrix_transform.h>
+#include <zmk/matrix.h>
+#include <dt-bindings/zmk/matrix-transform.h>
+
+#define HAS_TRANSFORM DT_HAS_CHOSEN(zmk_matrix_transform)
+
+#if HAS_TRANSFORM
+#define ZMK_KEYMAP_TRANSFORM_NODE DT_CHOSEN(zmk_matrix_transform)
+#define ZMK_KEYMAP_LEN DT_PROP_LEN(ZMK_KEYMAP_TRANSFORM_NODE, map)
+
+#define _TRANSFORM_ENTRY(i, _) \
+	[(KT_ROW(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i)) * ZMK_MATRIX_COLS) + KT_COL(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i))] = i,
+
+static u32_t transform[] = 
+    { UTIL_LISTIFY(ZMK_KEYMAP_LEN, _TRANSFORM_ENTRY, 0) };
+
+#endif
+
+u32_t zmk_matrix_transform_row_column_to_position(u32_t row, u32_t column)
+{
+    u32_t matrix_index = (row * ZMK_MATRIX_COLS) + column;
+
+#if HAS_TRANSFORM
+    return transform[matrix_index];
+#else
+    return matrix_index;
+#endif /* HAS_TRANSFORM */
+};