aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Sangdahl <[email protected]>2025-03-24 19:26:51 -0600
committerJack Sangdahl <[email protected]>2025-03-24 19:26:51 -0600
commitef8261e670cfcee6037278a7ca352db6efd55964 (patch)
tree94843992be084827169d3ca2901857c0eb8ed66a
parentce2f7d86be171f7273299720ba739b8c85d4c267 (diff)
downloadqmk_firmware-keyball.tar.gz
qmk_firmware-keyball.zip
Initial keyball61 firmwarekeyball
-rw-r--r--keyboards/keyball/keyball61/config.h20
-rw-r--r--keyboards/keyball/keyball61/halconf.h8
-rw-r--r--keyboards/keyball/keyball61/keyball61.c37
-rw-r--r--keyboards/keyball/keyball61/keyboard.json300
-rw-r--r--keyboards/keyball/keyball61/keymaps/default/keymap.c13
-rw-r--r--keyboards/keyball/keyball61/matrix.c77
-rw-r--r--keyboards/keyball/keyball61/mcuconf.h6
-rw-r--r--keyboards/keyball/keyball61/rules.mk4
8 files changed, 465 insertions, 0 deletions
diff --git a/keyboards/keyball/keyball61/config.h b/keyboards/keyball/keyball61/config.h
new file mode 100644
index 0000000000..6da0838516
--- /dev/null
+++ b/keyboards/keyball/keyball61/config.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#define MATRIX_ROWS (5 * 2)
+#define MATRIX_COLS (4 * 2)
+#define MATRIX_ROW_PINS {GP4, GP5, GP6, GP7, GP8}
+#define MATRIX_COL_PINS {GP29, GP28, GP27, GP26}
+#define MATRIX_MASKED
+
+#define SERIAL_USART_TX_PIN GP1
+#define SPLIT_HAND_MATRIX_GRID GP26, GP6
+#define SPLIT_HAND_MATRIX_GRID_LOW_IS_LEFT
+
+#define SPI_DRIVER SPID0
+#define SPI_SCK_PIN GP22
+#define SPI_MISO_PIN GP20
+#define SPI_MOSI_PIN GP23
+#define PMW33XX_CS_PIN GP21
+
+#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET
+#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT 1000U
diff --git a/keyboards/keyball/keyball61/halconf.h b/keyboards/keyball/keyball61/halconf.h
new file mode 100644
index 0000000000..aef989fe0d
--- /dev/null
+++ b/keyboards/keyball/keyball61/halconf.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#define HAL_USE_I2C TRUE
+#define HAL_USE_SPI TRUE
+#define SPI_USE_WAIT TRUE
+#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
+
+#include_next <halconf.h>
diff --git a/keyboards/keyball/keyball61/keyball61.c b/keyboards/keyball/keyball61/keyball61.c
new file mode 100644
index 0000000000..2b682f6537
--- /dev/null
+++ b/keyboards/keyball/keyball61/keyball61.c
@@ -0,0 +1,37 @@
+#include "quantum.h"
+
+// clang-format off
+const matrix_row_t matrix_mask[] = {
+ 0b01110111,
+ 0b01110111,
+ 0b01110111,
+ 0b11110111,
+ 0b11110111,
+ 0b01110111,
+ 0b01110111,
+ 0b01110111,
+ 0b11110111,
+ 0b11110111
+};
+// clang-format on
+
+#ifdef OLED_ENABLE
+static void render_logo(void) {
+ static const char PROGMEM qmk_logo[] = {
+ // clang-format off
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94,
+ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4,
+ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0x00
+ // clang-format on
+ };
+ oled_write(qmk_logo, false);
+}
+
+bool oled_task_kb(void) {
+ if (!oled_task_user()) {
+ return false;
+ }
+ render_logo();
+ return false;
+}
+#endif
diff --git a/keyboards/keyball/keyball61/keyboard.json b/keyboards/keyball/keyball61/keyboard.json
new file mode 100644
index 0000000000..4d09ed1abc
--- /dev/null
+++ b/keyboards/keyball/keyball61/keyboard.json
@@ -0,0 +1,300 @@
+{
+ "processor": "RP2040",
+ "bootloader": "rp2040",
+ "usb": {
+ "vid": "0x5957",
+ "pid": "0x0100",
+ "device_version": "1.0.0"
+ },
+ "features": {
+ "pointing_device": true,
+ "bootmagic": true,
+ "extrakey": true,
+ "oled": true,
+ "rgblight": true
+ },
+ "manufacturer": "Yowkees",
+ "keyboard_name": "Keyball61",
+ "rgblight": {
+ "driver": "ws2812",
+ "led_count": 74,
+ "split_count": [37, 37],
+ "max_brightness": 120
+ },
+ "ws2812": {
+ "driver": "vendor",
+ "pin": "GP0"
+ },
+ "split": {
+ "enabled": true,
+ "serial": {
+ "driver": "vendor"
+ }
+ },
+ "layout_aliases": {
+ "LAYOUT": "LAYOUT_right_ball",
+ "LAYOUT_universal": "LAYOUT_no_ball"
+ },
+ "layouts": {
+ "LAYOUT_dual_ball": {
+ "layout": [
+ { "label": "L00", "matrix": [0, 0], "x": 0, "y": 0 },
+ { "label": "L01", "matrix": [0, 1], "x": 1, "y": 0 },
+ { "label": "L02", "matrix": [0, 2], "x": 2, "y": 0 },
+ { "label": "L03", "matrix": [0, 4], "x": 3, "y": 0 },
+ { "label": "L04", "matrix": [0, 5], "x": 4, "y": 0 },
+ { "label": "L05", "matrix": [0, 6], "x": 5, "y": 0 },
+ { "label": "R05", "matrix": [5, 6], "x": 6, "y": 0 },
+ { "label": "R04", "matrix": [5, 5], "x": 7, "y": 0 },
+ { "label": "R03", "matrix": [5, 4], "x": 8, "y": 0 },
+ { "label": "R02", "matrix": [5, 2], "x": 9, "y": 0 },
+ { "label": "R01", "matrix": [5, 1], "x": 10, "y": 0 },
+ { "label": "R00", "matrix": [5, 0], "x": 11, "y": 0 },
+ { "label": "L10", "matrix": [1, 0], "x": 12, "y": 0 },
+ { "label": "L11", "matrix": [1, 1], "x": 13, "y": 0 },
+ { "label": "L12", "matrix": [1, 2], "x": 14, "y": 0 },
+ { "label": "L13", "matrix": [1, 4], "x": 15, "y": 0 },
+ { "label": "L14", "matrix": [1, 5], "x": 16, "y": 0 },
+ { "label": "L15", "matrix": [1, 6], "x": 17, "y": 0 },
+ { "label": "R15", "matrix": [6, 6], "x": 18, "y": 0 },
+ { "label": "R14", "matrix": [6, 5], "x": 19, "y": 0 },
+ { "label": "R13", "matrix": [6, 4], "x": 20, "y": 0 },
+ { "label": "R12", "matrix": [6, 2], "x": 21, "y": 0 },
+ { "label": "R11", "matrix": [6, 1], "x": 22, "y": 0 },
+ { "label": "R10", "matrix": [6, 0], "x": 23, "y": 0 },
+ { "label": "L20", "matrix": [2, 0], "x": 24, "y": 0 },
+ { "label": "L21", "matrix": [2, 1], "x": 25, "y": 0 },
+ { "label": "L22", "matrix": [2, 2], "x": 26, "y": 0 },
+ { "label": "L23", "matrix": [2, 4], "x": 27, "y": 0 },
+ { "label": "L24", "matrix": [2, 5], "x": 28, "y": 0 },
+ { "label": "L25", "matrix": [2, 6], "x": 29, "y": 0 },
+ { "label": "R25", "matrix": [7, 6], "x": 30, "y": 0 },
+ { "label": "R24", "matrix": [7, 5], "x": 31, "y": 0 },
+ { "label": "R23", "matrix": [7, 4], "x": 32, "y": 0 },
+ { "label": "R22", "matrix": [7, 2], "x": 33, "y": 0 },
+ { "label": "R21", "matrix": [7, 1], "x": 34, "y": 0 },
+ { "label": "R20", "matrix": [7, 0], "x": 35, "y": 0 },
+ { "label": "L30", "matrix": [3, 0], "x": 36, "y": 0 },
+ { "label": "L31", "matrix": [3, 1], "x": 37, "y": 0 },
+ { "label": "L32", "matrix": [3, 2], "x": 38, "y": 0 },
+ { "label": "L33", "matrix": [3, 4], "x": 39, "y": 0 },
+ { "label": "L34", "matrix": [3, 5], "x": 40, "y": 0 },
+ { "label": "L35", "matrix": [3, 6], "x": 41, "y": 0 },
+ { "label": "L36", "matrix": [3, 7], "x": 42, "y": 0 },
+ { "label": "R36", "matrix": [8, 7], "x": 43, "y": 0 },
+ { "label": "R35", "matrix": [8, 6], "x": 44, "y": 0 },
+ { "label": "R34", "matrix": [8, 5], "x": 45, "y": 0 },
+ { "label": "R33", "matrix": [8, 4], "x": 46, "y": 0 },
+ { "label": "R32", "matrix": [8, 2], "x": 47, "y": 0 },
+ { "label": "R31", "matrix": [8, 1], "x": 48, "y": 0 },
+ { "label": "R30", "matrix": [8, 0], "x": 49, "y": 0 },
+ { "label": "L40", "matrix": [4, 0], "x": 50, "y": 0 },
+ { "label": "L41", "matrix": [4, 1], "x": 51, "y": 0 },
+ { "label": "L45", "matrix": [4, 6], "x": 52, "y": 0 },
+ { "label": "L46", "matrix": [4, 7], "x": 53, "y": 0 },
+ { "label": "R46", "matrix": [9, 7], "x": 54, "y": 0 },
+ { "label": "R45", "matrix": [9, 6], "x": 55, "y": 0 },
+ { "label": "R41", "matrix": [9, 1], "x": 56, "y": 0 },
+ { "label": "R40", "matrix": [9, 0], "x": 57, "y": 0 }
+ ]
+ },
+ "LAYOUT_left_ball": {
+ "layout": [
+ { "label": "L00", "matrix": [0, 0], "x": 0, "y": 0 },
+ { "label": "L01", "matrix": [0, 1], "x": 1, "y": 0 },
+ { "label": "L02", "matrix": [0, 2], "x": 2, "y": 0 },
+ { "label": "L03", "matrix": [0, 4], "x": 3, "y": 0 },
+ { "label": "L04", "matrix": [0, 5], "x": 4, "y": 0 },
+ { "label": "L05", "matrix": [0, 6], "x": 5, "y": 0 },
+ { "label": "R05", "matrix": [5, 6], "x": 6, "y": 0 },
+ { "label": "R04", "matrix": [5, 5], "x": 7, "y": 0 },
+ { "label": "R03", "matrix": [5, 4], "x": 8, "y": 0 },
+ { "label": "R02", "matrix": [5, 2], "x": 9, "y": 0 },
+ { "label": "R01", "matrix": [5, 1], "x": 10, "y": 0 },
+ { "label": "R00", "matrix": [5, 0], "x": 11, "y": 0 },
+ { "label": "L10", "matrix": [1, 0], "x": 12, "y": 0 },
+ { "label": "L11", "matrix": [1, 1], "x": 13, "y": 0 },
+ { "label": "L12", "matrix": [1, 2], "x": 14, "y": 0 },
+ { "label": "L13", "matrix": [1, 4], "x": 15, "y": 0 },
+ { "label": "L14", "matrix": [1, 5], "x": 16, "y": 0 },
+ { "label": "L15", "matrix": [1, 6], "x": 17, "y": 0 },
+ { "label": "R15", "matrix": [6, 6], "x": 18, "y": 0 },
+ { "label": "R14", "matrix": [6, 5], "x": 19, "y": 0 },
+ { "label": "R13", "matrix": [6, 4], "x": 20, "y": 0 },
+ { "label": "R12", "matrix": [6, 2], "x": 21, "y": 0 },
+ { "label": "R11", "matrix": [6, 1], "x": 22, "y": 0 },
+ { "label": "R10", "matrix": [6, 0], "x": 23, "y": 0 },
+ { "label": "L20", "matrix": [2, 0], "x": 24, "y": 0 },
+ { "label": "L21", "matrix": [2, 1], "x": 25, "y": 0 },
+ { "label": "L22", "matrix": [2, 2], "x": 26, "y": 0 },
+ { "label": "L23", "matrix": [2, 4], "x": 27, "y": 0 },
+ { "label": "L24", "matrix": [2, 5], "x": 28, "y": 0 },
+ { "label": "L25", "matrix": [2, 6], "x": 29, "y": 0 },
+ { "label": "R25", "matrix": [7, 6], "x": 30, "y": 0 },
+ { "label": "R24", "matrix": [7, 5], "x": 31, "y": 0 },
+ { "label": "R23", "matrix": [7, 4], "x": 32, "y": 0 },
+ { "label": "R22", "matrix": [7, 2], "x": 33, "y": 0 },
+ { "label": "R21", "matrix": [7, 1], "x": 34, "y": 0 },
+ { "label": "R20", "matrix": [7, 0], "x": 35, "y": 0 },
+ { "label": "L30", "matrix": [3, 0], "x": 36, "y": 0 },
+ { "label": "L31", "matrix": [3, 1], "x": 37, "y": 0 },
+ { "label": "L32", "matrix": [3, 2], "x": 38, "y": 0 },
+ { "label": "L33", "matrix": [3, 4], "x": 39, "y": 0 },
+ { "label": "L34", "matrix": [3, 5], "x": 40, "y": 0 },
+ { "label": "L35", "matrix": [3, 6], "x": 41, "y": 0 },
+ { "label": "L36", "matrix": [3, 7], "x": 42, "y": 0 },
+ { "label": "R36", "matrix": [8, 7], "x": 43, "y": 0 },
+ { "label": "R35", "matrix": [8, 6], "x": 44, "y": 0 },
+ { "label": "R34", "matrix": [8, 5], "x": 45, "y": 0 },
+ { "label": "R33", "matrix": [8, 4], "x": 46, "y": 0 },
+ { "label": "R32", "matrix": [8, 2], "x": 47, "y": 0 },
+ { "label": "R31", "matrix": [8, 1], "x": 48, "y": 0 },
+ { "label": "R30", "matrix": [8, 0], "x": 49, "y": 0 },
+ { "label": "L40", "matrix": [4, 0], "x": 50, "y": 0 },
+ { "label": "L41", "matrix": [4, 1], "x": 51, "y": 0 },
+ { "label": "L45", "matrix": [4, 6], "x": 52, "y": 0 },
+ { "label": "L46", "matrix": [4, 7], "x": 53, "y": 0 },
+ { "label": "R46", "matrix": [9, 7], "x": 54, "y": 0 },
+ { "label": "R45", "matrix": [9, 6], "x": 55, "y": 0 },
+ { "label": "R44", "matrix": [9, 5], "x": 56, "y": 0 },
+ { "label": "R43", "matrix": [9, 4], "x": 57, "y": 0 },
+ { "label": "R42", "matrix": [9, 2], "x": 58, "y": 0 },
+ { "label": "R41", "matrix": [9, 1], "x": 59, "y": 0 },
+ { "label": "R40", "matrix": [9, 0], "x": 60, "y": 0 }
+ ]
+ },
+ "LAYOUT_no_ball": {
+ "layout": [
+ { "label": "L00", "matrix": [0, 0], "x": 0, "y": 0 },
+ { "label": "L01", "matrix": [0, 1], "x": 1, "y": 0 },
+ { "label": "L02", "matrix": [0, 2], "x": 2, "y": 0 },
+ { "label": "L03", "matrix": [0, 4], "x": 3, "y": 0 },
+ { "label": "L04", "matrix": [0, 5], "x": 4, "y": 0 },
+ { "label": "L05", "matrix": [0, 6], "x": 5, "y": 0 },
+ { "label": "R05", "matrix": [5, 6], "x": 8, "y": 0 },
+ { "label": "R04", "matrix": [5, 5], "x": 9, "y": 0 },
+ { "label": "R03", "matrix": [5, 4], "x": 10, "y": 0 },
+ { "label": "R02", "matrix": [5, 2], "x": 11, "y": 0 },
+ { "label": "R01", "matrix": [5, 1], "x": 12, "y": 0 },
+ { "label": "R00", "matrix": [5, 0], "x": 13, "y": 0 },
+ { "label": "L10", "matrix": [1, 0], "x": 0, "y": 1 },
+ { "label": "L11", "matrix": [1, 1], "x": 1, "y": 1 },
+ { "label": "L12", "matrix": [1, 2], "x": 2, "y": 1 },
+ { "label": "L13", "matrix": [1, 4], "x": 3, "y": 1 },
+ { "label": "L14", "matrix": [1, 5], "x": 4, "y": 1 },
+ { "label": "L15", "matrix": [1, 6], "x": 5, "y": 1 },
+ { "label": "R15", "matrix": [6, 6], "x": 8, "y": 1 },
+ { "label": "R14", "matrix": [6, 5], "x": 9, "y": 1 },
+ { "label": "R13", "matrix": [6, 4], "x": 10, "y": 1 },
+ { "label": "R12", "matrix": [6, 2], "x": 11, "y": 1 },
+ { "label": "R11", "matrix": [6, 1], "x": 12, "y": 1 },
+ { "label": "R10", "matrix": [6, 0], "x": 13, "y": 1 },
+ { "label": "L20", "matrix": [2, 0], "x": 0, "y": 2 },
+ { "label": "L21", "matrix": [2, 1], "x": 1, "y": 2 },
+ { "label": "L22", "matrix": [2, 2], "x": 2, "y": 2 },
+ { "label": "L23", "matrix": [2, 4], "x": 3, "y": 2 },
+ { "label": "L24", "matrix": [2, 5], "x": 4, "y": 2 },
+ { "label": "L25", "matrix": [2, 6], "x": 5, "y": 2 },
+ { "label": "R25", "matrix": [7, 6], "x": 8, "y": 2 },
+ { "label": "R24", "matrix": [7, 5], "x": 9, "y": 2 },
+ { "label": "R23", "matrix": [7, 4], "x": 10, "y": 2 },
+ { "label": "R22", "matrix": [7, 2], "x": 11, "y": 2 },
+ { "label": "R21", "matrix": [7, 1], "x": 12, "y": 2 },
+ { "label": "R20", "matrix": [7, 0], "x": 13, "y": 2 },
+ { "label": "L30", "matrix": [3, 0], "x": 0, "y": 3 },
+ { "label": "L31", "matrix": [3, 1], "x": 1, "y": 3 },
+ { "label": "L32", "matrix": [3, 2], "x": 2, "y": 3 },
+ { "label": "L33", "matrix": [3, 4], "x": 3, "y": 3 },
+ { "label": "L34", "matrix": [3, 5], "x": 4, "y": 3 },
+ { "label": "L35", "matrix": [3, 6], "x": 5, "y": 3 },
+ { "label": "L36", "matrix": [3, 7], "x": 6, "y": 3 },
+ { "label": "R36", "matrix": [8, 7], "x": 7, "y": 3 },
+ { "label": "R35", "matrix": [8, 6], "x": 8, "y": 3 },
+ { "label": "R34", "matrix": [8, 5], "x": 9, "y": 3 },
+ { "label": "R33", "matrix": [8, 4], "x": 10, "y": 3 },
+ { "label": "R32", "matrix": [8, 2], "x": 11, "y": 3 },
+ { "label": "R31", "matrix": [8, 1], "x": 12, "y": 3 },
+ { "label": "R30", "matrix": [8, 0], "x": 13, "y": 3 },
+ { "label": "L40", "matrix": [4, 0], "x": 0, "y": 4 },
+ { "label": "L41", "matrix": [4, 1], "x": 1, "y": 4 },
+ { "label": "L42", "matrix": [4, 2], "x": 2, "y": 4 },
+ { "label": "L43", "matrix": [4, 4], "x": 3, "y": 4 },
+ { "label": "L44", "matrix": [4, 5], "x": 4, "y": 4 },
+ { "label": "L45", "matrix": [4, 6], "x": 5, "y": 4 },
+ { "label": "L46", "matrix": [4, 7], "x": 6, "y": 4 },
+ { "label": "R46", "matrix": [9, 7], "x": 7, "y": 4 },
+ { "label": "R45", "matrix": [9, 6], "x": 8, "y": 4 },
+ { "label": "R44", "matrix": [9, 5], "x": 9, "y": 4 },
+ { "label": "R43", "matrix": [9, 4], "x": 10, "y": 4 },
+ { "label": "R42", "matrix": [9, 2], "x": 11, "y": 4 },
+ { "label": "R41", "matrix": [9, 1], "x": 12, "y": 4 },
+ { "label": "R40", "matrix": [9, 0], "x": 13, "y": 4 }
+ ]
+ },
+ "LAYOUT_right_ball": {
+ "layout": [
+ { "label": "L00", "matrix": [0, 0], "x": 0, "y": 0 },
+ { "label": "L01", "matrix": [0, 1], "x": 1, "y": 0 },
+ { "label": "L02", "matrix": [0, 2], "x": 2, "y": 0 },
+ { "label": "L03", "matrix": [0, 4], "x": 3, "y": 0 },
+ { "label": "L04", "matrix": [0, 5], "x": 4, "y": 0 },
+ { "label": "L05", "matrix": [0, 6], "x": 5, "y": 0 },
+ { "label": "R05", "matrix": [5, 6], "x": 6, "y": 0 },
+ { "label": "R04", "matrix": [5, 5], "x": 7, "y": 0 },
+ { "label": "R03", "matrix": [5, 4], "x": 8, "y": 0 },
+ { "label": "R02", "matrix": [5, 2], "x": 9, "y": 0 },
+ { "label": "R01", "matrix": [5, 1], "x": 10, "y": 0 },
+ { "label": "R00", "matrix": [5, 0], "x": 11, "y": 0 },
+ { "label": "L10", "matrix": [1, 0], "x": 12, "y": 0 },
+ { "label": "L11", "matrix": [1, 1], "x": 13, "y": 0 },
+ { "label": "L12", "matrix": [1, 2], "x": 14, "y": 0 },
+ { "label": "L13", "matrix": [1, 4], "x": 15, "y": 0 },
+ { "label": "L14", "matrix": [1, 5], "x": 16, "y": 0 },
+ { "label": "L15", "matrix": [1, 6], "x": 17, "y": 0 },
+ { "label": "R15", "matrix": [6, 6], "x": 18, "y": 0 },
+ { "label": "R14", "matrix": [6, 5], "x": 19, "y": 0 },
+ { "label": "R13", "matrix": [6, 4], "x": 20, "y": 0 },
+ { "label": "R12", "matrix": [6, 2], "x": 21, "y": 0 },
+ { "label": "R11", "matrix": [6, 1], "x": 22, "y": 0 },
+ { "label": "R10", "matrix": [6, 0], "x": 23, "y": 0 },
+ { "label": "L20", "matrix": [2, 0], "x": 24, "y": 0 },
+ { "label": "L21", "matrix": [2, 1], "x": 25, "y": 0 },
+ { "label": "L22", "matrix": [2, 2], "x": 26, "y": 0 },
+ { "label": "L23", "matrix": [2, 4], "x": 27, "y": 0 },
+ { "label": "L24", "matrix": [2, 5], "x": 28, "y": 0 },
+ { "label": "L25", "matrix": [2, 6], "x": 29, "y": 0 },
+ { "label": "R25", "matrix": [7, 6], "x": 30, "y": 0 },
+ { "label": "R24", "matrix": [7, 5], "x": 31, "y": 0 },
+ { "label": "R23", "matrix": [7, 4], "x": 32, "y": 0 },
+ { "label": "R22", "matrix": [7, 2], "x": 33, "y": 0 },
+ { "label": "R21", "matrix": [7, 1], "x": 34, "y": 0 },
+ { "label": "R20", "matrix": [7, 0], "x": 35, "y": 0 },
+ { "label": "L30", "matrix": [3, 0], "x": 36, "y": 0 },
+ { "label": "L31", "matrix": [3, 1], "x": 37, "y": 0 },
+ { "label": "L32", "matrix": [3, 2], "x": 38, "y": 0 },
+ { "label": "L33", "matrix": [3, 4], "x": 39, "y": 0 },
+ { "label": "L34", "matrix": [3, 5], "x": 40, "y": 0 },
+ { "label": "L35", "matrix": [3, 6], "x": 41, "y": 0 },
+ { "label": "L36", "matrix": [3, 7], "x": 42, "y": 0 },
+ { "label": "R36", "matrix": [8, 7], "x": 43, "y": 0 },
+ { "label": "R35", "matrix": [8, 6], "x": 44, "y": 0 },
+ { "label": "R34", "matrix": [8, 5], "x": 45, "y": 0 },
+ { "label": "R33", "matrix": [8, 4], "x": 46, "y": 0 },
+ { "label": "R32", "matrix": [8, 2], "x": 47, "y": 0 },
+ { "label": "R31", "matrix": [8, 1], "x": 48, "y": 0 },
+ { "label": "R30", "matrix": [8, 0], "x": 49, "y": 0 },
+ { "label": "L40", "matrix": [4, 0], "x": 50, "y": 0 },
+ { "label": "L41", "matrix": [4, 1], "x": 51, "y": 0 },
+ { "label": "L42", "matrix": [4, 2], "x": 52, "y": 0 },
+ { "label": "L43", "matrix": [4, 4], "x": 53, "y": 0 },
+ { "label": "L44", "matrix": [4, 5], "x": 54, "y": 0 },
+ { "label": "L45", "matrix": [4, 6], "x": 55, "y": 0 },
+ { "label": "L46", "matrix": [4, 7], "x": 56, "y": 0 },
+ { "label": "R46", "matrix": [9, 7], "x": 57, "y": 0 },
+ { "label": "R45", "matrix": [9, 6], "x": 58, "y": 0 },
+ { "label": "R41", "matrix": [9, 1], "x": 59, "y": 0 },
+ { "label": "R40", "matrix": [9, 0], "x": 60, "y": 0 }
+ ]
+ }
+ }
+}
diff --git a/keyboards/keyball/keyball61/keymaps/default/keymap.c b/keyboards/keyball/keyball61/keymaps/default/keymap.c
new file mode 100644
index 0000000000..768b3cc5cf
--- /dev/null
+++ b/keyboards/keyball/keyball61/keymaps/default/keymap.c
@@ -0,0 +1,13 @@
+#include QMK_KEYBOARD_H
+
+// clang-format off
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [0] = LAYOUT_universal(
+ KC_ESC , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_MINS ,
+ KC_DEL , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P , KC_INT3 ,
+ KC_TAB , KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L , KC_SCLN , S(KC_7) ,
+ MO(1) , KC_Z , KC_X , KC_C , KC_V , KC_B , KC_RBRC , KC_NUHS, KC_N , KC_M , KC_COMM , KC_DOT , KC_SLSH , KC_RSFT ,
+ _______ , KC_LCTL , KC_LALT , KC_LGUI,LT(1,KC_LNG2),LT(2,KC_SPC),LT(3,KC_LNG1), KC_BSPC,LT(2,KC_ENT),LT(1,KC_LNG2),KC_RGUI, _______ , KC_RALT , KC_PSCR
+ )
+};
+// clang-format on
diff --git a/keyboards/keyball/keyball61/matrix.c b/keyboards/keyball/keyball61/matrix.c
new file mode 100644
index 0000000000..1f8fb45819
--- /dev/null
+++ b/keyboards/keyball/keyball61/matrix.c
@@ -0,0 +1,77 @@
+#include "quantum.h"
+#include "matrix.h"
+#include "debounce.h"
+
+#define PINNUM_ROW (MATRIX_ROWS / 2)
+#define ROWS_PER_HAND (MATRIX_ROWS / 2)
+#define PINNUM_COL (MATRIX_COLS / 2)
+
+#define MATRIXSIZE_PER_HAND (ROWS_PER_HAND * sizeof(matrix_row_t))
+
+static pin_t row_pins[PINNUM_ROW] = MATRIX_ROW_PINS;
+static pin_t col_pins[PINNUM_COL] = MATRIX_COL_PINS;
+
+static void set_pins_input(pin_t* pins, uint8_t n) {
+ for (uint8_t i = 0; i < n; i++) {
+ gpio_set_pin_input_high(pins[i]);
+ }
+}
+
+static inline void set_pin_output(pin_t pin) {
+ gpio_set_pin_output(pin);
+ gpio_write_pin_low(pin);
+}
+
+static inline bool get_pin(pin_t pin) {
+ return gpio_read_pin(pin);
+}
+
+void duplex_scan_raw_post_kb(matrix_row_t out_matrix[]) {}
+
+static void duplex_scan_raw(matrix_row_t out_matrix[]) {
+ for (uint8_t row = 0; row < PINNUM_ROW; row++) {
+ set_pin_output(row_pins[row]);
+ matrix_output_select_delay();
+ for (uint8_t col = 0; col < PINNUM_COL; col++) {
+ if (!get_pin(col_pins[col])) {
+ out_matrix[row] |= 1 << col;
+ }
+ }
+ gpio_set_pin_input_high(row_pins[row]);
+ matrix_output_unselect_delay(row, false);
+ }
+
+ for (uint8_t col = 0; col < PINNUM_COL; col++) {
+ set_pin_output(col_pins[col]);
+ matrix_output_select_delay();
+ matrix_row_t shifter = ((matrix_row_t)1) << (col + PINNUM_COL);
+ for (uint8_t row = 0; row < PINNUM_ROW; row++) {
+ if (!get_pin(row_pins[row])) {
+ out_matrix[row] |= shifter;
+ }
+ }
+ gpio_set_pin_input_high(col_pins[col]);
+ matrix_output_unselect_delay(col, false);
+ }
+
+ duplex_scan_raw_post_kb(out_matrix);
+}
+
+bool matrix_scan_custom(matrix_row_t current_matrix[]) {
+ bool changed = false;
+ matrix_row_t tmp[MATRIX_ROWS] = {0};
+
+ duplex_scan_raw(tmp);
+ for (uint8_t row = 0; row < PINNUM_ROW; row++) {
+ if (tmp[row] != current_matrix[row]) {
+ changed = true;
+ current_matrix[row] = tmp[row];
+ }
+ }
+ return changed;
+}
+
+void matrix_init_custom(void) {
+ set_pins_input(col_pins, PINNUM_COL);
+ set_pins_input(row_pins, PINNUM_ROW);
+}
diff --git a/keyboards/keyball/keyball61/mcuconf.h b/keyboards/keyball/keyball61/mcuconf.h
new file mode 100644
index 0000000000..969514e4c4
--- /dev/null
+++ b/keyboards/keyball/keyball61/mcuconf.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include_next <mcuconf.h>
+
+#undef RP_SPI_USE_SPI0
+#define RP_SPI_USE_SPI0 TRUE
diff --git a/keyboards/keyball/keyball61/rules.mk b/keyboards/keyball/keyball61/rules.mk
new file mode 100644
index 0000000000..b9f5923ded
--- /dev/null
+++ b/keyboards/keyball/keyball61/rules.mk
@@ -0,0 +1,4 @@
+CUSTOM_MATRIX = lite
+SRC += matrix.c
+
+POINTING_DEVICE_DRIVER = pmw3360