diff options
| author | druotoni <89318351+druotoni@users.noreply.github.com> | 2022-01-13 20:00:35 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-01-13 11:00:35 -0800 |
| commit | b3c0548ed3cdb31c47d1a9e06c446c0804d6e1b6 (patch) | |
| tree | 87ba1062ffd5d3c77e7ea95fe537d32c3337da94 /keyboards/lily58 | |
| parent | 8a6da095d22d66c0ba36ce8731c9d821ca4262e9 (diff) | |
| download | qmk_firmware-b3c0548ed3cdb31c47d1a9e06c446c0804d6e1b6.tar.gz qmk_firmware-b3c0548ed3cdb31c47d1a9e06c446c0804d6e1b6.zip | |
[Keymap] Lily58 : HELL0 NAVI. Interface (#15469)
Co-authored-by: Drashna Jaelre <drashna@live.com>
Co-authored-by: Joel Challis <git@zvecr.com>
Diffstat (limited to 'keyboards/lily58')
21 files changed, 2879 insertions, 0 deletions
diff --git a/keyboards/lily58/keymaps/druotoni/boot.c b/keyboards/lily58/keymaps/druotoni/boot.c new file mode 100644 index 000000000..ba46f8e36 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/boot.c | |||
| @@ -0,0 +1,309 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include QMK_KEYBOARD_H | ||
| 5 | |||
| 6 | #include "boot.h" | ||
| 7 | #include "fast_random.h" | ||
| 8 | #include "draw_helper.h" | ||
| 9 | #include "gui_state.h" | ||
| 10 | |||
| 11 | // boot | ||
| 12 | #define ANIM_BOOT_FRAME_DURATION 8 | ||
| 13 | uint16_t anim_boot_timer = 0; | ||
| 14 | uint8_t anim_boot_current_frame = 0; | ||
| 15 | |||
| 16 | #define NAVI_DURATION 55 | ||
| 17 | |||
| 18 | // terminal stuff | ||
| 19 | #define TERMINAL_DURATION 25 | ||
| 20 | #define TERMINAL_LINE_NUMBER 19 | ||
| 21 | #define TERMINAL_LINE_MAX 14 | ||
| 22 | |||
| 23 | #define LILY_DURATION 50 | ||
| 24 | |||
| 25 | // halt | ||
| 26 | #define ANIM_HALT_FRAME_DURATION 55 | ||
| 27 | uint16_t anim_halt_timer = 0; | ||
| 28 | |||
| 29 | void reset_boot(void) { | ||
| 30 | // frame zero | ||
| 31 | anim_boot_current_frame = 0; | ||
| 32 | } | ||
| 33 | |||
| 34 | static void draw_lily_key(uint8_t x, uint8_t y, uint8_t *key_number, unsigned long key_state, uint8_t color) { | ||
| 35 | uint8_t v = *key_number; | ||
| 36 | unsigned long mask = 1; | ||
| 37 | mask = mask << v; | ||
| 38 | |||
| 39 | // ligth the key according to the mask | ||
| 40 | if (((key_state & mask) == mask)) { | ||
| 41 | color = !color; | ||
| 42 | } | ||
| 43 | |||
| 44 | draw_rectangle_fill(x, y, 3, 3, color); | ||
| 45 | *key_number = v + 1; | ||
| 46 | } | ||
| 47 | |||
| 48 | static void draw_lily_key_row(uint8_t x, uint8_t y, int w, uint8_t *key_number, unsigned long key_state, uint8_t color) { | ||
| 49 | // row of rectangle | ||
| 50 | for (uint8_t i = 0; i < w; i++) { | ||
| 51 | draw_lily_key(x + (i * 4), y, key_number, key_state, color); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | static void draw_lily_render(unsigned long key_state) { | ||
| 56 | // different orientation base on side | ||
| 57 | #if IS_LEFT | ||
| 58 | |||
| 59 | uint8_t x = 0; | ||
| 60 | uint8_t y = 56; | ||
| 61 | uint8_t x_ref = 10 + x; | ||
| 62 | uint8_t y_ref = 2 + y; | ||
| 63 | uint8_t i_key_number = 0; | ||
| 64 | |||
| 65 | for (uint8_t i = 0; i < 4; i++) { | ||
| 66 | draw_lily_key_row(x_ref, y_ref + (i * 4), 4, &i_key_number, key_state, true); | ||
| 67 | draw_lily_key_row(x_ref - 8, y_ref + 2 + (i * 4), 2, &i_key_number, key_state, true); | ||
| 68 | } | ||
| 69 | |||
| 70 | draw_lily_key_row(x_ref + 2, y_ref + (4 * 4), 3, &i_key_number, key_state, true); | ||
| 71 | |||
| 72 | uint8_t x_side = x_ref + (4 * 4); | ||
| 73 | |||
| 74 | draw_lily_key(x_side, y_ref + (2 * 4) + 2, &i_key_number, key_state, true); | ||
| 75 | draw_lily_key(x_side, y_ref + (4 * 4), &i_key_number, key_state, true); | ||
| 76 | |||
| 77 | // screen | ||
| 78 | draw_rectangle(x_side, y_ref, 4, 8, true); | ||
| 79 | |||
| 80 | // frame | ||
| 81 | drawline_hr(x + 1, y + 2, 8, true); | ||
| 82 | oled_write_pixel(x + 8, y + 1, true); | ||
| 83 | drawline_hr(x + 8, y, 23, true); | ||
| 84 | |||
| 85 | drawline_hr(x + 1, y + 20, 10, true); | ||
| 86 | oled_write_pixel(x + 10, y + 21, true); | ||
| 87 | drawline_hr(x + 10, y + 22, 16, true); | ||
| 88 | |||
| 89 | drawline_vb(x, y + 3, 17, true); | ||
| 90 | drawline_vb(x + 31, y + 1, 20, true); | ||
| 91 | oled_write_pixel(x + 30, y + 21, true); | ||
| 92 | oled_write_pixel(x + 29, y + 22, true); | ||
| 93 | oled_write_pixel(x + 28, y + 23, true); | ||
| 94 | oled_write_pixel(x + 27, y + 24, true); | ||
| 95 | oled_write_pixel(x + 26, y + 23, true); | ||
| 96 | #endif | ||
| 97 | |||
| 98 | #if IS_RIGHT | ||
| 99 | uint8_t i_key_number = 0; | ||
| 100 | |||
| 101 | for (uint8_t i = 0; i < 4; i++) { | ||
| 102 | draw_lily_key_row(7, 58 + (i * 4), 4, &i_key_number, key_state, true); | ||
| 103 | draw_lily_key_row(23, 60 + (i * 4), 2, &i_key_number, key_state, true); | ||
| 104 | } | ||
| 105 | |||
| 106 | draw_lily_key_row(9, 74, 3, &i_key_number, key_state, true); | ||
| 107 | |||
| 108 | draw_lily_key(3, 68, &i_key_number, key_state, true); | ||
| 109 | draw_lily_key(3, 74, &i_key_number, key_state, true); | ||
| 110 | |||
| 111 | // screen | ||
| 112 | draw_rectangle(2, 58, 4, 8, true); | ||
| 113 | |||
| 114 | // frame | ||
| 115 | drawline_hr(23, 58, 8, true); | ||
| 116 | oled_write_pixel(23, 57, true); | ||
| 117 | drawline_hr(1, 56, 23, true); | ||
| 118 | |||
| 119 | drawline_hr(21, 76, 10, true); | ||
| 120 | oled_write_pixel(21, 77, true); | ||
| 121 | drawline_hr(6, 78, 16, true); | ||
| 122 | |||
| 123 | drawline_vb(31, 59, 17, true); | ||
| 124 | drawline_vb(0, 57, 20, true); | ||
| 125 | oled_write_pixel(1, 77, true); | ||
| 126 | oled_write_pixel(2, 78, true); | ||
| 127 | oled_write_pixel(3, 79, true); | ||
| 128 | oled_write_pixel(4, 80, true); | ||
| 129 | oled_write_pixel(5, 79, true); | ||
| 130 | #endif | ||
| 131 | } | ||
| 132 | |||
| 133 | static void draw_lily(uint8_t f) { | ||
| 134 | // frame for the events | ||
| 135 | uint8_t tres_stroke = 10; | ||
| 136 | uint8_t tres_boom = 30; | ||
| 137 | uint8_t y_start = 56; | ||
| 138 | |||
| 139 | if (f == 0 || f == tres_stroke || f == tres_boom) { | ||
| 140 | // clean screen | ||
| 141 | oled_clear(); | ||
| 142 | } | ||
| 143 | |||
| 144 | // simple lily58 with all the keys | ||
| 145 | if (f < tres_stroke) { | ||
| 146 | draw_lily_render(0); | ||
| 147 | } | ||
| 148 | |||
| 149 | // increase number of random keys pressed | ||
| 150 | if (f >= tres_stroke && f < tres_boom) { | ||
| 151 | int inter_f = interpo_pourcent(tres_stroke, tres_boom, f); | ||
| 152 | |||
| 153 | unsigned long key_state = fastrand_long(); | ||
| 154 | for (int r = 100 - inter_f; r > 0; r = r - 10) { | ||
| 155 | key_state &= fastrand_long(); | ||
| 156 | } | ||
| 157 | draw_lily_render(key_state); | ||
| 158 | } | ||
| 159 | |||
| 160 | // statir explosion | ||
| 161 | if (f >= tres_boom) { | ||
| 162 | oled_clear(); | ||
| 163 | uint8_t density = (f - tres_boom); | ||
| 164 | if (density > 4) density = 4; | ||
| 165 | draw_static(0, y_start - 8, 32, 32, true, density); | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | static void draw_startup_navi(uint8_t f) { | ||
| 170 | // text | ||
| 171 | oled_write_cursor(0, 5, "HELL0", false); | ||
| 172 | oled_write_cursor(0, 7, "NAVI.", false); | ||
| 173 | |||
| 174 | // prompt | ||
| 175 | if ((f % 8) > 4) { | ||
| 176 | oled_write_cursor(0, 12, "> ", false); | ||
| 177 | } else { | ||
| 178 | oled_write_cursor(0, 12, ">_", false); | ||
| 179 | } | ||
| 180 | |||
| 181 | // frame threshold | ||
| 182 | uint8_t tres_shell = 15; | ||
| 183 | uint8_t tres_load = 35; | ||
| 184 | |||
| 185 | // rand text to init display | ||
| 186 | if (f > tres_shell) { | ||
| 187 | int inter_f = interpo_pourcent(tres_shell, tres_load, f); | ||
| 188 | |||
| 189 | draw_random_char(1, 12, 'i', 60 + inter_f, 0); | ||
| 190 | draw_random_char(2, 12, 'n', 20 + inter_f, 0); | ||
| 191 | draw_random_char(3, 12, 'i', inter_f, 0); | ||
| 192 | draw_random_char(4, 12, 't', 20 + inter_f, 0); | ||
| 193 | } | ||
| 194 | |||
| 195 | // loading propress bar | ||
| 196 | if (f > tres_load) { | ||
| 197 | int inter_f = interpo_pourcent(tres_load, 50, f); | ||
| 198 | |||
| 199 | // ease | ||
| 200 | float fv = inter_f / 100.00; | ||
| 201 | fv = fv * fv * fv * fv; | ||
| 202 | inter_f = fv * 100; | ||
| 203 | |||
| 204 | draw_rectangle(0, (15 * 8), 32, 8, 1); | ||
| 205 | draw_progress(0 + 3, (15 * 8) + 3, 26, 2, inter_f, 0, 1); | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | // text dispayed on terminal | ||
| 210 | static char *boot_ref[TERMINAL_LINE_NUMBER] = {"LT:", "RT:", "M :", " ", "cnx:", "A0:", "B0:", " ", "0x40", "0x60", "0x85", "0x0F", " ", "> run", "x ", "y ", " 100%", " ", "> key"}; | ||
| 211 | |||
| 212 | // prompt style for char in the font | ||
| 213 | char scan_font[5] = {'>', 1, 1, 1, 1}; | ||
| 214 | |||
| 215 | static char *get_terminal_line(uint8_t i) { | ||
| 216 | // display text | ||
| 217 | if (i < TERMINAL_LINE_NUMBER) { | ||
| 218 | return boot_ref[i]; | ||
| 219 | } | ||
| 220 | |||
| 221 | // blank line every 3 lines | ||
| 222 | if (i % 3 == 0) { | ||
| 223 | return " "; | ||
| 224 | } | ||
| 225 | |||
| 226 | // display consecutive chars in the font | ||
| 227 | i = (i - TERMINAL_LINE_NUMBER) * 4; | ||
| 228 | |||
| 229 | scan_font[1] = i; | ||
| 230 | scan_font[2] = i + 1; | ||
| 231 | scan_font[3] = i + 2; | ||
| 232 | scan_font[4] = i + 3; | ||
| 233 | |||
| 234 | return scan_font; | ||
| 235 | } | ||
| 236 | |||
| 237 | static void draw_startup_terminal(uint8_t f) { | ||
| 238 | // ease for printing on screen | ||
| 239 | f = f * 2; | ||
| 240 | f += (f / 5); | ||
| 241 | |||
| 242 | // scroll text | ||
| 243 | uint8_t i_start = 0; | ||
| 244 | uint8_t i_nb_char = f; | ||
| 245 | |||
| 246 | if (f > TERMINAL_LINE_MAX) { | ||
| 247 | i_start = f - TERMINAL_LINE_MAX; | ||
| 248 | i_nb_char = TERMINAL_LINE_MAX; | ||
| 249 | } | ||
| 250 | |||
| 251 | // display lines | ||
| 252 | oled_clear(); | ||
| 253 | for (uint8_t i = 0; i < i_nb_char; i++) { | ||
| 254 | char *s = get_terminal_line(i + i_start); | ||
| 255 | oled_write_cursor(0, i, s, false); | ||
| 256 | } | ||
| 257 | } | ||
| 258 | |||
| 259 | bool render_boot(void) { | ||
| 260 | // end of the boot sequence | ||
| 261 | if (anim_boot_current_frame >= NAVI_DURATION + TERMINAL_DURATION + LILY_DURATION) { | ||
| 262 | anim_boot_current_frame = 0; | ||
| 263 | oled_clear(); | ||
| 264 | return true; | ||
| 265 | } | ||
| 266 | |||
| 267 | if (timer_elapsed(anim_boot_timer) > ANIM_BOOT_FRAME_DURATION) { | ||
| 268 | anim_boot_timer = timer_read(); | ||
| 269 | if (anim_boot_current_frame < NAVI_DURATION) { | ||
| 270 | // 55 frames | ||
| 271 | draw_startup_navi(anim_boot_current_frame); | ||
| 272 | } else { | ||
| 273 | if (anim_boot_current_frame >= NAVI_DURATION && anim_boot_current_frame < NAVI_DURATION + TERMINAL_DURATION) { | ||
| 274 | // 25 | ||
| 275 | draw_startup_terminal(anim_boot_current_frame - NAVI_DURATION); | ||
| 276 | } else { | ||
| 277 | if (anim_boot_current_frame >= NAVI_DURATION + TERMINAL_DURATION) { | ||
| 278 | // 25 | ||
| 279 | draw_lily(anim_boot_current_frame - NAVI_DURATION - TERMINAL_DURATION); | ||
| 280 | } | ||
| 281 | } | ||
| 282 | } | ||
| 283 | |||
| 284 | anim_boot_current_frame++; | ||
| 285 | } | ||
| 286 | return false; | ||
| 287 | } | ||
| 288 | |||
| 289 | void render_halt(void) { | ||
| 290 | if (timer_elapsed(anim_halt_timer) > ANIM_HALT_FRAME_DURATION) { | ||
| 291 | anim_halt_timer = timer_read(); | ||
| 292 | |||
| 293 | // comb glitch for all the screen | ||
| 294 | draw_glitch_comb(0, 0, 32, 128, 3, true); | ||
| 295 | |||
| 296 | // random moving blocks of pixels | ||
| 297 | for (uint8_t i = 0; i < 6; i++) { | ||
| 298 | int r = fastrand(); | ||
| 299 | int rr = fastrand(); | ||
| 300 | uint8_t x = 4 + r % 28; | ||
| 301 | uint8_t y = rr % 128; | ||
| 302 | |||
| 303 | uint8_t w = 7 + r % 20; | ||
| 304 | uint8_t h = 3 + rr % 10; | ||
| 305 | int s = (fastrand() % 20) - 10; | ||
| 306 | move_block(x, y, w, h, s); | ||
| 307 | } | ||
| 308 | } | ||
| 309 | } | ||
diff --git a/keyboards/lily58/keymaps/druotoni/boot.h b/keyboards/lily58/keymaps/druotoni/boot.h new file mode 100644 index 000000000..7897e1792 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/boot.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | bool render_boot(void); | ||
| 7 | void render_halt(void); | ||
| 8 | |||
| 9 | void reset_boot(void); \ No newline at end of file | ||
diff --git a/keyboards/lily58/keymaps/druotoni/burst.c b/keyboards/lily58/keymaps/druotoni/burst.c new file mode 100644 index 000000000..6dd6579e7 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/burst.c | |||
| @@ -0,0 +1,252 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // Copyright 2020 Richard Sutherland (rich@brickbots.com) | ||
| 3 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 4 | |||
| 5 | #include QMK_KEYBOARD_H | ||
| 6 | |||
| 7 | #include "gui_state.h" | ||
| 8 | #include "fast_random.h" | ||
| 9 | #include "burst.h" | ||
| 10 | #include "draw_helper.h" | ||
| 11 | |||
| 12 | // burst stuff | ||
| 13 | static int current_burst = 0; | ||
| 14 | static uint16_t burst_timer = 0; | ||
| 15 | |||
| 16 | // WPM stuff | ||
| 17 | static int current_wpm = 0; | ||
| 18 | static uint16_t wpm_timer = 0; | ||
| 19 | |||
| 20 | // This smoothing is 40 keystrokes | ||
| 21 | static const float wpm_smoothing = WPM_SMOOTHING; | ||
| 22 | |||
| 23 | // store values | ||
| 24 | uint8_t burst_scope[SIZE_SCOPE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 25 | uint8_t wpm_scope[SIZE_SCOPE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 26 | |||
| 27 | // current max wpm | ||
| 28 | int max_wpm = MAX_WPM_INIT; | ||
| 29 | |||
| 30 | // scope animation stuff | ||
| 31 | #define ANIM_SCOPE_FRAME_DURATION 40 | ||
| 32 | #define ANIM_SLEEP_SCOPE_FRAME_NUMBER 10 | ||
| 33 | |||
| 34 | uint16_t anim_scope_timer = 0; | ||
| 35 | uint16_t anim_scope_idle_timer = 0; | ||
| 36 | uint16_t anim_sleep_scope_timer = 0; | ||
| 37 | |||
| 38 | uint8_t anim_sleep_scope_duration[ANIM_SLEEP_SCOPE_FRAME_NUMBER] = {30, 30, 30, 30, 20, 20, 30, 30, 32, 35}; | ||
| 39 | uint8_t current_sleep_scope_frame = 0; | ||
| 40 | uint8_t sleep_scope_frame_destination = ANIM_SLEEP_SCOPE_FRAME_NUMBER - 1; | ||
| 41 | |||
| 42 | // glitch animation | ||
| 43 | int current_glitch_scope_time = 150; | ||
| 44 | uint32_t glitch_scope_timer = 0; | ||
| 45 | uint8_t current_glitch_scope_index = 0; | ||
| 46 | |||
| 47 | static void update_wpm(void) { | ||
| 48 | if (wpm_timer > 0) { | ||
| 49 | current_wpm += ((60000 / timer_elapsed(wpm_timer) / WPM_ESTIMATED_WORD_SIZE) - current_wpm) * wpm_smoothing; | ||
| 50 | if (current_wpm > LIMIT_MAX_WPM) { | ||
| 51 | current_wpm = LIMIT_MAX_WPM; | ||
| 52 | } | ||
| 53 | } | ||
| 54 | wpm_timer = timer_read(); | ||
| 55 | } | ||
| 56 | |||
| 57 | void update_scope(void) { | ||
| 58 | update_wpm(); | ||
| 59 | |||
| 60 | uint16_t temps_ecoule = timer_elapsed(burst_timer); | ||
| 61 | |||
| 62 | if (temps_ecoule > BURST_FENETRE) { | ||
| 63 | // 1er frappe après longtemps | ||
| 64 | current_burst = 40; | ||
| 65 | } else { | ||
| 66 | int time_pourcent = ((100 * (temps_ecoule)) / (BURST_FENETRE)); | ||
| 67 | current_burst = 100 - time_pourcent; | ||
| 68 | } | ||
| 69 | burst_timer = timer_read(); | ||
| 70 | } | ||
| 71 | |||
| 72 | static void update_scope_array(void) { | ||
| 73 | // shift array | ||
| 74 | for (uint8_t i = 0; i < SIZE_SCOPE - 1; i++) { | ||
| 75 | burst_scope[i] = burst_scope[i + 1]; | ||
| 76 | wpm_scope[i] = wpm_scope[i + 1]; | ||
| 77 | } | ||
| 78 | |||
| 79 | int burst = current_burst; | ||
| 80 | int wpm = current_wpm; | ||
| 81 | |||
| 82 | // compute max wpm | ||
| 83 | max_wpm = (wpm == 0) ? MAX_WPM_INIT : ((wpm > max_wpm) ? wpm : max_wpm); | ||
| 84 | |||
| 85 | // current wpm ratio VS max | ||
| 86 | wpm = (100 * wpm) / max_wpm; | ||
| 87 | if (wpm > 100) wpm = 100; | ||
| 88 | |||
| 89 | // update last slot of the arrays | ||
| 90 | burst_scope[SIZE_SCOPE - 1] = burst; | ||
| 91 | wpm_scope[SIZE_SCOPE - 1] = wpm; | ||
| 92 | |||
| 93 | // apply decay to burst chart | ||
| 94 | uint8_t pBaisse = 0; | ||
| 95 | for (uint8_t i = 0; i < SIZE_SCOPE - (SIZE_SCOPE / 4); i++) { | ||
| 96 | pBaisse = 2 + ((SIZE_SCOPE - 1 - i)) / 2; | ||
| 97 | burst_scope[i] -= ((burst_scope[i] * pBaisse) / 100); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | static void RenderScopeBlack(void) { | ||
| 102 | // clean central zone | ||
| 103 | draw_rectangle_fill(3, 82, 28, 120, false); | ||
| 104 | |||
| 105 | // redraw some parts of the frame | ||
| 106 | drawline_hr(1, SCOPE_Y_BOTTOM, 32, 1); | ||
| 107 | drawline_vt(0, SCOPE_Y_BOTTOM - 1, 42, 1); | ||
| 108 | drawline_vt(31, SCOPE_Y_BOTTOM - 1, 47, 1); | ||
| 109 | } | ||
| 110 | |||
| 111 | static void render_scope_white(void) { | ||
| 112 | static const char PROGMEM raw_logo[] = { | ||
| 113 | 240, 8, 4, 226, 241, 248, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 0, 0, 255, 255, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 127, 128, 128, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 128, 128, 127, | ||
| 114 | }; | ||
| 115 | oled_write_raw_P_cursor(0, 10, raw_logo, sizeof(raw_logo)); | ||
| 116 | } | ||
| 117 | |||
| 118 | static void render_scope_chart(void) { | ||
| 119 | // clean the frame | ||
| 120 | render_scope_white(); | ||
| 121 | |||
| 122 | uint8_t y_offset = SCOPE_Y_BOTTOM - 3; | ||
| 123 | |||
| 124 | for (uint8_t i = 0; i < SIZE_SCOPE; i++) { | ||
| 125 | // offset | ||
| 126 | uint8_t x = 3 + i; | ||
| 127 | |||
| 128 | // new black vertical line for burst | ||
| 129 | uint8_t iCurrentBurst = burst_scope[i]; | ||
| 130 | drawline_vt(x, y_offset, (iCurrentBurst * 4) / 10, 0); | ||
| 131 | |||
| 132 | // new black point for wpm, white if it's on the burst line | ||
| 133 | uint8_t iCurrentWpm = wpm_scope[i]; | ||
| 134 | uint8_t yWpm = y_offset - ((iCurrentWpm * 4) / 10); | ||
| 135 | oled_write_pixel(x, yWpm, !(iCurrentWpm > iCurrentBurst)); | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | void reset_scope(void) { | ||
| 140 | // scope need wakeup | ||
| 141 | anim_sleep_scope_timer = timer_read(); | ||
| 142 | current_sleep_scope_frame = ANIM_SLEEP_SCOPE_FRAME_NUMBER - 1; | ||
| 143 | |||
| 144 | sleep_scope_frame_destination = 0; | ||
| 145 | } | ||
| 146 | |||
| 147 | static void render_glitch_square(void) { | ||
| 148 | if (timer_elapsed(anim_scope_idle_timer) > 60) { | ||
| 149 | anim_scope_idle_timer = timer_read(); | ||
| 150 | RenderScopeBlack(); | ||
| 151 | |||
| 152 | uint8_t color = 0; | ||
| 153 | uint8_t size = 0; | ||
| 154 | for (uint8_t i = 0; i < 4; i++) { | ||
| 155 | size = 4 + (fastrand() % 6); | ||
| 156 | |||
| 157 | draw_gradient(3 + (fastrand() % 19), 85 + (fastrand() % 20), size, size, 255, 255, 4); | ||
| 158 | |||
| 159 | size = (fastrand() % 6); | ||
| 160 | color = 100 + (fastrand() % 100); | ||
| 161 | draw_gradient(3 + (fastrand() % 19), 100 + (fastrand() % 20), size, size, color, color, 4); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | void render_scope_idle(void) { | ||
| 167 | uint8_t glitch_prob = get_glitch_probability(); | ||
| 168 | get_glitch_index(&glitch_scope_timer, ¤t_glitch_scope_time, ¤t_glitch_scope_index, 150, 350, glitch_prob, 2); | ||
| 169 | |||
| 170 | switch (current_glitch_scope_index) { | ||
| 171 | case 0: | ||
| 172 | RenderScopeBlack(); | ||
| 173 | return; | ||
| 174 | case 1: | ||
| 175 | render_glitch_square(); | ||
| 176 | return; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | static void RenderScopeSleep(void) { | ||
| 181 | if (current_sleep_scope_frame == sleep_scope_frame_destination) { | ||
| 182 | // animation finished | ||
| 183 | render_scope_idle(); | ||
| 184 | return; | ||
| 185 | } | ||
| 186 | |||
| 187 | if (timer_elapsed(anim_sleep_scope_timer) > anim_sleep_scope_duration[current_sleep_scope_frame]) { | ||
| 188 | anim_sleep_scope_timer = timer_read(); | ||
| 189 | |||
| 190 | // clean scope | ||
| 191 | RenderScopeBlack(); | ||
| 192 | |||
| 193 | // render animation | ||
| 194 | render_tv_animation(current_sleep_scope_frame, 3, 80, 25, 48); | ||
| 195 | |||
| 196 | // update frame number | ||
| 197 | if (sleep_scope_frame_destination > current_sleep_scope_frame) { | ||
| 198 | current_sleep_scope_frame++; | ||
| 199 | } else { | ||
| 200 | current_sleep_scope_frame--; | ||
| 201 | } | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | void render_scope(gui_state_t t) { | ||
| 206 | if (timer_elapsed(anim_scope_timer) > ANIM_SCOPE_FRAME_DURATION) { | ||
| 207 | anim_scope_timer = timer_read(); | ||
| 208 | |||
| 209 | // shift arrays | ||
| 210 | update_scope_array(); | ||
| 211 | |||
| 212 | // oled_set_cursor(0, 10); | ||
| 213 | |||
| 214 | if (t == _WAKINGUP) { | ||
| 215 | RenderScopeSleep(); | ||
| 216 | return; | ||
| 217 | } | ||
| 218 | |||
| 219 | if (t == _IDLE) { | ||
| 220 | sleep_scope_frame_destination = ANIM_SLEEP_SCOPE_FRAME_NUMBER - 1; | ||
| 221 | RenderScopeSleep(); | ||
| 222 | return; | ||
| 223 | } | ||
| 224 | |||
| 225 | render_scope_chart(); | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 229 | static void decay_burst(void) { | ||
| 230 | uint16_t temps_ecoule = timer_elapsed(burst_timer); | ||
| 231 | |||
| 232 | int poucentageEcoule = 100; | ||
| 233 | |||
| 234 | if (temps_ecoule <= BURST_FENETRE * 4) { | ||
| 235 | poucentageEcoule = ((100 * (temps_ecoule)) / (BURST_FENETRE * 4)); | ||
| 236 | } | ||
| 237 | |||
| 238 | current_burst = current_burst - poucentageEcoule; | ||
| 239 | if (current_burst <= 0) current_burst = 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | static void decay_wpm(void) { | ||
| 243 | if (timer_elapsed(wpm_timer) > 1000) { | ||
| 244 | wpm_timer = timer_read(); | ||
| 245 | current_wpm += (-current_wpm) * wpm_smoothing; | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | void decay_scope(void) { | ||
| 250 | decay_burst(); | ||
| 251 | decay_wpm(); | ||
| 252 | } | ||
diff --git a/keyboards/lily58/keymaps/druotoni/burst.h b/keyboards/lily58/keymaps/druotoni/burst.h new file mode 100644 index 000000000..8bc815350 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/burst.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // Copyright 2020 Richard Sutherland (rich@brickbots.com) | ||
| 3 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | // burst | ||
| 8 | #define MAX_WPM_INIT 40 | ||
| 9 | #define BURST_FENETRE 500 | ||
| 10 | |||
| 11 | // wpm | ||
| 12 | #define LIMIT_MAX_WPM 150 | ||
| 13 | #define WPM_ESTIMATED_WORD_SIZE 5 | ||
| 14 | #define WPM_SMOOTHING 0.0487 | ||
| 15 | |||
| 16 | // scope | ||
| 17 | #define SIZE_SCOPE 26 | ||
| 18 | #define SCOPE_Y_BOTTOM 127 | ||
| 19 | |||
| 20 | void update_scope(void); | ||
| 21 | void render_scope(gui_state_t t); | ||
| 22 | |||
| 23 | void reset_scope(void); | ||
| 24 | void decay_scope(void); | ||
diff --git a/keyboards/lily58/keymaps/druotoni/config.h b/keyboards/lily58/keymaps/druotoni/config.h new file mode 100644 index 000000000..37124fcaa --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/config.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // Copyright 2012 Jun Wako <wakojun@gmail.com> | ||
| 3 | // Copyright 2015 Jack Humbert | ||
| 4 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 5 | |||
| 6 | #pragma once | ||
| 7 | |||
| 8 | #define MASTER_LEFT | ||
| 9 | #define OLED_DRIVER_ENABLE | ||
| 10 | |||
| 11 | // tapping toggle for my layers | ||
| 12 | #define TAPPING_TOGGLE 2 | ||
| 13 | |||
| 14 | // choose IS_LEFT or IS_RIGHT for compilation and flash firmware | ||
| 15 | #define IS_LEFT 1 | ||
| 16 | //#define IS_RIGHT 1 | ||
| 17 | |||
| 18 | // logo glitch | ||
| 19 | #define WITH_GLITCH | ||
| 20 | // boot sequence | ||
| 21 | #define WITH_BOOT | ||
| 22 | |||
| 23 | // custom transport for displaying on both side | ||
| 24 | #define SPLIT_TRANSACTION_IDS_USER USER_SYNC_A | ||
| 25 | |||
| 26 | // custom font | ||
| 27 | #ifdef OLED_FONT_H | ||
| 28 | # undef OLED_FONT_H | ||
| 29 | #endif | ||
| 30 | #define OLED_FONT_H "navi_font.c" | ||
| 31 | #undef OLED_FONT_END | ||
| 32 | #define OLED_FONT_END 125 | ||
| 33 | |||
| 34 | // more space | ||
| 35 | #define NO_ACTION_MACRO | ||
| 36 | #define NO_ACTION_FUNCTION | ||
| 37 | #define NO_ACTION_ONESHOT | ||
| 38 | #define DISABLE_LEADER | ||
| 39 | |||
| 40 | // ??? | ||
| 41 | #undef LOCKING_SUPPORT_ENABLE | ||
| 42 | #undef LOCKING_RESYNC_ENABLE | ||
| 43 | |||
| 44 | // small layer state | ||
| 45 | #define LAYER_STATE_8BIT | ||
| 46 | |||
| 47 | // no debug or trace | ||
| 48 | #ifndef NO_DEBUG | ||
| 49 | # define NO_DEBUG | ||
| 50 | #endif | ||
| 51 | #if !defined(NO_PRINT) && !defined(CONSOLE_ENABLE) | ||
| 52 | # define NO_PRINT | ||
| 53 | #endif | ||
| 54 | |||
| 55 | |||
diff --git a/keyboards/lily58/keymaps/druotoni/draw_helper.c b/keyboards/lily58/keymaps/druotoni/draw_helper.c new file mode 100644 index 000000000..c6761d725 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/draw_helper.c | |||
| @@ -0,0 +1,768 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // Copyright 2021 ugfx | ||
| 3 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 4 | |||
| 5 | #include QMK_KEYBOARD_H | ||
| 6 | |||
| 7 | #include "draw_helper.h" | ||
| 8 | #include "fast_random.h" | ||
| 9 | |||
| 10 | void drawline(uint8_t x, uint8_t y, uint8_t width, bool bHorizontal, bool bPositiveDirection, bool color) { | ||
| 11 | if (width <= 0) return; | ||
| 12 | uint8_t yPlus = 0; | ||
| 13 | uint8_t yMois = 0; | ||
| 14 | uint8_t nbtour = 0; | ||
| 15 | |||
| 16 | if (!bPositiveDirection) { | ||
| 17 | if (bHorizontal) { | ||
| 18 | x -= width; | ||
| 19 | } else { | ||
| 20 | y -= width; | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | yMois = (width / 2) - 1 + (width % 2); | ||
| 25 | |||
| 26 | yPlus = (width / 2); | ||
| 27 | nbtour = (width / 4) + 1; | ||
| 28 | |||
| 29 | bool bWhite = color; | ||
| 30 | |||
| 31 | if (bHorizontal) { | ||
| 32 | for (uint8_t i = 0; i < nbtour; i++) { | ||
| 33 | oled_write_pixel(x + yPlus + i, y, bWhite); | ||
| 34 | oled_write_pixel(x + yMois - i, y, bWhite); | ||
| 35 | |||
| 36 | oled_write_pixel(x + i, y, bWhite); | ||
| 37 | oled_write_pixel(x + width - 1 - i, y, bWhite); | ||
| 38 | } | ||
| 39 | } else { | ||
| 40 | for (uint8_t i = 0; i < nbtour; i++) { | ||
| 41 | oled_write_pixel(x, y + yPlus + i, bWhite); | ||
| 42 | oled_write_pixel(x, y + yMois - i, bWhite); | ||
| 43 | |||
| 44 | oled_write_pixel(x, y + i, bWhite); | ||
| 45 | |||
| 46 | oled_write_pixel(x, y + width - 1 - i, bWhite); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | void drawline_vb(uint8_t x, uint8_t y, uint8_t width, bool color) { drawline(x, y, width, false, true, color); } | ||
| 52 | |||
| 53 | void drawline_vt(uint8_t x, uint8_t y, uint8_t width, bool color) { drawline(x, y, width, false, false, color); } | ||
| 54 | |||
| 55 | void drawline_hr(uint8_t x, uint8_t y, uint8_t width, bool color) { drawline(x, y, width, true, true, color); } | ||
| 56 | |||
| 57 | void drawline_hl(uint8_t x, uint8_t y, uint8_t width, bool color) { drawline(x, y, width, true, false, color); } | ||
| 58 | |||
| 59 | void draw_rectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color) { | ||
| 60 | drawline_hr(x, y, width, color); | ||
| 61 | drawline_hr(x, y + heigth - 1, width, color); | ||
| 62 | drawline_vb(x, y, heigth, color); | ||
| 63 | drawline_vb(x + width - 1, y, heigth, color); | ||
| 64 | } | ||
| 65 | |||
| 66 | void draw_rectangle_fill(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color) { | ||
| 67 | for (uint8_t i = 0; i < heigth; i++) { | ||
| 68 | drawline_hr(x, y + i, width, color); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | void drawline_hr_heigth(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color) { | ||
| 73 | for (int i = 0; i < heigth; i++) { | ||
| 74 | drawline_hr(x, y - i, width, color); | ||
| 75 | drawline_hr(x, y + i, width, color); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | void drawline_point_hr(short x, short y, short x1, bool color) { | ||
| 80 | if (y < 0 || y > 127) return; | ||
| 81 | |||
| 82 | if (x1 < x) { | ||
| 83 | short iTemp = x; | ||
| 84 | x = x1; | ||
| 85 | x1 = iTemp; | ||
| 86 | } | ||
| 87 | |||
| 88 | if (x1 > 31) x1 = 31; | ||
| 89 | if (x < 0) x = 0; | ||
| 90 | if (x > 31) x = 31; | ||
| 91 | |||
| 92 | drawline(x, y, x1 - x, true, true, color); | ||
| 93 | } | ||
| 94 | |||
| 95 | void flip_flap_x(short px, short py, uint8_t val, bool color) { | ||
| 96 | oled_write_pixel(px + val, py, color); | ||
| 97 | oled_write_pixel(px - val, py, color); | ||
| 98 | } | ||
| 99 | |||
| 100 | void draw_circle(uint8_t x, uint8_t y, uint8_t radius, bool color) { | ||
| 101 | short a, b, P; | ||
| 102 | |||
| 103 | // Calculate intermediates | ||
| 104 | a = 1; | ||
| 105 | b = radius; | ||
| 106 | P = 4 - radius; | ||
| 107 | |||
| 108 | short py, px; | ||
| 109 | |||
| 110 | // Away we go using Bresenham's circle algorithm | ||
| 111 | // Optimized to prevent double drawing | ||
| 112 | px = x; | ||
| 113 | py = y + b; | ||
| 114 | oled_write_pixel(px, py, color); | ||
| 115 | px = x; | ||
| 116 | py = y - b; | ||
| 117 | oled_write_pixel(px, py, color); | ||
| 118 | |||
| 119 | flip_flap_x(x, y, b, color); | ||
| 120 | |||
| 121 | do { | ||
| 122 | flip_flap_x(x, y + b, a, color); | ||
| 123 | flip_flap_x(x, y - b, a, color); | ||
| 124 | flip_flap_x(x, y + a, b, color); | ||
| 125 | flip_flap_x(x, y - a, b, color); | ||
| 126 | |||
| 127 | if (P < 0) | ||
| 128 | P += 3 + 2 * a++; | ||
| 129 | else | ||
| 130 | P += 5 + 2 * (a++ - b--); | ||
| 131 | } while (a < b); | ||
| 132 | |||
| 133 | flip_flap_x(x, y + b, a, color); | ||
| 134 | flip_flap_x(x, y - b, a, color); | ||
| 135 | } | ||
| 136 | |||
| 137 | void draw_ellipse(uint8_t x, uint8_t y, uint8_t a, uint8_t b, bool color) { | ||
| 138 | int dx, dy; | ||
| 139 | int a2, b2; | ||
| 140 | int err, e2; | ||
| 141 | |||
| 142 | // short py, px; | ||
| 143 | // Calculate intermediates | ||
| 144 | dx = 0; | ||
| 145 | dy = b; | ||
| 146 | a2 = a * a; | ||
| 147 | b2 = b * b; | ||
| 148 | err = b2 - (2 * b - 1) * a2; | ||
| 149 | |||
| 150 | // Away we go using Bresenham's ellipse algorithm | ||
| 151 | do { | ||
| 152 | flip_flap_x(x, y + dy, dx, color); | ||
| 153 | flip_flap_x(x, y - dy, dx, color); | ||
| 154 | |||
| 155 | e2 = 2 * err; | ||
| 156 | if (e2 < (2 * dx + 1) * b2) { | ||
| 157 | dx++; | ||
| 158 | err += (2 * dx + 1) * b2; | ||
| 159 | } | ||
| 160 | if (e2 > -(2 * dy - 1) * a2) { | ||
| 161 | dy--; | ||
| 162 | err -= (2 * dy - 1) * a2; | ||
| 163 | } | ||
| 164 | } while (dy >= 0); | ||
| 165 | } | ||
| 166 | |||
| 167 | void draw_ellipse_fill(uint8_t x, uint8_t y, uint8_t a, uint8_t b, bool color) { return; } | ||
| 168 | // void draw_ellipse_fill(uint8_t x, uint8_t y, uint8_t a, uint8_t b, uint8_t color) { | ||
| 169 | // int dx, dy; | ||
| 170 | // int a2, b2; | ||
| 171 | // int err, e2; | ||
| 172 | |||
| 173 | // // Calculate intermediates | ||
| 174 | // dx = 0; | ||
| 175 | // dy = b; | ||
| 176 | // a2 = a * a; | ||
| 177 | // b2 = b * b; | ||
| 178 | // err = b2 - (2 * b - 1) * a2; | ||
| 179 | |||
| 180 | // short py, px, px1; | ||
| 181 | |||
| 182 | // // Away we go using Bresenham's ellipse algorithm | ||
| 183 | // // This is optimized to prevent overdrawing by drawing a line only when a y is about to change value | ||
| 184 | // do { | ||
| 185 | // e2 = 2 * err; | ||
| 186 | // if (e2 < (2 * dx + 1) * b2) { | ||
| 187 | // dx++; | ||
| 188 | // err += (2 * dx + 1) * b2; | ||
| 189 | // } | ||
| 190 | // if (e2 > -(2 * dy - 1) * a2) { | ||
| 191 | // py = y + dy; | ||
| 192 | // px = x - dx; | ||
| 193 | // px1 = x + dx; | ||
| 194 | // drawline_point_hr(px, py, px1, color); | ||
| 195 | // if (y) { | ||
| 196 | // py = y - dy; | ||
| 197 | // px = x - dx; | ||
| 198 | // px1 = x + dx; | ||
| 199 | // drawline_point_hr(px, py, px1, color); | ||
| 200 | // } | ||
| 201 | // dy--; | ||
| 202 | // err -= (2 * dy - 1) * a2; | ||
| 203 | // } | ||
| 204 | // } while (dy >= 0); | ||
| 205 | // } | ||
| 206 | |||
| 207 | bool test_limit(short x, short y) { return !(y < 0 || y > 127 || x < 0 || x > 31); } | ||
| 208 | |||
| 209 | void flip_flap_y_point(short px, short py, short px1, uint8_t val, bool color) { | ||
| 210 | // firmware size optimisation : one fonction for 2 lines of code | ||
| 211 | drawline_point_hr(px, py + val, px1, color); | ||
| 212 | drawline_point_hr(px, py - val, px1, color); | ||
| 213 | } | ||
| 214 | |||
| 215 | void draw_fill_circle(short x, short y, uint8_t radius, bool color) { | ||
| 216 | short a, b, P; | ||
| 217 | |||
| 218 | // Calculate intermediates | ||
| 219 | a = 1; | ||
| 220 | b = radius; | ||
| 221 | P = 4 - radius; | ||
| 222 | |||
| 223 | // Away we go using Bresenham's circle algorithm | ||
| 224 | // This is optimized to prevent overdrawing by drawing a line only when a variable is about to change value | ||
| 225 | short py, px, px1; | ||
| 226 | |||
| 227 | py = y; | ||
| 228 | px = x - b; | ||
| 229 | px1 = x + b; | ||
| 230 | drawline_point_hr(px, py, px1, color); | ||
| 231 | |||
| 232 | py = y + b; | ||
| 233 | px = x; | ||
| 234 | if (test_limit(px, py)) oled_write_pixel(px, py, color); | ||
| 235 | py = y - b; | ||
| 236 | px = x; | ||
| 237 | if (test_limit(px, py)) oled_write_pixel(px, py, color); | ||
| 238 | do { | ||
| 239 | flip_flap_y_point(x - b, y, x + b, a, color); | ||
| 240 | |||
| 241 | if (P < 0) { | ||
| 242 | P += 3 + 2 * a++; | ||
| 243 | } else { | ||
| 244 | flip_flap_y_point(x - a, y, x + a, b, color); | ||
| 245 | |||
| 246 | P += 5 + 2 * (a++ - b--); | ||
| 247 | } | ||
| 248 | } while (a < b); | ||
| 249 | |||
| 250 | flip_flap_y_point(x - b, y, x + b, a, color); | ||
| 251 | } | ||
| 252 | |||
| 253 | bool apres_moitie(int a, int b) { return (a > b / 2); } | ||
| 254 | bool arrive_moitie(int a, int b) { return (a > b / 2); } | ||
| 255 | bool avant_moitie(int a, int b) { return (a <= b / 2 && !apres_moitie(a, b)); } | ||
| 256 | |||
| 257 | void draw_arc_sector(uint8_t x, uint8_t y, uint8_t radius, unsigned char sectors, unsigned char half, bool color) { | ||
| 258 | short a, b, P; | ||
| 259 | short py, px; | ||
| 260 | // Calculate intermediates | ||
| 261 | a = 1; // x in many explanations | ||
| 262 | b = radius; // y in many explanations | ||
| 263 | P = 4 - radius; | ||
| 264 | |||
| 265 | if (half != 2) { | ||
| 266 | // Away we go using Bresenham's circle algorithm | ||
| 267 | // Optimized to prevent double drawing | ||
| 268 | if (sectors & 0x06) { | ||
| 269 | px = x; | ||
| 270 | py = y - b; | ||
| 271 | oled_write_pixel(px, py, color); | ||
| 272 | } // Upper upper | ||
| 273 | if (sectors & 0x60) { | ||
| 274 | px = x; | ||
| 275 | py = y + b; | ||
| 276 | oled_write_pixel(px, py, color); | ||
| 277 | } // Lower lower | ||
| 278 | if (sectors & 0x81) { | ||
| 279 | px = x + b; | ||
| 280 | py = y; | ||
| 281 | oled_write_pixel(px, py, color); | ||
| 282 | } // Right right | ||
| 283 | if (sectors & 0x18) { | ||
| 284 | px = x - b; | ||
| 285 | py = y; | ||
| 286 | oled_write_pixel(px, py, color); | ||
| 287 | } // Left left | ||
| 288 | } | ||
| 289 | |||
| 290 | bool dessiner = false; | ||
| 291 | |||
| 292 | do { | ||
| 293 | if (half == 1 && arrive_moitie(a, b)) break; | ||
| 294 | |||
| 295 | if (half == 2 && avant_moitie(a, b)) { | ||
| 296 | dessiner = false; | ||
| 297 | } else { | ||
| 298 | dessiner = true; | ||
| 299 | } | ||
| 300 | |||
| 301 | if (dessiner) { | ||
| 302 | if (sectors & 0x01) { | ||
| 303 | px = x + b; | ||
| 304 | py = y - a; | ||
| 305 | oled_write_pixel(px, py, color); | ||
| 306 | } // Upper right right | ||
| 307 | if (sectors & 0x02) { | ||
| 308 | px = x + a; | ||
| 309 | py = y - b; | ||
| 310 | oled_write_pixel(px, py, color); | ||
| 311 | } // Upper upper right | ||
| 312 | if (sectors & 0x04) { | ||
| 313 | px = x - a; | ||
| 314 | py = y - b; | ||
| 315 | oled_write_pixel(px, py, color); | ||
| 316 | } // Upper upper left | ||
| 317 | if (sectors & 0x08) { | ||
| 318 | px = x - b; | ||
| 319 | py = y - a; | ||
| 320 | oled_write_pixel(px, py, color); | ||
| 321 | } // Upper left left | ||
| 322 | if (sectors & 0x10) { | ||
| 323 | px = x - b; | ||
| 324 | py = y + a; | ||
| 325 | oled_write_pixel(px, py, color); | ||
| 326 | } // Lower left left | ||
| 327 | if (sectors & 0x20) { | ||
| 328 | px = x - a; | ||
| 329 | py = y + b; | ||
| 330 | oled_write_pixel(px, py, color); | ||
| 331 | } // Lower lower left | ||
| 332 | if (sectors & 0x40) { | ||
| 333 | px = x + a; | ||
| 334 | py = y + b; | ||
| 335 | oled_write_pixel(px, py, color); | ||
| 336 | } // Lower lower right | ||
| 337 | if (sectors & 0x80) { | ||
| 338 | px = x + b; | ||
| 339 | py = y + a; | ||
| 340 | oled_write_pixel(px, py, color); | ||
| 341 | } // Lower right right | ||
| 342 | } | ||
| 343 | |||
| 344 | if (P < 0) | ||
| 345 | P += 3 + 2 * a++; | ||
| 346 | else | ||
| 347 | P += 5 + 2 * (a++ - b--); | ||
| 348 | } while (a < b); | ||
| 349 | |||
| 350 | if (half != 1) { | ||
| 351 | if (sectors & 0xC0) { | ||
| 352 | px = x + a; | ||
| 353 | py = y + b; | ||
| 354 | oled_write_pixel(px, py, color); | ||
| 355 | } // Lower right | ||
| 356 | if (sectors & 0x03) { | ||
| 357 | px = x + a; | ||
| 358 | py = y - b; | ||
| 359 | oled_write_pixel(px, py, color); | ||
| 360 | } // Upper right | ||
| 361 | if (sectors & 0x30) { | ||
| 362 | px = x - a; | ||
| 363 | py = y + b; | ||
| 364 | oled_write_pixel(px, py, color); | ||
| 365 | } // Lower left | ||
| 366 | if (sectors & 0x0C) { | ||
| 367 | px = x - a; | ||
| 368 | py = y - b; | ||
| 369 | oled_write_pixel(px, py, color); | ||
| 370 | } // Upper left | ||
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | void draw_static(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int color, uint8_t density) { | ||
| 375 | unsigned long rx = fastrand_long(); | ||
| 376 | unsigned long ry = fastrand_long(); | ||
| 377 | unsigned long maskx = 1; | ||
| 378 | unsigned long masky = 1; | ||
| 379 | unsigned long mask_base = 1; | ||
| 380 | |||
| 381 | // more 1 in the octet | ||
| 382 | for (int r = 0; r < density; r++) { | ||
| 383 | rx &= fastrand_long(); | ||
| 384 | ry &= fastrand_long(); | ||
| 385 | } | ||
| 386 | |||
| 387 | color = ((rx >> 1) % 2) == 0; | ||
| 388 | |||
| 389 | for (uint8_t i = 0; i < width; i++) { | ||
| 390 | for (uint8_t j = 0; j < heigth; j++) { | ||
| 391 | // new mask based on ij loop | ||
| 392 | maskx = (mask_base << i); | ||
| 393 | masky = (mask_base << j); | ||
| 394 | |||
| 395 | // logic AND with the masks | ||
| 396 | if (((rx & maskx) == maskx) && ((ry & masky) == masky)) { | ||
| 397 | oled_write_pixel(x + i, y + j, color); | ||
| 398 | } | ||
| 399 | } | ||
| 400 | } | ||
| 401 | } | ||
| 402 | |||
| 403 | void copy_pixel(int from, int shift, unsigned char mask) { | ||
| 404 | if (shift == 0) return; | ||
| 405 | |||
| 406 | // pixel cluster from | ||
| 407 | char c_from = get_oled_char(from); | ||
| 408 | char extract = c_from & mask; | ||
| 409 | |||
| 410 | // pixel cluster shift | ||
| 411 | char c_from_shift = get_oled_char(from + shift); | ||
| 412 | c_from_shift &= ~(mask); | ||
| 413 | c_from_shift |= extract; | ||
| 414 | oled_write_raw_byte(c_from_shift, from + shift); | ||
| 415 | |||
| 416 | // fill blank with black | ||
| 417 | c_from &= ~(mask); | ||
| 418 | oled_write_raw_byte(c_from, from); | ||
| 419 | } | ||
| 420 | |||
| 421 | void draw_glitch_comb(uint8_t x, uint8_t y, uint8_t width, uint16_t height, uint8_t iSize, bool odd) { | ||
| 422 | // work only on row | ||
| 423 | uint16_t y_start = (y / 8) * 32; | ||
| 424 | uint8_t nb_h = height / 8; | ||
| 425 | |||
| 426 | uint8_t w_max = width; | ||
| 427 | uint16_t index = y_start + x; | ||
| 428 | |||
| 429 | // shift pair even pixel | ||
| 430 | int mask_1 = 85; | ||
| 431 | int mask_2 = 170; | ||
| 432 | |||
| 433 | if (!odd) { | ||
| 434 | // shift odd pixel | ||
| 435 | mask_1 = 170; | ||
| 436 | mask_2 = 85; | ||
| 437 | } | ||
| 438 | |||
| 439 | // wobble | ||
| 440 | uint16_t pos = 0; | ||
| 441 | for (uint16_t j = 0; j < nb_h; j++) { | ||
| 442 | // next line | ||
| 443 | index = (y_start + x) + (j * 32); | ||
| 444 | |||
| 445 | for (uint16_t i = 0; i < w_max; i++) { | ||
| 446 | if (i + iSize < w_max) { | ||
| 447 | pos = index + i; | ||
| 448 | copy_pixel(pos + iSize, iSize * -1, mask_1); | ||
| 449 | } | ||
| 450 | |||
| 451 | if (w_max - 1 - i - iSize >= 0) { | ||
| 452 | pos = (index + w_max - 1) - i; | ||
| 453 | copy_pixel(pos - iSize, iSize, mask_2); | ||
| 454 | } | ||
| 455 | } | ||
| 456 | } | ||
| 457 | } | ||
| 458 | |||
| 459 | void draw_random_char(uint8_t column, uint8_t row, char final_char, int value, uint8_t style) { | ||
| 460 | if (value < 0) return; | ||
| 461 | |||
| 462 | char c = final_char; | ||
| 463 | |||
| 464 | if (value < 100) { | ||
| 465 | c = ((fastrand() % 15) + 1); | ||
| 466 | } | ||
| 467 | |||
| 468 | oled_set_cursor(column, row); | ||
| 469 | oled_write_char(c, false); | ||
| 470 | } | ||
| 471 | |||
| 472 | void get_glitch_index_new(uint16_t *glitch_timer, uint8_t *current_glitch_scope_time, uint8_t *glitch_index, uint8_t min_time, uint16_t max_time, uint8_t glitch_probobility, uint8_t glitch_frame_number) { | ||
| 473 | if (timer_elapsed(*glitch_timer) > *current_glitch_scope_time) { | ||
| 474 | // end of the last glitch period | ||
| 475 | *glitch_timer = timer_read(); | ||
| 476 | |||
| 477 | // new random glich period | ||
| 478 | *current_glitch_scope_time = min_time + fastrand() % (max_time - min_time); | ||
| 479 | |||
| 480 | bool bGenerateGlitch = (fastrand() % 100) < glitch_probobility; | ||
| 481 | if (!bGenerateGlitch) { | ||
| 482 | // no glitch | ||
| 483 | *glitch_index = 0; | ||
| 484 | return; | ||
| 485 | } | ||
| 486 | |||
| 487 | // get a new glitch index | ||
| 488 | *glitch_index = fastrand() % glitch_frame_number; | ||
| 489 | } | ||
| 490 | } | ||
| 491 | |||
| 492 | uint8_t get_glitch_frame_index(uint8_t glitch_probobility, uint8_t glitch_frame_number) { | ||
| 493 | bool bGenerateGlitch = (fastrand() % 100) < glitch_probobility; | ||
| 494 | if (!bGenerateGlitch) { | ||
| 495 | // no glitch | ||
| 496 | return 0; | ||
| 497 | } | ||
| 498 | |||
| 499 | // get a new glitch index | ||
| 500 | return fastrand() % glitch_frame_number; | ||
| 501 | } | ||
| 502 | |||
| 503 | uint8_t get_glitch_duration(uint8_t min_time, uint16_t max_time) { return min_time + fastrand() % (max_time - min_time); } | ||
| 504 | |||
| 505 | void get_glitch_index(uint32_t *glitch_timer, int *current_glitch_scope_time, uint8_t *glitch_index, uint8_t min_time, uint16_t max_time, uint8_t glitch_probobility, uint8_t glitch_frame_number) { | ||
| 506 | if (timer_elapsed32(*glitch_timer) > *current_glitch_scope_time) { | ||
| 507 | // end of the last glitch period | ||
| 508 | *glitch_timer = timer_read32(); | ||
| 509 | |||
| 510 | // new random glich period | ||
| 511 | *current_glitch_scope_time = min_time + fastrand() % (max_time - min_time); | ||
| 512 | |||
| 513 | bool bGenerateGlitch = (fastrand() % 100) < glitch_probobility; | ||
| 514 | if (!bGenerateGlitch) { | ||
| 515 | // no glitch | ||
| 516 | *glitch_index = 0; | ||
| 517 | return; | ||
| 518 | } | ||
| 519 | |||
| 520 | // get a new glitch index | ||
| 521 | *glitch_index = fastrand() % glitch_frame_number; | ||
| 522 | } | ||
| 523 | } | ||
| 524 | |||
| 525 | void draw_progress(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int value, uint8_t style, bool color) { | ||
| 526 | if (value > 100) { | ||
| 527 | value = 100; | ||
| 528 | } | ||
| 529 | int lenght = (width * value) / 100; | ||
| 530 | for (uint8_t i = 0; i < lenght; i++) { | ||
| 531 | switch (style) { | ||
| 532 | case 0: | ||
| 533 | drawline_vb(x + i, y, heigth - 1, color); | ||
| 534 | break; | ||
| 535 | |||
| 536 | // case 1: | ||
| 537 | // drawline_vb(x + i, y + 1, heigth - 3, ((i % 3) < 2)); | ||
| 538 | // break; | ||
| 539 | // case 2: | ||
| 540 | // // . . . . . | ||
| 541 | // drawline_vb(x + i, y + 3, 2, ((i % 2) == 0)); | ||
| 542 | // break; | ||
| 543 | } | ||
| 544 | } | ||
| 545 | } | ||
| 546 | |||
| 547 | void oled_write_raw_P_cursor(uint8_t col, uint8_t line, const char *data, uint16_t size) { | ||
| 548 | // raw_P at cursor position | ||
| 549 | oled_set_cursor(col, line); | ||
| 550 | oled_write_raw_P(data, size); | ||
| 551 | } | ||
| 552 | |||
| 553 | void oled_write_cursor(uint8_t col, uint8_t line, const char *data, bool invert) { | ||
| 554 | // write at cursor position | ||
| 555 | oled_set_cursor(col, line); | ||
| 556 | oled_write(data, invert); | ||
| 557 | } | ||
| 558 | |||
| 559 | void draw_label(const char *data, uint8_t len, uint8_t row, int value) { | ||
| 560 | if (value < 0) return; | ||
| 561 | if (row >= 16 || row < 0) return; | ||
| 562 | oled_write_cursor(0, row, data, false); | ||
| 563 | } | ||
| 564 | |||
| 565 | void draw_box(const char *data, uint8_t len, uint8_t row, long value, uint8_t style) { | ||
| 566 | if (value < 0) return; | ||
| 567 | if (row >= 16 || row < 0) return; | ||
| 568 | |||
| 569 | oled_write_cursor(0, row, data, false); | ||
| 570 | |||
| 571 | uint8_t y = row * 8; | ||
| 572 | |||
| 573 | uint8_t x = 6 * len; | ||
| 574 | uint8_t w = 32 - x; | ||
| 575 | |||
| 576 | if (value < 0) value = 0; | ||
| 577 | if (value > 100) value = 100; | ||
| 578 | draw_progress(x, y, w, 7, value, style, 1); | ||
| 579 | } | ||
| 580 | |||
| 581 | char get_oled_char(uint16_t start_index) { | ||
| 582 | oled_buffer_reader_t reader; | ||
| 583 | reader = oled_read_raw(start_index); | ||
| 584 | return *reader.current_element; | ||
| 585 | } | ||
| 586 | |||
| 587 | static int get_index_first_block(uint8_t y) { return ((y / 8) * 32); } | ||
| 588 | |||
| 589 | void move_block(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int shift) { | ||
| 590 | // clip | ||
| 591 | if (x >= 31) return; | ||
| 592 | if (y >= 127) return; | ||
| 593 | |||
| 594 | int max_screen = 32 - 1; | ||
| 595 | if ((width + x) > max_screen + 1) width = max_screen + 1 - x; | ||
| 596 | |||
| 597 | if (width <= 1) return; | ||
| 598 | |||
| 599 | if ((heigth + y) > 127) heigth = 127 - y; | ||
| 600 | if (heigth <= 1) return; | ||
| 601 | |||
| 602 | // [-32 & +32] | ||
| 603 | if (shift > max_screen) shift = max_screen; | ||
| 604 | if (shift < -1 * max_screen) shift = -1 * max_screen; | ||
| 605 | |||
| 606 | if ((width + x + shift) > max_screen) width = width - shift; | ||
| 607 | |||
| 608 | int pixelTop = 8 - (y % 8); | ||
| 609 | int pixelBottom = (y + heigth) % 8; | ||
| 610 | |||
| 611 | unsigned char cMastTop = ~((unsigned)255 >> (pixelTop)); | ||
| 612 | unsigned char cMastBottom = ~((unsigned)255 << (pixelBottom)); | ||
| 613 | |||
| 614 | int indexFirstBloc = get_index_first_block(y) + x; | ||
| 615 | int indexFirstBlocFull = get_index_first_block(y + pixelTop) + x; | ||
| 616 | int indexFirstBlocEnd = get_index_first_block(y + heigth) + x; | ||
| 617 | |||
| 618 | int nbBlockHeigth = (heigth - pixelTop - pixelBottom) / 8; | ||
| 619 | |||
| 620 | if (nbBlockHeigth < 0) { | ||
| 621 | // just single row | ||
| 622 | nbBlockHeigth = 0; | ||
| 623 | cMastBottom = 0; | ||
| 624 | } | ||
| 625 | |||
| 626 | if (shift < 0) { | ||
| 627 | for (uint16_t i = 0; i < width; i++) { | ||
| 628 | copy_pixel(indexFirstBloc + i, shift, cMastTop); | ||
| 629 | copy_pixel(indexFirstBlocEnd + i, shift, cMastBottom); | ||
| 630 | |||
| 631 | for (uint16_t j = 0; j < nbBlockHeigth; j++) { | ||
| 632 | copy_pixel(indexFirstBlocFull + i + (j * 32), shift, 255); | ||
| 633 | } | ||
| 634 | } | ||
| 635 | |||
| 636 | } else { | ||
| 637 | for (int i = width - 1; i >= 0; i--) { | ||
| 638 | copy_pixel(indexFirstBloc + i, shift, cMastTop); | ||
| 639 | copy_pixel(indexFirstBlocEnd + i, shift, cMastBottom); | ||
| 640 | |||
| 641 | for (uint16_t j = 0; j < nbBlockHeigth; j++) { | ||
| 642 | copy_pixel(indexFirstBlocFull + i + (j * 32), shift, 255); | ||
| 643 | } | ||
| 644 | } | ||
| 645 | } | ||
| 646 | } | ||
| 647 | |||
| 648 | int interpo_pourcent(int min, int max, int v) { | ||
| 649 | // interpolation | ||
| 650 | float x0 = min; | ||
| 651 | float x1 = max; | ||
| 652 | float y0 = 0; | ||
| 653 | float y1 = 100; | ||
| 654 | float xp = v; | ||
| 655 | float yp = y0 + ((y1 - y0) / (x1 - x0)) * (xp - x0); | ||
| 656 | |||
| 657 | return (int)yp; | ||
| 658 | } | ||
| 659 | |||
| 660 | uint8_t BAYER_PATTERN_4[4][4] = {{15, 135, 45, 165}, {195, 75, 225, 105}, {60, 180, 30, 150}, {240, 120, 210, 90}}; | ||
| 661 | |||
| 662 | void draw_gradient(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, uint8_t color_start, uint8_t color_end, uint8_t tres) { | ||
| 663 | bool invert = color_start > color_end; | ||
| 664 | |||
| 665 | if (invert) { | ||
| 666 | color_start = 255 - color_start; | ||
| 667 | color_end = 255 - color_end; | ||
| 668 | } | ||
| 669 | |||
| 670 | int step = (100 / tres); | ||
| 671 | int step_minus = (100 / (tres - 1)); | ||
| 672 | int distance = color_end - color_start; | ||
| 673 | |||
| 674 | for (uint8_t i = 0; i < width; i++) { | ||
| 675 | int position = interpo_pourcent(0, width, i); | ||
| 676 | |||
| 677 | float color = position; | ||
| 678 | color = ((int)(color / step)) * step_minus; | ||
| 679 | |||
| 680 | color = color_start + ((distance * color) / 100); | ||
| 681 | |||
| 682 | for (uint8_t j = 0; j < heigth; j++) { | ||
| 683 | uint8_t m = BAYER_PATTERN_4[i % 4][j % 4]; | ||
| 684 | unsigned char color_d = (color > m) ? !invert : invert; | ||
| 685 | |||
| 686 | oled_write_pixel(x + i, y + j, color_d); | ||
| 687 | } | ||
| 688 | } | ||
| 689 | } | ||
| 690 | |||
| 691 | void render_tv_animation(uint8_t frame_number, uint8_t x, uint8_t y, uint8_t width, uint8_t heigth) { | ||
| 692 | uint8_t xCenter = x + (width / 2); | ||
| 693 | uint8_t yCenter = y + (heigth / 2); | ||
| 694 | |||
| 695 | switch (frame_number) { | ||
| 696 | case 0: | ||
| 697 | // a fond : allume | ||
| 698 | drawline_hr_heigth(x, yCenter, width, 17, true); | ||
| 699 | break; | ||
| 700 | |||
| 701 | case 1: | ||
| 702 | drawline_hr_heigth(x, yCenter, width, 12, true); | ||
| 703 | draw_ellipse_fill(xCenter, yCenter, 7, 15, true); | ||
| 704 | break; | ||
| 705 | |||
| 706 | case 2: | ||
| 707 | drawline_hr_heigth(x, yCenter, width, 5, true); | ||
| 708 | draw_ellipse_fill(xCenter, yCenter, 5, 8, true); | ||
| 709 | break; | ||
| 710 | |||
| 711 | case 3: | ||
| 712 | drawline_hr_heigth(x, yCenter, width, 3, true); | ||
| 713 | draw_ellipse_fill(xCenter, yCenter, 3, 4, true); | ||
| 714 | break; | ||
| 715 | |||
| 716 | case 4: | ||
| 717 | drawline_hr_heigth(x, yCenter, width, 2, true); | ||
| 718 | draw_fill_circle(xCenter, yCenter, 3, true); | ||
| 719 | break; | ||
| 720 | |||
| 721 | case 5: | ||
| 722 | // central line | ||
| 723 | drawline_hr(x, yCenter, width, true); | ||
| 724 | draw_fill_circle(xCenter, yCenter, 2, true); | ||
| 725 | break; | ||
| 726 | |||
| 727 | case 6: | ||
| 728 | // cross | ||
| 729 | drawline_hr(xCenter, yCenter + 1, 2, true); | ||
| 730 | drawline_hr(xCenter, yCenter - 1, 2, true); | ||
| 731 | |||
| 732 | // central line | ||
| 733 | drawline_hr(x, yCenter, width, true); | ||
| 734 | break; | ||
| 735 | |||
| 736 | case 7: | ||
| 737 | // cross | ||
| 738 | drawline_hr(xCenter, yCenter + 1, 2, true); | ||
| 739 | drawline_hr(xCenter, yCenter - 1, 2, true); | ||
| 740 | // central line | ||
| 741 | drawline_hr(xCenter - 8, yCenter, 18, true); | ||
| 742 | // static | ||
| 743 | oled_write_pixel(xCenter - 11, yCenter, true); | ||
| 744 | oled_write_pixel(xCenter + 12, yCenter, true); | ||
| 745 | break; | ||
| 746 | |||
| 747 | case 8: | ||
| 748 | // cross | ||
| 749 | drawline_hr(xCenter, yCenter + 1, 2, true); | ||
| 750 | drawline_hr(xCenter, yCenter - 1, 2, true); | ||
| 751 | // central line | ||
| 752 | drawline_hr(xCenter - 2, yCenter, 4, true); | ||
| 753 | // static | ||
| 754 | drawline_hr(xCenter - 7, yCenter, 2, true); | ||
| 755 | drawline_hr(xCenter + 6, yCenter, 3, true); | ||
| 756 | |||
| 757 | // oled_write_pixel(xCenter - 11, yCenter, true); | ||
| 758 | oled_write_pixel(xCenter - 9, yCenter, true); | ||
| 759 | oled_write_pixel(xCenter + 12, yCenter, true); | ||
| 760 | oled_write_pixel(xCenter + 14, yCenter, true); | ||
| 761 | break; | ||
| 762 | |||
| 763 | case 9: | ||
| 764 | // central line | ||
| 765 | drawline_hr(xCenter, yCenter, 2, true); | ||
| 766 | break; | ||
| 767 | } | ||
| 768 | } \ No newline at end of file | ||
diff --git a/keyboards/lily58/keymaps/druotoni/draw_helper.h b/keyboards/lily58/keymaps/druotoni/draw_helper.h new file mode 100644 index 000000000..991ab0d0a --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/draw_helper.h | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // Copyright 2021 ugfx | ||
| 3 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | // line | ||
| 8 | void drawline_vb(uint8_t x, uint8_t y, uint8_t width, bool color); | ||
| 9 | void drawline_vt(uint8_t x, uint8_t y, uint8_t width, bool color); | ||
| 10 | void drawline_hr(uint8_t x, uint8_t y, uint8_t width, bool color); | ||
| 11 | void drawline_hl(uint8_t x, uint8_t y, uint8_t width, bool color); | ||
| 12 | void drawline_hr_heigth(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color); | ||
| 13 | |||
| 14 | // rectangle | ||
| 15 | void draw_rectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color); | ||
| 16 | void draw_rectangle_fill(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color); | ||
| 17 | void draw_gradient(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, uint8_t color_start, uint8_t color_end, uint8_t tres); | ||
| 18 | |||
| 19 | // circle | ||
| 20 | void draw_fill_circle(short x, short y, uint8_t radius, bool color); | ||
| 21 | void draw_circle(uint8_t x, uint8_t y, uint8_t radius, bool color); | ||
| 22 | void draw_ellipse(uint8_t x, uint8_t y, uint8_t a, uint8_t b, bool color); | ||
| 23 | void draw_ellipse_fill(uint8_t x, uint8_t y, uint8_t a, uint8_t b, bool color); | ||
| 24 | void draw_arc_sector(uint8_t x, uint8_t y, uint8_t radius, unsigned char sectors, unsigned char half, bool color); | ||
| 25 | void draw_static(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int color, uint8_t density); | ||
| 26 | |||
| 27 | // text | ||
| 28 | void draw_random_char(uint8_t column, uint8_t row, char final_char, int value, uint8_t style); | ||
| 29 | void draw_label(const char *data, uint8_t len, uint8_t row, int value); | ||
| 30 | void draw_box(const char *data, uint8_t len, uint8_t row, long value, uint8_t style); | ||
| 31 | void draw_progress(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int value, uint8_t style, bool color); | ||
| 32 | |||
| 33 | // oled drivers stuff | ||
| 34 | char get_oled_char(uint16_t start_index); | ||
| 35 | void oled_write_cursor(uint8_t col, uint8_t line, const char *data, bool invert); | ||
| 36 | void oled_write_raw_P_cursor(uint8_t col, uint8_t line, const char *data, uint16_t size); | ||
| 37 | |||
| 38 | // pixel manipulation | ||
| 39 | void copy_pixel(int from, int shift, unsigned char mask); | ||
| 40 | void move_block(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int shift); | ||
| 41 | void draw_glitch_comb(uint8_t x, uint8_t y, uint8_t width, uint16_t height, uint8_t iSize, bool odd); | ||
| 42 | |||
| 43 | // misc | ||
| 44 | void render_tv_animation(uint8_t frame_number, uint8_t x, uint8_t y, uint8_t width, uint8_t heigth); | ||
| 45 | int interpo_pourcent(int min, int max, int v); | ||
| 46 | void get_glitch_index(uint32_t *glitch_timer, int *current_glitch_scope_time, uint8_t *glitch_index, uint8_t min_time, uint16_t max_time, uint8_t glitch_probobility, uint8_t glitch_frame_number); | ||
| 47 | void get_glitch_index_new(uint16_t *glitch_timer, uint8_t *current_glitch_scope_time, uint8_t *glitch_index, uint8_t min_time, uint16_t max_time, uint8_t glitch_probobility, uint8_t glitch_frame_number); | ||
diff --git a/keyboards/lily58/keymaps/druotoni/fast_random.c b/keyboards/lily58/keymaps/druotoni/fast_random.c new file mode 100644 index 000000000..3028b57ac --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/fast_random.c | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | #include "fast_random.h" | ||
| 4 | |||
| 5 | // seed for random | ||
| 6 | static unsigned long g_seed = 0; | ||
| 7 | |||
| 8 | int fastrand(void) { | ||
| 9 | // todo : try with random16(); | ||
| 10 | g_seed = (214013 * g_seed + 2531011); | ||
| 11 | return (g_seed >> 16) & 0x7FFF; | ||
| 12 | } | ||
| 13 | |||
| 14 | unsigned long fastrand_long(void) { | ||
| 15 | g_seed = (214013 * g_seed + 2531011); | ||
| 16 | return g_seed; | ||
| 17 | } | ||
diff --git a/keyboards/lily58/keymaps/druotoni/fast_random.h b/keyboards/lily58/keymaps/druotoni/fast_random.h new file mode 100644 index 000000000..fe8c4a40a --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/fast_random.h | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | int fastrand(void); | ||
| 7 | unsigned long fastrand_long(void); \ No newline at end of file | ||
diff --git a/keyboards/lily58/keymaps/druotoni/gui_state.c b/keyboards/lily58/keymaps/druotoni/gui_state.c new file mode 100644 index 000000000..d86e67ec7 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/gui_state.c | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include QMK_KEYBOARD_H | ||
| 5 | |||
| 6 | #include "gui_state.h" | ||
| 7 | #include "draw_helper.h" | ||
| 8 | |||
| 9 | // timer for the gui state | ||
| 10 | uint32_t global_sleep_timer = 0; | ||
| 11 | uint32_t global_waking_up_timer = 0; | ||
| 12 | uint32_t global_booting_timer = 0; | ||
| 13 | |||
| 14 | // timers test for states | ||
| 15 | #ifdef WITH_BOOT | ||
| 16 | static bool IsBooting(void) { return (timer_elapsed32(global_booting_timer) < BOOTING_TIME_TRESHOLD); } | ||
| 17 | #else | ||
| 18 | static bool IsBooting(void) { return false; } | ||
| 19 | #endif | ||
| 20 | |||
| 21 | // state test | ||
| 22 | static bool IsWakingUp(void) { return (timer_elapsed32(global_waking_up_timer) < WAKING_UP_TIME_TRESHOLD); } | ||
| 23 | static bool IsIdle(void) { return (timer_elapsed32(global_sleep_timer) > IDLE_TIME_TRESHOLD && timer_elapsed32(global_sleep_timer) < HALTING_TIME_TRESHOLD); } | ||
| 24 | static bool IsSleep(void) { return (timer_elapsed32(global_sleep_timer) >= SLEEP_TIME_TRESHOLD); } | ||
| 25 | static bool IsHalting(void) { return (timer_elapsed32(global_sleep_timer) >= HALTING_TIME_TRESHOLD && timer_elapsed32(global_sleep_timer) < SLEEP_TIME_TRESHOLD); } | ||
| 26 | |||
| 27 | gui_state_t get_gui_state(void) { | ||
| 28 | // get gui states by testing timers | ||
| 29 | if (IsBooting()) return _BOOTING; | ||
| 30 | if (IsWakingUp()) return _WAKINGUP; | ||
| 31 | if (IsIdle()) return _IDLE; | ||
| 32 | if (IsHalting()) return _HALTING; | ||
| 33 | if (IsSleep()) return _SLEEP; | ||
| 34 | |||
| 35 | return _UP; | ||
| 36 | } | ||
| 37 | |||
| 38 | void update_gui_state(void) { | ||
| 39 | // what to do when a key is pressed | ||
| 40 | gui_state_t t = get_gui_state(); | ||
| 41 | |||
| 42 | #ifdef WITH_BOOT | ||
| 43 | if (t == _SLEEP) { | ||
| 44 | // booting | ||
| 45 | global_booting_timer = timer_read32(); | ||
| 46 | } | ||
| 47 | |||
| 48 | if (t == _BOOTING) { | ||
| 49 | // cancel booting | ||
| 50 | global_booting_timer = 1000000; | ||
| 51 | } | ||
| 52 | #else | ||
| 53 | if (t == _SLEEP) { | ||
| 54 | // waking up | ||
| 55 | global_waking_up_timer = timer_read32(); | ||
| 56 | } | ||
| 57 | #endif | ||
| 58 | |||
| 59 | if (t == _IDLE || t == _HALTING || t == _BOOTING) { | ||
| 60 | // waking up | ||
| 61 | global_waking_up_timer = timer_read32(); | ||
| 62 | } | ||
| 63 | |||
| 64 | // no sleep | ||
| 65 | global_sleep_timer = timer_read32(); | ||
| 66 | } | ||
| 67 | |||
| 68 | uint8_t get_glitch_probability(void) { | ||
| 69 | // more gliches could occur when halting time is near | ||
| 70 | return interpo_pourcent(IDLE_TIME_TRESHOLD, HALTING_TIME_TRESHOLD, timer_elapsed32(global_sleep_timer)); | ||
| 71 | } | ||
diff --git a/keyboards/lily58/keymaps/druotoni/gui_state.h b/keyboards/lily58/keymaps/druotoni/gui_state.h new file mode 100644 index 000000000..190e02d30 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/gui_state.h | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | // states timing | ||
| 7 | #define BOOTING_TIME_TRESHOLD 7000 | ||
| 8 | #define WAKING_UP_TIME_TRESHOLD 300 | ||
| 9 | #define IDLE_TIME_TRESHOLD 4000 | ||
| 10 | #define HALTING_TIME_TRESHOLD IDLE_TIME_TRESHOLD + 6000 | ||
| 11 | #define SLEEP_TIME_TRESHOLD HALTING_TIME_TRESHOLD + 8000 | ||
| 12 | |||
| 13 | typedef uint8_t gui_state_t; | ||
| 14 | enum gui_state { _WAKINGUP = 0, _IDLE, _SLEEP, _UP, _BOOTING, _HALTING }; | ||
| 15 | |||
| 16 | gui_state_t get_gui_state(void); | ||
| 17 | void update_gui_state(void); | ||
| 18 | uint8_t get_glitch_probability(void); \ No newline at end of file | ||
diff --git a/keyboards/lily58/keymaps/druotoni/keymap.c b/keyboards/lily58/keymaps/druotoni/keymap.c new file mode 100644 index 000000000..2db32047e --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/keymap.c | |||
| @@ -0,0 +1,253 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include QMK_KEYBOARD_H | ||
| 5 | #include "keymap_french.h" | ||
| 6 | #include "transactions.h" | ||
| 7 | |||
| 8 | // global | ||
| 9 | #include "gui_state.h" | ||
| 10 | #include "boot.h" | ||
| 11 | #include "navi_logo.h" | ||
| 12 | |||
| 13 | #include "draw_helper.h" | ||
| 14 | #include "fast_random.h" | ||
| 15 | |||
| 16 | // left side | ||
| 17 | #include "layer_frame.h" | ||
| 18 | #include "burst.h" | ||
| 19 | |||
| 20 | // right side | ||
| 21 | #include "ring.h" | ||
| 22 | |||
| 23 | // clang-format off | ||
| 24 | const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | ||
| 25 | /* QWERTY | ||
| 26 | * ,-----------------------------------------. ,-----------------------------------------. | ||
| 27 | * | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | DEL | | ||
| 28 | * |------+------+------+------+------+------| |------+------+------+------+------+------| | ||
| 29 | * | Tab | Q | W | E | R | T | | Y | U | I | O | P | ^ | | ||
| 30 | * |------+------+------+------+------+------| |------+------+------+------+------+------| | ||
| 31 | * |LShift| A | S | D | F | G |-------. ,-------| H | J | K | L | ; |RShift| | ||
| 32 | * |------+------+------+------+------+------| " | | ) |------+------+------+------+------+------| | ||
| 33 | * |LCTRL | Z | X | C | V | B |-------| |-------| N | M | , | . | / | $ | | ||
| 34 | * `-----------------------------------------/ / \ \-----------------------------------------' | ||
| 35 | * | LAlt | SPE | Space| / NAV / \Enter \ |BackSP| ] | RGUI | | ||
| 36 | * | | | |/ / \ \ | | | | | ||
| 37 | * `----------------------------' '------''--------------------' | ||
| 38 | */ | ||
| 39 | [_QWERTY] = LAYOUT( | ||
| 40 | KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DELETE, | ||
| 41 | KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, FR_CIRC, | ||
| 42 | KC_LSFT, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_RSFT, | ||
| 43 | KC_LCTRL, KC_Z, KC_X, KC_C, KC_V, KC_B, S(KC_Z), FR_RPRN, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_QUOT, | ||
| 44 | KC_LALT, TT(_RAISE), KC_SPC, TT(_LOWER), KC_ENT, KC_BSPC, KC_RBRC, KC_RGUI | ||
| 45 | ), | ||
| 46 | |||
| 47 | /* LOWER | ||
| 48 | * ,---------------------------------------------. ,------------------------------------------------. | ||
| 49 | * | ESC | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 | DEL | | ||
| 50 | * |------+-------+-------+------+-------+-------| |--------+--------+--------+-------+------+------| | ||
| 51 | * | RST | F11 | F12 | DEL | paste | copy | | home | pg up | print | redo | w | | | ||
| 52 | * |------+-------+-------+------+-------+-------| |--------+--------+--------+-------+------+------| | ||
| 53 | * | | all | | SAV | undo | BackSP|-------. ,-------| left | down | up | right | | | | ||
| 54 | * |------+-------+-------+------+-------+-------| enter| | |--------+--------+--------+-------+------+------| | ||
| 55 | * | F9 | F11 | F10 | F5 | TAB | cut |-------| |-------| end | pg dw | | | | | | ||
| 56 | * `---------------------------------------------/ / \ \-----------------------------------------------' | ||
| 57 | * | | SPE | | / / \ \ | | MENU | | | ||
| 58 | * | | | |/ / \ \ | | | | | ||
| 59 | * `--------------------------------' '-------''--------------------' | ||
| 60 | */ | ||
| 61 | [_LOWER] = LAYOUT( | ||
| 62 | KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_DELETE, | ||
| 63 | RESET, KC_F11, KC_F12, KC_DELETE, RCTL(FR_V), RCTL(FR_C), KC_HOME, KC_PGUP, KC_PSCR, RCTL(FR_Y), RCTL(KC_RIGHT), _______, | ||
| 64 | _______,RCTL(FR_A), _______,RCTL(FR_S), RCTL(FR_Z), KC_BSPC, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, _______, _______, | ||
| 65 | KC_F9, KC_F11, KC_F10, KC_F5, LALT(KC_TAB), RCTL(FR_X), KC_ENT, _______, KC_END, KC_PGDN, _______, _______, _______, _______, | ||
| 66 | _______,TT(_RAISE), _______, _______, _______, _______, KC_APP, _______), | ||
| 67 | |||
| 68 | /* RAISE | ||
| 69 | * ,-----------------------------------------. ,-------------------------------------------. | ||
| 70 | * | | | | | | | | | | / | * | - | RGB TOG| | ||
| 71 | * |------+------+------+------+------+------| |------+------+------+------+-----+--------| | ||
| 72 | * | ` | [ | ] | | | | | ^ | 7 | 8 | 9 | + | RGB HUI| | ||
| 73 | * |------+------+------+------+------+------| |------+------+------+------+-----+--------| | ||
| 74 | * | | @ | | | & | € | # |-------. ,-------| $ | 4 | 5 | 6 | | | | ||
| 75 | * |------+------+------+------+------+------| | | |------+------+------+------+-----+--------| | ||
| 76 | * | F7 | F8 | F9 | F10 | # | F12 |-------| |-------| | 1 | 2 | 3 | | | | ||
| 77 | * `-----------------------------------------/ / \ \------------------------------------------' | ||
| 78 | * | | | | / / \ \ | | 0 | . | | ||
| 79 | * | | | |/ / \ \ | | | | | ||
| 80 | * `----------------------------' '------''---------------------' | ||
| 81 | */ | ||
| 82 | [_RAISE] = LAYOUT( | ||
| 83 | _______, _______, _______, _______, _______, _______, _______, _______, KC_PSLS, KC_PAST, KC_PMNS, RGB_TOG, | ||
| 84 | KC_GRV, FR_LBRC, FR_RBRC, _______, _______, _______, FR_EQL, KC_KP_7, KC_KP_8, KC_KP_9, KC_PPLS, RGB_HUI, | ||
| 85 | _______, FR_AT, FR_PIPE, ALGR(KC_1), FR_EURO, FR_HASH, S(FR_EQL), KC_KP_4, KC_KP_5, KC_KP_6, _______, _______, | ||
| 86 | KC_F7, KC_F8, KC_F9, KC_F10, FR_HASH, KC_F12, _______, _______, _______, KC_KP_1, KC_KP_2, KC_KP_3, _______, _______, | ||
| 87 | _______, _______, _______, _______, _______, _______, KC_KP_0, KC_KP_DOT) | ||
| 88 | }; | ||
| 89 | // clang-format on | ||
| 90 | |||
| 91 | // sync transport | ||
| 92 | typedef struct _sync_keycode_t { | ||
| 93 | uint16_t keycode; | ||
| 94 | } sync_keycode_t; | ||
| 95 | |||
| 96 | // force rigth side to update | ||
| 97 | bool b_sync_need_send = false; | ||
| 98 | |||
| 99 | // last keycode typed | ||
| 100 | sync_keycode_t last_keycode; | ||
| 101 | |||
| 102 | oled_rotation_t oled_init_user(oled_rotation_t rotation) { | ||
| 103 | // vertical orientation | ||
| 104 | return OLED_ROTATION_270; | ||
| 105 | } | ||
| 106 | |||
| 107 | void render(gui_state_t t) { | ||
| 108 | // logo | ||
| 109 | render_logo(t); | ||
| 110 | |||
| 111 | #if IS_LEFT | ||
| 112 | // left side | ||
| 113 | render_layer_frame(t); | ||
| 114 | render_gears(); | ||
| 115 | |||
| 116 | decay_scope(); | ||
| 117 | render_scope(t); | ||
| 118 | #endif | ||
| 119 | |||
| 120 | #if IS_RIGHT | ||
| 121 | // right side | ||
| 122 | render_circle(t); | ||
| 123 | #endif | ||
| 124 | } | ||
| 125 | |||
| 126 | void update(uint16_t keycode) { | ||
| 127 | #if IS_LEFT | ||
| 128 | update_scope(); | ||
| 129 | #endif | ||
| 130 | |||
| 131 | #if IS_RIGHT | ||
| 132 | update_circle(keycode); | ||
| 133 | #endif | ||
| 134 | } | ||
| 135 | |||
| 136 | void reset(void) { | ||
| 137 | #if IS_LEFT | ||
| 138 | reset_scope(); | ||
| 139 | #endif | ||
| 140 | |||
| 141 | #if IS_RIGHT | ||
| 142 | reset_ring(); | ||
| 143 | #endif | ||
| 144 | } | ||
| 145 | |||
| 146 | void set_wackingup_mode_clean(void) { | ||
| 147 | oled_clear(); | ||
| 148 | reset(); | ||
| 149 | } | ||
| 150 | |||
| 151 | bool oled_task_user(void) { | ||
| 152 | gui_state_t t = get_gui_state(); | ||
| 153 | |||
| 154 | // in sleep mode => turn display off | ||
| 155 | if (t == _SLEEP) { | ||
| 156 | oled_off(); | ||
| 157 | return false; | ||
| 158 | } | ||
| 159 | |||
| 160 | // not in sleep mode => screen is on | ||
| 161 | oled_on(); | ||
| 162 | |||
| 163 | #ifdef WITH_BOOT | ||
| 164 | // in booting mode => display booting animation | ||
| 165 | if (t == _BOOTING) { | ||
| 166 | bool boot_finished = render_boot(); | ||
| 167 | if (boot_finished) { | ||
| 168 | // end of the boot : wacking up | ||
| 169 | set_wackingup_mode_clean(); | ||
| 170 | update_gui_state(); | ||
| 171 | } | ||
| 172 | return false; | ||
| 173 | } | ||
| 174 | #endif | ||
| 175 | |||
| 176 | // in halting mode => display booting animation | ||
| 177 | if (t == _HALTING) { | ||
| 178 | render_halt(); | ||
| 179 | return false; | ||
| 180 | } | ||
| 181 | |||
| 182 | render(t); | ||
| 183 | return false; | ||
| 184 | } | ||
| 185 | |||
| 186 | void process_key(uint16_t keycode) { | ||
| 187 | // update screen with the new key | ||
| 188 | update(keycode); | ||
| 189 | |||
| 190 | gui_state_t t = get_gui_state(); | ||
| 191 | |||
| 192 | if (t == _IDLE) { | ||
| 193 | // wake up animation | ||
| 194 | reset(); | ||
| 195 | } | ||
| 196 | |||
| 197 | if (t == _BOOTING || t == _HALTING) { | ||
| 198 | // cancel booting or halting : waking_up | ||
| 199 | set_wackingup_mode_clean(); | ||
| 200 | } | ||
| 201 | |||
| 202 | if (t == _SLEEP) { | ||
| 203 | // boot sequence | ||
| 204 | set_wackingup_mode_clean(); | ||
| 205 | reset_boot(); | ||
| 206 | } | ||
| 207 | |||
| 208 | update_gui_state(); | ||
| 209 | } | ||
| 210 | |||
| 211 | void user_sync_a_slave_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) { | ||
| 212 | const sync_keycode_t* m2s = (const sync_keycode_t*)in_data; | ||
| 213 | // get the last char typed on left side and update the right side | ||
| 214 | process_key(m2s->keycode); | ||
| 215 | } | ||
| 216 | |||
| 217 | void keyboard_post_init_user(void) { | ||
| 218 | // callback for tranport sync data | ||
| 219 | transaction_register_rpc(USER_SYNC_A, user_sync_a_slave_handler); | ||
| 220 | } | ||
| 221 | |||
| 222 | void housekeeping_task_user(void) { | ||
| 223 | // only for master side | ||
| 224 | if (!is_keyboard_master()) return; | ||
| 225 | |||
| 226 | // only if a new char was typed | ||
| 227 | if (!b_sync_need_send) return; | ||
| 228 | |||
| 229 | // send the char to the slave side : sync is done | ||
| 230 | if (transaction_rpc_send(USER_SYNC_A, sizeof(last_keycode), &last_keycode)) { | ||
| 231 | b_sync_need_send = false; | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | bool process_record_user(uint16_t keycode, keyrecord_t* record) { | ||
| 236 | if (record->event.pressed) { | ||
| 237 | // master : store keycode to sent to the other side to be process_key | ||
| 238 | last_keycode.keycode = keycode; | ||
| 239 | b_sync_need_send = true; | ||
| 240 | |||
| 241 | // gui process the input | ||
| 242 | process_key(keycode); | ||
| 243 | } | ||
| 244 | return true; | ||
| 245 | } | ||
| 246 | |||
| 247 | #if IS_LEFT | ||
| 248 | layer_state_t layer_state_set_user(layer_state_t state) { | ||
| 249 | // update the frame with the layer name | ||
| 250 | update_layer_frame(state); | ||
| 251 | return state; | ||
| 252 | } | ||
| 253 | #endif | ||
diff --git a/keyboards/lily58/keymaps/druotoni/layer_frame.c b/keyboards/lily58/keymaps/druotoni/layer_frame.c new file mode 100644 index 000000000..6f7ae1a25 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/layer_frame.c | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include QMK_KEYBOARD_H | ||
| 5 | |||
| 6 | #include "gui_state.h" | ||
| 7 | #include "layer_frame.h" | ||
| 8 | #include "draw_helper.h" | ||
| 9 | |||
| 10 | #define ANIM_LAYER_FRAME_DURATION 2 | ||
| 11 | #define ANIM_LAYER_FRAME_MAX 7 | ||
| 12 | |||
| 13 | // current layer | ||
| 14 | uint8_t current_layer = _QWERTY; | ||
| 15 | |||
| 16 | // layer animation stuff | ||
| 17 | uint16_t anim_layer_frame_timer = 0; | ||
| 18 | uint8_t current_layer_frame = ANIM_LAYER_FRAME_MAX; | ||
| 19 | uint8_t layer_frame_destination = ANIM_LAYER_FRAME_MAX; | ||
| 20 | |||
| 21 | // layer name for display | ||
| 22 | const char* layer_name; | ||
| 23 | static const char* layer_ref[3] = {LAYER_NAME_0, LAYER_NAME_1, LAYER_NAME_2}; | ||
| 24 | |||
| 25 | void update_layer_frame(layer_state_t state) { | ||
| 26 | // reset timer | ||
| 27 | anim_layer_frame_timer = timer_read(); | ||
| 28 | |||
| 29 | // direction for animation base on layer selected | ||
| 30 | current_layer = get_highest_layer(state); | ||
| 31 | if (current_layer == _QWERTY) { | ||
| 32 | layer_frame_destination = 0; | ||
| 33 | } else { | ||
| 34 | layer_frame_destination = ANIM_LAYER_FRAME_MAX; | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 38 | static void draw_black_screen(void) { | ||
| 39 | // clean frame center | ||
| 40 | draw_rectangle_fill(3, 42, 26, 20, false); | ||
| 41 | drawline_hr(17, 62, 12, false); | ||
| 42 | } | ||
| 43 | |||
| 44 | void render_gears(void) { | ||
| 45 | // 64 bytes, 8x8 font, 8 characters, 32x16 image, 4 columns, 2 rows | ||
| 46 | static const char PROGMEM raw_logo[] = { | ||
| 47 | 0, 6, 6, 54, 118, 96, 230, 192, 192, 128, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 18, 226, 2, 18, 226, 2, 18, 226, 2, 1, 0, 0, 0, 0, 0, 128, 128, 128, 185, 187, 187, 131, 128, 184, 128, 128, 128, 128, 128, 128, 128, 128, 128, 191, 128, 128, 191, 128, 128, 191, 128, 0, | ||
| 48 | }; | ||
| 49 | |||
| 50 | // extra line for complete the gui | ||
| 51 | oled_write_raw_P_cursor(0, 8, raw_logo, sizeof(raw_logo)); | ||
| 52 | } | ||
| 53 | |||
| 54 | void render_layer_frame(gui_state_t t) { | ||
| 55 | // 96 bytes, 8x8 font, 12 characters, 32x24 image, 4 columns, 3 rows | ||
| 56 | static const char PROGMEM raw_logo[] = { | ||
| 57 | 62, 1, 0, 56, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 124, 248, 241, 226, 4, 8, 240, 0, 28, 28, 28, 0, 0, 127, 4, 8, 16, 127, 0, 124, 18, 17, 18, 124, 0, 31, 32, 64, 32, 31, 0, 0, 0, 0, 255, 255, 0, 0, 255, 62, 64, 64, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 142, 30, 62, 126, 126, 70, 70, 126, 70, 70, 126, 70, 70, 127, 127, 0, 0, 255, | ||
| 58 | }; | ||
| 59 | oled_write_raw_P_cursor(0, 5, raw_logo, sizeof(raw_logo)); | ||
| 60 | |||
| 61 | // extra line for complete the gui | ||
| 62 | drawline_hr(2, 39, 25, 1); | ||
| 63 | |||
| 64 | if (current_layer_frame != layer_frame_destination) { | ||
| 65 | if (timer_elapsed(anim_layer_frame_timer) > ANIM_LAYER_FRAME_DURATION) { | ||
| 66 | anim_layer_frame_timer = timer_read(); | ||
| 67 | |||
| 68 | if (layer_frame_destination > current_layer_frame) { | ||
| 69 | current_layer_frame++; | ||
| 70 | } else { | ||
| 71 | current_layer_frame--; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | // black screen | ||
| 76 | draw_black_screen(); | ||
| 77 | |||
| 78 | // gradient animation on layer selection | ||
| 79 | draw_gradient(3, 42, current_layer_frame * 4, 10, 0, 255, 7); | ||
| 80 | draw_gradient(3 + (27 - current_layer_frame * 4), 57, current_layer_frame * 4, 6, 255, 0, 7); | ||
| 81 | |||
| 82 | drawline_hr(3, 46, 22, false); | ||
| 83 | drawline_hr(3, 47, 23, false); | ||
| 84 | |||
| 85 | draw_rectangle_fill(3, 55, 24, 2, false); | ||
| 86 | draw_rectangle_fill(24, 48, 3, 7, false); | ||
| 87 | |||
| 88 | draw_rectangle_fill(3, 60, 12, 2, false); | ||
| 89 | oled_write_pixel(15, 61, false); | ||
| 90 | drawline_hr(14, 62, 3, false); | ||
| 91 | drawline_hr(14, 62, 3, false); | ||
| 92 | drawline_hr(3, 62, 11, true); | ||
| 93 | } | ||
| 94 | |||
| 95 | // get current layer name | ||
| 96 | layer_name = layer_ref[current_layer]; | ||
| 97 | |||
| 98 | // gui on pause : no layer name on screen | ||
| 99 | if (t == _IDLE || t == _SLEEP || t == _WAKINGUP) { | ||
| 100 | layer_name = " "; | ||
| 101 | } | ||
| 102 | |||
| 103 | // display layer name in the frame | ||
| 104 | oled_write_cursor(1, 6, layer_name, false); | ||
| 105 | } | ||
diff --git a/keyboards/lily58/keymaps/druotoni/layer_frame.h b/keyboards/lily58/keymaps/druotoni/layer_frame.h new file mode 100644 index 000000000..abbd94839 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/layer_frame.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | // layer name : must be 3 chars | ||
| 7 | #define LAYER_NAME_0 "ABC" | ||
| 8 | #define LAYER_NAME_1 "NAV" | ||
| 9 | #define LAYER_NAME_2 "SPE" | ||
| 10 | |||
| 11 | enum layer_number { _QWERTY = 0, _LOWER, _RAISE }; | ||
| 12 | |||
| 13 | void render_gears(void); | ||
| 14 | void render_layer_frame(gui_state_t t); | ||
| 15 | void update_layer_frame(layer_state_t state); \ No newline at end of file | ||
diff --git a/keyboards/lily58/keymaps/druotoni/navi_font.c b/keyboards/lily58/keymaps/druotoni/navi_font.c new file mode 100644 index 000000000..2412256e6 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/navi_font.c | |||
| @@ -0,0 +1,139 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | // This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0. | ||
| 5 | // See gfxfont.h for newer custom bitmap font info. | ||
| 6 | |||
| 7 | #include "progmem.h" | ||
| 8 | |||
| 9 | // Standard ASCII 5x7 font | ||
| 10 | const unsigned char font[] PROGMEM = { | ||
| 11 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 12 | 0x42, 0x3A, 0x12, 0x12, 0x0E, 0x00, | ||
| 13 | 0x0C, 0x44, 0x47, 0x24, 0x1C, 0x00, | ||
| 14 | 0x24, 0x24, 0x14, 0x7F, 0x04, 0x00, | ||
| 15 | 0x42, 0x3F, 0x02, 0x22, 0x1E, 0x00, | ||
| 16 | 0x0A, 0x0A, 0x7F, 0x0A, 0x0A, 0x00, | ||
| 17 | 0x02, 0x47, 0x42, 0x22, 0x1F, 0x00, | ||
| 18 | 0x21, 0x15, 0x09, 0x15, 0x63, 0x00, | ||
| 19 | 0x44, 0x44, 0x3F, 0x04, 0x04, 0x00, | ||
| 20 | 0x22, 0x1A, 0x02, 0x7F, 0x12, 0x00, | ||
| 21 | 0x22, 0x22, 0x12, 0x0A, 0x06, 0x00, | ||
| 22 | 0x08, 0x47, 0x42, 0x22, 0x1E, 0x00, | ||
| 23 | 0x10, 0x52, 0x54, 0x30, 0x16, 0x00, | ||
| 24 | 0x40, 0x3A, 0x02, 0x3E, 0x42, 0x00, | ||
| 25 | 0x5E, 0x52, 0x52, 0x52, 0x5E, 0x00, | ||
| 26 | 0x04, 0x27, 0x44, 0x44, 0x3C, 0x00, | ||
| 27 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 28 | 0x77, 0x00, 0x77, 0x00, 0x77, 0x00, | ||
| 29 | 0x14, 0x22, 0x7F, 0x22, 0x14, 0x00, | ||
| 30 | 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x00, | ||
| 31 | 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00, | ||
| 32 | 0x00, 0x66, 0x89, 0x95, 0x6A, 0x00, | ||
| 33 | 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, | ||
| 34 | 0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x00, | ||
| 35 | 0x08, 0x04, 0x7E, 0x04, 0x08, 0x00, | ||
| 36 | 0x10, 0x20, 0x7E, 0x20, 0x10, 0x00, | ||
| 37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 39 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 40 | 0x00, 0x1C, 0x1C, 0x1C, 0x00, 0x00, | ||
| 41 | 0x00, 0x08, 0x1C, 0x08, 0x00, 0x00, | ||
| 42 | 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, | ||
| 43 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 44 | 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, | ||
| 45 | 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, | ||
| 46 | 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00, | ||
| 47 | 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00, | ||
| 48 | 0x23, 0x13, 0x08, 0x64, 0x62, 0x00, | ||
| 49 | 0x36, 0x49, 0x56, 0x20, 0x50, 0x00, | ||
| 50 | 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, | ||
| 51 | 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, | ||
| 52 | 0x00, 0x41, 0x22, 0x1C, 0x00, 0x00, | ||
| 53 | 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00, | ||
| 54 | 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, | ||
| 55 | 0x00, 0x80, 0x70, 0x30, 0x00, 0x00, | ||
| 56 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, | ||
| 57 | 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, | ||
| 58 | 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, | ||
| 59 | 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, | ||
| 60 | 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, | ||
| 61 | 0x72, 0x49, 0x49, 0x49, 0x46, 0x00, | ||
| 62 | 0x21, 0x41, 0x49, 0x4D, 0x33, 0x00, | ||
| 63 | 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, | ||
| 64 | 0x27, 0x45, 0x45, 0x45, 0x39, 0x00, | ||
| 65 | 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00, | ||
| 66 | 0x41, 0x21, 0x11, 0x09, 0x07, 0x00, | ||
| 67 | 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, | ||
| 68 | 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00, | ||
| 69 | 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, | ||
| 70 | 0x00, 0x40, 0x34, 0x00, 0x00, 0x00, | ||
| 71 | 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, | ||
| 72 | 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, | ||
| 73 | 0x00, 0x41, 0x22, 0x14, 0x08, 0x00, | ||
| 74 | 0x02, 0x01, 0x59, 0x09, 0x06, 0x00, | ||
| 75 | 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00, | ||
| 76 | 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00, | ||
| 77 | 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, | ||
| 78 | 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00, | ||
| 79 | 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00, | ||
| 80 | 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00, | ||
| 81 | 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00, | ||
| 82 | 0x3E, 0x41, 0x41, 0x51, 0x73, 0x00, | ||
| 83 | 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, | ||
| 84 | 0x00, 0x41, 0x7F, 0x41, 0x00, 0x00, | ||
| 85 | 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00, | ||
| 86 | 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, | ||
| 87 | 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00, | ||
| 88 | 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00, | ||
| 89 | 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00, | ||
| 90 | 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, | ||
| 91 | 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00, | ||
| 92 | 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00, | ||
| 93 | 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00, | ||
| 94 | 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, | ||
| 95 | 0x03, 0x01, 0x7F, 0x01, 0x03, 0x00, | ||
| 96 | 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00, | ||
| 97 | 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00, | ||
| 98 | 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00, | ||
| 99 | 0x63, 0x14, 0x08, 0x14, 0x63, 0x00, | ||
| 100 | 0x03, 0x04, 0x78, 0x04, 0x03, 0x00, | ||
| 101 | 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, | ||
| 102 | 0x00, 0x7F, 0x41, 0x41, 0x41, 0x00, | ||
| 103 | 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, | ||
| 104 | 0x00, 0x41, 0x41, 0x41, 0x7F, 0x00, | ||
| 105 | 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, | ||
| 106 | 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, | ||
| 107 | 0x00, 0x03, 0x07, 0x08, 0x00, 0x00, | ||
| 108 | 0x20, 0x54, 0x54, 0x78, 0x40, 0x00, | ||
| 109 | 0x7F, 0x28, 0x44, 0x44, 0x38, 0x00, | ||
| 110 | 0x38, 0x44, 0x44, 0x44, 0x28, 0x00, | ||
| 111 | 0x38, 0x44, 0x44, 0x28, 0x7F, 0x00, | ||
| 112 | 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, | ||
| 113 | 0x00, 0x08, 0x7E, 0x09, 0x02, 0x00, | ||
| 114 | 0x18, 0x24, 0x24, 0x1C, 0x78, 0x00, | ||
| 115 | 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, | ||
| 116 | 0x00, 0x44, 0x7D, 0x40, 0x00, 0x00, | ||
| 117 | 0x20, 0x40, 0x40, 0x3D, 0x00, 0x00, | ||
| 118 | 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, | ||
| 119 | 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, | ||
| 120 | 0x7C, 0x04, 0x78, 0x04, 0x78, 0x00, | ||
| 121 | 0x7C, 0x08, 0x04, 0x04, 0x78, 0x00, | ||
| 122 | 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, | ||
| 123 | 0x7C, 0x18, 0x24, 0x24, 0x18, 0x00, | ||
| 124 | 0x18, 0x24, 0x24, 0x18, 0x7C, 0x00, | ||
| 125 | 0x7C, 0x08, 0x04, 0x04, 0x08, 0x00, | ||
| 126 | 0x48, 0x54, 0x54, 0x54, 0x24, 0x00, | ||
| 127 | 0x04, 0x04, 0x3F, 0x44, 0x24, 0x00, | ||
| 128 | 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00, | ||
| 129 | 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00, | ||
| 130 | 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00, | ||
| 131 | 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, | ||
| 132 | 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x00, | ||
| 133 | 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, | ||
| 134 | 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, | ||
| 135 | 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, | ||
| 136 | 0x00, 0x41, 0x36, 0x08, 0x00, 0x00, | ||
| 137 | 0x02, 0x01, 0x02, 0x04, 0x02, 0x00, | ||
| 138 | 0x3C, 0x26, 0x23, 0x26, 0x3C, 0x00 | ||
| 139 | }; | ||
diff --git a/keyboards/lily58/keymaps/druotoni/navi_logo.c b/keyboards/lily58/keymaps/druotoni/navi_logo.c new file mode 100644 index 000000000..6041aa5eb --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/navi_logo.c | |||
| @@ -0,0 +1,117 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include QMK_KEYBOARD_H | ||
| 5 | |||
| 6 | #include "gui_state.h" | ||
| 7 | #include "navi_logo.h" | ||
| 8 | #include "fast_random.h" | ||
| 9 | #include "draw_helper.h" | ||
| 10 | |||
| 11 | #define LOGO_SIZE 128 | ||
| 12 | |||
| 13 | // glitch stuff | ||
| 14 | #define GLITCH_FRAME_NUMBER 11 | ||
| 15 | |||
| 16 | uint8_t current_glitch_index = 0; | ||
| 17 | int current_glitch_time = 150; | ||
| 18 | uint32_t glitch_timer = 0; | ||
| 19 | |||
| 20 | static void render_logo_clean(void) { | ||
| 21 | // your logo here | ||
| 22 | static const char PROGMEM raw_logo[] = { | ||
| 23 | 0, 0, 0, 0, 0, 0, 128, 128, 0, 0, 128, 128, 192, 192, 204, 222, 222, 204, 192, 192, 128, 0, 0, 0, 128, 128, 0, 0, 0, 0, 0, 0, 192, 240, 248, 28, 14, 7, 3, 249, 252, 255, 15, 7, 3, 225, 241, 241, 241, 241, 225, 3, 7, 15, 255, 252, 249, 3, 7, 14, 28, 248, 240, 192, 192, 227, 231, 206, 28, 56, 112, 99, 15, 31, 60, 120, 240, 225, 227, 3, 3, 227, 225, 240, 120, 60, 31, 15, 103, 112, 56, 28, 206, 231, 227, 192, 0, 1, 1, 0, 0, 0, 56, 120, 96, 192, 192, 192, 96, 127, 63, 0, 0, 63, 127, 96, 192, 192, 192, 96, 120, 56, 0, 0, 0, 1, 1, 0, | ||
| 24 | }; | ||
| 25 | oled_write_raw_P(raw_logo, sizeof(raw_logo)); | ||
| 26 | } | ||
| 27 | |||
| 28 | void render_glitch_bar(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t iProb) { | ||
| 29 | // random horizontal scanlines | ||
| 30 | for (uint8_t i = 0; i < height; i++) { | ||
| 31 | bool bGenerateGlitch = (fastrand() % 100) < iProb; | ||
| 32 | |||
| 33 | if (bGenerateGlitch) { | ||
| 34 | drawline_hr(x, y + i, width, true); | ||
| 35 | } | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | void render_misc_glitch(uint8_t algo) { | ||
| 40 | char c = 0; | ||
| 41 | switch (algo) { | ||
| 42 | case 7: | ||
| 43 | // invert | ||
| 44 | for (uint8_t i = 0; i < LOGO_SIZE; i++) { | ||
| 45 | c = get_oled_char(i); | ||
| 46 | oled_write_raw_byte(~(c), i); | ||
| 47 | } | ||
| 48 | break; | ||
| 49 | |||
| 50 | case 8: | ||
| 51 | // wobble | ||
| 52 | for (uint8_t i = 0; i < LOGO_SIZE; i++) { | ||
| 53 | if (i < LOGO_SIZE - 1) { | ||
| 54 | copy_pixel(i + 1, -1, 85); | ||
| 55 | |||
| 56 | copy_pixel(LOGO_SIZE - 1 - 1 - i, 1, 170); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | break; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | static void render_logo_glitch(void) { | ||
| 64 | #ifdef WITH_GLITCH | ||
| 65 | // get a random glitch index | ||
| 66 | uint8_t glitch_prob = get_glitch_probability(); | ||
| 67 | get_glitch_index(&glitch_timer, ¤t_glitch_time, ¤t_glitch_index, 0, 150, glitch_prob, GLITCH_FRAME_NUMBER); | ||
| 68 | |||
| 69 | // no glitch | ||
| 70 | if (current_glitch_index <= 3) { | ||
| 71 | render_logo_clean(); | ||
| 72 | return; | ||
| 73 | } | ||
| 74 | |||
| 75 | // glitch time ! | ||
| 76 | switch (current_glitch_index) { | ||
| 77 | case 4: | ||
| 78 | move_block(1, 11, 24, 3, 5); | ||
| 79 | move_block(2, 19, 14, 3, 4); | ||
| 80 | move_block(9, 22, 7, 4, 4); | ||
| 81 | return; | ||
| 82 | |||
| 83 | case 5: | ||
| 84 | move_block(6, 25, 20, 7, 4); | ||
| 85 | move_block(0, 8, 32, 8, 7); | ||
| 86 | return; | ||
| 87 | case 6: | ||
| 88 | move_block(3, 7, 27, 4, -3); | ||
| 89 | move_block(13, 23, 19, 4, -4); | ||
| 90 | return; | ||
| 91 | |||
| 92 | case 7: | ||
| 93 | case 8: | ||
| 94 | render_misc_glitch(current_glitch_index); | ||
| 95 | return; | ||
| 96 | |||
| 97 | case 9: | ||
| 98 | render_glitch_bar(0, 0, 32, 32, 25); | ||
| 99 | return; | ||
| 100 | |||
| 101 | case 10: | ||
| 102 | draw_static(0, 0, 32, 32, true, 0); | ||
| 103 | return; | ||
| 104 | } | ||
| 105 | #endif | ||
| 106 | } | ||
| 107 | |||
| 108 | void render_logo(gui_state_t t) { | ||
| 109 | if (t == _IDLE) { | ||
| 110 | // on idle : glitch time ! | ||
| 111 | render_logo_glitch(); | ||
| 112 | return; | ||
| 113 | } | ||
| 114 | |||
| 115 | // standart logo | ||
| 116 | render_logo_clean(); | ||
| 117 | } | ||
diff --git a/keyboards/lily58/keymaps/druotoni/navi_logo.h b/keyboards/lily58/keymaps/druotoni/navi_logo.h new file mode 100644 index 000000000..3504568e5 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/navi_logo.h | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | void render_logo(gui_state_t t); | ||
| 7 | |||
diff --git a/keyboards/lily58/keymaps/druotoni/readme.md b/keyboards/lily58/keymaps/druotoni/readme.md new file mode 100644 index 000000000..c6d47da5d --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/readme.md | |||
| @@ -0,0 +1,133 @@ | |||
| 1 | # HELL0 NAVI. Interface | ||
| 2 | |||
| 3 | HELL0 NAVI. Interface is a GUI based en [Serial Experiments Lain](https://en.wikipedia.org/wiki/Serial_Experiments_Lain). Turn your [Lily58](https://github.com/kata0510/Lily58) keyboard into a Navi computer with its own Copland OS. | ||
| 4 | |||
| 5 | |||
| 6 | Ready to dive into the Wired ? | ||
| 7 | |||
| 8 | |||
| 9 | HELL0 NAVI provides interactive animations for both sides : | ||
| 10 | - a scope on left side for burst, WPM and active layer | ||
| 11 | - a ring on right side for the last key stroke | ||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | |||
| 17 | |||
| 18 | |||
| 19 | ## Typing animation | ||
| 20 | |||
| 21 | The scope displays your burst time on a chart. The WPM is represented by an horizontal line. | ||
| 22 | |||
| 23 | The ring display the last letter in the upper frame. Each time you enter a key, the Navi searches into the circular database and locks the position. A special animation is displayed when Enter, Backspce or Escape are struck. | ||
| 24 | |||
| 25 | <img src="https://imgur.com/Yf7D6UN.gif" height="400" > | ||
| 26 | |||
| 27 | ## Startup animation | ||
| 28 | |||
| 29 | Your Navi boots when it leaves the sleep mode. The animation can be canceled by typing. | ||
| 30 | |||
| 31 | |||
| 32 | |||
| 33 | <img src="https://imgur.com/EXU92Ev.gif" height="400" > | ||
| 34 | |||
| 35 | |||
| 36 | |||
| 37 | ## Waking up animation | ||
| 38 | |||
| 39 | After a period of inactivity, the scope and the ring turn off and the Navi runs in Idle mode. A new key stroke wakes them up. | ||
| 40 | |||
| 41 | |||
| 42 | <img src="https://imgur.com/9GWa7rR.gif" height="400" > | ||
| 43 | |||
| 44 | |||
| 45 | ## Idle animation | ||
| 46 | |||
| 47 | The Copland OS is still in beta test. After a while, some visual glitches will occur. | ||
| 48 | |||
| 49 | |||
| 50 | <img src="https://imgur.com/eKZ7qgC.gif" height="400" > | ||
| 51 | |||
| 52 | |||
| 53 | |||
| 54 | ## Shutdown animation | ||
| 55 | The Navi runs in sleep mode after 10 seconds in Idle mode. A nice (and difficul to render in a gif) animation is run. The OLED display turns off. | ||
| 56 | |||
| 57 | # How to build & flash | ||
| 58 | |||
| 59 | You need to flash each side with a specific version based on config.h configuration. | ||
| 60 | |||
| 61 | ## Left side (master) | ||
| 62 | |||
| 63 | IS_RIGHT needs to be commented in config.h | ||
| 64 | ``` | ||
| 65 | #define IS_LEFT 1 | ||
| 66 | //#define IS_RIGHT 1 | ||
| 67 | ``` | ||
| 68 | Connect the left side and flash | ||
| 69 | |||
| 70 | ## Right side (slave) | ||
| 71 | |||
| 72 | Comment IS_LEFT and uncomment IS_RIGHT in config.h | ||
| 73 | ``` | ||
| 74 | //#define IS_LEFT 1 | ||
| 75 | #define IS_RIGHT 1 | ||
| 76 | ``` | ||
| 77 | Connect the right side and flash | ||
| 78 | |||
| 79 | # Customization | ||
| 80 | |||
| 81 | ## Logo | ||
| 82 | Logo can be change in navi_logo.c. | ||
| 83 | The new logo must be 32x32 pixels. | ||
| 84 | ``` | ||
| 85 | static void render_logo_clean(void) { | ||
| 86 | // your logo here | ||
| 87 | static const char PROGMEM logo_raw[] = { | ||
| 88 | 0, 0, 0, 0, 0, 0, 128, 128, 0, 0, 128, 128, 192, 192, 204, 222, 222, 204, 192, 192, 128, 0, 0, 0, 128, 128, 0, 0, | ||
| 89 | 0, 0, 0, 0, 192, 240, 248, 28, 14, 7, 3, 249, 252, 255, 15, 7, 3, 225, 241, 241, 241, 241, 225, 3, 7, 15, 255, 252, | ||
| 90 | 249, 3, 7, 14, 28, 248, 240, 192, 192, 227, 231, 206, 28, 56, 112, 99, 15, 31, 60, 120, 240, 225, 227, 3, 3, 227, | ||
| 91 | 225, 240, 120, 60, 31, 15, 103, 112, 56, 28, 206, 231, 227, 192, 0, 1, 1, 0, 0, 0, 56, 120, 96, 192, 192, 192, | ||
| 92 | 96, 127, 63, 0, 0, 63, 127, 96, 192, 192, 192, 96, 120, 56, 0, 0, 0, 1, 1, 0, | ||
| 93 | }; | ||
| 94 | oled_write_raw_P(logo_raw, sizeof(logo_raw)); | ||
| 95 | } | ||
| 96 | ``` | ||
| 97 | ## Layer names | ||
| 98 | |||
| 99 | The current version handle 3 differents layers. Names can be changed in layer_frame.h. | ||
| 100 | ``` | ||
| 101 | // layer name : must be 3 chars | ||
| 102 | #define LAYER_NAME_0 "ABC" | ||
| 103 | #define LAYER_NAME_1 "NAV" | ||
| 104 | #define LAYER_NAME_2 "SPE" | ||
| 105 | ``` | ||
| 106 | |||
| 107 | ## Timing | ||
| 108 | |||
| 109 | You can tweak states timing in gui_state.h. | ||
| 110 | ``` | ||
| 111 | // states timing | ||
| 112 | #define BOOTING_TIME_TRESHOLD 7000 | ||
| 113 | #define WAKING_UP_TIME_TRESHOLD 300 | ||
| 114 | #define IDLE_TIME_TRESHOLD 4000 | ||
| 115 | #define HALTING_TIME_TRESHOLD IDLE_TIME_TRESHOLD + 6000 | ||
| 116 | #define SLEEP_TIME_TRESHOLD HALTING_TIME_TRESHOLD + 8000 | ||
| 117 | ``` | ||
| 118 | |||
| 119 | ## Need space ? | ||
| 120 | Boot and gliches can be commented in config.h | ||
| 121 | ``` | ||
| 122 | // states timing | ||
| 123 | // logo glitch | ||
| 124 | //#define WITH_GLITCH | ||
| 125 | // boot sequence | ||
| 126 | //#define WITH_BOOT | ||
| 127 | ``` | ||
| 128 | |||
| 129 |  | ||
| 130 | > Keyboard : https://github.com/kata0510/Lily58 | ||
| 131 | > | ||
| 132 | > Case : https://github.com/BoardSodie/Lily58-Acrylic-Case | ||
| 133 | |||
diff --git a/keyboards/lily58/keymaps/druotoni/ring.c b/keyboards/lily58/keymaps/druotoni/ring.c new file mode 100644 index 000000000..e3b747287 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/ring.c | |||
| @@ -0,0 +1,494 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include QMK_KEYBOARD_H | ||
| 5 | #include "gui_state.h" | ||
| 6 | #include "ring.h" | ||
| 7 | |||
| 8 | #include "fast_random.h" | ||
| 9 | #include "draw_helper.h" | ||
| 10 | |||
| 11 | char tListeTotal[SIZE_ARRAY_1] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'}; | ||
| 12 | char tListeTotal2[SIZE_ARRAY_1] = {'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ',', '.', '/', '1', '2', '3'}; | ||
| 13 | |||
| 14 | static char tRefArc[SIZE_ARRAY_1] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'}; | ||
| 15 | static char tRefArc2[SIZE_ARRAY_1] = {'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ',', '.', '/', '1', '2', '3'}; | ||
| 16 | |||
| 17 | // ring target and previous char | ||
| 18 | char c_target = 'A'; | ||
| 19 | char c_target2 = 'Q'; | ||
| 20 | char c_last = ' '; | ||
| 21 | char c_previous = ' '; | ||
| 22 | |||
| 23 | static const char PROGMEM code_to_name[60] = {' ', ' ', ' ', ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'R', 'E', 'B', 'T', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ';', '\'', ' ', ',', '.', '/', ' ', ' ', ' '}; | ||
| 24 | |||
| 25 | // main circle | ||
| 26 | #define CIRCLE_ANIM_FRAME_DURATION 40 | ||
| 27 | uint16_t circle_timer = 0; | ||
| 28 | |||
| 29 | // special animation for special keys | ||
| 30 | #define ANIM_CENTER_FRAME_NUMBER 5 | ||
| 31 | #define ANIM_CENTER_FRAME_DURATION 40 | ||
| 32 | uint16_t anim_center_timer = 0; | ||
| 33 | uint8_t anim_center_current_frame = 0; | ||
| 34 | |||
| 35 | // sleep animation | ||
| 36 | #define ANIM_SLEEP_RING_FRAME_NUMBER 9 | ||
| 37 | #define ANIM_SLEEP_RING_FRAME_DURATION 20 | ||
| 38 | uint16_t anim_sleep_ring_timer = 0; | ||
| 39 | uint8_t current_sleep_ring_frame = 0; | ||
| 40 | uint8_t sleep_ring_frame_destination = ANIM_SLEEP_RING_FRAME_NUMBER - 1; | ||
| 41 | |||
| 42 | // glitch animation | ||
| 43 | uint16_t anim_ring_idle_timer = 0; | ||
| 44 | int current_glitch_ring_time = 150; | ||
| 45 | uint32_t glitch_ring_timer = 0; | ||
| 46 | uint8_t current_glitch_ring_index = 0; | ||
| 47 | |||
| 48 | // central frame keylog animation | ||
| 49 | #define ANIM_KEYLOG_FRAME_NUMBER 8 | ||
| 50 | #define ANIM_KEYLOG_FRAME_DURATION 20 | ||
| 51 | uint8_t anim_keylog_current_frame = 0; | ||
| 52 | uint16_t anim_keylog_timer = 0; | ||
| 53 | |||
| 54 | static const char PROGMEM raw_ring_sleep[4][64] = {{ | ||
| 55 | 192, 32, 16, 8, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 8, 16, 32, 192, 3, 4, 8, 16, 32, 32, 32, 64, 64, 64, 64, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 64, 32, 32, 32, 16, 8, 4, 3, | ||
| 56 | }, | ||
| 57 | |||
| 58 | { | ||
| 59 | 128, 64, 32, 32, 16, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 32, 32, 64, 128, 0, 1, 2, 2, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 2, 2, 1, 0, | ||
| 60 | }, | ||
| 61 | |||
| 62 | { | ||
| 63 | 248, 192, 128, 128, 128, 128, 128, 128, 128, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 128, 128, 128, 128, 128, 128, 128, 192, 248, 15, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 15, | ||
| 64 | }, | ||
| 65 | |||
| 66 | { | ||
| 67 | 255, 240, 128, 128, 0, 128, 128, 0, 0, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 0, 0, 128, 128, 0, 128, 128, 248, 255, 255, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, | ||
| 68 | }}; | ||
| 69 | |||
| 70 | static const char PROGMEM raw_circle[4][128] = {{ | ||
| 71 | 0, 0, 0, 192, 32, 16, 8, 8, 4, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 4, 8, 8, 16, 32, 192, 0, 0, 0, 240, 14, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 238, 240, 15, 112, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 192, 240, 255, 127, 15, 0, 0, 0, 3, 4, 8, 16, 16, 32, 64, 64, 64, 128, 128, 192, 192, 224, 224, 224, 240, 112, 120, 124, 60, 30, 30, 15, 7, 3, 0, 0, 0, | ||
| 72 | }, | ||
| 73 | { | ||
| 74 | 0, 0, 0, 192, 32, 16, 8, 8, 4, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 4, 8, 8, 48, 224, 192, 0, 0, 0, 240, 14, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 255, 254, 240, 15, 112, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 192, 224, 240, 248, 248, 254, 255, 255, 127, 15, 0, 0, 0, 3, 7, 15, 31, 30, 62, 126, 126, 126, 254, 254, 254, 254, 254, 255, 255, 255, 127, 127, 127, 63, 31, 31, 15, 7, 3, 0, 0, 0, | ||
| 75 | }, | ||
| 76 | { | ||
| 77 | 0, 0, 0, 192, 32, 16, 8, 8, 4, 2, 2, 2, 1, 1, 1, 1, 3, 15, 255, 255, 254, 254, 254, 252, 248, 248, 240, 224, 192, 0, 0, 0, 240, 14, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 192, 240, 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 240, 15, 126, 252, 248, 248, 248, 248, 248, 252, 252, 254, 254, 255, 255, 255, 255, 255, 255, 255, 127, 63, 31, 15, 7, 7, 3, 3, 3, 7, 143, 127, 15, 0, 0, 0, 3, 7, 15, 31, 31, 63, 127, 127, 127, 255, 255, 255, 255, 255, 255, 195, 128, 64, 64, 64, 32, 16, 16, 8, 4, 3, 0, 0, 0, | ||
| 78 | }, | ||
| 79 | { | ||
| 80 | 0, 0, 0, 192, 224, 240, 248, 248, 124, 62, 30, 14, 15, 7, 7, 3, 3, 3, 1, 1, 2, 2, 2, 4, 8, 8, 16, 32, 192, 0, 0, 0, 240, 254, 255, 31, 15, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14, 240, 15, 115, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 112, 15, 0, 0, 0, 3, 4, 8, 16, 16, 32, 64, 64, 64, 128, 128, 128, 128, 128, 128, 128, 128, 64, 64, 64, 32, 16, 16, 8, 4, 3, 0, 0, 0, | ||
| 81 | }}; | ||
| 82 | |||
| 83 | static const char PROGMEM raw_bottom[] = { | ||
| 84 | 127, 192, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 192, 127, | ||
| 85 | }; | ||
| 86 | |||
| 87 | static const char PROGMEM raw_middle[] = { | ||
| 88 | 240, 8, 4, 226, 241, 248, 124, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 56, 0, 1, 62, 255, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 28, 0, 255, 0, 0, 127, 127, 70, 70, 126, 70, 70, 126, 70, 70, 126, 126, 62, 30, 142, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 64, 64, 62, 1, 2, 114, 114, 2, 2, 114, 114, 2, 2, 114, 114, 2, 2, 2, 2, 1, 0, 0, 0, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 0, 0, 128, 131, 131, 132, 136, 179, 131, 132, 184, 131, 131, 188, 128, 128, 128, 128, 128, 128, 128, 143, 144, 149, 144, 149, 144, 149, 144, 149, 144, 143, 0, | ||
| 89 | }; | ||
| 90 | |||
| 91 | static void rotate_right(char str[]) { | ||
| 92 | uint8_t iSize = SIZE_ARRAY_1; | ||
| 93 | char cFist = str[0]; | ||
| 94 | |||
| 95 | // rotate array to the right | ||
| 96 | for (uint8_t i = 0; i < iSize - 1; i++) { | ||
| 97 | str[i] = str[i + 1]; | ||
| 98 | } | ||
| 99 | str[iSize - 1] = cFist; | ||
| 100 | } | ||
| 101 | |||
| 102 | static void rotate_left(char str[]) { | ||
| 103 | uint8_t iSize = SIZE_ARRAY_1; | ||
| 104 | char cLast = str[iSize - 1]; | ||
| 105 | |||
| 106 | // rotate array to the left | ||
| 107 | for (uint8_t i = iSize - 1; i > 0; i--) { | ||
| 108 | str[i] = str[i - 1]; | ||
| 109 | } | ||
| 110 | str[0] = cLast; | ||
| 111 | } | ||
| 112 | |||
| 113 | static signed char GetPosition(char c, char tListe[]) { | ||
| 114 | uint8_t iSize = SIZE_ARRAY_1; | ||
| 115 | |||
| 116 | // find position of c in the array | ||
| 117 | for (uint8_t i = 0; i < iSize; i++) { | ||
| 118 | if (tListe[i] == c) return i; | ||
| 119 | } | ||
| 120 | |||
| 121 | // not found | ||
| 122 | return -1; | ||
| 123 | } | ||
| 124 | |||
| 125 | static signed char GetDistance(char cNew, char tListe[]) { | ||
| 126 | signed char iPositionNew = GetPosition(cNew, tListe); | ||
| 127 | if (iPositionNew == -1) { | ||
| 128 | // not found | ||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | return iPositionNew - CURSOR_1; | ||
| 133 | } | ||
| 134 | |||
| 135 | static bool TesterEstDansListe(char c, char tListe[]) { | ||
| 136 | // char in the list ? | ||
| 137 | return GetPosition(c, tListe) != -1; | ||
| 138 | } | ||
| 139 | |||
| 140 | static void SmartRotation(char c, char tListe[]) { | ||
| 141 | signed char i = GetDistance(c, tListe); | ||
| 142 | if (i == 0) return; | ||
| 143 | |||
| 144 | // rotate in the shorter way | ||
| 145 | if (i < 0) { | ||
| 146 | rotate_left(tListe); | ||
| 147 | return; | ||
| 148 | } | ||
| 149 | |||
| 150 | if (i > 0) { | ||
| 151 | rotate_right(tListe); | ||
| 152 | return; | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | static void update_list(char cNouveau, char tListe[]) { | ||
| 157 | signed char iDistance = GetDistance(cNouveau, tListe); | ||
| 158 | if (iDistance != 0) { | ||
| 159 | // the new char is in the list : rotation | ||
| 160 | SmartRotation(cNouveau, tListe); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | static void draw_arc_sector_16(uint8_t x, uint8_t y, uint8_t radius, int position, bool color) { | ||
| 165 | unsigned int s = 1; | ||
| 166 | s = s << (position / 2); | ||
| 167 | |||
| 168 | if (position % 4 == 0 || position % 4 == 3) { | ||
| 169 | draw_arc_sector(x, y, radius, s, 1, color); | ||
| 170 | } else { | ||
| 171 | draw_arc_sector(x, y, radius, s, 2, color); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | static void render_set(uint8_t x, uint8_t y, uint8_t r, int p, bool color) { | ||
| 176 | // 2 pixels arc sector | ||
| 177 | draw_arc_sector_16(x, y, r, p, color); | ||
| 178 | draw_arc_sector_16(x, y, r - 1, p, color); | ||
| 179 | } | ||
| 180 | |||
| 181 | static void draw_letter_circle(char t[], char tRef[], char ct, uint8_t x, uint8_t y, uint8_t r, bool invert) { | ||
| 182 | char c = t[CURSOR_1]; | ||
| 183 | |||
| 184 | signed char p = GetPosition(c, tRef); | ||
| 185 | signed char pt = GetPosition(ct, tRef); | ||
| 186 | |||
| 187 | if (!invert) { | ||
| 188 | draw_fill_circle(x, y, r, false); | ||
| 189 | draw_circle(x, y, r, false); | ||
| 190 | draw_circle(x, y, r - 1, false); | ||
| 191 | draw_circle(x, y, r - 2, false); | ||
| 192 | draw_circle(x, y, r - 4, true); | ||
| 193 | draw_circle(x, y, r - 5, true); | ||
| 194 | } | ||
| 195 | |||
| 196 | int pafter = (pt + 1) % SIZE_ARRAY_1; | ||
| 197 | int pbefore = (pt + SIZE_ARRAY_1 - 1) % SIZE_ARRAY_1; | ||
| 198 | render_set(x, y, r, pt, true); | ||
| 199 | render_set(x, y, r, pafter, true); | ||
| 200 | render_set(x, y, r, pbefore, true); | ||
| 201 | |||
| 202 | pafter = (pt + 2) % SIZE_ARRAY_1; | ||
| 203 | pbefore = (pt + SIZE_ARRAY_1 - 2) % SIZE_ARRAY_1; | ||
| 204 | render_set(x, y, r, pafter, true); | ||
| 205 | render_set(x, y, r, pbefore, true); | ||
| 206 | |||
| 207 | r -= 4; | ||
| 208 | |||
| 209 | pafter = (p + 1) % SIZE_ARRAY_1; | ||
| 210 | pbefore = (p + SIZE_ARRAY_1 - 1) % SIZE_ARRAY_1; | ||
| 211 | |||
| 212 | render_set(x, y, r, p, false); | ||
| 213 | render_set(x, y, r, pafter, false); | ||
| 214 | render_set(x, y, r, pbefore, false); | ||
| 215 | |||
| 216 | draw_circle(x, y, r - 6, true); | ||
| 217 | } | ||
| 218 | |||
| 219 | static void draw_center_circle_frame(uint8_t x, uint8_t y, uint8_t r, uint8_t f) { | ||
| 220 | draw_fill_circle(x, y, r, 0); | ||
| 221 | draw_circle(x, y, r, 0); | ||
| 222 | |||
| 223 | if (f == 0) { | ||
| 224 | draw_circle(x, y, r, 1); | ||
| 225 | } else { | ||
| 226 | // animation | ||
| 227 | oled_write_raw_P_cursor(0, 11, raw_circle[f - 1], sizeof(raw_circle[f - 1])); | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | static void render_anim_center_circle(uint8_t x, uint8_t y, uint8_t r) { | ||
| 232 | if (anim_center_current_frame == ANIM_CENTER_FRAME_NUMBER) { | ||
| 233 | // last frame : no animation | ||
| 234 | return; | ||
| 235 | } | ||
| 236 | |||
| 237 | if (timer_elapsed(anim_center_timer) > ANIM_CENTER_FRAME_DURATION) { | ||
| 238 | anim_center_timer = timer_read(); | ||
| 239 | |||
| 240 | draw_center_circle_frame(x, y, r, anim_center_current_frame); | ||
| 241 | |||
| 242 | anim_center_current_frame++; | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | static void write_char(char c) { | ||
| 247 | // write keylog char in the frame then offset to center | ||
| 248 | oled_set_cursor(2, 6); | ||
| 249 | oled_write_char(c, false); | ||
| 250 | move_block(12, 48, 6, 8, 2); | ||
| 251 | } | ||
| 252 | |||
| 253 | static void render_keylog(gui_state_t t) { | ||
| 254 | if (anim_keylog_current_frame != ANIM_KEYLOG_FRAME_NUMBER) { | ||
| 255 | if (timer_elapsed(anim_keylog_timer) > ANIM_KEYLOG_FRAME_DURATION) { | ||
| 256 | // update frame number | ||
| 257 | anim_keylog_timer = timer_read(); | ||
| 258 | anim_keylog_current_frame++; | ||
| 259 | } | ||
| 260 | |||
| 261 | // clean frame | ||
| 262 | draw_rectangle_fill(7, 46, 21, 11, false); | ||
| 263 | |||
| 264 | // comb motion to merge current and previous | ||
| 265 | if (anim_keylog_current_frame < ANIM_KEYLOG_FRAME_NUMBER / 2) { | ||
| 266 | // expand the previous char | ||
| 267 | write_char(c_previous); | ||
| 268 | draw_glitch_comb(9, 6 * 8, 18, 8, anim_keylog_current_frame + 1, true); | ||
| 269 | } else { | ||
| 270 | // shrink the current char | ||
| 271 | write_char(c_last); | ||
| 272 | draw_glitch_comb(9, 6 * 8, 18, 8, ANIM_KEYLOG_FRAME_NUMBER - anim_keylog_current_frame, false); | ||
| 273 | } | ||
| 274 | |||
| 275 | return; | ||
| 276 | } | ||
| 277 | |||
| 278 | write_char(c_last); | ||
| 279 | } | ||
| 280 | |||
| 281 | void reset_ring(void) { | ||
| 282 | // need to open | ||
| 283 | anim_sleep_ring_timer = timer_read(); | ||
| 284 | current_sleep_ring_frame = ANIM_SLEEP_RING_FRAME_NUMBER - 1; | ||
| 285 | sleep_ring_frame_destination = 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static void render_tv_circle(uint8_t x, uint8_t y, uint8_t r, uint8_t f) { | ||
| 289 | // raw image | ||
| 290 | if (f == 2 || f == 3) { | ||
| 291 | oled_write_raw_P_cursor(0, 12, raw_ring_sleep[f - 2], sizeof(raw_ring_sleep[f - 2])); | ||
| 292 | return; | ||
| 293 | } | ||
| 294 | |||
| 295 | // raw image | ||
| 296 | if (f == 5 || f == 6) { | ||
| 297 | oled_write_raw_P_cursor(0, 12, raw_ring_sleep[f - 3], sizeof(raw_ring_sleep[f - 3])); | ||
| 298 | return; | ||
| 299 | } | ||
| 300 | |||
| 301 | // other frames : lighter to draw than using raw image | ||
| 302 | switch (f) { | ||
| 303 | case 1: | ||
| 304 | draw_circle(x, y, r, 1); | ||
| 305 | break; | ||
| 306 | |||
| 307 | case 4: | ||
| 308 | drawline_hr(1, y, 12, 1); | ||
| 309 | drawline_hr(19, y, 12, 1); | ||
| 310 | drawline_vb(0, y - 1, 3, true); | ||
| 311 | drawline_vb(31, y - 1, 3, true); | ||
| 312 | break; | ||
| 313 | |||
| 314 | case 7: | ||
| 315 | |||
| 316 | oled_write_pixel(1, y, true); | ||
| 317 | oled_write_pixel(3, y, true); | ||
| 318 | oled_write_pixel(28, y, true); | ||
| 319 | oled_write_pixel(30, y, true); | ||
| 320 | |||
| 321 | drawline_vb(0, y - 12, 26, true); | ||
| 322 | drawline_vb(31, y - 12, 26, true); | ||
| 323 | break; | ||
| 324 | |||
| 325 | case 8: | ||
| 326 | drawline_vb(0, 88, 32, true); | ||
| 327 | drawline_vb(31, 88, 32, true); | ||
| 328 | break; | ||
| 329 | } | ||
| 330 | } | ||
| 331 | |||
| 332 | static void render_circle_white(void) { | ||
| 333 | // top | ||
| 334 | oled_write_raw_P_cursor(0, 5, raw_middle, sizeof(raw_middle)); | ||
| 335 | drawline_hr(5, 39, 25, 1); | ||
| 336 | |||
| 337 | // clean center | ||
| 338 | draw_rectangle_fill(0, 80, 32, 40, false); | ||
| 339 | |||
| 340 | // bottom | ||
| 341 | drawline_vb(0, 80, 8, 1); | ||
| 342 | drawline_vb(31, 80, 8, 1); | ||
| 343 | oled_write_pixel(1, 80, true); | ||
| 344 | oled_write_pixel(30, 80, true); | ||
| 345 | |||
| 346 | oled_write_raw_P_cursor(0, 15, raw_bottom, sizeof(raw_bottom)); | ||
| 347 | } | ||
| 348 | |||
| 349 | static void render_ring_clean_close(void) { | ||
| 350 | render_circle_white(); | ||
| 351 | drawline_vb(0, 88, 32, true); | ||
| 352 | drawline_vb(31, 88, 32, true); | ||
| 353 | } | ||
| 354 | |||
| 355 | static void render_glitch_square(void) { | ||
| 356 | if (timer_elapsed(anim_ring_idle_timer) > 60) { | ||
| 357 | anim_ring_idle_timer = timer_read(); | ||
| 358 | |||
| 359 | render_ring_clean_close(); | ||
| 360 | |||
| 361 | uint8_t size = 0; | ||
| 362 | for (uint8_t i = 0; i < 4; i++) { | ||
| 363 | size = 4 + (fastrand() % 6); | ||
| 364 | draw_rectangle_fill(3 + (fastrand() % 19), 85 + (fastrand() % 20), size, size, true); | ||
| 365 | |||
| 366 | size = (fastrand() % 6); | ||
| 367 | draw_rectangle_fill(3 + (fastrand() % 19), 100 + (fastrand() % 20), size, size, true); | ||
| 368 | } | ||
| 369 | } | ||
| 370 | } | ||
| 371 | |||
| 372 | static void render_ring_idle(void) { | ||
| 373 | uint8_t glitch_prob = get_glitch_probability(); | ||
| 374 | get_glitch_index(&glitch_ring_timer, ¤t_glitch_ring_time, ¤t_glitch_ring_index, 150, 350, glitch_prob, 2); | ||
| 375 | |||
| 376 | switch (current_glitch_ring_index) { | ||
| 377 | case 0: | ||
| 378 | // no glitch | ||
| 379 | render_ring_clean_close(); | ||
| 380 | return; | ||
| 381 | case 1: | ||
| 382 | // square gliches | ||
| 383 | render_glitch_square(); | ||
| 384 | return; | ||
| 385 | } | ||
| 386 | } | ||
| 387 | |||
| 388 | static void render_ring_sleep(void) { | ||
| 389 | if (current_sleep_ring_frame == sleep_ring_frame_destination) { | ||
| 390 | // no more animation needes : render the idle animation | ||
| 391 | render_ring_idle(); | ||
| 392 | return; | ||
| 393 | } | ||
| 394 | |||
| 395 | // display wacking up / sleep animation | ||
| 396 | if (timer_elapsed(anim_sleep_ring_timer) > ANIM_SLEEP_RING_FRAME_DURATION) { | ||
| 397 | anim_sleep_ring_timer = timer_read(); | ||
| 398 | |||
| 399 | // clean + new frame | ||
| 400 | render_circle_white(); | ||
| 401 | render_tv_circle(15, 103, 11, current_sleep_ring_frame); | ||
| 402 | |||
| 403 | // update frame number | ||
| 404 | if (sleep_ring_frame_destination > current_sleep_ring_frame) { | ||
| 405 | current_sleep_ring_frame++; | ||
| 406 | } else { | ||
| 407 | current_sleep_ring_frame--; | ||
| 408 | } | ||
| 409 | } | ||
| 410 | } | ||
| 411 | |||
| 412 | static void render_circle_middle(void) { | ||
| 413 | // clean | ||
| 414 | render_circle_white(); | ||
| 415 | |||
| 416 | // center special animation | ||
| 417 | if (anim_center_current_frame < ANIM_CENTER_FRAME_NUMBER) { | ||
| 418 | render_anim_center_circle(15, 103, 15 - 4); | ||
| 419 | return; | ||
| 420 | } | ||
| 421 | |||
| 422 | // ring render | ||
| 423 | if (anim_center_current_frame == ANIM_CENTER_FRAME_NUMBER) { | ||
| 424 | draw_letter_circle(tListeTotal, tRefArc, c_target, 15, 103, 15, false); | ||
| 425 | draw_letter_circle(tListeTotal2, tRefArc2, c_target2, 15, 103, 15, true); | ||
| 426 | } | ||
| 427 | } | ||
| 428 | |||
| 429 | void render_circle(gui_state_t t) { | ||
| 430 | if (timer_elapsed(circle_timer) > CIRCLE_ANIM_FRAME_DURATION) { | ||
| 431 | // new frame | ||
| 432 | circle_timer = timer_read(); | ||
| 433 | |||
| 434 | // shift rings | ||
| 435 | update_list(c_target, tListeTotal); | ||
| 436 | update_list(c_target2, tListeTotal2); | ||
| 437 | |||
| 438 | // waking up animation | ||
| 439 | if (t == _WAKINGUP) { | ||
| 440 | render_ring_sleep(); | ||
| 441 | return; | ||
| 442 | } | ||
| 443 | |||
| 444 | // idle animation | ||
| 445 | if (t == _IDLE) { | ||
| 446 | sleep_ring_frame_destination = ANIM_SLEEP_RING_FRAME_NUMBER - 1; | ||
| 447 | render_ring_sleep(); | ||
| 448 | return; | ||
| 449 | } | ||
| 450 | |||
| 451 | // render on display | ||
| 452 | render_circle_middle(); | ||
| 453 | render_keylog(t); | ||
| 454 | } | ||
| 455 | } | ||
| 456 | |||
| 457 | void update_circle(uint16_t keycode) { | ||
| 458 | // special animation for special keys | ||
| 459 | if (keycode == KC_ESC || keycode == KC_SPACE || keycode == KC_ENTER) { | ||
| 460 | anim_center_timer = timer_read(); | ||
| 461 | anim_center_current_frame = 0; | ||
| 462 | return; | ||
| 463 | } | ||
| 464 | |||
| 465 | // cancel special animation on a new key | ||
| 466 | anim_center_current_frame = ANIM_CENTER_FRAME_NUMBER; | ||
| 467 | |||
| 468 | // out of scope key | ||
| 469 | if (keycode >= 60) { | ||
| 470 | return; | ||
| 471 | } | ||
| 472 | |||
| 473 | // keycode to char | ||
| 474 | char c = pgm_read_byte(&code_to_name[keycode]); | ||
| 475 | |||
| 476 | // stock previous char | ||
| 477 | c_previous = c_last; | ||
| 478 | c_last = c; | ||
| 479 | |||
| 480 | // start keylog animation | ||
| 481 | anim_keylog_current_frame = 0; | ||
| 482 | |||
| 483 | // update target in ring #1 position | ||
| 484 | if (TesterEstDansListe(c, tListeTotal)) { | ||
| 485 | c_target = c; | ||
| 486 | return; | ||
| 487 | } | ||
| 488 | |||
| 489 | // update target in #2 position | ||
| 490 | if (TesterEstDansListe(c, tListeTotal2)) { | ||
| 491 | c_target2 = c; | ||
| 492 | return; | ||
| 493 | } | ||
| 494 | } | ||
diff --git a/keyboards/lily58/keymaps/druotoni/ring.h b/keyboards/lily58/keymaps/druotoni/ring.h new file mode 100644 index 000000000..9ce4520e6 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/ring.h | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #define SIZE_ARRAY_1 16 | ||
| 7 | #define CURSOR_1 9 | ||
| 8 | |||
| 9 | void update_circle(uint16_t); | ||
| 10 | void render_circle(gui_state_t t); | ||
| 11 | void reset_ring(void); | ||
diff --git a/keyboards/lily58/keymaps/druotoni/rules.mk b/keyboards/lily58/keymaps/druotoni/rules.mk new file mode 100644 index 000000000..c07761108 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/rules.mk | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | # Build Options | ||
| 2 | # change to "no" to disable the options, or define them in the Makefile in | ||
| 3 | # the appropriate keymap folder that will get included automatically | ||
| 4 | # | ||
| 5 | RGBLIGHT_ENABLE = yes # Enable WS2812 RGB underlight. | ||
| 6 | |||
| 7 | # Bootloader selection | ||
| 8 | BOOTLOADER = atmel-dfu | ||
| 9 | |||
| 10 | # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE | ||
| 11 | SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend | ||
| 12 | # EXTRAFLAGS += -flto | ||
| 13 | LTO_ENABLE = yes | ||
| 14 | SPACE_CADET_ENABLE = no | ||
| 15 | GRAVE_ESC_ENABLE = no | ||
| 16 | MAGIC_ENABLE = no | ||
| 17 | |||
| 18 | # If you want to change the display of OLED, you need to change here | ||
| 19 | SRC += ./lib/rgb_state_reader.c \ | ||
| 20 | ./burst.c \ | ||
| 21 | ./navi_logo.c \ | ||
| 22 | ./gui_state.c \ | ||
| 23 | ./fast_random.c \ | ||
| 24 | ./layer_frame.c \ | ||
| 25 | ./ring.c \ | ||
| 26 | ./boot.c \ | ||
| 27 | ./draw_helper.c \ | ||
| 28 | |||
