aboutsummaryrefslogtreecommitdiff
path: root/keyboards
diff options
context:
space:
mode:
authorleah-splitkb <103112489+leah-splitkb@users.noreply.github.com>2025-03-02 22:33:03 +0100
committerGitHub <noreply@github.com>2025-03-02 14:33:03 -0700
commitcb6e1c1af54790e778062ba7203aa23370c263b0 (patch)
tree5fb1b3c42c293af6c03741f96e52a5e9370351fa /keyboards
parent563eb6fdc9224a772d19e2d5714e903fa7c021c6 (diff)
downloadqmk_firmware-master.tar.gz
qmk_firmware-master.zip
Add splitkb.com's Elora (#22557)master
* Add splitkb's Elora * WIP * Make requested changes * fix missing call to keyboard init user for elora * sync vial_qmk with qmk * Add fixes * Add encoder quadrature and update files * Update Readme * Implement changes * Remove encoder driver from keyboard.json * make requested changed * Implement changes and remove myriad_task as it wasn't actually doing anything. * Remove myriad.h from matrix.c * Simplify OLED code debug * Update RGB keycodes (qmk#24484) * remove rules.mk (qmk#23281) * Add matrix state sync --------- Co-authored-by: NapOli1084 <10320176+NapOli1084@users.noreply.github.com> Co-authored-by: harveysch <126267034+harvey-splitkb@users.noreply.github.com> Co-authored-by: harvey <harvey@splitkb.com> Co-authored-by: VeyPatch <126267034+VeyPatch@users.noreply.github.com>
Diffstat (limited to 'keyboards')
-rw-r--r--keyboards/splitkb/elora/info.json172
-rw-r--r--keyboards/splitkb/elora/keymaps/debug/config.h9
-rw-r--r--keyboards/splitkb/elora/keymaps/debug/keymap.c71
-rw-r--r--keyboards/splitkb/elora/keymaps/debug/readme.md22
-rw-r--r--keyboards/splitkb/elora/keymaps/debug/rules.mk2
-rw-r--r--keyboards/splitkb/elora/keymaps/default/config.h7
-rw-r--r--keyboards/splitkb/elora/keymaps/default/keymap.c320
-rw-r--r--keyboards/splitkb/elora/keymaps/default/readme.md50
-rw-r--r--keyboards/splitkb/elora/readme.md43
-rw-r--r--keyboards/splitkb/elora/rev1/config.h60
-rw-r--r--keyboards/splitkb/elora/rev1/halconf.h13
-rw-r--r--keyboards/splitkb/elora/rev1/keyboard.json108
-rw-r--r--keyboards/splitkb/elora/rev1/matrix.c57
-rw-r--r--keyboards/splitkb/elora/rev1/mcuconf.h18
-rw-r--r--keyboards/splitkb/elora/rev1/myriad.c315
-rw-r--r--keyboards/splitkb/elora/rev1/myriad.h52
-rw-r--r--keyboards/splitkb/elora/rev1/rev1.c214
-rw-r--r--keyboards/splitkb/elora/rev1/rev1.h14
-rw-r--r--keyboards/splitkb/elora/rev1/rules.mk7
19 files changed, 1554 insertions, 0 deletions
diff --git a/keyboards/splitkb/elora/info.json b/keyboards/splitkb/elora/info.json
new file mode 100644
index 0000000000..2ed11bfd19
--- /dev/null
+++ b/keyboards/splitkb/elora/info.json
@@ -0,0 +1,172 @@
+{
+ "manufacturer": "splitkb.com",
+ "keyboard_name": "Elora",
+ "maintainer": "splitkb",
+ "build": {
+ "lto": true
+ },
+ "split": {
+ "enabled": true
+ },
+ "url": "https://splitkb.com",
+ "usb": {
+ "device_version": "1.0.0",
+ "vid": "0x8D1D"
+ },
+ "layouts": {
+ "LAYOUT": {
+ "layout": [
+ {"label": "MX101", "matrix": [4, 1], "x": 0, "y": 0.75},
+ {"label": "MX105", "matrix": [4, 2], "x": 1, "y": 0.75},
+ {"label": "MX109", "matrix": [3, 1], "x": 2, "y": 0.25},
+ {"label": "MX113", "matrix": [3, 2], "x": 3, "y": 0},
+ {"label": "MX117", "matrix": [2, 1], "x": 4, "y": 0.25},
+ {"label": "MX121", "matrix": [2, 2], "x": 5, "y": 0.5},
+ {"label": "LPED1", "matrix": [0, 1], "x": 7, "y": 0},
+ {"label": "RPED1", "matrix": [6, 6], "x": 8.5, "y": 0},
+ {"label": "MX221", "matrix": [8, 5], "x": 10.5, "y": 0.5},
+ {"label": "MX217", "matrix": [8, 6], "x": 11.5, "y": 0.25},
+ {"label": "MX213", "matrix": [9, 5], "x": 12.5, "y": 0},
+ {"label": "MX209", "matrix": [9, 6], "x": 13.5, "y": 0.25},
+ {"label": "MX205", "matrix": [10, 5], "x": 14.5, "y": 0.75},
+ {"label": "MX201", "matrix": [10, 6], "x": 15.5, "y": 0.75},
+ {"label": "MX102", "matrix": [4, 0], "x": 0, "y": 1.75},
+ {"label": "MX106", "matrix": [4, 3], "x": 1, "y": 1.75},
+ {"label": "MX110", "matrix": [3, 0], "x": 2, "y": 1.25},
+ {"label": "MX114", "matrix": [3, 3], "x": 3, "y": 1},
+ {"label": "MX118", "matrix": [2, 0], "x": 4, "y": 1.25},
+ {"label": "MX122", "matrix": [2, 3], "x": 5, "y": 1.5},
+ {"label": "LPED2", "matrix": [0, 2], "x": 7, "y": 1},
+ {"label": "RPED2", "matrix": [6, 5], "x": 8.5, "y": 1},
+ {"label": "MX222", "matrix": [8, 4], "x": 10.5, "y": 1.5},
+ {"label": "MX218", "matrix": [8, 7], "x": 11.5, "y": 1.25},
+ {"label": "MX214", "matrix": [9, 4], "x": 12.5, "y": 1},
+ {"label": "MX210", "matrix": [9, 7], "x": 13.5, "y": 1.25},
+ {"label": "MX206", "matrix": [10, 4], "x": 14.5, "y": 1.75},
+ {"label": "MX202", "matrix": [10, 7], "x": 15.5, "y": 1.75},
+ {"label": "MX103", "matrix": [4, 7], "x": 0, "y": 2.75},
+ {"label": "MX107", "matrix": [4, 4], "x": 1, "y": 2.75},
+ {"label": "MX111", "matrix": [3, 7], "x": 2, "y": 2.25},
+ {"label": "MX115", "matrix": [3, 4], "x": 3, "y": 2},
+ {"label": "MX119", "matrix": [2, 7], "x": 4, "y": 2.25},
+ {"label": "MX123", "matrix": [2, 4], "x": 5, "y": 2.5},
+ {"label": "LPED3", "matrix": [0, 3], "x": 7, "y": 2},
+ {"label": "RPED3", "matrix": [6, 4], "x": 8.5, "y": 2},
+ {"label": "MX223", "matrix": [8, 3], "x": 10.5, "y": 2.5},
+ {"label": "MX219", "matrix": [8, 0], "x": 11.5, "y": 2.25},
+ {"label": "MX215", "matrix": [9, 3], "x": 12.5, "y": 2},
+ {"label": "MX211", "matrix": [9, 0], "x": 13.5, "y": 2.25},
+ {"label": "MX207", "matrix": [10, 3], "x": 14.5, "y": 2.75},
+ {"label": "MX203", "matrix": [10, 0], "x": 15.5, "y": 2.75},
+ {"label": "MX104", "matrix": [4, 6], "x": 0, "y": 3.75},
+ {"label": "MX108", "matrix": [4, 5], "x": 1, "y": 3.75},
+ {"label": "MX112", "matrix": [3, 6], "x": 2, "y": 3.25},
+ {"label": "MX116", "matrix": [3, 5], "x": 3, "y": 3},
+ {"label": "MX120", "matrix": [2, 6], "x": 4, "y": 3.25},
+ {"label": "MX124", "matrix": [2, 5], "x": 5, "y": 3.5},
+ {"label": "MX131", "matrix": [0, 0], "x": 6, "y": 4},
+ {"label": "MX130", "matrix": [0, 4], "x": 7, "y": 4.25},
+ {"label": "MX230", "matrix": [6, 3], "x": 8.5, "y": 4.25},
+ {"label": "MX231", "matrix": [6, 7], "x": 9.5, "y": 4},
+ {"label": "MX224", "matrix": [8, 2], "x": 10.5, "y": 3.5},
+ {"label": "MX220", "matrix": [8, 1], "x": 11.5, "y": 3.25},
+ {"label": "MX216", "matrix": [9, 2], "x": 12.5, "y": 3},
+ {"label": "MX212", "matrix": [9, 1], "x": 13.5, "y": 3.25},
+ {"label": "MX208", "matrix": [10, 2], "x": 14.5, "y": 3.75},
+ {"label": "MX204", "matrix": [10, 1], "x": 15.5, "y": 3.75},
+ {"label": "MX125", "matrix": [1, 7], "x": 2.5, "y": 4.25},
+ {"label": "MX126", "matrix": [1, 6], "x": 3.5, "y": 4.25},
+ {"label": "MX127", "matrix": [1, 5], "x": 4.5, "y": 4.5},
+ {"label": "MX128", "matrix": [1, 4], "x": 5.5, "y": 5},
+ {"label": "MX129", "matrix": [0, 5], "x": 6.5, "y": 5.25},
+ {"label": "MX229", "matrix": [6, 2], "x": 9, "y": 5.25},
+ {"label": "MX228", "matrix": [7, 3], "x": 10, "y": 5},
+ {"label": "MX227", "matrix": [7, 2], "x": 11, "y": 4.5},
+ {"label": "MX226", "matrix": [7, 1], "x": 12, "y": 4.25},
+ {"label": "MX225", "matrix": [7, 0], "x": 13, "y": 4.25}
+ ]
+ },
+ "LAYOUT_myr": {
+ "layout": [
+ {"label": "MX101", "matrix": [4, 1], "x": 0, "y": 0.75},
+ {"label": "MX105", "matrix": [4, 2], "x": 1, "y": 0.75},
+ {"label": "MX109", "matrix": [3, 1], "x": 2, "y": 0.25},
+ {"label": "MX113", "matrix": [3, 2], "x": 3, "y": 0},
+ {"label": "MX117", "matrix": [2, 1], "x": 4, "y": 0.25},
+ {"label": "MX121", "matrix": [2, 2], "x": 5, "y": 0.5},
+ {"label": "LPED1", "matrix": [0, 1], "x": 7, "y": 0},
+ {"label": "RPED1", "matrix": [6, 6], "x": 8.5, "y": 0},
+ {"label": "MX221", "matrix": [8, 5], "x": 10.5, "y": 0.5},
+ {"label": "MX217", "matrix": [8, 6], "x": 11.5, "y": 0.25},
+ {"label": "MX213", "matrix": [9, 5], "x": 12.5, "y": 0},
+ {"label": "MX209", "matrix": [9, 6], "x": 13.5, "y": 0.25},
+ {"label": "MX205", "matrix": [10, 5], "x": 14.5, "y": 0.75},
+ {"label": "MX201", "matrix": [10, 6], "x": 15.5, "y": 0.75},
+ {"label": "MX102", "matrix": [4, 0], "x": 0, "y": 1.75},
+ {"label": "MX106", "matrix": [4, 3], "x": 1, "y": 1.75},
+ {"label": "MX110", "matrix": [3, 0], "x": 2, "y": 1.25},
+ {"label": "MX114", "matrix": [3, 3], "x": 3, "y": 1},
+ {"label": "MX118", "matrix": [2, 0], "x": 4, "y": 1.25},
+ {"label": "MX122", "matrix": [2, 3], "x": 5, "y": 1.5},
+ {"label": "LPED2", "matrix": [0, 2], "x": 7, "y": 1},
+ {"label": "RPED2", "matrix": [6, 5], "x": 8.5, "y": 1},
+ {"label": "MX222", "matrix": [8, 4], "x": 10.5, "y": 1.5},
+ {"label": "MX218", "matrix": [8, 7], "x": 11.5, "y": 1.25},
+ {"label": "MX214", "matrix": [9, 4], "x": 12.5, "y": 1},
+ {"label": "MX210", "matrix": [9, 7], "x": 13.5, "y": 1.25},
+ {"label": "MX206", "matrix": [10, 4], "x": 14.5, "y": 1.75},
+ {"label": "MX202", "matrix": [10, 7], "x": 15.5, "y": 1.75},
+ {"label": "MX103", "matrix": [4, 7], "x": 0, "y": 2.75},
+ {"label": "MX107", "matrix": [4, 4], "x": 1, "y": 2.75},
+ {"label": "MX111", "matrix": [3, 7], "x": 2, "y": 2.25},
+ {"label": "MX115", "matrix": [3, 4], "x": 3, "y": 2},
+ {"label": "MX119", "matrix": [2, 7], "x": 4, "y": 2.25},
+ {"label": "MX123", "matrix": [2, 4], "x": 5, "y": 2.5},
+ {"label": "LPED3", "matrix": [0, 3], "x": 7, "y": 2},
+ {"label": "RPED3", "matrix": [6, 4], "x": 8.5, "y": 2},
+ {"label": "MX223", "matrix": [8, 3], "x": 10.5, "y": 2.5},
+ {"label": "MX219", "matrix": [8, 0], "x": 11.5, "y": 2.25},
+ {"label": "MX215", "matrix": [9, 3], "x": 12.5, "y": 2},
+ {"label": "MX211", "matrix": [9, 0], "x": 13.5, "y": 2.25},
+ {"label": "MX207", "matrix": [10, 3], "x": 14.5, "y": 2.75},
+ {"label": "MX203", "matrix": [10, 0], "x": 15.5, "y": 2.75},
+ {"label": "MX104", "matrix": [4, 6], "x": 0, "y": 3.75},
+ {"label": "MX108", "matrix": [4, 5], "x": 1, "y": 3.75},
+ {"label": "MX112", "matrix": [3, 6], "x": 2, "y": 3.25},
+ {"label": "MX116", "matrix": [3, 5], "x": 3, "y": 3},
+ {"label": "MX120", "matrix": [2, 6], "x": 4, "y": 3.25},
+ {"label": "MX124", "matrix": [2, 5], "x": 5, "y": 3.5},
+ {"label": "MX131", "matrix": [0, 0], "x": 6, "y": 4},
+ {"label": "MX130", "matrix": [0, 4], "x": 7, "y": 4.25},
+ {"label": "MX230", "matrix": [6, 3], "x": 8.5, "y": 4.25},
+ {"label": "MX231", "matrix": [6, 7], "x": 9.5, "y": 4},
+ {"label": "MX224", "matrix": [8, 2], "x": 10.5, "y": 3.5},
+ {"label": "MX220", "matrix": [8, 1], "x": 11.5, "y": 3.25},
+ {"label": "MX216", "matrix": [9, 2], "x": 12.5, "y": 3},
+ {"label": "MX212", "matrix": [9, 1], "x": 13.5, "y": 3.25},
+ {"label": "MX208", "matrix": [10, 2], "x": 14.5, "y": 3.75},
+ {"label": "MX204", "matrix": [10, 1], "x": 15.5, "y": 3.75},
+ {"label": "MX125", "matrix": [1, 7], "x": 2.5, "y": 4.25},
+ {"label": "MX126", "matrix": [1, 6], "x": 3.5, "y": 4.25},
+ {"label": "MX127", "matrix": [1, 5], "x": 4.5, "y": 4.5},
+ {"label": "MX128", "matrix": [1, 4], "x": 5.5, "y": 5},
+ {"label": "MX129", "matrix": [0, 5], "x": 6.5, "y": 5.25},
+ {"label": "MX229", "matrix": [6, 2], "x": 9, "y": 5.25},
+ {"label": "MX228", "matrix": [7, 3], "x": 10, "y": 5},
+ {"label": "MX227", "matrix": [7, 2], "x": 11, "y": 4.5},
+ {"label": "MX226", "matrix": [7, 1], "x": 12, "y": 4.25},
+ {"label": "MX225", "matrix": [7, 0], "x": 13, "y": 4.25},
+ {"label": "MYRL1", "matrix": [5, 0], "x": 0, "y": 6},
+ {"label": "MYRL2", "matrix": [5, 1], "x": 1, "y": 6},
+ {"label": "MYRL3", "matrix": [5, 2], "x": 2, "y": 6},
+ {"label": "MYRL4", "matrix": [5, 3], "x": 3, "y": 6},
+ {"label": "MYRL5", "matrix": [5, 4], "x": 5, "y": 6},
+ {"label": "MYRR1", "matrix": [11, 0], "x": 8, "y": 6},
+ {"label": "MYRR2", "matrix": [11, 1], "x": 9, "y": 6},
+ {"label": "MYRR3", "matrix": [11, 2], "x": 10, "y": 6},
+ {"label": "MYRR4", "matrix": [11, 3], "x": 11, "y": 6},
+ {"label": "MYRR5", "matrix": [11, 4], "x": 13, "y": 6}
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/keyboards/splitkb/elora/keymaps/debug/config.h b/keyboards/splitkb/elora/keymaps/debug/config.h
new file mode 100644
index 0000000000..0024fe4dfe
--- /dev/null
+++ b/keyboards/splitkb/elora/keymaps/debug/config.h
@@ -0,0 +1,9 @@
+// Copyright 2024 splitkb.com (support@splitkb.com)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+// Myriad boilerplate
+#define MYRIAD_ENABLE
+
+#define RGBLIGHT_EFFECT_BREATHING \ No newline at end of file
diff --git a/keyboards/splitkb/elora/keymaps/debug/keymap.c b/keyboards/splitkb/elora/keymaps/debug/keymap.c
new file mode 100644
index 0000000000..a8a5973b00
--- /dev/null
+++ b/keyboards/splitkb/elora/keymaps/debug/keymap.c
@@ -0,0 +1,71 @@
+// Copyright 2024 splitkb.com (support@splitkb.com)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include QMK_KEYBOARD_H
+
+enum layers {
+ _DEFAULT = 0,
+};
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [_DEFAULT] = LAYOUT_myr(
+ KC_A, KC_E, KC_I, KC_M, KC_Q, KC_U, KC_9, KC_9, S(KC_U), S(KC_Q), S(KC_M), S(KC_I), S(KC_E), S(KC_A),
+ KC_B, KC_F, KC_J, KC_N, KC_R, KC_V, KC_8, KC_8, S(KC_V), S(KC_R), S(KC_N), S(KC_J), S(KC_F), S(KC_B),
+ KC_C, KC_G, KC_K, KC_O, KC_S, KC_W, KC_7, KC_7, S(KC_W), S(KC_S), S(KC_O), S(KC_K), S(KC_G), S(KC_C),
+ KC_D, KC_H, KC_L, KC_P, KC_T, KC_X, KC_5, KC_6, KC_6, KC_5, S(KC_X), S(KC_T), S(KC_P), S(KC_L), S(KC_H), S(KC_D),
+ KC_0, KC_1, KC_2, KC_3, KC_4, KC_4, KC_3, KC_2, KC_1, KC_0,
+
+ KC_A, KC_B, KC_C, KC_D, KC_E, KC_A, KC_B, KC_C, KC_D, KC_E
+ ),
+};
+
+void keyboard_post_init_user(void) {
+ #ifdef RGBLIGHT_ENABLE
+ rgblight_enable_noeeprom(); // enables RGB, without saving settings
+ rgblight_sethsv_noeeprom(HSV_RED); // sets the color to red without saving
+ rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING + 3); // sets mode to Fast breathing without saving
+ #endif
+}
+
+#ifdef ENCODER_ENABLE
+bool encoder_update_user(uint8_t index, bool clockwise) {
+ // 0-3 left-half encoders
+ // 4-7 are right-half encoders
+ if (index == 0) {
+ tap_code(KC_0);
+ } else if (index == 1) {
+ tap_code(KC_1);
+ } else if (index == 2) {
+ tap_code(KC_2);
+ } else if (index == 3) {
+ // Myriad
+ tap_code(KC_3);
+ } else if (index == 4) {
+ tap_code(KC_4);
+ } else if (index == 5) {
+ tap_code(KC_5);
+ } else if (index == 6) {
+ tap_code(KC_6);
+ } else if (index == 7) {
+ // Myriad
+ tap_code(KC_7);
+ }
+
+ if (clockwise) {
+ tap_code16(KC_PLUS);
+ } else {
+ tap_code(KC_MINUS);
+ }
+
+ return false;
+}
+#endif
+
+#ifdef OLED_ENABLE
+bool oled_task_user(void) {
+ // A 128x32 OLED rotated 90 degrees is 5 characters wide and 16 characters tall
+ // This example string should fill that neatly
+ oled_write_P(PSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789!@#$%^&*()[]{}-=_+?"), is_keyboard_master());
+ return false;
+}
+#endif
diff --git a/keyboards/splitkb/elora/keymaps/debug/readme.md b/keyboards/splitkb/elora/keymaps/debug/readme.md
new file mode 100644
index 0000000000..ec5705070c
--- /dev/null
+++ b/keyboards/splitkb/elora/keymaps/debug/readme.md
@@ -0,0 +1,22 @@
+# Elora's Debug Keymap
+
+To make debugging your build as easy as possible, we have provided a special debugging keymap. It is not intended to actually type on, it is just here to make sure that your hardware is working correctly.
+
+## Keys
+
+The left side uses lowercase letters, the right side uses uppercase ones.
+
+## Encoders
+
+Encoders output a number, depending on the installed position.
+These correspond to the index used for custom encoder code.
+
+The number is followed by either a `+` or a `-`, depending on the direction turned.
+
+## LEDs
+
+Underglow RGB should be fading between red and off.
+
+## OLEDs
+
+Both the primary and secondary side should be filled with characters.
diff --git a/keyboards/splitkb/elora/keymaps/debug/rules.mk b/keyboards/splitkb/elora/keymaps/debug/rules.mk
new file mode 100644
index 0000000000..6c52b64847
--- /dev/null
+++ b/keyboards/splitkb/elora/keymaps/debug/rules.mk
@@ -0,0 +1,2 @@
+RGB_MATRIX_ENABLE = no
+RGBLIGHT_ENABLE = yes \ No newline at end of file
diff --git a/keyboards/splitkb/elora/keymaps/default/config.h b/keyboards/splitkb/elora/keymaps/default/config.h
new file mode 100644
index 0000000000..e35c193957
--- /dev/null
+++ b/keyboards/splitkb/elora/keymaps/default/config.h
@@ -0,0 +1,7 @@
+// Copyright 2024 splitkb.com (support@splitkb.com)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+// Myriad boilerplate
+#define MYRIAD_ENABLE \ No newline at end of file
diff --git a/keyboards/splitkb/elora/keymaps/default/keymap.c b/keyboards/splitkb/elora/keymaps/default/keymap.c
new file mode 100644
index 0000000000..84f53561fd
--- /dev/null
+++ b/keyboards/splitkb/elora/keymaps/default/keymap.c
@@ -0,0 +1,320 @@
+// Copyright 2024 splitkb.com (support@splitkb.com)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include QMK_KEYBOARD_H
+
+enum layers {
+ _QWERTY = 0,
+ _DVORAK,
+ _COLEMAK_DH,
+ _NAV,
+ _SYM,
+ _FUNCTION,
+ _ADJUST,
+};
+
+// Aliases for readability
+#define QWERTY DF(_QWERTY)
+#define COLEMAK DF(_COLEMAK_DH)
+#define DVORAK DF(_DVORAK)
+
+#define SYM MO(_SYM)
+#define NAV MO(_NAV)
+#define FKEYS MO(_FUNCTION)
+#define ADJUST MO(_ADJUST)
+
+#define CTL_ESC MT(MOD_LCTL, KC_ESC)
+#define CTL_QUOT MT(MOD_RCTL, KC_QUOTE)
+#define CTL_MINS MT(MOD_RCTL, KC_MINUS)
+#define ALT_ENT MT(MOD_LALT, KC_ENT)
+
+// Note: LAlt/Enter (ALT_ENT) is not the same thing as the keyboard shortcut Alt+Enter.
+// The notation `mod/tap` denotes a key that activates the modifier `mod` when held down, and
+// produces the key `tap` when tapped (i.e. pressed and released).
+
+// clang-format off
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/*
+ * Base Layer: QWERTY
+ *
+ * ,-------------------------------------------. ,------. ,------. ,-------------------------------------------.
+ * | Esc | 1 | 2 | 3 | 4 | 5 | |LShift| |RShift| | 6 | 7 | 8 | 9 | 0 | Esc |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | |LCtrl | | RCtrl| | Y | U | I | O | P | Bksp |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * |Ctrl/Esc| A | S | D | F | G | | LAlt | | RAlt | | H | J | K | L | ; : |Ctrl/' "|
+ * |--------+------+------+------+------+------+------+------| |------|------+------+------+------+------+------+--------|
+ * | LShift | Z | X | C | V | B | [ { |CapsLk| |F-keys| ] } | N | M | , < | . > | / ? | RShift |
+ * `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
+ * |Adjust| LGUI | LAlt/| Space| Nav | | Sym | Space| AltGr| RGUI | Menu |
+ * | | | Enter| | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ *
+ * ,----------------------------. ,------. ,----------------------------. ,------.
+ * | Prev | Next | Pause | Stop | | Mute | | Prev | Next | Pause | Stop | | Mute |
+ * `----------------------------' `------' `----------------------------' '------'
+ */
+ [_QWERTY] = LAYOUT_myr(
+ KC_ESC , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_LSFT, KC_RSFT, KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_ESC,
+ KC_TAB , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_LCTL, KC_RCTL, KC_Y , KC_U , KC_I , KC_O , KC_P , KC_BSPC,
+ CTL_ESC , KC_A , KC_S , KC_D , KC_F , KC_G , KC_LALT, KC_RALT, KC_H , KC_J , KC_K , KC_L ,KC_SCLN,CTL_QUOT,
+ KC_LSFT , KC_Z , KC_X , KC_C , KC_V , KC_B , KC_LBRC,KC_CAPS, FKEYS , KC_RBRC, KC_N , KC_M ,KC_COMM, KC_DOT ,KC_SLSH, KC_RSFT,
+ ADJUST , KC_LGUI, ALT_ENT, KC_SPC , NAV , SYM , KC_SPC ,KC_RALT, KC_RGUI, KC_APP,
+
+ KC_MPRV, KC_MNXT, KC_MPLY, KC_MSTP, KC_MUTE, KC_MPRV, KC_MNXT, KC_MPLY, KC_MSTP, KC_MUTE
+ ),
+
+/*
+ * Base Layer: Dvorak
+ *
+ * ,-------------------------------------------. ,------. ,------. ,-------------------------------------------.
+ * | Esc | 1 | 2 | 3 | 4 | 5 | |LShift| |RShift| | 6 | 7 | 8 | 9 | 0 | Esc |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * | Tab | ' " | , < | . > | P | Y | |LCtrl | | RCtrl| | F | G | C | R | L | Bksp |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * |Ctrl/Esc| A | O | E | U | I | | LAlt | | RAlt | | D | H | T | N | S |Ctrl/- _|
+ * |--------+------+------+------+------+------+------+------| |------|------+------+------+------+------+------+--------|
+ * | LShift | ; : | Q | J | K | X | [ { |CapsLk| |F-keys| ] } | B | M | W | V | Z | RShift |
+ * `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
+ * |Adjust| LGUI | LAlt/| Space| Nav | | Sym | Space| AltGr| RGUI | Menu |
+ * | | | Enter| | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ *
+ * ,----------------------------. ,------. ,----------------------------. ,------.
+ * | Prev | Next | Pause | Stop | | Mute | | Prev | Next | Pause | Stop | | Mute |
+ * `----------------------------' `------' `----------------------------' '------'
+ */
+ [_DVORAK] = LAYOUT_myr(
+ KC_ESC , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_LSFT, KC_RSFT, KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_ESC,
+ KC_TAB ,KC_QUOTE,KC_COMM, KC_DOT, KC_P , KC_Y , KC_LCTL, KC_RCTL, KC_F, KC_G , KC_C , KC_R , KC_L , KC_BSPC,
+ CTL_ESC , KC_A , KC_O , KC_E , KC_U , KC_I , KC_LALT, KC_RALT, KC_D, KC_H , KC_T , KC_N , KC_S , CTL_MINS,
+ KC_LSFT ,KC_SCLN, KC_Q , KC_J , KC_K , KC_X , KC_LBRC,KC_CAPS, FKEYS , KC_RBRC, KC_B, KC_M , KC_W , KC_V , KC_Z , KC_RSFT,
+ ADJUST, KC_LGUI, ALT_ENT, KC_SPC , NAV , SYM , KC_SPC ,KC_RALT, KC_RGUI, KC_APP,
+
+ KC_MPRV, KC_MNXT, KC_MPLY, KC_MSTP, KC_MUTE, KC_MPRV, KC_MNXT, KC_MPLY, KC_MSTP, KC_MUTE
+ ),
+
+/*
+ * Base Layer: Colemak DH
+ *
+ * ,-------------------------------------------. ,------. ,------. ,-------------------------------------------.
+ * | Esc | 1 | 2 | 3 | 4 | 5 | |LShift| |RShift| | 6 | 7 | 8 | 9 | 0 | Esc |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * | Tab | Q | W | F | P | B | |LCtrl | | RCtrl| | J | L | U | Y | ; : | Bksp |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * |Ctrl/Esc| A | R | S | T | G | | LAlt | | RAlt | | M | N | E | I | O |Ctrl/' "|
+ * |--------+------+------+------+------+------+------+------| |------|------+------+------+------+------+------+--------|
+ * | LShift | Z | X | C | D | V | [ { |CapsLk| |F-keys| ] } | K | H | , < | . > | / ? | RShift |
+ * `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
+ * |Adjust| LGUI | LAlt/| Space| Nav | | Sym | Space| AltGr| RGUI | Menu |
+ * | | | Enter| | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ *
+ * ,----------------------------. ,------. ,----------------------------. ,------.
+ * | Prev | Next | Pause | Stop | | Mute | | Prev | Next | Pause | Stop | | Mute |
+ * `----------------------------' `------' `----------------------------' '------'
+ */
+ [_COLEMAK_DH] = LAYOUT_myr(
+ KC_ESC , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_LSFT, KC_RSFT, KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_ESC,
+ KC_TAB , KC_Q , KC_W , KC_F , KC_P , KC_B , KC_LCTL, KC_RCTL, KC_J, KC_L , KC_U , KC_Y ,KC_SCLN, KC_BSPC,
+ CTL_ESC , KC_A , KC_R , KC_S , KC_T , KC_G , KC_LALT, KC_RALT, KC_M, KC_N , KC_E , KC_I , KC_O , CTL_QUOT,
+ KC_LSFT , KC_Z , KC_X , KC_C , KC_D , KC_V , KC_LBRC,KC_CAPS, FKEYS , KC_RBRC, KC_K, KC_H ,KC_COMM, KC_DOT ,KC_SLSH, KC_RSFT,
+ ADJUST, KC_LGUI, ALT_ENT, KC_SPC , NAV , SYM , KC_SPC ,KC_RALT, KC_RGUI, KC_APP,
+
+ KC_MPRV, KC_MNXT, KC_MPLY, KC_MSTP, KC_MUTE, KC_MPRV, KC_MNXT, KC_MPLY, KC_MSTP, KC_MUTE
+ ),
+
+/*
+ * Nav Layer: Media, navigation
+ *
+ * ,-------------------------------------------. ,------. ,------. ,-------------------------------------------.
+ * | | | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | PgUp | Home | ↑ | End | VolUp| Delete |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * | | GUI | Alt | Ctrl | Shift| | | | | | | PgDn | ← | ↓ | → | VolDn| Insert |
+ * |--------+------+------+------+------+------+------+------| |------|------+------+------+------+------+------+--------|
+ * | | | | | | | |ScLck | | | | Pause|M Prev|M Play|M Next|VolMut| PrtSc |
+ * `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
+ * | | | | | | | | | | | |
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ *
+ * ,----------------------------. ,------. ,----------------------------. ,------.
+ * | Prev | Next | Pause | Stop | | Mute | | Prev | Next | Pause | Stop | | Mute |
+ * `----------------------------' `------' `----------------------------' '------'
+ */
+ [_NAV] = LAYOUT_myr(
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, KC_PGUP, KC_HOME, KC_UP, KC_END, KC_VOLU, KC_DEL,
+ _______, KC_LGUI, KC_LALT, KC_LCTL, KC_LSFT, _______, _______, _______, KC_PGDN, KC_LEFT, KC_DOWN, KC_RGHT, KC_VOLD, KC_INS,
+ _______, _______, _______, _______, _______, _______, _______, KC_SCRL, _______, _______,KC_PAUSE, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_PSCR,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
+ ),
+
+/*
+ * Sym Layer: Numbers and symbols
+ *
+ * ,-------------------------------------------. ,------. ,------. ,-------------------------------------------.
+ * | | | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * | ` | 1 | 2 | 3 | 4 | 5 | | | | | | 6 | 7 | 8 | 9 | 0 | = |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * | ~ | ! | @ | # | $ | % | | | | | | ^ | & | * | ( | ) | + |
+ * |--------+------+------+------+------+------+------+------| |------|------+------+------+------+------+------+--------|
+ * | | | \ | : | ; | - | [ | { | | | | } | ] | _ | , | . | / | ? |
+ * `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
+ * | | | | | | | | | | | |
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ *
+ * ,-----------------------------. ,------. ,---------------------------. ,------.
+ * | | | | | | | | | | | | | |
+ * `-----------------------------' `------' `---------------------------' '------'
+ */
+ [_SYM] = LAYOUT_myr(
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ KC_GRV , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , _______, _______, KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_EQL ,
+ KC_TILD , KC_EXLM, KC_AT , KC_HASH, KC_DLR, KC_PERC, _______, _______, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_PLUS,
+ KC_PIPE , KC_BSLS, KC_COLN, KC_SCLN, KC_MINS, KC_LBRC, KC_LCBR, _______, _______, KC_RCBR, KC_RBRC, KC_UNDS, KC_COMM, KC_DOT, KC_SLSH, KC_QUES,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
+ ),
+
+/*
+ * Function Layer: Function keys
+ *
+ * ,-------------------------------------------. ,------. ,------. ,-------------------------------------------.
+ * | | | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * | | F9 | F10 | F11 | F12 | | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * | | F5 | F6 | F7 | F8 | | | | | | | | Shift| Ctrl | Alt | GUI | |
+ * |--------+------+------+------+------+------+------+------| |------|------+------+------+------+------+------+--------|
+ * | | F1 | F2 | F3 | F4 | | | | | | | | | | | | |
+ * `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
+ * | | | | | | | | | | | |
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ *
+ * ,-----------------------------. ,------. ,---------------------------. ,------.
+ * | | | | | | | | | | | | | |
+ * `-----------------------------' `------' `---------------------------' '------'
+ */
+ [_FUNCTION] = LAYOUT_myr(
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, KC_F9 , KC_F10, KC_F11, KC_F12, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, KC_F5 , KC_F6 , KC_F7 , KC_F8 , _______, _______, _______, _______, KC_RSFT, KC_RCTL, KC_LALT, KC_RGUI, _______,
+ _______, KC_F1 , KC_F2 , KC_F3 , KC_F4 , _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
+ ),
+
+/*
+ * Adjust Layer: Default layer settings, RGB
+ *
+ * ,-------------------------------------------. ,------. ,------. ,-------------------------------------------.
+ * | | | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * | | | |QWERTY| | | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+ * | | | |Dvorak| | | | | | | | TOG | SAI | HUI | VAI | MOD | |
+ * |--------+------+------+------+------+------+------+------| |------|------+------+------+------+------+------+--------|
+ * | | | |Colmak| | | | | | | | | SAD | HUD | VAD | RMOD | |
+ * `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
+ * | | | | | | | | | | | |
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ *
+ * ,-----------------------------. ,------. ,---------------------------. ,------.
+ * | | | | | | | | | | | | | |
+ * `-----------------------------' `------' `---------------------------' '------'
+ */
+ [_ADJUST] = LAYOUT_myr(
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, _______, _______, QWERTY , _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, _______, _______, DVORAK , _______, _______, _______, _______, RM_TOGG, RM_SATU, RM_HUEU, RM_VALU, RM_NEXT, _______,
+ _______, _______, _______, COLEMAK, _______, _______,_______, _______, _______, _______, _______, RM_SATD, RM_HUED, RM_VALD, RM_PREV, _______,
+ _______, _______, _______,_______, _______, _______, _______, _______, _______, _______,
+
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
+
+ ),
+
+// /*
+// * Layer template - LAYOUT
+// *
+// * ,-------------------------------------------. ,------. ,------. ,-------------------------------------------.
+// * | | | | | | | | | | | | | | | | | |
+// * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+// * | | | | | | | | | | | | | | | | | |
+// * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+// * | | | | | | | | | | | | | | | | | |
+// * |--------+------+------+------+------+------+------+------| |------|------+------+------+------+------+------+--------|
+// * | | | | | | | | | | | | | | | | | |
+// * `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
+// * | | | | | | | | | | | |
+// * | | | | | | | | | | | |
+// * `----------------------------------' `----------------------------------'
+// */
+// [_LAYERINDEX] = LAYOUT(
+// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
+// ),
+
+// /*
+// * Layer template - LAYOUT_myr
+// *
+// * ,-------------------------------------------. ,------. ,------. ,-------------------------------------------.
+// * | | | | | | | | | | | | | | | | | |
+// * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+// * | | | | | | | | | | | | | | | | | |
+// * |--------+------+------+------+------+------| |------| |------| |------+------+------+------+------+--------|
+// * | | | | | | | | | | | | | | | | | |
+// * |--------+------+------+------+------+------+------+------| |------|------+------+------+------+------+------+--------|
+// * | | | | | | | | | | | | | | | | | |
+// * `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
+// * | | | | | | | | | | | |
+// * | | | | | | | | | | | |
+// * `----------------------------------' `----------------------------------'
+// *
+// * ,-----------------------------. ,------. ,---------------------------. ,------.
+// * | | | | | | | | | | | | | |
+// * `-----------------------------' `------' `---------------------------' '------'
+// */
+// [_LAYERINDEX] = LAYOUT_myr(
+// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+//
+// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
+// ),
+};
+
+/* The default OLED and rotary encoder code can be found at the bottom of qmk_firmware/keyboards/splitkb/elora/rev1/rev1.c
+ * These default settings can be overriden by your own settings in your keymap.c
+ * DO NOT edit the rev1.c file; instead override the weakly defined default functions by your own.
+ */
+
+/* DELETE THIS LINE TO UNCOMMENT (1/2)
+#ifdef OLED_ENABLE
+bool oled_task_user(void) {
+ // Your code goes here
+}
+#endif
+
+#ifdef ENCODER_ENABLE
+bool encoder_update_user(uint8_t index, bool clockwise) {
+ // Your code goes here
+}
+#endif
+DELETE THIS LINE TO UNCOMMENT (2/2) */
diff --git a/keyboards/splitkb/elora/keymaps/default/readme.md b/keyboards/splitkb/elora/keymaps/default/readme.md
new file mode 100644
index 0000000000..7e95db3938
--- /dev/null
+++ b/keyboards/splitkb/elora/keymaps/default/readme.md
@@ -0,0 +1,50 @@
+# Elora's Default Keymap
+The default keymap contains 5 layers which allows it to include all keys found on an ANSI layout TKL keyboard plus media keys.
+Hardware features of the Elora such as OLEDs, rotary encoders and underglow are also supported.
+
+The Elora keymap is in essence identical to the [Kyria keymap](https://github.com/qmk/qmk_firmware/blob/master/keyboards/splitkb/kyria/keymaps/default/readme.md), just with an additional number row. A deep dive into the keymap is provided there.
+
+The five different layers are the following:
+1. Base layer (QWERTY, Colemak-DH or Dvorak)
+2. Navigation layer
+3. Symbols/Numbers layer
+4. Function layer
+5. Adjust layer
+
+## Base layer(s)
+### Qwerty
+![Qwerty](https://i.imgur.com/SZB1Z5gh.jpg)
+
+### Dvorak
+![Dvorak](https://i.imgur.com/RWB5Qhnh.jpg)
+
+### Colemak-DH
+![Colemak](https://i.imgur.com/4DjdGsGh.jpg)
+
+## Navigation layer
+![Navigation](https://i.imgur.com/tDM1MZeh.jpg)
+
+## Symbols layer
+![Symbol](https://i.imgur.com/9LsxnLRh.jpg)
+
+## Function layer
+![Function](https://i.imgur.com/KMCqh7Ch.jpg)
+
+## Adjust layer
+![Adjust](https://i.imgur.com/6WtMo8ih.jpg)
+
+# Hardware Features
+
+## Rotary Encoder
+The left rotary encoders are programmed to send <kbd>Left</kbd> or <kbd>Right</kbd> whereas the right encoder sends <kbd>PgUp</kbd> or <kbd>PgDn</kbd> on every turn.
+
+## OLEDs
+The OLEDs display the current layer at the top of the active layers stack, the Elora logo and lock status (caps lock, num lock, scroll lock).
+
+## Underglow
+The underglow LEDs should default red.
+
+## Going further…
+This default keymap can be used as is, unchanged, as a daily driver for your Elora but you're invited to treat your keymap like a bonsai. At the beginning, it's just like the default keymap but from time to time, you can tweak it a little. Cut a little key here, let another combo grow there. Slowly but surely it will be a unique keymap that will fit you like a glove.
+
+Check out the #keymap-ideas channel on the official splitkb Discord server for inspiration. \ No newline at end of file
diff --git a/keyboards/splitkb/elora/readme.md b/keyboards/splitkb/elora/readme.md
new file mode 100644
index 0000000000..2935b7bd7d
--- /dev/null
+++ b/keyboards/splitkb/elora/readme.md
@@ -0,0 +1,43 @@
+![Elora](https://i.imgur.com/AUCjyBuh.jpg)
+
+# Elora
+The Elora is a 62-key keyboard, based on the Kyria by splitkb.com. It comes preassembled, is compatible with Vial so you don't need to program or compile your firmware, and accepts Myriad modules so you can add cool features with just a screwdriver.
+
+Keyboard Maintainer: [splitkb.com](https://github.com/splitkb)
+Hardware Availability: [splitkb.com](https://splitkb.com).
+
+Make example for this keyboard (after setting up your build environment):
+
+ make splitkb/elora/rev1:default
+
+The keyboard can be flashed by copying the resulting `splitkb_elora_rev1_default.uf2` file onto the `RPI-RP2` flash drive.
+
+See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
+
+## Bootloader
+You can enter the bootloader in 3 ways:
+
+* **Reset button**: Double-tap the reset button on the side of the PCB.
+* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available.
+* **Bootloader reset**: As a last resort, hold down the small "Boot" button near the USB connector while plugging in the keyboard.
+
+# Features
+The Elora is an evolved version of the Kyria that comes with a number row, and has an emphasis on ease of use for beginners, as well as being hackable for advanced customers. It comes preassembled: the only tool you need is a screwdriver.
+
+- A comfortable 62 keys, including a number row. It's perfect for beginners who want to feel what a split keyboard feels like without the layout feeling cramped, and a nice option for people who know they frequently use the number row, like typists, gamers, some software engineers and Excel warriors.
+- Powered by an RP2040 controller, it’s quick enough to handle anything a keyboard should be able to do… and much more.
+- 16 megabytes of flash memory ensure that it’s ready for just about everything. Putting a sped-up movie on an RGB display you’ve wired up to your prototyping Myriad module? Say no more.
+- Supports MX switches with preassembled hot-swap sockets. No soldering iron needed. You can solder them to the alternative set of pads if you'd prefer to, though.
+- Supports Choc switches by soldering. This does require assembly with tools like a soldering iron. Hot swap is still possible using Mill-Max sockets, which too require soldering.
+- Subtle RGB underglow with 6 LEDs per half to personalise the colour of your keyboard. It can be disabled for those who don't want it.
+- Supports the tenting puck, which allows you to mount it to most camera tripods so you can place your keyboard at exactly the angle you want it.
+- Supports up to one Myriad module per half, so you can add a myriad of available modules without having to solder.
+- Supports up to one 128x64 pixel OLED display per half, which doesn't require soldering.
+- There's a TRRS jack for foot pedal or external switch support. You can use one such switch per half by default, but the wiring supports up to three external switches per half. Great for accessibility purposes, or just plain fun if you want to hook up a digital foot pedal to your voice chat software, game or whatever else you can think of.
+- If you're into soldering, you can put up to three encoders per half on seven predefined locations: near the top of the thumb cluster, at the innermost thumb cluster button, or each location on the outer columns. If you don't want to solder, you can of course still use a rotary encoder Myriad module.
+
+# What's Myriad?
+
+![A collection of Myriad modules](https://i.imgur.com/86u7BLMl.jpg)
+
+Myriad is a system that allows you to plug in modules to add new functionality to your keyboard, all without having to solder. It's an [open standard](https://myriad.splitkb.com/), meaning that anyone will be able to create their own modules, which you can then plug into your keyboard. It's a very capable standard, so we're very curious to see what other modules you will come up with!
diff --git a/keyboards/splitkb/elora/rev1/config.h b/keyboards/splitkb/elora/rev1/config.h
new file mode 100644
index 0000000000..7633cf00af
--- /dev/null
+++ b/keyboards/splitkb/elora/rev1/config.h
@@ -0,0 +1,60 @@
+// Copyright 2024 splitkb.com (support@splitkb.com)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+// Make it easier to enter the bootloader
+#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET
+#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT 1000U
+
+// I2C0, onboard SSD1306 socket and I2C to Myriad module
+#define I2C_DRIVER I2CD0
+#define I2C1_SDA_PIN GP0
+#define I2C1_SCL_PIN GP1
+// We need to slow down the I2C clock because the default of 400.000
+// fails to communicate with Zetta ZD24C02A EEPROM on a Myriad card.
+#define I2C1_CLOCK_SPEED 100000
+
+// SPI1, both for onboard matrix data and SPI to Myriad module
+#define SPI_DRIVER SPID1
+#define SPI_SCK_PIN GP10
+#define SPI_MOSI_PIN GP11
+#define SPI_MISO_PIN GP12
+
+// UART1, communication between the two halves
+#define SERIAL_USART_FULL_DUPLEX
+#define SERIAL_USART_DRIVER SIOD1
+#define SERIAL_USART_TX_PIN GP20
+#define SERIAL_USART_RX_PIN GP21
+
+// Potential onboard speaker, not populated by default
+#define AUDIO_PIN GP23
+
+// Transmitting pointing device status to the master side
+#define SPLIT_POINTING_ENABLE
+#define POINTING_DEVICE_COMBINED
+
+// VBUS detection
+#define USB_VBUS_PIN GP25
+
+// Define matrix size
+#define MATRIX_COLS 8
+#define MATRIX_ROWS 12
+
+// Encoders
+// 3 onboard, 1 for Myriad
+#define NUM_ENCODERS_LEFT 4
+#define NUM_ENCODERS_RIGHT 4
+#define ENCODER_RESOLUTION 2
+
+// OLED display
+#define OLED_DISPLAY_128X64
+// If someone has only one OLED display
+// and that display was on the slave side.
+// It wouldn't work at all. This fixes that
+// including some code in rev1.c but makes
+// it so the timeout's are not synced
+// between halves.
+#undef SPLIT_OLED_ENABLE
+#define OLED_TIMEOUT 0
+
diff --git a/keyboards/splitkb/elora/rev1/halconf.h b/keyboards/splitkb/elora/rev1/halconf.h
new file mode 100644
index 0000000000..9798aa34f9
--- /dev/null
+++ b/keyboards/splitkb/elora/rev1/halconf.h
@@ -0,0 +1,13 @@
+// Copyright 2024 splitkb.com (support@splitkb.com)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#define HAL_USE_SIO TRUE
+#define HAL_USE_I2C TRUE
+#define HAL_USE_SPI TRUE
+#define SPI_USE_WAIT TRUE
+#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
+#define HAL_USE_ADC TRUE
+
+#include_next <halconf.h>
diff --git a/keyboards/splitkb/elora/rev1/keyboard.json b/keyboards/splitkb/elora/rev1/keyboard.json
new file mode 100644
index 0000000000..a2d02a9a49
--- /dev/null
+++ b/keyboards/splitkb/elora/rev1/keyboard.json
@@ -0,0 +1,108 @@
+{
+ "keyboard_name": "Elora rev1",
+ "bootloader": "rp2040",
+ "features": {
+ "pointing_device": true,
+ "rgb_matrix": true,
+ "rgblight": false,
+ "encoder": true,
+ "oled": true,
+ "extrakey": true,
+ "mousekey": true,
+ "nkro": true,
+ "audio": false
+ },
+ "processor": "RP2040",
+ "rgb_matrix": {
+ "animations": {
+ "alphas_mods": true,
+ "band_pinwheel_sat": true,
+ "band_pinwheel_val": true,
+ "band_sat": true,
+ "band_spiral_sat": true,
+ "band_spiral_val": true,
+ "band_val": true,
+ "breathing": true,
+ "cycle_all": true,
+ "cycle_left_right": true,
+ "cycle_out_in": true,
+ "cycle_out_in_dual": true,
+ "cycle_pinwheel": true,
+ "cycle_spiral": true,
+ "cycle_up_down": true,
+ "digital_rain": true,
+ "dual_beacon": true,
+ "gradient_left_right": true,
+ "gradient_up_down": true,
+ "hue_breathing": true,
+ "hue_pendulum": true,
+ "hue_wave": true,
+ "jellybean_raindrops": true,
+ "multisplash": true,
+ "pixel_flow": true,
+ "pixel_fractal": true,
+ "pixel_rain": true,
+ "rainbow_beacon": true,
+ "rainbow_moving_chevron": true,
+ "rainbow_pinwheels": true,
+ "raindrops": true,
+ "solid_color": true,
+ "solid_multisplash": true,
+ "solid_reactive": true,
+ "solid_reactive_cross": true,
+ "solid_reactive_multicross": true,
+ "solid_reactive_multinexus": true,
+ "solid_reactive_multiwide": true,
+ "solid_reactive_nexus": true,
+ "solid_reactive_simple": true,
+ "solid_reactive_wide": true,
+ "solid_splash": true,
+ "splash": true,
+ "typing_heatmap": true
+ },
+ "driver": "ws2812",
+ "layout": [
+ {"x": 90, "y": 0, "flags": 2},
+ {"x": 45, "y": 0, "flags": 2},
+ {"x": 0, "y": 0, "flags": 2},
+ {"x": 0, "y": 64, "flags": 2},
+ {"x": 45, "y": 64, "flags": 2},
+ {"x": 90, "y": 64, "flags": 2},
+ {"x": 134, "y": 0, "flags": 2},
+ {"x": 179, "y": 0, "flags": 2},
+ {"x": 224, "y": 0, "flags": 2},
+ {"x": 224, "y": 64, "flags": 2},
+ {"x": 179, "y": 64, "flags": 2},
+ {"x": 134, "y": 64, "flags": 2}
+ ],
+ "max_brightness": 150,
+ "split_count": [6, 6]
+ },
+ "rgblight": {
+ "led_count": 12,
+ "split": true
+ },
+ "split": {
+ "enabled": true,
+ "handedness": {
+ "pin": "GP14"
+ },
+ "serial": {
+ "driver": "usart"
+ },
+ "transport": {
+ "sync": {
+ "matrix_state": true
+ },
+ "watchdog": true,
+ "watchdog_timeout": 3000
+ }
+ },
+ "usb": {
+ "pid": "0x9D9D"
+ },
+ "ws2812": {
+ "driver": "vendor",
+ "pin": "GP15"
+ }
+}
diff --git a/keyboards/splitkb/elora/rev1/matrix.c b/keyboards/splitkb/elora/rev1/matrix.c
new file mode 100644
index 0000000000..625eafcd85
--- /dev/null
+++ b/keyboards/splitkb/elora/rev1/matrix.c
@@ -0,0 +1,57 @@
+// Copyright 2024 splitkb.com (support@splitkb.com)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "matrix.h"
+#include "spi_master.h"
+
+// The matrix is hooked up to a chain of 74xx165 shift registers.
+// Pin F0 acts as Chip Select (active-low)
+// The signal goes to a NOT gate, whose output is wired to
+// a) the latch pin of the shift registers
+// b) the "enable" pin of a tri-state buffer,
+// attached between the shift registers and MISO
+// F0 has an external pull-up.
+// SCK works as usual.
+//
+// Note that the matrix contains a variety of data.
+// In addition to the keys, it also reads the rotary encoders
+// and whether the board is the left/right half.
+
+void matrix_init_custom(void) {
+ // Note: `spi_init` has already been called
+ // in `keyboard_pre_init_kb()`, so nothing to do here
+}
+
+bool matrix_scan_custom(matrix_row_t current_matrix[]) {
+ // Enough to hold the shift registers
+ uint16_t length = 5;
+ uint8_t data[length];
+
+ // Matrix SPI config
+ // 1) Pin
+ // 2) Mode: Register shifts on rising clock, and clock idles low
+ // pol = 0 & pha = 0 => mode 0
+ // 3) LSB first: Register outputs H first, and we want H as MSB,
+ // as this result in a neat A-H order in the layout macro.
+ // 4) Divisor: 2 is the fastest possible, at Fclk / 2.
+ // range is 2-128
+ spi_start(GP13, false, 0, 128);
+ spi_receive(data, length);
+ spi_stop();
+
+ bool matrix_has_changed = false;
+ for (uint8_t i = 0; i < length; i++) {
+ // Bitwise NOT because we use pull-ups,
+ // and switches short the pin to ground,
+ // but the matrix uses 1 to indicate a pressed switch
+ uint8_t word = ~data[i];
+ matrix_has_changed |= current_matrix[i] ^ word;
+ current_matrix[i] = word;
+ }
+#ifdef MYRIAD_ENABLE
+ bool myriad_hook_matrix(matrix_row_t current_matrix[]);
+ return matrix_has_changed || myriad_hook_matrix(current_matrix);
+#else
+ return matrix_has_changed;
+#endif
+} \ No newline at end of file
diff --git a/keyboards/splitkb/elora/rev1/mcuconf.h b/keyboards/splitkb/elora/rev1/mcuconf.h
new file mode 100644
index 0000000000..58290187cf
--- /dev/null
+++ b/keyboards/splitkb/elora/rev1/mcuconf.h
@@ -0,0 +1,18 @@
+// Copyright 2024 splitkb.com (support@splitkb.com)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include_next <mcuconf.h>
+
+#undef RP_SIO_USE_UART1
+#define RP_SIO_USE_UART1 TRUE
+
+#undef RP_I2C_USE_I2C0
+#define RP_I2C_USE_I2C0 TRUE
+
+#undef RP_SPI_USE_SPI1
+#define RP_SPI_USE_SPI1 TRUE
+
+#undef RP_ADC_USE_ADC1
+#define RP_ADC_USE_ADC1 TRUE
diff --git a/keyboards/splitkb/elora/rev1/myriad.c b/keyboards/splitkb/elora/rev1/myriad.c
new file mode 100644
index 0000000000..8bb6054df9
--- /dev/null
+++ b/keyboards/splitkb/elora/rev1/myriad.c
@@ -0,0 +1,315 @@
+// Copyright 2024 splitkb.com (support@splitkb.com)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include QMK_KEYBOARD_H
+
+#include "myriad.h"
+
+#include "i2c_master.h"
+#include "analog.h"
+
+typedef struct __attribute__((__packed__)) {
+ char magic_numbers[3];
+ uint8_t version_major;
+ uint8_t version_minor;
+ uint8_t version_patch;
+ uint32_t checksum;
+ uint16_t payload_length;
+} myriad_header_t;
+
+typedef struct __attribute__((__packed__)) {
+ uint16_t vendor_id;
+ uint16_t product_id;
+ uint8_t revision;
+} identity_record_t;
+
+static bool myriad_reader(uint8_t *data, uint16_t length) {
+ const uint8_t eeprom_address = 0x50; // 1010 000 - NOT shifted for R/W bit
+ const uint16_t i2c_timeout = 100; // in milliseconds
+
+ uint8_t num_pages = (length / 256) + 1;
+ uint8_t last_page_size = length % 256;
+
+ for (int i = 0; i < num_pages; i++) {
+ uint8_t reg = 0; // We always start on a page boundary, so this is always zero
+ uint16_t read_length;
+ if (i == num_pages - 1) {
+ read_length = last_page_size;
+ } else {
+ read_length = 256;
+ }
+ i2c_status_t s = i2c_read_register((eeprom_address + i) << 1, reg, &(data[i*256]), read_length, i2c_timeout);
+ if (s != I2C_STATUS_SUCCESS) { return false; }
+ }
+ return true;
+}
+
+static bool verify_header(myriad_header_t *header) {
+ char magic_numbers[] = {'M', 'Y', 'R'};
+ uint8_t version_major = 1;
+ uint16_t version_minor = 0;
+
+ for (int i = 0; i < sizeof(magic_numbers); i++) {
+ // Check that the header starts with 'MYR', indicating that this is indeed a Myriad card.
+ if (header->magic_numbers[i] != magic_numbers[i]) {
+ return false;
+ }
+ }
+
+ if (header->version_major != version_major || header->version_minor > version_minor) {
+ // We obviously don't support cards with a different major version, because that indicates a breaking change.
+ // We also don't support cards with HIGHER minor version,
+ // as we are not guaranteed to be able to properly use all its features.
+ return false;
+ }
+
+ if (header->payload_length > (2048 - sizeof(myriad_header_t))) {
+ // The EEPROM chips are *at most* 16kb / 2kB large,
+ // and some of that is taken up by the header.
+ // We obviously can't have a payload which exceeds the EEPROM's size.
+ return false;
+ }
+
+ return true;
+}
+
+// Sourced from https://en.wikipedia.org/wiki/Adler-32#Example_implementation
+static bool verify_checksum(uint8_t *data, uint16_t length, uint32_t checksum) {
+ // Skip the header
+ data += sizeof(myriad_header_t);
+ length -= sizeof(myriad_header_t);
+
+ const uint32_t MOD_ADLER = 65521;
+
+ uint32_t a = 1, b = 0;
+ size_t index;
+
+ // Process each byte of the data in order
+ for (index = 0; index < length; ++index)
+ {
+ a = (a + data[index]) % MOD_ADLER;
+ b = (b + a) % MOD_ADLER;
+ }
+ uint32_t calculated = ((b << 16) | a);
+
+ return calculated == checksum;
+}
+
+// Locates a specific entry by type
+// Returns the offset of the PAYLOAD.
+static int16_t locate_entry(uint8_t entry_type, uint8_t entry_data_length, uint8_t *data, uint16_t minimum, uint16_t maximum) {
+ if (minimum < sizeof(myriad_header_t)) {
+ // Records must start *after* the header.
+ // We silently allow this so the caller can just specify `0` as minimum for the first entry.
+ minimum = sizeof(myriad_header_t);
+ }
+
+ uint16_t offset = minimum;
+ while (offset < maximum) {
+ if (data[offset] == entry_type) {
+ // Type matches!
+ if (data[offset+1] == entry_data_length) {
+ // We found what we are looking for, so return payload reference.
+ return offset+2;
+ } else {
+ // The entry is the wrong length?
+ return -2;
+ }
+ } else {
+ // No type match, so skip this one
+ // We skip the type byte, the length byte, and any potential data (with length stored in the length byte)
+ offset += 2 + data[offset+1];
+ }
+ }
+
+ // We hit the maximum and didn't find what we are looking for
+ return -1;
+}
+
+static bool read_card_identity(uint8_t *data, uint16_t length, identity_record_t *record) {
+ const uint8_t identity_type = 0x01;
+ const uint8_t entry_data_length = sizeof(identity_record_t);
+ int16_t result = locate_entry(identity_type, entry_data_length, data, 0, length);
+ if (result < 0) { return false; }
+
+ for (int i = 0; i < sizeof(identity_record_t); i++) {
+ ((uint8_t*)record)[i] = data[result + i];
+ }
+ return true;
+}
+
+static myriad_card_t _detect_myriad(void) {
+ gpio_set_pin_input(MYRIAD_PRESENT);
+ wait_ms(100);
+ // The pin has an external pull-up, and a Myriad card shorts it to ground.
+ #ifndef MYRIAD_OVERRIDE_PRESENCE
+ if (gpio_read_pin(MYRIAD_PRESENT)) {
+ return NONE;
+ }
+ #endif
+
+ // Attempt to read header
+ myriad_header_t header;
+ if (!myriad_reader((uint8_t*)&header, sizeof(header))) { return INVALID; }
+ if (!verify_header(&header)) { return INVALID; }
+
+ // Now that we have determined that the header is valid
+ // and we know the payload length, read the entire thing
+ uint8_t data[2048]; // Guaranteed to be large enough.
+ uint16_t data_size = sizeof(header)+header.payload_length;
+ if (!myriad_reader(data, data_size)) { return INVALID; }
+ if (!verify_checksum(data, data_size, header.checksum)) { return INVALID; }
+
+ identity_record_t identity;
+ if (!read_card_identity(data, data_size, &identity)) { return INVALID; }
+
+ if (identity.vendor_id == 0x0001 && identity.product_id == 0x0001) {
+ return SKB_ENCODER;
+ } else if (identity.vendor_id == 0x0001 && identity.product_id == 0x0002) {
+ return SKB_JOYSTICK;
+ } else if (identity.vendor_id == 0x0001 && identity.product_id == 0x0003) {
+ return SKB_SWITCHES;
+ }
+
+ return UNKNOWN;
+}
+
+// Determine card presence & identity
+// Does NOT initialize the card for use!
+myriad_card_t detect_myriad(void) {
+ static myriad_card_t card = UNINITIALIZED;
+
+ if (card == UNINITIALIZED) {
+ i2c_init();
+ card = _detect_myriad();
+ }
+
+ return card;
+}
+
+static void myr_switches_init(void) {
+ gpio_set_pin_input_high(MYRIAD_GPIO1); // S4
+ gpio_set_pin_input_high(MYRIAD_GPIO2); // S2
+ gpio_set_pin_input_high(MYRIAD_GPIO3); // S1
+ gpio_set_pin_input_high(MYRIAD_GPIO4); // S3
+}
+
+static void myr_encoder_init(void) {
+ gpio_set_pin_input_high(MYRIAD_GPIO1); // Press
+ gpio_set_pin_input_high(MYRIAD_GPIO2); // A
+ gpio_set_pin_input_high(MYRIAD_GPIO3); // B
+}
+
+static uint16_t myr_joystick_timer;
+static void myr_joystick_init(void) {
+ gpio_set_pin_input_high(MYRIAD_GPIO1); // Press
+
+ myr_joystick_timer = timer_read();
+}
+
+// Make sure any card present is ready for use
+static myriad_card_t myriad_card_init(void) {
+ static bool initialized = false;
+
+ myriad_card_t card = detect_myriad();
+ if (initialized) {
+ return card;
+ }
+ initialized = true;
+
+ switch (card) {
+ case SKB_SWITCHES:
+ myr_switches_init();
+ break;
+ case SKB_ENCODER:
+ myr_encoder_init();
+ break;
+ case SKB_JOYSTICK:
+ myr_joystick_init();
+ break;
+ default:
+ break;
+ }
+ return card;
+}
+
+bool myriad_hook_matrix(matrix_row_t current_matrix[]) {
+ myriad_card_t card = myriad_card_init();
+ uint8_t word = 0;
+
+ if (card == SKB_SWITCHES) {
+ word |= ((!gpio_read_pin(MYRIAD_GPIO3)) & 1) << 0;
+ word |= ((!gpio_read_pin(MYRIAD_GPIO2)) & 1) << 1;
+ word |= ((!gpio_read_pin(MYRIAD_GPIO4)) & 1) << 2;
+ word |= ((!gpio_read_pin(MYRIAD_GPIO1)) & 1) << 3;
+ } else if (card == SKB_ENCODER) {
+ word |= ((!gpio_read_pin(MYRIAD_GPIO1)) & 1) << 4;
+ } else if (card == SKB_JOYSTICK) {
+ word |= ((!gpio_read_pin(MYRIAD_GPIO1)) & 1) << 4;
+ } else {
+ return false;
+ }
+
+ // 5 bytes of on-board keys, so we are the 6th
+ bool matrix_has_changed = current_matrix[5] ^ word;
+ current_matrix[5] = word;
+
+ return matrix_has_changed;
+}
+
+static pin_t encoders_pad_a[NUM_ENCODERS_MAX_PER_SIDE];
+static pin_t encoders_pad_b[NUM_ENCODERS_MAX_PER_SIDE];
+
+uint8_t myriad_hook_encoder(uint8_t index, bool pad_b) {
+ if (myriad_card_init() != SKB_ENCODER) { return 0; }
+ // 3 onboard encoders, so we are number 4
+ pin_t pin = pad_b ? encoders_pad_b[index] : encoders_pad_a[index];
+ encoders_pad_a[3] = MYRIAD_GPIO2;
+ encoders_pad_b[3] = MYRIAD_GPIO3;
+ return gpio_read_pin(pin) ? 1 : 0;
+}
+
+report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) {
+ if (myriad_card_init() != SKB_JOYSTICK) { return mouse_report; }
+
+ if (timer_elapsed(myr_joystick_timer) < 10) {
+ wait_ms(2);
+ return mouse_report;
+ }
+
+ myr_joystick_timer = timer_read();
+
+ // `analogReadPin` returns 0..1023
+ int32_t y = (analogReadPin(MYRIAD_ADC1) - 512) * -1; // Note: axis is flipped
+ int32_t x = analogReadPin(MYRIAD_ADC2) - 512;
+ // Values are now -512..512
+
+ // Create a dead zone in the middle where the mouse doesn't move
+ const int16_t dead_zone = 10;
+ if ((y < 0 && y > -1*dead_zone) || (y > 0 && y < dead_zone)) {
+ y = 0;
+ }
+ if ((x < 0 && x > -1*dead_zone) || (x > 0 && x < dead_zone)) {
+ x = 0;
+ }
+
+ // quadratic movement
+ x = abs(x) * x / 5000;
+ y = abs(y) * y / 5000;
+
+ // Clamp final value to make sure we don't under/overflow
+ if (y < -127) { y = -127; }
+ if (y > 127) { y = 127; }
+ if (x < -127) { x = -127; }
+ if (x > 127) { x = 127; }
+
+ mouse_report.x = x;
+ mouse_report.y = y;
+
+ return mouse_report;
+}
+
+void pointing_device_driver_init(void) {
+ gpio_set_pin_input(MYRIAD_ADC1); // Y
+ gpio_set_pin_input(MYRIAD_ADC2); // X
+} \ No newline at end of file
diff --git a/keyboards/splitkb/elora/rev1/myriad.h b/keyboards/splitkb/elora/rev1/myriad.h
new file mode 100644
index 0000000000..03fe2b5e6b
--- /dev/null
+++ b/keyboards/splitkb/elora/rev1/myriad.h
@@ -0,0 +1,52 @@
+// Copyright 2024 splitkb.com (support@splitkb.com)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "matrix.h"
+
+typedef enum { UNINITIALIZED, NONE, INVALID, UNKNOWN, SKB_SWITCHES, SKB_ENCODER, SKB_JOYSTICK } myriad_card_t;
+
+bool myriad_hook_matrix(matrix_row_t current_matrix[]);
+uint8_t myriad_hook_encoder(uint8_t index, bool pad_b);
+myriad_card_t detect_myriad(void);
+
+//// Elora-specific pinout
+
+// Control signals
+#define MYRIAD_PRESENT GP3
+#define MYRIAD_MCU_OVERRIDE GP2
+
+// General I/O
+#define MYRIAD_ADC1 GP26
+#define MYRIAD_ADC2 GP27
+#define MYRIAD_ADC1_CHANNEL 0
+#define MYRIAD_ADC2_CHANNEL 1
+#define MYRIAD_PWM1 GP23
+#define MYRIAD_PWM2 GP24
+#define MYRIAD_GPIO1 GP4
+#define MYRIAD_GPIO2 GP5
+#define MYRIAD_GPIO3 GP6
+#define MYRIAD_GPIO4 GP8
+
+// UART
+#define MYRIAD_RX GP17
+#define MYRIAD_TX GP16
+#define MYRIAD_CTS GP18
+#define MYRIAD_RTS GP19
+
+// SPI
+#define MYRIAD_MISO GP12
+#define MYRIAD_MOSI GP11
+#define MYRIAD_SCK GP10
+#define MYRIAD_MODULE_CS GP9
+#define MYRIAD_MATRIX_CS GP13
+
+// I2C
+#define MYRIAD_SDA GP0
+#define MYRIAD_SCL GP1
+
+// RGB
+#define MYRIAD_RGB GP15
diff --git a/keyboards/splitkb/elora/rev1/rev1.c b/keyboards/splitkb/elora/rev1/rev1.c
new file mode 100644
index 0000000000..6ffc23a4cf
--- /dev/null
+++ b/keyboards/splitkb/elora/rev1/rev1.c
@@ -0,0 +1,214 @@
+// Copyright 2024 splitkb.com (support@splitkb.com)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "rev1.h"
+#include "spi_master.h"
+#include "myriad.h"
+
+bool is_oled_enabled = true;
+
+//// HW init
+
+// Make sure all external hardware is
+// in a known-good state on powerup
+void keyboard_pre_init_kb(void) {
+ /// SPI Chip Select pins for various hardware
+ // Matrix CS
+ gpio_set_pin_output(GP13);
+ gpio_write_pin_high(GP13);
+ // Myriad Module CS
+ gpio_set_pin_output(GP9);
+ gpio_write_pin_high(GP9);
+
+ gpio_set_pin_output(ELORA_CC1_PIN);
+ gpio_write_pin_low(ELORA_CC1_PIN);
+
+ gpio_set_pin_output(ELORA_CC2_PIN);
+ gpio_write_pin_low(ELORA_CC2_PIN);
+
+ // We have to get the SPI interface working quite early,
+ // So make sure it is available well before we need it
+ spi_init();
+
+ keyboard_pre_init_user();
+}
+
+//// Encoder functionality
+
+// The encoders are hooked in to the same shift registers as the switch matrix, so we can just piggyback on that.
+
+// Clone of a variant in quantum/matrix_common.c, but matrix-agnostic
+bool mat_is_on(matrix_row_t mat[], uint8_t row, uint8_t col) {
+ return (mat[row] & ((matrix_row_t)1 << col));
+}
+
+uint8_t encoder_read_pads_from(uint8_t index, bool pad_b, matrix_row_t mat[]) {
+ // First two matrix rows:
+ //
+ // Pin A B C D E F G H
+ // Left:
+ // { __, __, __, __, __, __, A1, B1 },
+ // { A3, B3, A2, B2, __, __, __, __ }
+ // Right:
+ // { A1, B1, __, __, __, __, __, __ },
+ // { __, __, __, __, A2, B2, A3, B3 }
+ //
+ // See also rev1.h
+
+ bool pad_value = false;
+
+ if (is_keyboard_left()) {
+ if (index == 0) {
+ pad_value = pad_b ? mat_is_on(mat, 0, 7) : mat_is_on(mat, 0, 6); // B1, A1
+ } else if (index == 1) {
+ pad_value = pad_b ? mat_is_on(mat, 1, 3) : mat_is_on(mat, 1, 2); // B2, A2
+ } else if (index == 2) {
+ pad_value = pad_b ? mat_is_on(mat, 1, 1) : mat_is_on(mat, 1, 0); // B3, A3
+ }
+ } else {
+ if (index == 0) {
+ pad_value = pad_b ? mat_is_on(mat, 0, 1) : mat_is_on(mat, 0, 0); // B1, A1
+ } else if (index == 1) {
+ pad_value = pad_b ? mat_is_on(mat, 1, 5) : mat_is_on(mat, 1, 4); // B2, A2
+ } else if (index == 2) {
+ pad_value = pad_b ? mat_is_on(mat, 1, 7) : mat_is_on(mat, 1, 6); // B3, A3
+ }
+ }
+
+ return pad_value ? 1 : 0;
+}
+
+void encoder_quadrature_init_pin(uint8_t index, bool pad_b) {
+ // At this point the first matrix scan hasn't happened yet,
+ // so we can't use raw_matrix to initialize our encoder state
+ // as it contains all zeroes - so we have to do our own first scan
+ // The pins for myriad are initialized in myriad.c
+
+ matrix_row_t mat[MATRIX_ROWS];
+
+ encoder_read_pads_from(index, pad_b, mat);
+}
+
+extern matrix_row_t raw_matrix[MATRIX_ROWS]; // From quantum/matrix_common.c
+
+uint8_t encoder_quadrature_read_pin(uint8_t index, bool pad_b) {
+ // The matrix code already keeps the raw matrix up-to-date,
+ // so we only have to read the values from it
+ if(index <= 2) {
+ return encoder_read_pads_from(index, pad_b, raw_matrix);
+ } else {
+ #ifdef MYRIAD_ENABLE
+ return myriad_hook_encoder(index, pad_b);
+ #endif
+ return 0;
+ }
+ return 0;
+}
+
+//// Default functionality
+
+#ifdef OLED_ENABLE
+oled_rotation_t oled_init_kb(oled_rotation_t rotation) {
+ if (is_keyboard_left()) {
+ return OLED_ROTATION_270;
+ } else {
+ return OLED_ROTATION_90;
+ }
+}
+
+bool oled_task_kb(void) {
+ if (!oled_task_user()) {
+ return false;
+ }
+
+ if (!is_oled_enabled) {
+ oled_off();
+ return false;
+ } else {
+ oled_on();
+ }
+
+ if (is_keyboard_master()) {
+ oled_write_P(PSTR("Elora rev1\n\n"), false);
+
+ // Keyboard Layer Status
+ // Ideally we'd print the layer name, but no way to know that for sure
+ // Fallback option: just print the layer number
+ uint8_t layer = get_highest_layer(layer_state | default_layer_state);
+ oled_write_P(PSTR("Layer: "), false);
+ oled_write(get_u8_str(layer, ' '), false);
+
+ // Keyboard LED Status
+ led_t led_state = host_keyboard_led_state();
+ oled_write_P(led_state.num_lock ? PSTR(" NUM") : PSTR(" "), false);
+ oled_write_P(led_state.caps_lock ? PSTR("CAP") : PSTR(" "), false);
+ oled_write_P(led_state.scroll_lock ? PSTR("SCR") : PSTR(" "), false);
+
+ // QMK Logo
+ // clang-format off
+ static const char PROGMEM qmk_logo[] = {
+ 0x81,0x82,0x83,0x84,0x0a,
+ 0xa1,0xa2,0xa3,0xa4,0x85,0x86,0x87,0x88,0x89,0x0a,
+ 0xc1,0xc2,0xc3,0xc4,0xa5,0xa6,0xa7,0xa8,0xa9,0x0a,
+ 0x8a,0x8b,0x8c,0x8d,0xc5,0xc6,0xc7,0xc8,0xc9,0x0a,
+ 0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0x00
+ };
+ // clang-format on
+ oled_set_cursor(0, oled_max_lines()-5);
+ oled_write_P(qmk_logo, false);
+ } else {
+ // Elora sigil
+ // clang-format off
+ static const char PROGMEM elora_logo[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,128,192,224,224,240,248,120, 56, 60,188,158,158,222,206,207,207,207,239,239,239,239,239,239,207,207,207,206,222,158,158,188, 60, 56,120,248,240,224,224,192,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,224,248,252,126, 31,143,199,227,243,249,124, 60, 30, 31, 15, 7, 7, 3, 3, 3,131,193,225,241,249,253,255,255,255,255,127, 63, 31, 15, 7, 7, 7,143,223,254,252,252,249,243,227,199,143, 31,126,252,248,224,192, 0, 0, 0, 0, 0,
+ 0,192,240,254,255, 63, 7,227,248,252,127, 31, 15, 3, 1, 0, 0, 0,128,192,224,240,248,252,254,255,255,255,127, 63, 31, 15, 7, 3, 1,128,192,224,240,248,252,254,255,255,255,255,127, 63, 31, 15, 7, 15, 31,255,252,248,227, 7, 63,255,254,240,192, 0,252,255,255,255, 1,224,255,255,255, 7, 0, 0, 0, 0, 0, 0, 0, 0, 31, 31, 31, 31, 31, 15, 7, 3, 1, 0, 0, 0,240,248,252,254,255,255,255,255,127, 63, 31, 15, 7, 3, 1,128,192,224,240,248,252,254,255,255,255,255,255,255,224, 1,255,255,255,252,
+ 63,255,255,255,128, 7,255,255,255,224, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,192,224,240,248,248,248,248,248,248, 0, 3, 3, 3, 3, 3, 3, 1,128,192,224,240,248,252,254,255,255,255,127, 63, 31, 15, 7, 3, 1,224,255,255,255, 7,128,255,255,255, 63, 0, 3, 15,127,255,252,224,199, 31, 63,254,248,240,192,128, 0, 0, 0, 0, 31, 31, 31, 31, 31, 31, 15, 7, 3, 1, 0, 0, 0, 0, 0, 0, 62, 63, 63, 63, 63, 63, 31, 15, 7, 3, 1, 0, 0, 0,128,192,240,248,254, 63, 31,199,224,252,255,127, 15, 3, 0,
+ 0, 0, 0, 0, 0, 3, 7, 31, 63,126,248,241,227,199,207,159, 62, 60,120,248,240,224,224,192,192,192,192,128,128,128,128,128,128,128,128,128,128,192,192,192,192,224,224,240,248,120, 60, 62,159,207,199,227,241,248,126, 63, 31, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 3, 7, 7, 15, 31, 30, 28, 60, 61,121,121,123,115,243,243,243,247,247,247,247,247,247,243,243,243,115,123,121,121, 61, 60, 28, 30, 31, 15, 7, 7, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+ // clang-format on
+ oled_set_cursor(0, (oled_max_lines()/2)-4); // logo is 8 lines high, so center vertically
+ oled_write_raw_P(elora_logo, sizeof(elora_logo));
+ }
+
+ return false;
+}
+
+void housekeeping_task_kb(void) {
+ is_oled_enabled = last_input_activity_elapsed() < 60000;
+}
+#endif
+
+#ifdef ENCODER_ENABLE
+bool encoder_update_kb(uint8_t index, bool clockwise) {
+ if (!encoder_update_user(index, clockwise)) {
+ return false;
+ }
+
+ if (index == 0 || index == 1 || index == 2) {
+ // Left side
+ // Arrow keys
+ if (clockwise) {
+ tap_code(KC_RIGHT);
+ } else {
+ tap_code(KC_LEFT);
+ }
+ } else if (index == 4 || index == 5 || index == 6) {
+ // Right side
+ // Page up/Page down
+ if (clockwise) {
+ tap_code(KC_PGDN);
+ } else {
+ tap_code(KC_PGUP);
+ }
+ } else if (index == 3 || index == 7) {
+ // Myriad
+ // Volume control
+ if (clockwise) {
+ tap_code(KC_VOLU);
+ } else {
+ tap_code(KC_VOLD);
+ }
+ }
+ return true;
+}
+#endif
diff --git a/keyboards/splitkb/elora/rev1/rev1.h b/keyboards/splitkb/elora/rev1/rev1.h
new file mode 100644
index 0000000000..d4c1ffedb2
--- /dev/null
+++ b/keyboards/splitkb/elora/rev1/rev1.h
@@ -0,0 +1,14 @@
+// Copyright 2024 splitkb.com (support@splitkb.com)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "quantum.h"
+
+//// Custom pins, might be useful in a keymap
+// Wired to input of last shift register, overrides 10k pullup/pulldown
+#define ELORA_SELFTEST_PIN GP14
+
+// Can be used for USB current detection
+#define ELORA_CC1_PIN GP28
+#define ELORA_CC2_PIN GP29
diff --git a/keyboards/splitkb/elora/rev1/rules.mk b/keyboards/splitkb/elora/rev1/rules.mk
new file mode 100644
index 0000000000..643fdc9a1b
--- /dev/null
+++ b/keyboards/splitkb/elora/rev1/rules.mk
@@ -0,0 +1,7 @@
+SPI_DRIVER_REQUIRED = yes
+CUSTOM_MATRIX = lite
+
+# Myriad boilerplate
+SRC += myriad.c matrix.c
+ANALOG_DRIVER_REQUIRED = yes
+POINTING_DEVICE_DRIVER = custom \ No newline at end of file