Browse Source

Add Mechboards Lily58 variant and common code. (#24937)

* Add lily58 and common code

* Apply suggestions from code review

Co-authored-by: jack <jack@pngu.org>

* Apply suggestions from code review

Co-authored-by: jack <jack@pngu.org>

---------

Co-authored-by: jack <jack@pngu.org>
Dasky 1 year ago
parent
commit
a4d86a63f2

+ 385 - 0
keyboards/mechboards/common/display_oled.c

@@ -0,0 +1,385 @@
+// Copyright 2025 Dasky (@daskygit)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "quantum.h"
+
+static uint16_t current_keycode = 0xFF;
+
+static const char *depad_str(const char *depad_str, char depad_char) {
+    while (*depad_str == depad_char)
+        ++depad_str;
+    return depad_str;
+}
+
+static void render_spacer(uint8_t char_length) {
+    static const char PROGMEM spacer_char[] = {8, 8, 8, 8, 8, 8, 8};
+    if (char_length > 5) {
+        char_length = 5;
+    }
+    for (uint8_t i = 0; i < char_length; i++) {
+        oled_write_raw_P(spacer_char, sizeof(spacer_char));
+        oled_advance_char();
+    }
+}
+
+__attribute__((weak)) void render_logo(void) {
+    static const char PROGMEM mb_logo[] = {
+        252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 31, 31, 31, 31,  31,  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   227, 227, 227, 3,   227, 227, 227, 3,   227, 227, 227, 3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   7,   254, 252, 255, 255, 255, 255, 255, 7,   7,   7,   7,   7,   255, 7,   7,   7,   7,   7,   255, 7,   7,   7,   7,   7,   255, 7,   7,   7,   7,   7,   255, 7,   7,   7,   7,   7,   255, 255, 255, 4,   4,   4,   4,   4,  255,
+        7,   7,   7,   7,   7,   255, 7,   7,   7,   7,   7,   255, 255, 255, 255, 255, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,  0,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   224, 224, 224, 0,   238, 238, 238, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   255, 255, 255, 255, 255, 255, 255, 65,  65,  65,  65,  65,  255, 255, 255, 255, 255, 255, 255, 65,  65,  65,  65,  65,  255, 255, 255, 255, 255, 255, 255, 65,  65,  65,  65,  65,  255, 255, 255, 65,  65,  65,  65,  65,  255, 127, 127, 127, 127, 127, 255, 65,  65,  65,  65,  65,  255, 255, 255, 255, 255, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   14,  14,  14,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,  0,  255, 255, 63,  127, 255, 255, 255, 240, 240, 240, 240, 240, 255, 255, 255, 255, 255, 255, 255, 240, 240, 240, 240, 240, 255, 255, 255, 255, 255, 255, 255, 240, 240, 240, 240, 240, 255, 255, 255, 240, 240, 240, 240, 240, 255, 240, 240, 240, 240, 240, 255, 240, 240, 240, 240, 240, 255, 255, 255, 255, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 199, 199, 199, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 224, 127, 63,
+    };
+    oled_write_raw_P(mb_logo, sizeof(mb_logo));
+}
+
+void render_small_mb_logo(void) {
+    static const char PROGMEM small_mb_logo[] = {
+        112, 112, 112, 0, 112, 112, 112, 0, 112, 112, 112, 0, 112, 112, 112, 0, 112, 112, 112, 0, 0, 119, 119, 119, 0, 112, 112, 112, 0, 112, 112, 112, 119, 119, 119, 0, 0, 0, 0, 0, 119, 119, 119, 0, 0, 0, 0, 0, 119, 119, 119, 0, 0, 119, 119, 119, 0, 112, 112, 112, 0, 119, 119, 119,
+    };
+    oled_write_raw_P(small_mb_logo, sizeof(small_mb_logo));
+}
+
+static uint8_t last_hue;
+static uint8_t last_sat;
+static uint8_t last_val;
+static uint8_t last_mode;
+
+void render_rgb_info(void) {
+    last_hue  = rgb_matrix_get_hue();
+    last_sat  = rgb_matrix_get_sat();
+    last_val  = rgb_matrix_get_val();
+    last_mode = rgb_matrix_get_mode();
+    oled_set_cursor(0, 6);
+    oled_write("H:", false);
+    oled_write(depad_str(get_u16_str(last_hue, ' '), ' '), false);
+    oled_set_cursor(0, 7);
+    oled_write("S:", false);
+    oled_write_ln(depad_str(get_u16_str(last_sat, ' '), ' '), false);
+    oled_set_cursor(0, 8);
+    oled_write("V:", false);
+    oled_write_ln(depad_str(get_u16_str(last_val, ' '), ' '), false);
+    oled_set_cursor(0, 9);
+    oled_write("M:", false);
+    oled_write_ln(depad_str(get_u16_str(last_mode, ' '), ' '), false);
+}
+
+oled_rotation_t oled_init_kb(oled_rotation_t rotation) {
+    if (is_keyboard_master()) {
+        return OLED_ROTATION_270;
+    }
+    return rotation;
+}
+
+char basic_codes_to_name[57] = {' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'R', 'E', 'B', 'T', '_', '-', '=', '[', ']', '\\', '#', ';', '\'', '`', ',', '.', '/'};
+
+const char *keycode_string(uint16_t keycode) {
+    char       *keycode_str;
+    static char key;
+    switch (keycode) {
+        case 0 ... 56:
+            key = pgm_read_byte(&basic_codes_to_name[keycode]);
+            return &key;
+        case KC_CAPS:
+            keycode_str = "Caps\0";
+            break;
+        case KC_SCRL:
+            keycode_str = "Scrl\0";
+            break;
+        case KC_PAUS:
+            keycode_str = "Pause\0";
+            break;
+        case KC_DEL:
+            keycode_str = "Del\0";
+            break;
+        case KC_NUM:
+            keycode_str = "Num\0";
+            break;
+        case KC_MUTE:
+            keycode_str = "Mute\0";
+            break;
+        case KC_VOLU:
+            keycode_str = "VolUp\0";
+            break;
+        case KC_VOLD:
+            keycode_str = "VolD\0";
+            break;
+        case KC_MNXT:
+            keycode_str = "Next\0";
+            break;
+        case KC_MPRV:
+            keycode_str = "Prev\0";
+            break;
+        case KC_MSTP:
+            keycode_str = "Stop\0";
+            break;
+        case KC_MPLY:
+            keycode_str = "Play\0";
+            break;
+        case QK_MODS ... QK_MODS_MAX:
+            keycode_str = "MOD()\0";
+            break;
+        case QK_MOD_TAP ... QK_MOD_TAP_MAX:
+            keycode_str = "MT()\0";
+            break;
+        case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
+            keycode_str = "LT()\0";
+            break;
+        case QK_LAYER_MOD ... QK_LAYER_MOD_MAX:
+            keycode_str = "LM()\0";
+            break;
+        case QK_TO ... QK_TO_MAX:
+            keycode_str = "TO()\0";
+            break;
+        case QK_MOMENTARY ... QK_MOMENTARY_MAX:
+            keycode_str = "MO()\0";
+            break;
+        case QK_DEF_LAYER ... QK_DEF_LAYER_MAX:
+            keycode_str = "DF()\0";
+            break;
+        case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX:
+            keycode_str = "TG()\0";
+            break;
+        case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_MOD_MAX:
+            keycode_str = "1SHOT\0";
+            break;
+        case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
+            keycode_str = "TT()\0";
+            break;
+        case QK_PERSISTENT_DEF_LAYER ... QK_PERSISTENT_DEF_LAYER_MAX:
+            keycode_str = "PDF()\0";
+            break;
+        case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
+            keycode_str = "SWAP\0";
+            break;
+        case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
+            keycode_str = "TD()\0";
+            break;
+        case QK_MAGIC ... QK_MAGIC_MAX:
+            keycode_str = "Magic\0";
+            break;
+        case QK_MIDI ... QK_MIDI_MAX:
+            keycode_str = "Midi\0";
+            break;
+        case QK_SEQUENCER ... QK_SEQUENCER_MAX:
+            keycode_str = "Seq\0";
+            break;
+        case QK_JOYSTICK ... QK_JOYSTICK_MAX:
+            keycode_str = "Joy\0";
+            break;
+        case QK_PROGRAMMABLE_BUTTON ... QK_PROGRAMMABLE_BUTTON_MAX:
+            keycode_str = "Prog\0";
+            break;
+        case QK_AUDIO ... QK_AUDIO_MAX:
+            keycode_str = "Audio\0";
+            break;
+        case QK_STENO ... QK_STENO_MAX:
+            keycode_str = "Steno\0";
+            break;
+        case QK_MACRO ... QK_MACRO_MAX:
+            keycode_str = "Macro\0";
+            break;
+        case QK_CONNECTION ... QK_CONNECTION_MAX:
+            keycode_str = "Conn\0";
+            break;
+        case QK_LIGHTING ... QK_LIGHTING_MAX:
+            keycode_str = "Light\0";
+            break;
+        case QK_QUANTUM ... QK_QUANTUM_MAX:
+            keycode_str = "Quant\0";
+            break;
+        case QK_KB ... QK_KB_MAX:
+            keycode_str = "KB\0";
+            break;
+        case QK_USER ... QK_USER_MAX:
+            keycode_str = "USER\0";
+            break;
+        case QK_UNICODEMAP ... QK_UNICODEMAP_PAIR_MAX:
+            keycode_str = "Uni\0";
+            break;
+        default:
+            keycode_str = "Undef\0";
+            break;
+    }
+
+    return keycode_str;
+}
+
+const char *layer_string(uint32_t layer) {
+    char *layer_str;
+    switch (layer) {
+        case 0:
+            layer_str = "Zero\0";
+            break;
+        case 1:
+            layer_str = "One\0";
+            break;
+        case 2:
+            layer_str = "Two\0";
+            break;
+        case 3:
+            layer_str = "Three\0";
+            break;
+        case 4:
+            layer_str = "Four\0";
+            break;
+        case 5:
+            layer_str = "Five\0";
+            break;
+        case 6:
+            layer_str = "Six\0";
+            break;
+        case 7:
+            layer_str = "Seven\0";
+            break;
+        default:
+            return get_u16_str(layer, ' ');
+    }
+
+    return layer_str;
+}
+
+bool process_detected_host_os_kb(os_variant_t detected_os) {
+    if (!process_detected_host_os_user(detected_os)) {
+        return false;
+    }
+
+    oled_set_cursor(0, 10);
+    switch (detected_os) {
+        case OS_MACOS:
+            oled_write_ln("MacOS", false);
+        case OS_IOS:
+            oled_write_ln("Apple", false);
+            break;
+        case OS_WINDOWS:
+            oled_write_ln("Win", false);
+            break;
+        case OS_LINUX:
+            oled_write_ln("Linux", false);
+            break;
+        case OS_UNSURE:
+            oled_write_ln("Unkno", false);
+
+            break;
+    }
+
+    return true;
+}
+
+void keyboard_post_init_kb(void) {
+    if (!is_keyboard_master()) {
+        render_logo();
+    } else {
+        oled_set_cursor(0, 0);
+        oled_write("Layer", false);
+        render_spacer(5);
+        oled_write_ln(layer_string(get_highest_layer(layer_state)), false);
+
+        oled_set_cursor(0, 4);
+        oled_write_ln("Key", false);
+        render_spacer(3);
+        oled_advance_page(false);
+        oled_write_ln("None", false);
+
+        oled_set_cursor(0, 8);
+        oled_write_ln("OS", false);
+        render_spacer(2);
+        oled_advance_page(false);
+        oled_write_ln("Wait", false);
+
+        oled_set_cursor(0, 12);
+        oled_write_ln("Rate", false);
+        render_spacer(4);
+    }
+    keyboard_post_init_user();
+}
+
+layer_state_t layer_state_set_kb(layer_state_t state) {
+    state = layer_state_set_user(state);
+    oled_set_cursor(0, 2);
+    oled_write_ln(layer_string(get_highest_layer(state)), false);
+    return state;
+}
+
+bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
+    current_keycode = keycode;
+    return process_record_user(keycode, record);
+};
+
+uint16_t loop_rate = 0;
+void     housekeeping_task_kb(void) {
+    if (is_keyboard_master()) {
+        static uint32_t     loop_count = 0;
+        static fast_timer_t loop_time  = 0;
+        loop_count++;
+        if (timer_elapsed_fast(loop_time) > 1000) {
+            loop_time  = timer_read_fast();
+            loop_rate  = loop_count > UINT16_MAX ? UINT16_MAX : loop_count;
+            loop_count = 0;
+            if (is_oled_on()) {
+                oled_set_cursor(0, 14);
+                oled_write(depad_str(get_u16_str(loop_rate, ' '), ' '), false);
+            }
+        }
+    }
+    if (is_oled_on() && last_input_activity_elapsed() > OLED_TIMEOUT) {
+        oled_off();
+    }
+}
+
+void oled_reinit_slave(void) {
+    oled_init(OLED_ROTATION_270);
+    oled_clear();
+    oled_set_cursor(0, 0);
+    oled_write_ln("WPM", false);
+    render_spacer(3);
+    oled_advance_page(false);
+    oled_write_ln(depad_str(get_u16_str(get_current_wpm(), ' '), ' '), false);
+
+    oled_set_cursor(0, 4);
+    oled_write_ln("RGB", false);
+    render_spacer(3);
+    render_rgb_info();
+
+    oled_set_cursor(0, 13);
+    render_small_mb_logo();
+}
+
+bool oled_task_kb(void) {
+    if (!oled_task_user()) {
+        return false;
+    }
+
+    static uint16_t last_keycode         = 0xFF;
+    static bool     oled_slave_init_done = false;
+
+    if (is_keyboard_master()) {
+        if (last_keycode != current_keycode) {
+            oled_set_cursor(0, 6);
+            if (current_keycode < ARRAY_SIZE(basic_codes_to_name)) {
+                oled_write_char(basic_codes_to_name[current_keycode], false);
+                oled_advance_page(true);
+            } else {
+                oled_write_ln(keycode_string(current_keycode), false);
+            }
+            last_keycode = current_keycode;
+        }
+    } else {
+        if (!oled_slave_init_done) {
+            if (timer_elapsed32(0) > 5000) {
+                oled_slave_init_done = true;
+                oled_reinit_slave();
+            }
+        } else {
+            static uint16_t last_wpm = 0;
+            if (rgb_matrix_get_hue() != last_hue || rgb_matrix_get_sat() != last_sat || rgb_matrix_get_val() != last_val || rgb_matrix_get_mode() != last_mode) {
+                render_rgb_info();
+            }
+            if (last_wpm != get_current_wpm()) {
+                last_wpm = get_current_wpm();
+                oled_set_cursor(0, 2);
+                oled_write_ln(depad_str(get_u16_str(last_wpm, ' '), ' '), false);
+            }
+        }
+    }
+
+    return false;
+}

+ 3 - 0
keyboards/mechboards/common/post_rules.mk

@@ -0,0 +1,3 @@
+ifeq ($(strip $(OLED_ENABLE)), yes)
+	SRC += keyboards/mechboards/common/display_oled.c
+endif

+ 54 - 0
keyboards/mechboards/common/rgb_effects.h

@@ -0,0 +1,54 @@
+// Copyright 2025 Dasky (@daskygit)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#ifdef CONVERTER_ENABLED
+#    define ENABLE_RGB_MATRIX_ALPHA_MODS
+#    define ENABLE_RGB_MATRIX_BREATHING
+#    define ENABLE_RGB_MATRIX_COLORBAND_PINWHEEL_SAT
+#    define ENABLE_RGB_MATRIX_COLORBAND_PINWHEEL_VAL
+#    define ENABLE_RGB_MATRIX_COLORBAND_SAT
+#    define ENABLE_RGB_MATRIX_COLORBAND_SPIRIAL_SAT
+#    define ENABLE_RGB_MATRIX_COLORBAND_SPIRIAL_VAL
+#    define ENABLE_RGB_MATRIX_COLORBAND_VAL
+#    define ENABLE_RGB_MATRIX_CYCLE_ALL
+#    define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
+#    define ENABLE_RGB_MATRIX_CYCLE_OUT_IN
+#    define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
+#    define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL
+#    define ENABLE_RGB_MATRIX_CYCLE_SPIRAL
+#    define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN
+#    define ENABLE_RGB_MATRIX_DIGITAL_RAIN
+#    define ENABLE_RGB_MATRIX_DUAL_BEACON
+#    define ENABLE_RGB_MATRIX_FLOWER_BLOOMING
+#    define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
+#    define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
+#    define ENABLE_RGB_MATRIX_HUE_BREATHING
+#    define ENABLE_RGB_MATRIX_HUE_PENDULUM
+#    define ENABLE_RGB_MATRIX_HUE_WAVE
+#    define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
+#    define ENABLE_RGB_MATRIX_PIXEL_FLOW
+#    define ENABLE_RGB_MATRIX_PIXEL_FRACTAL
+#    define ENABLE_RGB_MATRIX_PIXEL_RAIN
+#    define ENABLE_RGB_MATRIX_RAINBOW_BEACON
+#    define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
+#    define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
+#    define ENABLE_RGB_MATRIX_RAINDROPS
+#    define ENABLE_RGB_MATRIX_RIVERFLOW
+#    define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH
+#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE
+#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
+#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
+#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
+#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
+#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
+#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
+#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
+#    define ENABLE_RGB_MATRIX_SOLID_SPLASH
+#    define ENABLE_RGB_MATRIX_SPLASH
+#    define ENABLE_RGB_MATRIX_STARLIGHT
+#    define ENABLE_RGB_MATRIX_STARLIGHT_DUAL_HUE
+#    define ENABLE_RGB_MATRIX_STARLIGHT_DUAL_SAT
+#    define ENABLE_RGB_MATRIX_TYPING_HEATMAP
+#endif

+ 6 - 0
keyboards/mechboards/lily58/pro/config.h

@@ -0,0 +1,6 @@
+// Copyright 2025 Dasky (@daskygit)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "keyboards/mechboards/common/rgb_effects.h"

+ 206 - 0
keyboards/mechboards/lily58/pro/keyboard.json

@@ -0,0 +1,206 @@
+{
+    "manufacturer": "Mechboards",
+    "keyboard_name": "Lily58 Pro",
+    "maintainer": "dasky",
+    "build": {
+        "lto": true
+    },
+    "development_board": "promicro",
+    "diode_direction": "COL2ROW",
+    "encoder": {
+        "rotary": [
+            {"pin_a": "F5", "pin_b": "F4"}
+        ]
+    },
+    "features": {
+        "bootmagic": true,
+        "encoder": true,
+        "extrakey": true,
+        "mousekey": true,
+        "oled": true,
+        "os_detection": true,
+        "rgb_matrix": true,
+        "wpm": true
+    },
+    "matrix_pins": {
+        "cols": ["F6", "F7", "B1", "B3", "B2", "B6"],
+        "rows": ["C6", "D7", "E6", "B4", "B5"]
+    },
+    "rgb_matrix": {
+        "animations": {
+            "cycle_left_right": true
+        },
+        "default": {
+            "animation": "cycle_left_right"
+        },
+        "driver": "ws2812",
+        "layout": [
+            {"matrix": [0, 5], "x": 72, "y": 4, "flags": 4},
+            {"matrix": [0, 4], "x": 58, "y": 2, "flags": 4},
+            {"matrix": [0, 3], "x": 43, "y": 0, "flags": 4},
+            {"matrix": [0, 2], "x": 29, "y": 2, "flags": 4},
+            {"matrix": [0, 1], "x": 14, "y": 6, "flags": 4},
+            {"matrix": [0, 0], "x": 0, "y": 8, "flags": 4},
+            {"matrix": [1, 0], "x": 0, "y": 23, "flags": 4},
+            {"matrix": [1, 1], "x": 14, "y": 21, "flags": 4},
+            {"matrix": [1, 2], "x": 29, "y": 17, "flags": 4},
+            {"matrix": [1, 3], "x": 43, "y": 15, "flags": 4},
+            {"matrix": [1, 4], "x": 58, "y": 17, "flags": 4},
+            {"matrix": [1, 5], "x": 72, "y": 19, "flags": 4},
+            {"matrix": [2, 5], "x": 72, "y": 34, "flags": 4},
+            {"matrix": [2, 4], "x": 58, "y": 32, "flags": 4},
+            {"matrix": [2, 3], "x": 43, "y": 30, "flags": 4},
+            {"matrix": [2, 2], "x": 29, "y": 32, "flags": 4},
+            {"matrix": [2, 1], "x": 14, "y": 36, "flags": 4},
+            {"matrix": [2, 0], "x": 0, "y": 38, "flags": 4},
+            {"matrix": [3, 0], "x": 0, "y": 53, "flags": 4},
+            {"matrix": [3, 1], "x": 14, "y": 51, "flags": 4},
+            {"matrix": [3, 2], "x": 29, "y": 47, "flags": 4},
+            {"matrix": [3, 3], "x": 43, "y": 45, "flags": 4},
+            {"matrix": [3, 4], "x": 58, "y": 47, "flags": 4},
+            {"matrix": [3, 5], "x": 72, "y": 49, "flags": 4},
+            {"matrix": [4, 5], "x": 87, "y": 41, "flags": 4},
+            {"matrix": [4, 4], "x": 87, "y": 64, "flags": 4},
+            {"matrix": [4, 3], "x": 65, "y": 64, "flags": 4},
+            {"matrix": [4, 2], "x": 51, "y": 62, "flags": 4},
+            {"matrix": [4, 1], "x": 36, "y": 62, "flags": 4},
+            {"x": 96, "y": 64, "flags": 2},
+            {"x": 32, "y": 64, "flags": 2},
+            {"x": 0, "y": 64, "flags": 2},
+            {"x": 0, "y": 32, "flags": 2},
+            {"x": 16, "y": 0, "flags": 2},
+            {"x": 50, "y": 0, "flags": 2},
+            {"x": 80, "y": 0, "flags": 2},
+            {"x": 96, "y": 32, "flags": 2},
+            {"matrix": [5, 5], "x": 152, "y": 4, "flags": 4},
+            {"matrix": [5, 4], "x": 166, "y": 2, "flags": 4},
+            {"matrix": [5, 3], "x": 181, "y": 0, "flags": 4},
+            {"matrix": [5, 2], "x": 195, "y": 2, "flags": 4},
+            {"matrix": [5, 1], "x": 210, "y": 6, "flags": 4},
+            {"matrix": [5, 0], "x": 224, "y": 8, "flags": 4},
+            {"matrix": [6, 0], "x": 224, "y": 23, "flags": 4},
+            {"matrix": [6, 1], "x": 210, "y": 21, "flags": 4},
+            {"matrix": [6, 2], "x": 195, "y": 17, "flags": 4},
+            {"matrix": [6, 3], "x": 181, "y": 15, "flags": 4},
+            {"matrix": [6, 4], "x": 166, "y": 17, "flags": 4},
+            {"matrix": [6, 5], "x": 152, "y": 19, "flags": 4},
+            {"matrix": [7, 5], "x": 152, "y": 34, "flags": 4},
+            {"matrix": [7, 4], "x": 166, "y": 32, "flags": 4},
+            {"matrix": [7, 3], "x": 181, "y": 30, "flags": 4},
+            {"matrix": [7, 2], "x": 195, "y": 32, "flags": 4},
+            {"matrix": [7, 1], "x": 210, "y": 36, "flags": 4},
+            {"matrix": [7, 0], "x": 224, "y": 38, "flags": 4},
+            {"matrix": [8, 0], "x": 224, "y": 53, "flags": 4},
+            {"matrix": [8, 1], "x": 210, "y": 51, "flags": 4},
+            {"matrix": [8, 2], "x": 195, "y": 47, "flags": 4},
+            {"matrix": [8, 3], "x": 181, "y": 45, "flags": 4},
+            {"matrix": [8, 4], "x": 166, "y": 47, "flags": 4},
+            {"matrix": [8, 5], "x": 152, "y": 49, "flags": 4},
+            {"matrix": [9, 5], "x": 137, "y": 41, "flags": 4},
+            {"matrix": [9, 4], "x": 137, "y": 64, "flags": 4},
+            {"matrix": [9, 3], "x": 159, "y": 64, "flags": 4},
+            {"matrix": [9, 2], "x": 173, "y": 62, "flags": 4},
+            {"matrix": [9, 1], "x": 188, "y": 62, "flags": 4},
+            {"x": 128, "y": 64, "flags": 2},
+            {"x": 192, "y": 64, "flags": 2},
+            {"x": 224, "y": 64, "flags": 2},
+            {"x": 224, "y": 32, "flags": 2},
+            {"x": 206, "y": 0, "flags": 2},
+            {"x": 150, "y": 0, "flags": 2},
+            {"x": 140, "y": 0, "flags": 2},
+            {"x": 128, "y": 32, "flags": 2}
+        ],
+        "max_brightness": 120,
+        "sleep": true,
+        "split_count": [37, 37]
+    },
+    "rgblight": {
+        "max_brightness": 120
+    },
+    "split": {
+        "enabled": true,
+        "serial": {
+            "pin": "D2"
+        },
+        "transport": {
+            "sync": {
+                "matrix_state": true,
+                "oled": true,
+                "wpm": true
+            }
+        }
+    },
+    "url": "mechboards.co.uk",
+    "usb": {
+        "device_version": "1.0.0",
+        "pid": "0x0002",
+        "vid": "0x7171"
+    },
+    "ws2812": {
+        "pin": "D3"
+    },
+    "layouts": {
+        "LAYOUT": {
+            "layout": [
+                {"matrix": [0, 0], "x": 0, "y": 0.5},
+                {"matrix": [0, 1], "x": 1, "y": 0.375},
+                {"matrix": [0, 2], "x": 2, "y": 0.125},
+                {"matrix": [0, 3], "x": 3, "y": 0},
+                {"matrix": [0, 4], "x": 4, "y": 0.125},
+                {"matrix": [0, 5], "x": 5, "y": 0.25},
+                {"matrix": [5, 5], "x": 10.5, "y": 0.25},
+                {"matrix": [5, 4], "x": 11.5, "y": 0.125},
+                {"matrix": [5, 3], "x": 12.5, "y": 0},
+                {"matrix": [5, 2], "x": 13.5, "y": 0.125},
+                {"matrix": [5, 1], "x": 14.5, "y": 0.375},
+                {"matrix": [5, 0], "x": 15.5, "y": 0.5},
+                {"matrix": [1, 0], "x": 0, "y": 1.5},
+                {"matrix": [1, 1], "x": 1, "y": 1.375},
+                {"matrix": [1, 2], "x": 2, "y": 1.125},
+                {"matrix": [1, 3], "x": 3, "y": 1},
+                {"matrix": [1, 4], "x": 4, "y": 1.125},
+                {"matrix": [1, 5], "x": 5, "y": 1.25},
+                {"matrix": [6, 5], "x": 10.5, "y": 1.25},
+                {"matrix": [6, 4], "x": 11.5, "y": 1.125},
+                {"matrix": [6, 3], "x": 12.5, "y": 1},
+                {"matrix": [6, 2], "x": 13.5, "y": 1.125},
+                {"matrix": [6, 1], "x": 14.5, "y": 1.375},
+                {"matrix": [6, 0], "x": 15.5, "y": 1.5},
+                {"matrix": [2, 0], "x": 0, "y": 2.5},
+                {"matrix": [2, 1], "x": 1, "y": 2.375},
+                {"matrix": [2, 2], "x": 2, "y": 2.125},
+                {"matrix": [2, 3], "x": 3, "y": 2},
+                {"matrix": [2, 4], "x": 4, "y": 2.125},
+                {"matrix": [2, 5], "x": 5, "y": 2.25},
+                {"matrix": [7, 5], "x": 10.5, "y": 2.25},
+                {"matrix": [7, 4], "x": 11.5, "y": 2.125},
+                {"matrix": [7, 3], "x": 12.5, "y": 2},
+                {"matrix": [7, 2], "x": 13.5, "y": 2.125},
+                {"matrix": [7, 1], "x": 14.5, "y": 2.375},
+                {"matrix": [7, 0], "x": 15.5, "y": 2.5},
+                {"matrix": [3, 0], "x": 0, "y": 3.5},
+                {"matrix": [3, 1], "x": 1, "y": 3.375},
+                {"matrix": [3, 2], "x": 2, "y": 3.125},
+                {"matrix": [3, 3], "x": 3, "y": 3},
+                {"matrix": [3, 4], "x": 4, "y": 3.125},
+                {"matrix": [3, 5], "x": 5, "y": 3.25},
+                {"matrix": [4, 5], "x": 6, "y": 2.75},
+                {"matrix": [9, 5], "x": 9.5, "y": 2.75},
+                {"matrix": [8, 5], "x": 10.5, "y": 3.25},
+                {"matrix": [8, 4], "x": 11.5, "y": 3.125},
+                {"matrix": [8, 3], "x": 12.5, "y": 3},
+                {"matrix": [8, 2], "x": 13.5, "y": 3.125},
+                {"matrix": [8, 1], "x": 14.5, "y": 3.375},
+                {"matrix": [8, 0], "x": 15.5, "y": 3.5},
+                {"matrix": [4, 1], "x": 2.5, "y": 4.125},
+                {"matrix": [4, 2], "x": 3.5, "y": 4.15},
+                {"matrix": [4, 3], "x": 4.5, "y": 4.25},
+                {"matrix": [4, 4], "x": 6, "y": 4.25, "h": 1.5},
+                {"matrix": [9, 4], "x": 9.5, "y": 4.25, "h": 1.5},
+                {"matrix": [9, 3], "x": 11, "y": 4.25},
+                {"matrix": [9, 2], "x": 12, "y": 4.15},
+                {"matrix": [9, 1], "x": 13, "y": 4.15}
+            ]
+        }
+    }
+}

+ 51 - 0
keyboards/mechboards/lily58/pro/keymaps/default/keymap.c

@@ -0,0 +1,51 @@
+// Copyright 2025 Dasky (@daskygit)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include QMK_KEYBOARD_H
+
+// clang-format off
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+ [0] = LAYOUT(
+  KC_ESC,   KC_1,   KC_2,    KC_3,    KC_4,    KC_5,                     KC_6,    KC_7,    KC_8,    KC_9,    KC_0,    KC_GRV,
+  KC_TAB,   KC_Q,   KC_W,    KC_E,    KC_R,    KC_T,                     KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    KC_MINS,
+  KC_LCTL,  KC_A,   KC_S,    KC_D,    KC_F,    KC_G,                     KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_QUOT,
+  KC_LSFT,  KC_Z,   KC_X,    KC_C,    KC_V,    KC_B, KC_LBRC,  KC_RBRC,  KC_N,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH,  KC_RSFT,
+                           KC_LALT, KC_LGUI, MO(1), KC_SPC, KC_ENT, MO(2), KC_BSPC, KC_RGUI
+),
+
+[1] = LAYOUT(
+  _______, _______, _______, _______, _______, _______,                   _______, _______, _______,_______, _______, _______,
+  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,                     KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,
+  KC_GRV, KC_EXLM, KC_AT,   KC_HASH, KC_DLR,  KC_PERC,                   KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_TILD,
+  _______, _______, _______, _______, _______, _______, _______, _______, XXXXXXX, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE,
+                             _______, _______, _______, _______, _______,  MO(3), _______, _______
+),
+
+
+[2] = LAYOUT(
+  _______, _______, _______, _______, _______, _______,                     _______, _______, _______, _______, _______, _______,
+  KC_GRV,  KC_1,    KC_2,    KC_3,    KC_4,    KC_5,                        KC_6,    KC_7,    KC_8,    KC_9,    KC_0,    _______,
+  KC_F1,  KC_F2,    KC_F3,   KC_F4,   KC_F5,   KC_F6,                       XXXXXXX, KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT, XXXXXXX,
+  KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,   _______, _______,  KC_PLUS, KC_MINS, KC_EQL,  KC_LBRC, KC_RBRC, KC_BSLS,
+                             _______, _______, MO(3),  _______, _______,  _______, _______, _______
+),
+
+  [3] = LAYOUT(
+  XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,                   XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
+  XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,                   XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
+  RM_TOGG, RM_HUEU, RM_SATU, RM_VALU, XXXXXXX, XXXXXXX,                   XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
+  RM_NEXT, RM_HUED, RM_SATD, RM_VALD, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
+                             _______, _______, _______, _______, _______,  _______, _______, _______
+  )
+};
+
+#if defined(ENCODER_MAP_ENABLE)
+const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
+    [0] =  { ENCODER_CCW_CW(KC_VOLD, KC_VOLU),      ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
+    [1] =  { ENCODER_CCW_CW(KC_TRNS, KC_TRNS),      ENCODER_CCW_CW(KC_TRNS, KC_TRNS)},
+    [2] =  { ENCODER_CCW_CW(KC_TRNS, KC_TRNS),      ENCODER_CCW_CW(KC_TRNS, KC_TRNS)},
+    [3] =  { ENCODER_CCW_CW(KC_TRNS, KC_TRNS),      ENCODER_CCW_CW(KC_TRNS, KC_TRNS)}
+};
+#endif
+// clang-format on

