wave.h (4978B)
1 /* Copyright 2021 HorrorTroll <https://github.com/HorrorTroll> 2 * Copyright 2021 Gopolar 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #pragma once 19 20 extern const unsigned char font[] PROGMEM; 21 22 #define ROW_1 OLED_DISPLAY_WIDTH 23 #define ROW_2 (OLED_DISPLAY_WIDTH * 2) 24 25 static uint32_t wave_sleep = 0; 26 27 #define FRAME_TIMEOUT (1000/28) 28 29 static uint16_t wave_timer = 0; 30 31 static uint8_t next_bar_val = 0; 32 static uint8_t next_log_byte[OLED_FONT_WIDTH] = {0}; 33 static uint8_t line1[OLED_DISPLAY_WIDTH] = {0}; 34 static uint8_t line2[OLED_DISPLAY_WIDTH] = {0}; 35 36 static const uint8_t PROGMEM bar_lut[8] = {0, 16, 24, 56, 60, 124, 126, 255}; 37 38 #define BAR_KEY_WEIGHT 128 39 #define BAR_KEY_DECAY_MAX 18 40 41 static uint8_t bar_key_decay = BAR_KEY_DECAY_MAX; 42 43 // clang-format off 44 static const char PROGMEM code_to_name[0xFF] = { 45 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 46 ' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', // 0x 47 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', // 1x 48 '3', '4', '5', '6', '7', '8', '9', '0', 128, 136, 132, 131, 22, '-', '=', '[', // 2x 49 ']','\\', '#', ';','\'', '`', ',', '.', '/', 130, 7, 7, 7, 7, 7, 7, // 3x 50 7, 7, 7, 7, 7, 7, 137, 138, 139, 140, 141, 30, 143, 142, 31, 26, // 4x 51 27, 25, 24, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // 5x 52 ' ', ' ', ' ', ' ','\\', 135, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // 6x 53 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // 7x 54 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // 8x 55 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // 9x 56 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // Ax 57 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // Bx 58 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // Cx 59 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // Dx 60 15, 129, 133, 4, 15, 129, 133, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // Ex 61 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' // Fx 62 }; 63 // clang-format on 64 65 void add_keylog(uint16_t keycode) { 66 if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || 67 (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) || 68 (keycode >= QK_MODS && keycode <= QK_MODS_MAX)) { 69 keycode = keycode & 0xFF; 70 } else if (keycode > 0xFF) { 71 keycode = 0; 72 } 73 74 if (keycode < ARRAY_SIZE(code_to_name)) { 75 char log_char = pgm_read_byte(&code_to_name[keycode]); 76 77 for (uint8_t j = 0; j < OLED_FONT_WIDTH; j++) { 78 const uint8_t glyph_line = pgm_read_byte(&font[log_char * OLED_FONT_WIDTH + j]); 79 next_log_byte[j] = glyph_line; 80 } 81 } 82 } 83 84 bool process_record_user_oled(uint16_t keycode, keyrecord_t *record) { 85 if (record->event.pressed) { 86 wave_sleep = timer_read32(); 87 add_keylog(keycode); 88 89 uint8_t t = next_bar_val + BAR_KEY_WEIGHT; 90 91 if (t < next_bar_val) { 92 next_bar_val = 255; 93 } else { 94 next_bar_val = t; 95 } 96 97 bar_key_decay = BAR_KEY_DECAY_MAX; 98 } 99 100 return true; 101 } 102 103 void render_frame(void) { 104 // rotate line 1, and stick in the next byte of the next char, 105 // then rotate the next char buffer 106 memmove(line1+1, line1, OLED_DISPLAY_WIDTH - 1); 107 line1[0] = next_log_byte[OLED_FONT_WIDTH - 1]; 108 memmove(next_log_byte+1, next_log_byte, OLED_FONT_WIDTH - 1); 109 next_log_byte[0] = 0; 110 111 // rotate line 2, sticking in the next display value 112 uint8_t disp_val = pgm_read_byte(&bar_lut[next_bar_val / 32]); 113 memmove(line2+1, line2, OLED_DISPLAY_WIDTH - 1); 114 line2[0] = disp_val; 115 116 // draw both bars 117 for (uint8_t i = 0; i < OLED_DISPLAY_WIDTH; i++) { 118 oled_write_raw_byte(line1[i], ROW_1 + i); 119 oled_write_raw_byte(line2[i], ROW_2 + i); 120 } 121 122 // decay the next bar value 123 if (next_bar_val > bar_key_decay) { 124 next_bar_val -= bar_key_decay; 125 } else { 126 next_bar_val = 0; 127 } 128 129 if (bar_key_decay > 1) { 130 bar_key_decay -= 1; 131 } 132 }