aboutsummaryrefslogtreecommitdiff
path: root/keyboards/mechboards/common/display_oled.c
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/mechboards/common/display_oled.c')
-rw-r--r--keyboards/mechboards/common/display_oled.c385
1 files changed, 385 insertions, 0 deletions
diff --git a/keyboards/mechboards/common/display_oled.c b/keyboards/mechboards/common/display_oled.c
new file mode 100644
index 0000000000..fed13c22fd
--- /dev/null
+++ b/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;
+}