summaryrefslogtreecommitdiff
path: root/users/bcat/bcat_oled_pet_isda.c
blob: 98abddb13b0518eb04a50ddcb6ebd57a28fefc9a (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
134
/* Copyright 2018 sparrow666
 * Copyright 2021 Jonathan Rascher
 *
 * 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/>.
 */

/* OLED pet "Isda" (animated unicorn) featuring artwork by OpenGameArt user
 * sparrow666, licensed under GPL v2.0.
 *
 * The animation is 32x72 pixels (9 lines tall).
 *
 * Runs faster the quicker you type. Shows LED indicator (Num/Caps/Scroll Lock)
 * status in the bottom-right corner.
 *
 * Named after the goddess Ehlonna's personal unicorn in the first D&D campaign
 * I ever played. :)
 *
 * Artwork source: https://opengameart.org/content/unicorn-2
 */

#include "bcat_oled_pet.h"

#include <stdbool.h>
#include <stdint.h>

#include "bcat_oled.h"
#include "led.h"
#include "oled_driver.h"
#include "progmem.h"

#define NUM_FRAMES 4
#define FRAME_BYTES 288 /* (32 pixel) * (72 pixel) / (8 pixel/byte) */

uint16_t oled_pet_frame_bytes(void) { return FRAME_BYTES; }
uint8_t  oled_pet_frame_lines(void) { return 9 /* (72 pixel) / (8 pixel/line) */; }
bool     oled_pet_can_jump(void) { return false; }

uint16_t oled_pet_update_millis(const oled_keyboard_state_t *keyboard_state) {
    static const uint16_t MIN_MILLIS = 75;
    static const uint16_t MAX_MILLIS = 300;
    static const uint8_t  MAX_WPM    = 150;
    uint8_t               wpm        = keyboard_state->wpm;
    if (wpm > MAX_WPM) {
        wpm = MAX_WPM;
    }
    return MAX_MILLIS - (MAX_MILLIS - MIN_MILLIS) * wpm / MAX_WPM;
}

oled_pet_state_t oled_pet_next_state(oled_pet_state_t state, const oled_keyboard_state_t *keyboard_state) {
    /* When the user stops typing, cycle the animation to frame 0 and stop. */
    return state != 0 || keyboard_state->wpm > 0 ? (state + 1) % NUM_FRAMES : 0;
}

void oled_pet_post_render(uint8_t col, uint8_t line, const oled_keyboard_state_t *keyboard_state, bool redraw) {
    /* Draws LED indicator status in the bottom-right corner of the OLED pet,
     * atop the animation frame. Redrawn only when necessary, e.g., when LED
     * status changes or the animation itself updated (which overwrites any
     * previously drawn indicators).
     */
    static led_t prev_leds = {.raw = 0};
    led_t        leds      = keyboard_state->leds;
    if (redraw || leds.raw != prev_leds.raw) {
        oled_set_cursor(col + 4, line + 4);
        oled_write_char(leds.num_lock ? 'N' : ' ', /*invert=*/false);
        oled_set_cursor(col + 4, line + 6);
        oled_write_char(leds.caps_lock ? 'C' : ' ', /*invert=*/false);
        oled_set_cursor(col + 4, line + 8);
        oled_write_char(leds.scroll_lock ? 'S' : ' ', /*invert=*/false);
        prev_leds = leds;
    }
}

const char *oled_pet_frame(oled_pet_state_t state) {
    static const char PROGMEM FRAMES[NUM_FRAMES][FRAME_BYTES] = {
        // clang-format off
        {
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0xa0, 0x60, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x88, 0xd0, 0x78, 0x04, 0x28, 0x70, 0x60, 0x90, 0x88, 0xc4, 0x22, 0x19, 0x04, 0x03, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x84, 0x8c, 0x08, 0x01, 0x01, 0x02, 0x02, 0x04, 0x88, 0xf0, 0x00,
            0xc0, 0xe0, 0xe0, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0xff, 0xff, 0xff, 0x7f, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x0f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0xfc, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0x3c, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x01, 0x03, 0xc6, 0x3c, 0x00, 0x80, 0x70, 0x1c, 0x0f, 0x03, 0x0f, 0x3f, 0xff, 0xff, 0xfc, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x80, 0xe0, 0xf8, 0xfe, 0x7f, 0x1f, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x01, 0x0e, 0x30, 0x40, 0x47, 0x4f, 0x77, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        },
        {
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0xc0, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0xa0, 0xf0, 0x08, 0x50, 0xe0, 0xc0, 0x20, 0x10, 0x88, 0x44, 0x32, 0x09, 0x06, 0x01, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x19, 0x11, 0x03, 0x02, 0x04, 0x04, 0x08, 0x10, 0xe0, 0x00,
            0xc0, 0xe0, 0xe0, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x3f, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x00,
            0x00, 0x1f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x03, 0x00, 0x00, 0x80, 0xc0, 0x20, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0x3c, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x01, 0x03, 0xc6, 0x3c, 0x00, 0x80, 0x70, 0x18, 0x0f, 0x03, 0x0f, 0x3f, 0xff, 0xff, 0xfc, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0xc0, 0x38, 0x07, 0xc0, 0x38, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x7f, 0xff, 0xff, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x21, 0x20, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x0f, 0x0f, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        },
        {
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0xc0, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0xa0, 0xf0, 0x08, 0x50, 0xe0, 0xc0, 0x20, 0x10, 0x88, 0x44, 0x32, 0x09, 0x06, 0x01, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x19, 0x11, 0x03, 0x02, 0x04, 0x04, 0x08, 0x10, 0xe0, 0x00,
            0xc0, 0xc0, 0xc0, 0x20, 0x20, 0x10, 0x08, 0x04, 0x03, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x3f, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x00,
            0x00, 0x1f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x03, 0x00, 0x00, 0x80, 0xc0, 0x20, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x01, 0x03, 0xc3, 0xfe, 0xfe, 0xfc, 0x7c, 0x1c, 0x0c, 0x0c, 0x08, 0x10, 0x60, 0x83, 0x07, 0x18, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x71, 0x0e, 0x80, 0x70, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x01, 0x0f, 0x3f, 0x7f, 0x7f, 0x78, 0xe0, 0x90, 0x88, 0x66, 0x11, 0x08, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        },
        {
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0xa0, 0x60, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x88, 0xd0, 0x78, 0x04, 0x28, 0x70, 0x60, 0x90, 0x88, 0xc4, 0x22, 0x19, 0x04, 0x03, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x84, 0x8c, 0x08, 0x01, 0x01, 0x02, 0x02, 0x04, 0x88, 0xf0, 0x00,
            0xc0, 0xe0, 0xe0, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0xff, 0xff, 0xff, 0x7f, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x0f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0xe0, 0xfc, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x01, 0x03, 0xc6, 0xfc, 0xfc, 0xfc, 0x7c, 0x18, 0x08, 0x08, 0x08, 0x30, 0xc0, 0x03, 0x0c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0xc0, 0xf8, 0xff, 0xff, 0x3f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x70, 0x80, 0x1f, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x18, 0x3e, 0x3f, 0x3f, 0x1f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x09, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        },
        // clang-format on
    };
    return FRAMES[state];
}