summaryrefslogtreecommitdiffstats
path: root/keyboards/handwired/horrortroll/k552/lib/wave.c
blob: 79b4e0ced7f3dd4969a1e301768cf58cf4f1095f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* Copyright 2021 HorrorTroll <https://github.com/HorrorTroll>
 *
 * 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/>.
 */

extern const unsigned char font[] PROGMEM;

#define ROW_1 OLED_DISPLAY_WIDTH
#define ROW_2 (OLED_DISPLAY_WIDTH * 2)

static uint32_t wave_sleep = 0;

#define FRAME_TIMEOUT (1000/24)

static uint16_t wave_timer = 0;

static uint8_t next_bar_val = 0;
static uint8_t next_log_byte[OLED_FONT_WIDTH] = {0};
static uint8_t line1[OLED_DISPLAY_WIDTH] = {0};
static uint8_t line2[OLED_DISPLAY_WIDTH] = {0};

static const uint8_t PROGMEM bar_lut[8] = {0, 16, 24, 56, 60, 124, 126, 255};

#define BAR_KEY_WEIGHT 128
#define BAR_KEY_DECAY_MAX 18

static uint8_t bar_key_decay = BAR_KEY_DECAY_MAX;

// clang-format off
static const char PROGMEM code_to_name[0xFF] = {
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    ' ', ' ', ' ', ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',  // 0x
    'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2',  // 1x
    '3', '4', '5', '6', '7', '8', '9', '0', 128, 136, 132, 131,  22, '-', '=', '[',  // 2x
    ']','\\', '#', ';','\'', '`', ',', '.', '/', 130,   7,   7,   7,   7,   7,   7,  // 3x
      7,   7,   7,   7,   7,   7, 137, 138, 139, 140, 141,  30, 143, 142,  31,  26,  // 4x
     27,  25,  24, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',  // 5x
    ' ', ' ', ' ', ' ', ' ', 135, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',  // 6x
    ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',  // 7x
    ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',  // 8x
    ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',  // 9x
    ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',  // Ax
    ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',  // Bx
    ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',  // Cx
    ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',  // Dx
     15, 129, 133,   4,  15, 129, 133, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',  // Ex
    ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '        // Fx
};
// clang-format on

void add_keylog(uint16_t keycode) {
    if ((keycode >= QK_MOD_TAP   && keycode <= QK_MOD_TAP_MAX)   ||
        (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) ||
        (keycode >= QK_MODS      && keycode <= QK_MODS_MAX)) {
        keycode = keycode & 0xFF;
    } else if (keycode > 0xFF) {
        keycode = 0;
    }

    if (keycode < (sizeof(code_to_name) / sizeof(char))) {
        char log_char = pgm_read_byte(&code_to_name[keycode]);

        for (uint8_t j = 0; j < OLED_FONT_WIDTH; j++) {
            const uint8_t glyph_line = pgm_read_byte(&font[log_char * OLED_FONT_WIDTH + j]);
            next_log_byte[j] = glyph_line;
        }
    }
}

bool process_record_user_oled(uint16_t keycode, keyrecord_t *record) {
    if (record->event.pressed) {
        wave_sleep = timer_read32();
        add_keylog(keycode);

        uint8_t t = next_bar_val + BAR_KEY_WEIGHT;

        if (t < next_bar_val) {
            next_bar_val = 255;
        } else {
            next_bar_val = t;
        }

        bar_key_decay = BAR_KEY_DECAY_MAX;
    }

    return true;
}

void render_layer_name(void) {
    oled_write_P(PSTR("LAYER: WAVE"), false);
}

void render_frame(void) {
    // rotate line 1, and stick in the next byte of the next char,
    // then rotate the next char buffer
    memmove(line1+1, line1, OLED_DISPLAY_WIDTH - 1);
    line1[0] = next_log_byte[OLED_FONT_WIDTH - 1];
    memmove(next_log_byte+1, next_log_byte, OLED_FONT_WIDTH - 1);
    next_log_byte[0] = 0;

    // rotate line 2, sticking in the next display value
    uint8_t disp_val = pgm_read_byte(&bar_lut[next_bar_val / 32]);
    memmove(line2+1, line2, OLED_DISPLAY_WIDTH - 1);
    line2[0] = disp_val;

    // draw both bars
    for (uint8_t i = 0; i < OLED_DISPLAY_WIDTH; i++) {
        oled_write_raw_byte(line1[i], ROW_1 + i);
        oled_write_raw_byte(line2[i], ROW_2 + i);
    }

    // decay the next bar value
    if (next_bar_val > bar_key_decay) {
        next_bar_val -= bar_key_decay;
    } else {
        next_bar_val = 0;
    }

    if (bar_key_decay > 1) {
        bar_key_decay -= 1;
    }
}