summaryrefslogtreecommitdiffstats
path: root/keyboards/ergodox_infinity/keymaps/halfkeyboard/visualizer.c
blob: 7bd5a0783f8f6b1bb11ab96400d4a8194436527f (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*
Copyright 2017 Fred Sundvik
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 "visualizer.h"
#include "gfx.h"
#include "math.h"
#include "default_animations.h"
#include "led_backlight_keyframes.h"

#define ONESIDESCAN 9
#define BOTHSIDESCAN 16
#define FULL_ON LUMA2COLOR(255)
#define THREE_QUARTER LUMA2COLOR(200)
#define HALF_ON LUMA2COLOR(150)
#define ONE_QUARTER LUMA2COLOR(50)
#define CROSSFADE_TIME 8000
bool KITT_scan_one_side_left_to_right(keyframe_animation_t* animation, visualizer_state_t* state);
bool KITT_scan_one_side_right_to_left(keyframe_animation_t* animation, visualizer_state_t* state);
keyframe_animation_t Fade_in_all_leds = {
    .num_frames = 1,
    .loop = false,
    .frame_lengths = {
        CROSSFADE_TIME,
    },
    .frame_functions = {
        led_backlight_keyframe_fade_in_all,
    },
};
/*
 *  one set left to right.  then reverse to go back.
 *  |    left side              |       right side          |       |
    |---|---|---|---|---|---|---|:-:|---|---|---|---|---|---|-------|
    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | phase |
    _________________________________________________________________
    | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0     |
    | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1     |
    | 2 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2     |
    | 1 | 2 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 3     |
    | 0 | 1 | 2 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 4     |
    | 0 | 0 | 1 | 2 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 5     |
    | 0 | 0 | 0 | 1 | 2 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 6     |
    | 0 | 0 | 0 | 0 | 1 | 2 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 7     |
    | 0 | 0 | 0 | 0 | 0 | 1 | 2 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 8     |
    | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 2 | 3 | 0 | 0 | 0 | 0 | 0 | 9     |
    | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 2 | 3 | 0 | 0 | 0 | 0 | 10    |
    | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 2 | 3 | 0 | 0 | 0 | 11    |
    | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 2 | 3 | 0 | 0 | 12    |
    | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 2 | 3 | 0 | 13    |
    | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 2 | 3 | 14    |
    | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 2 | 15    |
    | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 16    |
  */

#ifdef MASTER_IS_ON_RIGHT /*right side*/

keyframe_animation_t KITT_Scanner_animation = {
    .num_frames = 2,
    .loop = true,
    .frame_lengths = {
        CROSSFADE_TIME * BOTHSIDESCAN,
        CROSSFADE_TIME * BOTHSIDESCAN,
    },
    .frame_functions = {
        KITT_scan_one_side_left_to_right,
        KITT_scan_one_side_right_to_left,
    },
};

bool KITT_scan_one_side_left_to_right(keyframe_animation_t* animation, visualizer_state_t* state) {
    (void)state;
    float frame_length = animation->frame_lengths[animation->current_frame];
    float current_pos = frame_length - animation->time_left_in_frame;
    int phase = current_pos/(frame_length/BOTHSIDESCAN);
    int row = 0;
    gdispGClear(LED_DISPLAY, ONE_QUARTER);
    gdispGDrawPixel(LED_DISPLAY, 14-phase, row, FULL_ON);
    gdispGDrawPixel(LED_DISPLAY, 15-phase, row, THREE_QUARTER);
    gdispGDrawPixel(LED_DISPLAY, 16-phase, row, HALF_ON);
    gdispGDrawPixel(LED_DISPLAY, 6, row, ONE_QUARTER);
    return true;
}

bool KITT_scan_one_side_right_to_left(keyframe_animation_t* animation, visualizer_state_t* state) {
    (void)state;
    float frame_length = animation->frame_lengths[animation->current_frame];
    float current_pos = frame_length - animation->time_left_in_frame;
    int phase = current_pos/(frame_length/BOTHSIDESCAN);
    int row = 0;
    gdispGClear(LED_DISPLAY, ONE_QUARTER);
    gdispGDrawPixel(LED_DISPLAY, phase, row, FULL_ON);
    gdispGDrawPixel(LED_DISPLAY, phase-1, row, THREE_QUARTER);
    gdispGDrawPixel(LED_DISPLAY, phase-2, row, HALF_ON);
    gdispGDrawPixel(LED_DISPLAY, 6, row, ONE_QUARTER);
    return true;
}
#else /*left side*/
keyframe_animation_t KITT_Scanner_animation = {
    .num_frames = 2,
    .loop = true,
    .frame_lengths = {
        CROSSFADE_TIME * BOTHSIDESCAN,
        CROSSFADE_TIME * BOTHSIDESCAN,
    },
    .frame_functions = {
        KITT_scan_one_side_left_to_right,
        KITT_scan_one_side_right_to_left,
    },
};

bool KITT_scan_one_side_left_to_right(keyframe_animation_t* animation, visualizer_state_t* state) {
    (void)state;
    float frame_length = animation->frame_lengths[animation->current_frame];
    float current_pos = frame_length - animation->time_left_in_frame;
    int phase = current_pos/(frame_length/BOTHSIDESCAN);
    int row = 0;
    gdispGClear(LED_DISPLAY, ONE_QUARTER);
    gdispGDrawPixel(LED_DISPLAY, phase, row, FULL_ON);
    gdispGDrawPixel(LED_DISPLAY, phase-1, row, THREE_QUARTER);
    gdispGDrawPixel(LED_DISPLAY, phase-2, row, HALF_ON);
    gdispGDrawPixel(LED_DISPLAY, 6, row, ONE_QUARTER);
    return true;
}

bool KITT_scan_one_side_right_to_left(keyframe_animation_t* animation, visualizer_state_t* state) {
    (void)state;
    float frame_length = animation->frame_lengths[animation->current_frame];
    float current_pos = frame_length - animation->time_left_in_frame;
    int phase = current_pos/(frame_length/BOTHSIDESCAN);
    int row = 0;
    gdispGClear(LED_DISPLAY, ONE_QUARTER);
    gdispGDrawPixel(LED_DISPLAY, (14 - phase), row, FULL_ON);
    gdispGDrawPixel(LED_DISPLAY, 14 - (phase-1), row, THREE_QUARTER);
    gdispGDrawPixel(LED_DISPLAY, 14 - (phase-2), row, HALF_ON);
    gdispGDrawPixel(LED_DISPLAY, 6, row, ONE_QUARTER);
    return true;
}
#endif

#define RED 0
#define ORANGE 21
#define YELLOW 42
#define SPRING_GREEN 64
#define GREEN 85
#define TURQUOISE 107
#define CYAN 127
#define OCEAN 149
#define BLUE 170
#define VIOLET 192
#define MAGENTA 212
#define RASPBERRY 234

// This function should be implemented by the keymap visualizer
// Don't change anything else than state->target_lcd_color and state->layer_text as that's the only thing
// that the simple_visualizer assumes that you are updating
// Also make sure that the buffer passed to state->layer_text remains valid until the previous animation is
// stopped. This can be done by either double buffering it or by using constant strings
static void get_visualizer_layer_and_color(visualizer_state_t* state) {
    uint8_t saturation = 255;
    /* if (state->status.leds & (1u << USB_LED_CAPS_LOCK)) {
        saturation = 255;
    } */
    if (state->status.layer & 0x200) {
        state->target_lcd_color = LCD_COLOR(GREEN, saturation, 0xFF);
        state->layer_text = "MOUSE";
    }
    else if (state->status.layer & 0x100) {
        state->target_lcd_color = LCD_COLOR(MAGENTA, saturation, 0xFF);
        state->layer_text = "Shortcuts Layer";
    }
    else    if (state->status.layer & 0x80) {
        state->target_lcd_color = LCD_COLOR(VIOLET, saturation, 0xFF);
        state->layer_text = "Plover";
        start_keyframe_animation(&KITT_Scanner_animation);

    }
    else if (state->status.layer & 0x40) {
        state->target_lcd_color = LCD_COLOR(RASPBERRY, saturation, 0xFF);
        state->layer_text = "Mirrored Symbols";
    }
    else if (state->status.layer & 0x20) {
        state->target_lcd_color = LCD_COLOR(RED, saturation, 0xFF);
        state->layer_text = "Symbols";
    }
    else if (state->status.layer & 0x8) {
        state->target_lcd_color = LCD_COLOR(OCEAN, saturation, 0xFF);
        state->layer_text = "Mirrored Dvorak";
    }
    else if (state->status.layer & 0x4) {
        state->target_lcd_color = LCD_COLOR(BLUE, saturation, 0xFF);
        state->layer_text = "Dvorak";
    }
    else if (state->status.layer & 0x2) {
        state->target_lcd_color = LCD_COLOR(ORANGE, saturation, 0xFF);
        state->layer_text = "Mirrored Qwerty";
    }
    else {
        state->target_lcd_color = LCD_COLOR(YELLOW, saturation, 0xFF);
        state->layer_text = "Qwerty";
        stop_keyframe_animation(&KITT_Scanner_animation);
        start_keyframe_animation(&Fade_in_all_leds);
    }
}