[Keymap Removal] keyboard with most keymaps (#23092)
This commit is contained in:
		
							parent
							
								
									b8646bc40b
								
							
						
					
					
						commit
						78a74ca974
					
				
					 426 changed files with 0 additions and 27404 deletions
				
			
		| 
						 | 
				
			
			@ -1,46 +0,0 @@
 | 
			
		|||
/* Copyright 2022 Chris Tanaka <https://github.com/christanaka>
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
| 
						 | 
				
			
			@ -1,157 +0,0 @@
 | 
			
		|||
/* Copyright 2022 Chris Tanaka <https://github.com/christanaka>
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#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][NUM_DIRECTIONS] = {
 | 
			
		||||
    [_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 led_t persistent_led_state = {0};
 | 
			
		||||
    led_t led_state = host_keyboard_led_state();
 | 
			
		||||
 | 
			
		||||
    // Only update if the LED state has changed
 | 
			
		||||
    // Otherwise, the OLED will not turn off if an LED is on.
 | 
			
		||||
    if (persistent_led_state.raw != led_state.raw) {
 | 
			
		||||
        persistent_led_state = led_state;
 | 
			
		||||
 | 
			
		||||
        oled_write_ln_P(PSTR("            "), false);
 | 
			
		||||
 | 
			
		||||
        if (led_state.caps_lock) {
 | 
			
		||||
            oled_set_cursor(0, 1);
 | 
			
		||||
            oled_write_P(PSTR("CAPS"), false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (led_state.num_lock) {
 | 
			
		||||
            oled_set_cursor(5, 1);
 | 
			
		||||
            oled_write_P(PSTR("NUM"), true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (led_state.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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,51 +0,0 @@
 | 
			
		|||
# Typehud Keymap
 | 
			
		||||
 | 
			
		||||
VIA compatible keymap that displays a live wpm HUD on your OLED.
 | 
			
		||||
 | 
			
		||||
<https://nullbits.co/static/file/snap-typehud.webp>
 | 
			
		||||
 | 
			
		||||
## 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
 | 
			
		||||
```
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +0,0 @@
 | 
			
		|||
OLED_ENABLE = yes
 | 
			
		||||
WPM_ENABLE = yes
 | 
			
		||||
VIA_ENABLE = yes
 | 
			
		||||
ENCODER_MAP_ENABLE = yes
 | 
			
		||||
 | 
			
		||||
SRC += typehud.c
 | 
			
		||||
| 
						 | 
				
			
			@ -1,349 +0,0 @@
 | 
			
		|||
/* 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 <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,87 +0,0 @@
 | 
			
		|||
/* Copyright 2022 Chris Tanaka <https://github.com/christanaka>
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue