From 27e6e27d3a2ff9d91bcf0f189cdc39509bef0335 Mon Sep 17 00:00:00 2001 From: Jay Greco Date: Sun, 2 Apr 2023 12:12:06 -0700 Subject: [Keyboard] Add nullbits SNAP keyboard (#18916) Co-authored-by: Ryan --- keyboards/nullbitsco/snap/keymaps/typehud/config.h | 46 +++ keyboards/nullbitsco/snap/keymaps/typehud/keymap.c | 157 +++++++++ .../nullbitsco/snap/keymaps/typehud/readme.md | 51 +++ keyboards/nullbitsco/snap/keymaps/typehud/rules.mk | 7 + .../nullbitsco/snap/keymaps/typehud/typehud.c | 349 +++++++++++++++++++++ .../nullbitsco/snap/keymaps/typehud/typehud.h | 87 +++++ 6 files changed, 697 insertions(+) create mode 100644 keyboards/nullbitsco/snap/keymaps/typehud/config.h create mode 100644 keyboards/nullbitsco/snap/keymaps/typehud/keymap.c create mode 100644 keyboards/nullbitsco/snap/keymaps/typehud/readme.md create mode 100644 keyboards/nullbitsco/snap/keymaps/typehud/rules.mk create mode 100644 keyboards/nullbitsco/snap/keymaps/typehud/typehud.c create mode 100644 keyboards/nullbitsco/snap/keymaps/typehud/typehud.h (limited to 'keyboards/nullbitsco/snap/keymaps/typehud') diff --git a/keyboards/nullbitsco/snap/keymaps/typehud/config.h b/keyboards/nullbitsco/snap/keymaps/typehud/config.h new file mode 100644 index 0000000000..62c11709a2 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/typehud/config.h @@ -0,0 +1,46 @@ +/* Copyright 2022 Chris Tanaka + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +/* space savers */ +#define DYNAMIC_KEYMAP_LAYER_COUNT 3 +#define NO_ACTION_TAPPING +#define NO_ACTION_ONESHOT +#define TAPPING_FORCE_HOLD + +// Old configuration +#define OLED_BRIGHTNESS 128 +#define OLED_TIMEOUT 30000 +#define OLED_UPDATE_INTERVAL 200 + +// Selectively undefine to save space +// VIA support won't fit otherwise +#ifdef RGBLIGHT_ENABLE +#undef RGBLIGHT_EFFECT_TWINKLE +#endif //RGB LIGHT_ENABLE + +// Split configuration +#define SPLIT_TRANSPORT_MIRROR +#define SPLIT_WPM_ENABLE + +// Typehud configuration +#define TYPEHUD_FILLGRAPH +#define TYPEHUD_MATRIX_COLS 16 +// #define TYPEHUD_MASTER +// #define TYPEHUD_MATRIX_ROTATE_90 +// #define TYPEHUD_MATRIX_ROTATE_180 +// #define TYPEHUD_MATRIX_ROTATE_270 diff --git a/keyboards/nullbitsco/snap/keymaps/typehud/keymap.c b/keyboards/nullbitsco/snap/keymaps/typehud/keymap.c new file mode 100644 index 0000000000..ea3fc2e8eb --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/typehud/keymap.c @@ -0,0 +1,157 @@ +/* Copyright 2022 Chris Tanaka + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include QMK_KEYBOARD_H +#include "typehud.h" + +// clang-format off +enum layers { + _BASE, + _VIA1, + _VIA2 +}; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [_BASE] = LAYOUT_all( + KC_ESC, 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_PSCR, KC_PAUS, + KC_F13, KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL, KC_HOME, + KC_F14, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_END, + KC_F15, KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGUP, + KC_F16, KC_LSFT, KC_NUHS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_PGDN, + KC_F17, KC_LCTL, KC_LGUI, KC_LALT, MO(_VIA1), KC_SPC, KC_SPC, MO(_VIA1), KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + ), + [_VIA1] = LAYOUT_all( + QK_BOOT,KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO + ), + [_VIA2] = LAYOUT_all( + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO + ) +}; +// clang-format on + +#if defined(ENCODER_MAP_ENABLE) +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { + [_BASE] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_MPRV, KC_MNXT) }, + [_VIA1] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) }, + [_VIA2] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) } +}; +#endif + +oled_rotation_t oled_init_user(oled_rotation_t rotation) { + oled_clear(); + +#ifdef TYPEHUD_MASTER + if (is_keyboard_master()) { +#else + if (!is_keyboard_master()) { +#endif + typehud_init(); + } + + if (is_keyboard_left()) + return OLED_ROTATION_0; + else + return OLED_ROTATION_180; +} + +static void render_status(void) { + oled_set_cursor(0, 0); + oled_write_P(PSTR("SNAP75 "), false); + oled_write_P(PSTR("Layer "), false); + switch (get_highest_layer(layer_state)) { + case _VIA1: + oled_write_P(PSTR("FN1 "), false); + break; + case _VIA2: + oled_write_P(PSTR("FN2 "), false); + break; + default: // use BASE case as default + oled_write_P(PSTR("Base"), false); + } + + // Host Keyboard LED Status + oled_set_cursor(0, 1); + static uint8_t persistent_led_state = 0; + uint8_t led_usb_state = host_keyboard_leds(); + + // Only update if the LED state has changed + // Otherwise, the OLED will not turn off if an LED is on. + if (persistent_led_state != led_usb_state) { + persistent_led_state = led_usb_state; + + oled_write_ln_P(PSTR(" "), false); + + if (IS_LED_ON(led_usb_state, USB_LED_CAPS_LOCK)) { + oled_set_cursor(0, 1); + oled_write_P(PSTR("CAPS"), false); + } + + if (IS_LED_ON(led_usb_state, USB_LED_NUM_LOCK)) { + oled_set_cursor(5, 1); + oled_write_P(PSTR("NUM"), true); + } + + if (IS_LED_ON(led_usb_state, USB_LED_SCROLL_LOCK)) { + oled_set_cursor(9, 1); + oled_write_P(PSTR("SCR"), false); + } + } + + // WPM and max WPM + oled_set_cursor(0, 2); + oled_write_P(PSTR("WPM "), false); + uint8_t current_wpm = get_current_wpm(); + oled_write(get_u8_str(current_wpm, '0'), true); + + oled_set_cursor(8, 2); + oled_write_P(PSTR("MAX "), false); + static uint8_t max_wpm; + max_wpm = MAX(max_wpm, current_wpm); + oled_write(get_u8_str(max_wpm, '0'), true); +} + +bool oled_task_user(void) { +#ifdef TYPEHUD_MASTER + if (is_keyboard_master()) { +#else + if (!is_keyboard_master()) { +#endif + typehud_render(); + } else { + render_status(); + } + + return true; +} + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + typehud_process_record(record); + return true; +} + +bool should_process_keypress(void) { + return true; +} diff --git a/keyboards/nullbitsco/snap/keymaps/typehud/readme.md b/keyboards/nullbitsco/snap/keymaps/typehud/readme.md new file mode 100644 index 0000000000..d5f50f310c --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/typehud/readme.md @@ -0,0 +1,51 @@ +# Typehud Keymap + +VIA compatible keymap that displays a live wpm HUD on your OLED. + + + +## Configuration + +Configuration options (other than the keymap itself) can be found in `typehud/config.h`. + +### Graph Type + +By default the graph is filled. For a non-filled graph remove or comment out the following line: + +```c +#define TYPEHUD_FILLGRAPH +``` + +### Keyboard Matrix Orientation + +To change the keyboard matrix orientation add one of the following: + +- `TYPEHUD_MATRIX_ROTATE_90` +- `TYPEHUD_MATRIX_ROTATE_180` +- `TYPEHUD_MATRIX_ROTATE_270` + +### Keyboard Matrix Key Overrides + +If the number of physical keys doesn't match the keyboard matrix rows/columns you can override it: + +```c +#define TYPEHUD_MATRIX_ROWS 6 +#define TYPEHUD_MATRIX_COLS 16 +``` + +In addition if the position of the physical keys doesn't match the matrix you can override it. Negative numbers will shift the keys left/up and positive numbers will shift the keys right/down: + +```c +#define TYPEHUD_MATRIX_ROW_SHIFT -1 +#define TYPEHUD_MATRIX_COL_SHIFT -2 +``` + +### Split Keyboard Side + +For split keyboards, the keymap assumes it will be rendered to the slave side. + +To render to master instead, add the following configuration line: + +```c +#define TYPEHUD_MASTER +``` diff --git a/keyboards/nullbitsco/snap/keymaps/typehud/rules.mk b/keyboards/nullbitsco/snap/keymaps/typehud/rules.mk new file mode 100644 index 0000000000..151e44f4aa --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/typehud/rules.mk @@ -0,0 +1,7 @@ +OLED_ENABLE = yes +OLED_DRIVER = SSD1306 +WPM_ENABLE = yes +VIA_ENABLE = yes +ENCODER_MAP_ENABLE = yes + +SRC += typehud.c diff --git a/keyboards/nullbitsco/snap/keymaps/typehud/typehud.c b/keyboards/nullbitsco/snap/keymaps/typehud/typehud.c new file mode 100644 index 0000000000..ad884f843b --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/typehud/typehud.c @@ -0,0 +1,349 @@ +/* Copyright 2023 Jay Greco + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "typehud.h" + +static bool is_initialized; +static uint16_t timer; +static int8_t bar_height; +static uint8_t wpm_arr[_GRAPH_WIDTH]; +static uint8_t point_arr[_GRAPH_WIDTH]; + + +static void + render_graph(uint8_t wpm), + render_caret(void), + render_axis(void), + render_bar(void), + render_init(void); + +/* + * Renders the wpm counter. + */ +static void render_wpm(uint8_t wpm) { + oled_set_cursor(0, 0); + oled_write("WPM", false); + oled_set_cursor(0, 1); + oled_write(get_u8_str(wpm, '0'), false); +} + +/* + * Renders the keyboard matrix. + */ +static void render_matrix(keyrecord_t *record) { + uint8_t x = _MATRIX_X; + uint8_t y = _MATRIX_Y; + uint8_t width = _MATRIX_WIDTH; + uint8_t height = _MATRIX_HEIGHT; +#ifdef SPLIT_KEYBOARD + uint8_t rows = _NML_MATRIX_ROWS; + uint8_t cols = _NML_MATRIX_COLS; +#endif + + // On initial render draw the matrix outline + if (!is_initialized) { + for (uint8_t i = 1; i <= width - 2; i++) { + oled_write_pixel(x + i, y, true); + oled_write_pixel(x + i, y + height - 1, true); + } + for (uint8_t j = 1; j <= height - 2; j++) { + oled_write_pixel(x, y + j, true); + oled_write_pixel(x + width - 1, y + j, true); + } + return; + } + + // Determine position based on matrix rotation + // For split keyboards the keys on the right half get appended as additional rows and + // have their columns reset at 0 +#ifdef SPLIT_KEYBOARD + uint8_t row = (record->event.key.row % rows); + uint8_t col = record->event.key.col; + if (record->event.key.row >= rows) { + col += (cols / 2); + } +#else + uint8_t row = record->event.key.row; + uint8_t col = record->event.key.col; +#endif + +#ifdef TYPEHUD_MATRIX_ROW_SHIFT + row += TYPEHUD_MATRIX_ROW_SHIFT; +#endif +#ifdef TYPEHUD_MATRIX_COL_SHIFT + col += TYPEHUD_MATRIX_COL_SHIFT; +#endif + + // Scale position to key size + uint8_t size = _MATRIX_SIZE; + row *= size; + col *= size; + + // Render key in matrix + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { +#if defined(TYPEHUD_MATRIX_ROTATE_90) + uint8_t key_x = x + width - 1 - size - row; + uint8_t key_y = y + 1 + col; +#elif defined(TYPEHUD_MATRIX_ROTATE_180) + uint8_t key_x = x + width - 1 - size - col; + uint8_t key_y = y + height - 1 - size - row; +#elif defined(TYPEHUD_MATRIX_ROTATE_270) + uint8_t key_x = x + 1 + row; + uint8_t key_y = y + height - 1 - size - col; +#else + uint8_t key_x = x + 1 + col; + uint8_t key_y = y + 1 + row; +#endif + oled_write_pixel(key_x + i, key_y + j, record->event.pressed); + } + } +} + +/* + * Renders the graph. + */ +static void render_graph(uint8_t wpm) { + uint8_t x = _GRAPH_X; + uint8_t y = _GRAPH_Y + _GRAPH_HEIGHT; + uint8_t width = _GRAPH_WIDTH; + uint8_t height = _GRAPH_HEIGHT; + + // Handle intial graph render + if (!is_initialized) { + for (uint8_t i = 0; i < width; i++) { + oled_write_pixel(x + i, y, true); + } + return; + } + + uint8_t i = 0; + + // Shift all graph points except last to the left and re-render + for (; i < width - 1; i++) { + int8_t point_delta = point_arr[i + 1] - point_arr[i]; + +#ifdef TYPEHUD_FILLGRAPH + if (point_delta < 0) { +#else + if (point_delta != 0) { +#endif + oled_write_pixel(x + i, y - point_arr[i], false); + } + + wpm_arr[i] = wpm_arr[i + 1]; + point_arr[i] = point_arr[i + 1]; + + if (point_delta != 0) { + oled_write_pixel(x + i, y - point_arr[i], true); + } + } + + // Clear last graph point + if (wpm > wpm_arr[i] && point_arr[i] + 1 <= height) { +#ifndef TYPEHUD_FILLGRAPH + oled_write_pixel(x + i, y - point_arr[i], false); +#endif + point_arr[i] = point_arr[i] + 1; + } else if ((wpm < wpm_arr[i] && point_arr[i] - 1 >= 0) || (wpm <= 0 && point_arr[i] > 0)) { + oled_write_pixel(x + i, y - point_arr[i], false); + point_arr[i] = point_arr[i] - 1; + } + + // Render last graph point + wpm_arr[i] = wpm; + + if (point_arr[i] != point_arr[i - 1]) { + oled_write_pixel(x + i, y - point_arr[i], true); + } +} + +/* + * Renders the caret. + */ +static void render_caret(void) { + uint8_t x = _GRAPH_X + _GRAPH_WIDTH + _GRAPH_RPAD + _CARET_WIDTH; + uint8_t y = 0; + uint8_t width = _CARET_WIDTH; + uint8_t height = _CARET_HEIGHT; + uint8_t g_width = _GRAPH_WIDTH; + uint8_t g_height = _GRAPH_HEIGHT; + + // Handle initial caret render + if (!is_initialized) { + y = g_height - point_arr[g_width - 1]; + + for (uint8_t i = 0; i < width; i++) { + for (uint8_t j = i; j < height - i; j++) { + oled_write_pixel(x - i, y - j, true); + } + } + return; + } + + // Handle caret updates and re-render + int8_t point_delta = point_arr[g_width - 1] - point_arr[g_width - 2]; + if (point_delta > 0) { + y = g_height - point_arr[g_width - 2]; + if (y - height + 1 > 0) { + for (uint8_t i = 0; i < width; i++) { + oled_write_pixel(x - i, y - i, false); + oled_write_pixel(x - i, y - height + i, true); + } + } + } else if (point_delta < 0) { + y = g_height - point_arr[g_width - 1]; + if (y - height + 1 > 0) { + for (uint8_t i = 0; i < width; i++) { + oled_write_pixel(x - i, y - height + i, false); + oled_write_pixel(x - i, y - i, true); + } + } + } +} + +/* + * Renders the axis. + */ +static void render_axis(void) { + uint8_t x = _AXIS_X; + uint8_t y = _AXIS_HEIGHT; + uint8_t width = _AXIS_WIDTH; + uint8_t height = _AXIS_HEIGHT; + uint8_t tick_width = _AXIS_TICK_WIDTH; + uint8_t subtick_width = _AXIS_SUBTICK_WIDTH; + uint8_t interval = _AXIS_INTERVAL; + uint8_t tick_interval = _AXIS_TICK_INTERVAL; + + for (uint8_t j = 0; j <= height; j += interval) { + uint8_t curr_tick_width = 0; + + // Determine tick width and draw extra point if at interval + if (j % tick_interval == 0) { + curr_tick_width = tick_width; + oled_write_pixel(x, y - j, true); + } else { + curr_tick_width = subtick_width; + } + + // Draw tick + for (uint8_t i = 0; i < curr_tick_width; i++) { + oled_write_pixel(x + width - i, y - j, true); + } + } +} + +/* + * Renders the input bar. + */ +static void render_bar(void) { + uint8_t x = _BAR_X; + uint8_t width = _BAR_WIDTH; + uint8_t height = _BAR_HEIGHT; + + // Increment bar height + bar_height = (bar_height + 1) % height; + + // When bar resets back to 0, clear bar pixels + if (bar_height % height == 0) { + for (uint8_t i = 0; i < width; i++) { + for (uint8_t j = 0; j < height; j++) { + oled_write_pixel(x + i, j, false); + } + } + } + + // Draw new bar pixels + for (uint8_t i = 0; i < width; i++) { + oled_write_pixel(x + i, height - bar_height, true); + } +} + +/* + * Renders the initial frame for all components. + */ +static void render_init(void) { + render_graph(0); + render_caret(); + render_matrix(NULL); + render_axis(); +} + +/* + * Initializes and resets the typehud. + */ +void typehud_init(void) { + // Reset variables + is_initialized = false; + timer = 0; + bar_height = -1; + + for (uint8_t i = 0; i < _GRAPH_WIDTH; i++) { + wpm_arr[i] = 0; + point_arr[i] = 0; + } + + // Draw the initial graph + for (uint8_t i = 0; i < _GRAPH_WIDTH; i++) { + oled_write_pixel(_GRAPH_X + i, _GRAPH_HEIGHT, true); + } +} + +/* + * Renders the typehud. + */ +void typehud_render(void) { + uint8_t wpm = get_current_wpm(); + + // Run initial rendering once + if (!is_initialized) { + render_init(); + is_initialized = true; + } + + // Render wpm + render_wpm(wpm); + + // Render next graph and caret frame when timer reaches refresh rate + if (timer_elapsed(timer) > _GRAPH_REFRESH) { + render_graph(wpm); + render_caret(); + timer = timer_read(); + } +} + +/* + * Handles keypresses for the typehud. + */ +void typehud_process_record(keyrecord_t *record) { + // For split keyboards, only draw on correct side +#ifdef SPLIT_KEYBOARD +# ifdef TYPEHUD_MASTER + if (!is_keyboard_master()) { +# else + if (is_keyboard_master()) { +# endif + return; + } +#endif + // Render/update matrix + render_matrix(record); + + // Render/update input bar on keypress + if (record->event.pressed) { + render_bar(); + } +} diff --git a/keyboards/nullbitsco/snap/keymaps/typehud/typehud.h b/keyboards/nullbitsco/snap/keymaps/typehud/typehud.h new file mode 100644 index 0000000000..c3ed876c42 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/typehud/typehud.h @@ -0,0 +1,87 @@ +/* Copyright 2022 Chris Tanaka + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include QMK_KEYBOARD_H + +// clang-format off +#define _OLED_WIDTH (OLED_DISPLAY_WIDTH - 1) +#define _OLED_HEIGHT (OLED_DISPLAY_HEIGHT - 1) + +#ifdef SPLIT_KEYBOARD +#define _PHYSICAL_PARTS 2 +#else +#define _PHYSICAL_PARTS 1 +#endif + +#ifdef TYPEHUD_MATRIX_ROWS +#define _NML_MATRIX_ROWS TYPEHUD_MATRIX_ROWS +#else +# ifdef SPLIT_KEYBOARD +#define _NML_MATRIX_ROWS (MATRIX_ROWS / 2) +# else +#define _NML_MATRIX_ROWS MATRIX_ROWS +# endif +#endif + +#ifdef TYPEHUD_MATRIX_COLS +#define _NML_MATRIX_COLS TYPEHUD_MATRIX_COLS +#else +#define _NML_MATRIX_COLS (MATRIX_COLS * _PHYSICAL_PARTS) +#endif + +#define _MATRIX_SIZE 2 +#if defined(TYPEHUD_MATRIX_ROTATE_90) || defined(TYPEHUD_MATRIX_ROTATE_270) +#define _MATRIX_WIDTH (_NML_MATRIX_ROWS * _MATRIX_SIZE + 2) +#define _MATRIX_HEIGHT (_NML_MATRIX_COLS * _MATRIX_SIZE + 2) +#else +#define _MATRIX_WIDTH (_NML_MATRIX_COLS * _MATRIX_SIZE + 2) +#define _MATRIX_HEIGHT (_NML_MATRIX_ROWS * _MATRIX_SIZE + 2) +#endif +#define _MATRIX_X 0 +#define _MATRIX_Y (_OLED_HEIGHT - _MATRIX_HEIGHT + 1) +#define _MATRIX_RPAD 2 +#define _MATRIX_PAD_WIDTH (_MATRIX_WIDTH + _MATRIX_RPAD) + +#define _BAR_WIDTH 3 +#define _BAR_HEIGHT _OLED_HEIGHT +#define _BAR_X (_OLED_WIDTH - _BAR_WIDTH) + +#define _AXIS_WIDTH 5 +#define _AXIS_HEIGHT _OLED_HEIGHT +#define _AXIS_TICK_WIDTH 3 +#define _AXIS_SUBTICK_WIDTH 2 +#define _AXIS_INTERVAL 3 +#define _AXIS_TICK_INTERVAL 15 +#define _AXIS_RPAD 2 +#define _AXIS_PAD_WIDTH (_AXIS_WIDTH + _AXIS_RPAD) +#define _AXIS_X (_OLED_WIDTH - _BAR_WIDTH - _AXIS_PAD_WIDTH) + +#define _CARET_WIDTH 3 +#define _CARET_HEIGHT 5 + +#define _GRAPH_RPAD 2 +#define _GRAPH_MAX_WIDTH (_OLED_WIDTH - _BAR_WIDTH - _AXIS_PAD_WIDTH - _CARET_WIDTH - _GRAPH_RPAD - _MATRIX_PAD_WIDTH) +#define _GRAPH_WIDTH (_GRAPH_MAX_WIDTH - 4) +#define _GRAPH_HEIGHT 31 +#define _GRAPH_REFRESH 300 +#define _GRAPH_X (_MATRIX_WIDTH + _MATRIX_RPAD) +#define _GRAPH_Y 0 +// clang-format on + +void + typehud_init(void), + typehud_render(void), + typehud_process_record(keyrecord_t *record); -- cgit v1.2.3