From c843ad1268863849f84dead17c3cea57800879df Mon Sep 17 00:00:00 2001
From: Nick Brassel <nick@tzarc.org>
Date: Wed, 20 Nov 2024 08:59:07 +1100
Subject: [PATCH] Add Sagittarius encoder support. (#24617)

---
 .../cannonkeys/sagittarius/keyboard.json      |  8 ++++
 .../sagittarius/keymaps/default/keymap.c      |  7 ++++
 .../sagittarius/keymaps/default/rules.mk      |  2 +
 .../cannonkeys/sagittarius/sagittarius.c      | 40 +++++++++++++++++++
 4 files changed, 57 insertions(+)
 create mode 100644 keyboards/cannonkeys/sagittarius/keymaps/default/rules.mk
 create mode 100644 keyboards/cannonkeys/sagittarius/sagittarius.c

diff --git a/keyboards/cannonkeys/sagittarius/keyboard.json b/keyboards/cannonkeys/sagittarius/keyboard.json
index 8f83a42984..e64268ab53 100644
--- a/keyboards/cannonkeys/sagittarius/keyboard.json
+++ b/keyboards/cannonkeys/sagittarius/keyboard.json
@@ -60,6 +60,14 @@
             "resync": true
         }
     },
+    "encoder": {
+        "rotary": [
+            {"pin_a": "B12", "pin_b": "B11", "resolution": 2},
+            {"pin_a": "B12", "pin_b": "B11", "resolution": 2},
+            {"pin_a": "B12", "pin_b": "B11", "resolution": 2},
+            {"pin_a": "B12", "pin_b": "B11", "resolution": 2}
+        ]
+    },
     "layouts": {
         "LAYOUT_default": {
             "layout": [
diff --git a/keyboards/cannonkeys/sagittarius/keymaps/default/keymap.c b/keyboards/cannonkeys/sagittarius/keymaps/default/keymap.c
index 093895bb99..a97574c774 100644
--- a/keyboards/cannonkeys/sagittarius/keymaps/default/keymap.c
+++ b/keyboards/cannonkeys/sagittarius/keymaps/default/keymap.c
@@ -44,3 +44,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
         KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
     )
 };
+
+#if defined(ENCODER_MAP_ENABLE)
+const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
+    [0] = { ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN), ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(UG_HUED, UG_HUEU), ENCODER_CCW_CW(UG_SATD, UG_SATU)  },
+    [1] = { ENCODER_CCW_CW(UG_VALD, UG_VALU),           ENCODER_CCW_CW(UG_SPDD, UG_SPDU), ENCODER_CCW_CW(UG_PREV, UG_NEXT), ENCODER_CCW_CW(KC_RIGHT, KC_LEFT) },
+};
+#endif
diff --git a/keyboards/cannonkeys/sagittarius/keymaps/default/rules.mk b/keyboards/cannonkeys/sagittarius/keymaps/default/rules.mk
new file mode 100644
index 0000000000..376fe3d8dc
--- /dev/null
+++ b/keyboards/cannonkeys/sagittarius/keymaps/default/rules.mk
@@ -0,0 +1,2 @@
+ENCODER_ENABLE = yes
+ENCODER_MAP_ENABLE = yes
diff --git a/keyboards/cannonkeys/sagittarius/sagittarius.c b/keyboards/cannonkeys/sagittarius/sagittarius.c
new file mode 100644
index 0000000000..1000f7dd43
--- /dev/null
+++ b/keyboards/cannonkeys/sagittarius/sagittarius.c
@@ -0,0 +1,40 @@
+// Copyright 2024 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include QMK_KEYBOARD_H
+
+#if defined(ENCODER_ENABLE) || defined(ENCODER_MAP_ENABLE)
+
+#    if !defined(ENCODER_SETTLE_PIN_STATE_DELAY_US)
+#        define ENCODER_SETTLE_PIN_STATE_DELAY_US 2
+#    endif
+
+static pin_t matrix_row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
+
+void encoder_driver_task(void) {
+    // Set all relevant rows to output, which is different to the matrix expectations
+    for (uint8_t i = 0; i < 4; i++) {
+        gpio_set_pin_output(matrix_row_pins[i]);
+    }
+
+    // Read each encoder
+    for (uint8_t i = 0; i < 4; i++) {
+        // Set the row pin low for the corresponding encoder...
+        for (uint8_t j = 0; j < 4; j++) {
+            gpio_write_pin(matrix_row_pins[j], (i == j) ? 0 : 1);
+        }
+        // ...and let them settle.
+        wait_us(ENCODER_SETTLE_PIN_STATE_DELAY_US);
+
+        // Run the normal encoder handling
+        extern void encoder_quadrature_handle_read(uint8_t index, uint8_t pin_a_state, uint8_t pin_b_state);
+        extern uint8_t encoder_quadrature_read_pin(uint8_t index, bool pad_b);
+        encoder_quadrature_handle_read(i, encoder_quadrature_read_pin(i, false), encoder_quadrature_read_pin(i, true));
+    }
+
+    // Set all rows back to input-high as per matrix expectations
+    for (uint8_t i = 0; i < 4; i++) {
+        gpio_set_pin_input_high(matrix_row_pins[i]);
+    }
+}
+
+#endif // defined(ENCODER_ENABLE) || defined(ENCODER_MAP_ENABLE)