From 28acdf31386101fd8b53b0e8e9e221c268521bc3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 12 Apr 2026 22:59:49 +0000 Subject: [PATCH 1/3] Fix OLED display: remove bogus OLED_IC/FLIP_SEGMENT/128X64 defines and restore original rotation logic The previous PR #5 added OLED defines (OLED_IC_SSD1312, OLED_DISPLAY_128X64, OLED_FLIP_SEGMENT, etc.) from a hallucinated "Keebart vial_oled reference" keymap that doesn't exist. These caused the display to be flipped horizontally and upside down. Restores: - Original oled_init_user: default rotation for master, OLED_ROTATION_180 for slave - is_keyboard_master() routing in oled_task_user - Clean config.h without bogus OLED hardware defines - Clean rules.mk without redundant OLED_DRIVER/OLED_TRANSPORT Agent-Logs-Url: https://github.com/timfee/qmk_userspace/sessions/efa72aeb-690c-4f81-8e57-678197ccc4ab Co-authored-by: timfee <3246342+timfee@users.noreply.github.com> --- users/timfee/config.h | 12 +----------- users/timfee/rules.mk | 2 -- users/timfee/timfee.c | 9 ++++++--- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/users/timfee/config.h b/users/timfee/config.h index f75804a5..b542624b 100644 --- a/users/timfee/config.h +++ b/users/timfee/config.h @@ -15,17 +15,7 @@ #define COMBO_TERM 40 #define COMBO_ONLY_FROM_LAYER 0 -// ── OLED (matches Keebart vial_oled reference) ── -#define OLED_IC OLED_IC_SSD1312 -#define OLED_DISPLAY_128X64 -#define OLED_FLIP_SEGMENT -#define OLED_DISPLAY_ADDRESS 0x3C -#define OLED_CHARGE_PUMP_VALUE 0x72 -#define OLED_BRIGHTNESS 64 -#define OLED_TIMEOUT 0 -#define OLED_FADE_OUT - -// ── Split sync ── +// ── OLED / split sync ── #define SPLIT_OLED_ENABLE #define SPLIT_WPM_ENABLE #define SPLIT_LAYER_STATE_ENABLE diff --git a/users/timfee/rules.mk b/users/timfee/rules.mk index 6960764d..260c9eb0 100644 --- a/users/timfee/rules.mk +++ b/users/timfee/rules.mk @@ -1,5 +1,3 @@ COMBO_ENABLE = yes WPM_ENABLE = yes OLED_ENABLE = yes -OLED_DRIVER = ssd1306 -OLED_TRANSPORT = i2c diff --git a/users/timfee/timfee.c b/users/timfee/timfee.c index 5f276023..01cf5f72 100644 --- a/users/timfee/timfee.c +++ b/users/timfee/timfee.c @@ -127,11 +127,14 @@ uint16_t get_quick_tap_term(uint16_t keycode, keyrecord_t *record) { } } -// ── OLED display (rotation matches Keebart vial_oled reference) ── +// ── OLED display ── #ifdef OLED_ENABLE oled_rotation_t oled_init_user(oled_rotation_t rotation) { - return OLED_ROTATION_90; + if (!is_keyboard_master()) { + return OLED_ROTATION_180; + } + return rotation; } static void render_layer(void) { @@ -177,7 +180,7 @@ static void render_wpm(void) { } bool oled_task_user(void) { - if (is_keyboard_left()) { + if (is_keyboard_master()) { render_layer(); render_keycode(); render_wpm(); From d4fd2c14b6569405352ae25852e9983599dbd029 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 12 Apr 2026 23:04:07 +0000 Subject: [PATCH 2/3] =?UTF-8?q?Revert=20all=20OLED=20changes=20from=20PR?= =?UTF-8?q?=20#4=20and=20#5=20=E2=80=94=20restore=20original=20working=20c?= =?UTF-8?q?ode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes ALL OLED code added by previous Copilot agents. The original user code had no OLED customization — the keyboard-level defaults handled the displays correctly. Files now exactly match their pre-PR#4 state (b686f0a). Agent-Logs-Url: https://github.com/timfee/qmk_userspace/sessions/efa72aeb-690c-4f81-8e57-678197ccc4ab Co-authored-by: timfee <3246342+timfee@users.noreply.github.com> --- users/timfee/config.h | 5 ---- users/timfee/rules.mk | 2 -- users/timfee/timfee.c | 68 ------------------------------------------- 3 files changed, 75 deletions(-) diff --git a/users/timfee/config.h b/users/timfee/config.h index b542624b..5ce6c48c 100644 --- a/users/timfee/config.h +++ b/users/timfee/config.h @@ -14,8 +14,3 @@ #define COMBO_COUNT 8 #define COMBO_TERM 40 #define COMBO_ONLY_FROM_LAYER 0 - -// ── OLED / split sync ── -#define SPLIT_OLED_ENABLE -#define SPLIT_WPM_ENABLE -#define SPLIT_LAYER_STATE_ENABLE diff --git a/users/timfee/rules.mk b/users/timfee/rules.mk index 260c9eb0..ab1e4381 100644 --- a/users/timfee/rules.mk +++ b/users/timfee/rules.mk @@ -1,3 +1 @@ COMBO_ENABLE = yes -WPM_ENABLE = yes -OLED_ENABLE = yes diff --git a/users/timfee/timfee.c b/users/timfee/timfee.c index 01cf5f72..7bac4a4f 100644 --- a/users/timfee/timfee.c +++ b/users/timfee/timfee.c @@ -2,7 +2,6 @@ // ── State for require-prior-idle ── static uint16_t last_key_time = 0; -static uint16_t last_keycode = KC_NO; // ── Combos (matching Vial config) ── const uint16_t PROGMEM lparen_combo[] = {KC_R, KC_T, COMBO_END}; @@ -28,7 +27,6 @@ combo_t key_combos[COMBO_COUNT] = { // ── Require-prior-idle: bypass hold-tap during typing ── bool process_record_user(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { - last_keycode = keycode; uint16_t elapsed = timer_elapsed(last_key_time); switch (keycode) { @@ -126,69 +124,3 @@ uint16_t get_quick_tap_term(uint16_t keycode, keyrecord_t *record) { default: return QUICK_TAP_TERM; } } - -// ── OLED display ── -#ifdef OLED_ENABLE - -oled_rotation_t oled_init_user(oled_rotation_t rotation) { - if (!is_keyboard_master()) { - return OLED_ROTATION_180; - } - return rotation; -} - -static void render_layer(void) { - oled_write_P(PSTR("Layer: "), false); - switch (get_highest_layer(layer_state)) { - case 0: - oled_write_ln_P(PSTR("Base"), false); - break; - case 1: - oled_write_ln_P(PSTR("Symbols"), false); - break; - case 2: - oled_write_ln_P(PSTR("Nav/Fn"), false); - break; - default: - oled_write_ln_P(PSTR("???"), false); - break; - } -} - -static void render_keycode(void) { - oled_write_P(PSTR("Key: 0x"), false); - // Print last keycode as 4-digit hex - static const char hex[] = "0123456789ABCDEF"; - char buf[5]; - buf[0] = hex[(last_keycode >> 12) & 0xF]; - buf[1] = hex[(last_keycode >> 8) & 0xF]; - buf[2] = hex[(last_keycode >> 4) & 0xF]; - buf[3] = hex[ last_keycode & 0xF]; - buf[4] = '\0'; - oled_write_ln(buf, false); -} - -static void render_wpm(void) { - oled_write_P(PSTR("WPM: "), false); - uint8_t wpm = get_current_wpm(); - char buf[4]; - buf[0] = (wpm >= 100) ? ('0' + wpm / 100) : ' '; - buf[1] = (wpm >= 10) ? ('0' + (wpm / 10) % 10) : ' '; - buf[2] = '0' + wpm % 10; - buf[3] = '\0'; - oled_write_ln(buf, false); -} - -bool oled_task_user(void) { - if (is_keyboard_master()) { - render_layer(); - render_keycode(); - render_wpm(); - } else { - render_wpm(); - render_layer(); - } - return false; -} - -#endif From db75e079eebcb8f96a2d29ab8574b2d0251daecd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 12 Apr 2026 23:18:01 +0000 Subject: [PATCH 3/3] Add OLED support based on Keebart vial_oled reference (no Keebart logo) Agent-Logs-Url: https://github.com/timfee/qmk_userspace/sessions/4a24a9cd-66a0-48c5-9207-bd980524ca2a Co-authored-by: timfee <3246342+timfee@users.noreply.github.com> --- users/timfee/bitmaps.h | 21 +++ users/timfee/config.h | 17 +++ users/timfee/rules.mk | 5 + users/timfee/timfee.c | 300 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 users/timfee/bitmaps.h diff --git a/users/timfee/bitmaps.h b/users/timfee/bitmaps.h new file mode 100644 index 00000000..27c3bd1b --- /dev/null +++ b/users/timfee/bitmaps.h @@ -0,0 +1,21 @@ +#pragma once + +static const char EMPTY_BITMAP [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const char NUM_LOCK_BITMAP [] PROGMEM = { + 0x00, 0xc0, 0x20, 0x38, 0x24, 0xb2, 0xaa, 0x2a, 0x2a, 0x2a, 0xb2, 0x24, 0x38, 0x20, 0xc0, 0x00, + 0x00, 0x3f, 0x40, 0x40, 0x40, 0x5f, 0x40, 0x43, 0x4c, 0x50, 0x5f, 0x40, 0x40, 0x40, 0x3f, 0x00 +}; + +static const char CAPS_LOCK_BITMAP [] PROGMEM = { + 0x00, 0xc0, 0x20, 0x38, 0x24, 0x32, 0xaa, 0xaa, 0xaa, 0xaa, 0x32, 0x24, 0x38, 0x20, 0xc0, 0x00, + 0x00, 0x3f, 0x40, 0x40, 0x40, 0x4f, 0x50, 0x50, 0x50, 0x50, 0x49, 0x40, 0x40, 0x40, 0x3f, 0x00 +}; + +static const char SCROLL_LOCK_BITMAP [] PROGMEM = { + 0x00, 0xc0, 0x20, 0x38, 0x24, 0x32, 0xaa, 0xaa, 0xaa, 0xaa, 0xb2, 0x24, 0x38, 0x20, 0xc0, 0x00, + 0x00, 0x3f, 0x40, 0x40, 0x40, 0x53, 0x52, 0x52, 0x54, 0x54, 0x4c, 0x40, 0x40, 0x40, 0x3f, 0x00 +}; diff --git a/users/timfee/config.h b/users/timfee/config.h index 5ce6c48c..96d73f79 100644 --- a/users/timfee/config.h +++ b/users/timfee/config.h @@ -14,3 +14,20 @@ #define COMBO_COUNT 8 #define COMBO_TERM 40 #define COMBO_ONLY_FROM_LAYER 0 + +// ── OLED (SSD1312 on Keebart Corne Choc Pro) ── +#define OLED_IC OLED_IC_SSD1312 +#define OLED_DISPLAY_128X64 +#define OLED_FLIP_SEGMENT +#define OLED_DISPLAY_ADDRESS 0x3C +#define OLED_CHARGE_PUMP_VALUE 0x72 +#define OLED_BRIGHTNESS 64 +#define OLED_TIMEOUT 0 +#define OLED_TIMEOUT_USER 60000 +#define OLED_FADE_OUT + +// ── Split transport ── +#define SPLIT_TRANSPORT_MIRROR +#define SPLIT_WPM_ENABLE +#define SPLIT_WATCHDOG_TIMEOUT 4000 +#define SPLIT_TRANSACTION_IDS_USER USER_SYNC_OLED_STATE, USER_SYNC_LASTKEY, USER_SYNC_PRESSES diff --git a/users/timfee/rules.mk b/users/timfee/rules.mk index ab1e4381..9bccca09 100644 --- a/users/timfee/rules.mk +++ b/users/timfee/rules.mk @@ -1 +1,6 @@ COMBO_ENABLE = yes +OLED_ENABLE = yes +OLED_DRIVER = ssd1306 +OLED_TRANSPORT = i2c +WPM_ENABLE = yes +KEYCODE_STRING_ENABLE = yes diff --git a/users/timfee/timfee.c b/users/timfee/timfee.c index 7bac4a4f..27f9f7d4 100644 --- a/users/timfee/timfee.c +++ b/users/timfee/timfee.c @@ -1,5 +1,10 @@ #include "timfee.h" +#ifdef OLED_ENABLE +#include "bitmaps.h" +#include "transactions.h" +#endif + // ── State for require-prior-idle ── static uint16_t last_key_time = 0; @@ -24,9 +29,180 @@ combo_t key_combos[COMBO_COUNT] = { COMBO(bslh_combo, KC_BSLS), }; -// ── Require-prior-idle: bypass hold-tap during typing ── +// ═══════════════════════════════════════════════════════════════════ +// OLED state (compiled only when OLED_ENABLE is set) +// ═══════════════════════════════════════════════════════════════════ +#ifdef OLED_ENABLE + +static const uint8_t OLED_WIDTH = OLED_DISPLAY_HEIGHT; + +static const char PROGMEM QMK_LOGO_1[] = { 0x81, 0x82, 0x83, 0x84, 0x00 }; +static const char PROGMEM QMK_LOGO_2[] = { 0xA1, 0xA2, 0xA3, 0xA4, 0x00 }; +static const char PROGMEM QMK_LOGO_3[] = { 0xC1, 0xC2, 0xC3, 0xC4, 0x00 }; + +typedef struct { bool oled_on; } oled_state_m2s_t; +typedef struct { uint16_t keycode; } lastkey_m2s_t; +typedef struct { uint32_t left; uint32_t right; } presses_m2s_t; + +static bool g_oled_init_done = false; +static uint8_t g_oled_max_char; +static uint32_t g_user_ontime = 0; +static uint16_t g_last_keycode = KC_NO; +static uint32_t g_press_left = 0; +static uint32_t g_press_right = 0; +static oled_state_m2s_t g_remote_oled_state = { false }; +static presses_m2s_t g_remote_presses = { 0, 0 }; + +// ── Charge-pump enable pin (hardware-specific) ── +static inline pin_t get_charge_pump_enable_pin(void) { + return is_keyboard_left() ? GP5 : GP25; +} + +// ── Raw-byte blit for 16×16 icons ── +void oled_blit_16x16_P(const char *icon, uint8_t x, uint8_t page) { + for (uint8_t i = 0; i < 16; i++) { + oled_write_raw_byte(pgm_read_byte(&icon[i]), page * OLED_WIDTH + x + i); + oled_write_raw_byte(pgm_read_byte(&icon[16 + i]), (page + 1) * OLED_WIDTH + x + i); + } +} + +// ── Helpers ── +static uint16_t unwrap_keycode(uint16_t kc) { + if (kc >= QK_MOD_TAP && kc <= QK_MOD_TAP_MAX) + return QK_MOD_TAP_GET_TAP_KEYCODE(kc); + if (kc >= QK_LAYER_TAP && kc <= QK_LAYER_TAP_MAX) + return QK_LAYER_TAP_GET_TAP_KEYCODE(kc); + return kc; +} + +static uint8_t round_percentage(float x) { + float f = x + 0.5f; + uint8_t r = (uint8_t)f; + if ((f - (float)r) == 0.0f && (r & 1)) r--; + return r; +} + +static void oled_print_right_aligned(const char *text, uint8_t width) { + uint8_t len = strlen(text); + uint8_t pad = (len < width) ? (width - len) : 0; + for (uint8_t i = 0; i < pad; i++) oled_write_P(PSTR(" "), false); + oled_write(text, false); +} + +// ── Info renderers ── +static void print_current_layer(uint8_t row) { + char buf[8]; + switch (get_highest_layer(layer_state)) { + case 0: strcpy(buf, "Base"); break; + case 1: strcpy(buf, "Symbols"); break; + case 2: strcpy(buf, "Nav"); break; + default: snprintf(buf, sizeof(buf), "%d", (int)get_highest_layer(layer_state)); break; + } + oled_set_cursor(0, row); + oled_print_right_aligned(buf, g_oled_max_char); +} + +static void print_uptime(uint8_t row) { + uint32_t total_min = timer_read32() / 60000u; + uint32_t hours = total_min / 60u; + uint32_t minutes = total_min % 60u; + if (hours > 999u) { hours = 999u; minutes = 59u; } + char buf[8]; + snprintf(buf, sizeof(buf), "%3luh%02lum", hours, minutes); + oled_set_cursor(0, row); + oled_print_right_aligned(buf, g_oled_max_char); +} + +static void print_wpm(uint8_t row) { + uint16_t dwpm = (uint16_t)get_current_wpm() * 10u; + char buf[11]; + snprintf(buf, sizeof(buf), "%3u.%1u WPM", dwpm / 10u, dwpm % 10u); + oled_set_cursor(0, row); + oled_print_right_aligned(buf, g_oled_max_char); +} + +static void print_balance(uint8_t row, uint8_t pct) { + char buf[6]; + snprintf(buf, sizeof(buf), "%3u %%", pct); + oled_set_cursor(0, row); + oled_print_right_aligned(buf, g_oled_max_char); +} + +// ── Split RPC callbacks (slave side) ── +static void user_sync_oled_state_slave(uint8_t in_len, const void *in_data, + uint8_t out_len, void *out_data) { + if (in_len >= sizeof(oled_state_m2s_t)) + memcpy(&g_remote_oled_state, in_data, sizeof(oled_state_m2s_t)); +} + +static void user_sync_lastkey_slave(uint8_t in_len, const void *in_data, + uint8_t out_len, void *out_data) { + if (in_len >= sizeof(lastkey_m2s_t)) + g_last_keycode = ((const lastkey_m2s_t *)in_data)->keycode; +} + +static void user_sync_presses_slave(uint8_t in_len, const void *in_data, + uint8_t out_len, void *out_data) { + if (in_len >= sizeof(presses_m2s_t)) + memcpy(&g_remote_presses, in_data, sizeof(presses_m2s_t)); +} + +#endif // OLED_ENABLE + +// ═══════════════════════════════════════════════════════════════════ +// QMK hooks +// ═══════════════════════════════════════════════════════════════════ + +#ifdef OLED_ENABLE +void keyboard_post_init_user(void) { + pin_t pen = get_charge_pump_enable_pin(); + gpio_set_pin_output(pen); + gpio_write_pin_low(pen); + wait_ms(5); + + transaction_register_rpc(USER_SYNC_OLED_STATE, user_sync_oled_state_slave); + transaction_register_rpc(USER_SYNC_LASTKEY, user_sync_lastkey_slave); + transaction_register_rpc(USER_SYNC_PRESSES, user_sync_presses_slave); + + if (!is_keyboard_master()) wait_ms(90); +} + +void housekeeping_task_user(void) { + if (is_keyboard_master()) { + static uint32_t last_sync = 0; + if (timer_elapsed32(last_sync) > 500) { + oled_state_m2s_t pkt = { is_oled_on() }; + (void)transaction_rpc_send(USER_SYNC_OLED_STATE, sizeof(pkt), &pkt); + last_sync = timer_read32(); + } + } +} +#endif // OLED_ENABLE + +// ── Require-prior-idle + OLED keypress tracking ── bool process_record_user(uint16_t keycode, keyrecord_t *record) { +#ifdef OLED_ENABLE + g_user_ontime = timer_read32(); +#endif + if (record->event.pressed) { +#ifdef OLED_ENABLE + // Track every keypress for OLED (before RPI may intercept) + g_last_keycode = keycode; + if (record->event.key.row < MATRIX_ROWS / 2) { + g_press_left++; + } else { + g_press_right++; + } + if (is_keyboard_master()) { + lastkey_m2s_t kpkt = { g_last_keycode }; + (void)transaction_rpc_send(USER_SYNC_LASTKEY, sizeof(kpkt), &kpkt); + presses_m2s_t ppkt = { g_press_left, g_press_right }; + (void)transaction_rpc_send(USER_SYNC_PRESSES, sizeof(ppkt), &ppkt); + } +#endif + + // Require-prior-idle handling uint16_t elapsed = timer_elapsed(last_key_time); switch (keycode) { @@ -124,3 +300,125 @@ uint16_t get_quick_tap_term(uint16_t keycode, keyrecord_t *record) { default: return QUICK_TAP_TERM; } } + +// ═══════════════════════════════════════════════════════════════════ +// OLED rendering +// ═══════════════════════════════════════════════════════════════════ +#ifdef OLED_ENABLE + +oled_rotation_t oled_init_user(oled_rotation_t rotation) { + return OLED_ROTATION_90; +} + +static bool oled_post_init(void) { + if (!g_oled_init_done) { + g_oled_max_char = oled_max_chars(); + + pin_t pen = get_charge_pump_enable_pin(); + gpio_write_pin_high(pen); + wait_ms(20); + oled_clear(); + + g_user_ontime = timer_read32(); + g_oled_init_done = true; + } + return false; +} + +bool oled_task_user(void) { + oled_post_init(); + + // ── Resolve press counts (master has live data, slave gets synced) ── + uint32_t lpresses, rpresses; + if (is_keyboard_master()) { + lpresses = g_press_left; + rpresses = g_press_right; + } else { + lpresses = g_remote_presses.left; + rpresses = g_remote_presses.right; + } + + // ── OLED on/off management ── + if (is_keyboard_master()) { + uint32_t idle = timer_elapsed32(g_user_ontime); + if (is_oled_on() && idle > OLED_TIMEOUT_USER) { + oled_off(); + oled_state_m2s_t pkt = { false }; + (void)transaction_rpc_send(USER_SYNC_OLED_STATE, sizeof(pkt), &pkt); + return false; + } + if (!is_oled_on() && idle <= OLED_TIMEOUT_USER) { + oled_on(); + oled_state_m2s_t pkt = { true }; + (void)transaction_rpc_send(USER_SYNC_OLED_STATE, sizeof(pkt), &pkt); + } + } else { + if (g_remote_oled_state.oled_on) { + if (!is_oled_on()) oled_on(); + } else { + if (is_oled_on()) oled_off(); + return false; + } + } + + // ── Compute balance ── + uint32_t total = lpresses + rpresses; + if (total == 0) total = 1; + uint8_t pct_left = round_percentage((100.0f * lpresses) / total); + uint8_t pct_right = round_percentage((100.0f * rpresses) / total); + + // ── Left half ── + if (is_keyboard_left()) { + oled_set_cursor(0, 0); + oled_write_P(PSTR("Layer:"), false); + print_current_layer(1); + + // Lock indicators (16×16 bitmaps) + led_t led_state = host_keyboard_led_state(); + oled_blit_16x16_P(led_state.num_lock ? NUM_LOCK_BITMAP : EMPTY_BITMAP, 0, 3); + oled_blit_16x16_P(led_state.caps_lock ? CAPS_LOCK_BITMAP : EMPTY_BITMAP, 24, 3); + oled_blit_16x16_P(led_state.scroll_lock ? SCROLL_LOCK_BITMAP : EMPTY_BITMAP, 48, 3); + + oled_set_cursor(0, 7); + oled_write_P(PSTR("Left:"), false); + print_balance(8, pct_left); + + oled_set_cursor(0, 10); + oled_write_P(PSTR("Last Key:"), false); + oled_set_cursor(0, 11); + oled_print_right_aligned(get_keycode_string(unwrap_keycode(g_last_keycode)), + g_oled_max_char); + + // QMK logo + oled_set_cursor(0, 13); oled_write_P(QMK_LOGO_1, false); + oled_set_cursor(0, 14); oled_write_P(QMK_LOGO_2, false); + oled_set_cursor(0, 15); oled_write_P(QMK_LOGO_3, false); + oled_set_cursor(7, 15); oled_write_P(PSTR("QMK"), false); + } + // ── Right half ── + else { + oled_set_cursor(0, 0); + oled_write_P(PSTR("Uptime:"), false); + print_uptime(1); + + oled_set_cursor(0, 3); + oled_write_P(PSTR("Avg Speed"), false); + oled_set_cursor(0, 4); + oled_write_P(PSTR("(25 s):"), false); + print_wpm(5); + + oled_set_cursor(0, 7); + oled_write_P(PSTR("Right:"), false); + print_balance(8, pct_right); + + // QMK logo + oled_set_cursor(0, 13); oled_write_P(QMK_LOGO_1, false); + oled_set_cursor(0, 14); oled_write_P(QMK_LOGO_2, false); + oled_set_cursor(0, 15); oled_write_P(QMK_LOGO_3, false); + oled_set_cursor(7, 15); oled_write_P(PSTR("QMK"), false); + } + + return false; +} + +#endif // OLED_ENABLE