+ 1 - 0
keyboards/mechboards/lily58/pro/keymaps/default/rules.mk

@@ -0,0 +1 @@
+ENCODER_MAP_ENABLE = yes

+ 1 - 0
keyboards/mechboards/lily58/pro/post_rules.mk

@@ -0,0 +1 @@
+include keyboards/mechboards/common/post_rules.mk

+ 15 - 0
keyboards/mechboards/lily58/pro/pro.c

@@ -0,0 +1,15 @@
+// Copyright 2025 Dasky (@daskygit)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "quantum.h"
+
+#ifdef OLED_ENABLE
+void render_logo(void) {
+    static const char PROGMEM pro_logo[] = {
+        252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 31,  31,  31,  31, 31, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 252, 0,   0,   0,   248, 248, 0,   0,   0,   0,   0,   0,   0,   0,   128, 128, 0,   0,   224, 224, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   248, 248, 24,  24,  24,  24,  24,  24,  0,   0,   240, 248, 24, 24, 24, 24, 24, 248, 240, 0,   0,   0,   0,   0,   0,  0,  0,  0,  0,  0,   0,   0,   0,  0,  0,  0,  0,  0,   255, 255, 255, 255, 255, 7,   7,  7,  7,  7,  255, 7,   7,   7,   7,   7,   255, 7, 7, 7, 7, 7, 255, 7,  7,  7,  7,  7,  255, 7,  7,  7,  7,  7,  255, 255, 255, 4,   4,   4,   4,   4,   255,
+        7,   7,   7,   7,   7,   255, 7,   7,   7,   7,   7,   255, 255, 255, 255, 255, 0,   0,   0,   255, 255, 0,   0,   0,   0,   0,   0,   0,   0,   249, 249, 0,   0,   255, 255, 0,   0,   248, 248, 0,   0,  0,  0,   248, 248, 0,   0,   7,   7,   6,   6,   6,   6,   254, 252, 0,   0,   251, 255, 6,   6,   6,   6,   6,   255, 251, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   255, 255, 255, 255, 255, 65,  65,  65,  65,  65,  255, 255, 255, 255, 255, 255, 255, 65, 65, 65, 65, 65, 255, 255, 255, 255, 255, 255, 255, 65, 65, 65, 65, 65, 255, 255, 255, 65, 65, 65, 65, 65, 255, 127, 127, 127, 127, 127, 255, 65, 65, 65, 65, 65,  255, 255, 255, 255, 255, 0,   0, 0, 3, 3, 3, 3,   3,  3,  3,  3,  0,  0,   3,  3,  0,  0,  3,  3,   0,   0,   131, 131, 131, 131, 131, 131,
+        255, 255, 0,   0,   3,   3,   3,   3,   3,   3,   3,   1,   0,   0,   1,   3,   3,   3,   3,   3,   3,   3,   225, 240, 48,  176, 176, 112, 240, 48,  176, 176, 112, 240, 112, 176, 176, 112, 240, 224, 0,  0,  63,  127, 255, 255, 255, 240, 240, 240, 240, 240, 255, 255, 255, 255, 255, 255, 255, 240, 240, 240, 240, 240, 255, 255, 255, 255, 255, 255, 255, 240, 240, 240, 240, 240, 255, 255, 255, 240, 240, 240, 240, 240, 255, 240, 240, 240, 240, 240, 255, 240, 240, 240, 240, 240, 255, 255, 255, 127, 63,  0,   0,  0,  0,  0,  0,  0,   0,   0,   0,   0,   0,   0,   0,  0,  0,  0,  0,  0,   0,   0,   1,  1,  1,  1,  1,  1,   1,   1,   0,   0,   0,   0,   0,  0,  0,  0,  0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 31,  63, 48, 61, 61, 62, 63,  48, 61, 61, 50, 63, 56,  55,  55,  56,  63,  31,  0,   0,
+    };
+    oled_write_raw_P(pro_logo, sizeof(pro_logo));
+}
+#endif

+ 25 - 0
keyboards/mechboards/lily58/pro/readme.md

@@ -0,0 +1,25 @@
+# Lily58 Pro
+
+A refreshed Lily58 PCB with RGB, battery, power switch and encoder support.
+
+* Keyboard Maintainer: [dasky](https://github.com/daskygit)
+* Hardware Supported: Controllers using promicro footprint.
+* Hardware Availability: https://mechboards.co.uk
+
+Make example for this keyboard (after setting up your build environment):
+
+    qmk compile -kb mechboards/lily58/pro -km default
+
+Flashing example for this keyboard:
+
+    qmk flash -kb mechboards/lily58/pro -km default
+
+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
+
+Enter the bootloader in 3 ways:
+
+* **Bootmagic reset**: Hold down the top left key (for left half) or top right key (for right half) when plugging in USB.
+* **Physical reset button**: Briefly double press the button below the TRRS socket.
+* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available