[Keymap] Lily58 : HELL0 NAVI. Interface (#15469)
Co-authored-by: Drashna Jaelre <drashna@live.com> Co-authored-by: Joel Challis <git@zvecr.com>
This commit is contained in:
		
							parent
							
								
									8a6da095d2
								
							
						
					
					
						commit
						b3c0548ed3
					
				
					 21 changed files with 2879 additions and 0 deletions
				
			
		
							
								
								
									
										309
									
								
								keyboards/lily58/keymaps/druotoni/boot.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										309
									
								
								keyboards/lily58/keymaps/druotoni/boot.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,309 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include QMK_KEYBOARD_H
 | 
			
		||||
 | 
			
		||||
#include "boot.h"
 | 
			
		||||
#include "fast_random.h"
 | 
			
		||||
#include "draw_helper.h"
 | 
			
		||||
#include "gui_state.h"
 | 
			
		||||
 | 
			
		||||
// boot
 | 
			
		||||
#define ANIM_BOOT_FRAME_DURATION 8
 | 
			
		||||
uint16_t anim_boot_timer         = 0;
 | 
			
		||||
uint8_t  anim_boot_current_frame = 0;
 | 
			
		||||
 | 
			
		||||
#define NAVI_DURATION 55
 | 
			
		||||
 | 
			
		||||
// terminal stuff
 | 
			
		||||
#define TERMINAL_DURATION 25
 | 
			
		||||
#define TERMINAL_LINE_NUMBER 19
 | 
			
		||||
#define TERMINAL_LINE_MAX 14
 | 
			
		||||
 | 
			
		||||
#define LILY_DURATION 50
 | 
			
		||||
 | 
			
		||||
// halt
 | 
			
		||||
#define ANIM_HALT_FRAME_DURATION 55
 | 
			
		||||
uint16_t anim_halt_timer = 0;
 | 
			
		||||
 | 
			
		||||
void reset_boot(void) {
 | 
			
		||||
    // frame zero
 | 
			
		||||
    anim_boot_current_frame = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void draw_lily_key(uint8_t x, uint8_t y, uint8_t *key_number, unsigned long key_state, uint8_t color) {
 | 
			
		||||
    uint8_t       v    = *key_number;
 | 
			
		||||
    unsigned long mask = 1;
 | 
			
		||||
    mask               = mask << v;
 | 
			
		||||
 | 
			
		||||
    // ligth the key according to the mask
 | 
			
		||||
    if (((key_state & mask) == mask)) {
 | 
			
		||||
        color = !color;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    draw_rectangle_fill(x, y, 3, 3, color);
 | 
			
		||||
    *key_number = v + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
    // row of rectangle
 | 
			
		||||
    for (uint8_t i = 0; i < w; i++) {
 | 
			
		||||
        draw_lily_key(x + (i * 4), y, key_number, key_state, color);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void draw_lily_render(unsigned long key_state) {
 | 
			
		||||
    // different orientation base on side
 | 
			
		||||
#if IS_LEFT
 | 
			
		||||
 | 
			
		||||
    uint8_t x            = 0;
 | 
			
		||||
    uint8_t y            = 56;
 | 
			
		||||
    uint8_t x_ref        = 10 + x;
 | 
			
		||||
    uint8_t y_ref        = 2 + y;
 | 
			
		||||
    uint8_t i_key_number = 0;
 | 
			
		||||
 | 
			
		||||
    for (uint8_t i = 0; i < 4; i++) {
 | 
			
		||||
        draw_lily_key_row(x_ref, y_ref + (i * 4), 4, &i_key_number, key_state, true);
 | 
			
		||||
        draw_lily_key_row(x_ref - 8, y_ref + 2 + (i * 4), 2, &i_key_number, key_state, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    draw_lily_key_row(x_ref + 2, y_ref + (4 * 4), 3, &i_key_number, key_state, true);
 | 
			
		||||
 | 
			
		||||
    uint8_t x_side = x_ref + (4 * 4);
 | 
			
		||||
 | 
			
		||||
    draw_lily_key(x_side, y_ref + (2 * 4) + 2, &i_key_number, key_state, true);
 | 
			
		||||
    draw_lily_key(x_side, y_ref + (4 * 4), &i_key_number, key_state, true);
 | 
			
		||||
 | 
			
		||||
    // screen
 | 
			
		||||
    draw_rectangle(x_side, y_ref, 4, 8, true);
 | 
			
		||||
 | 
			
		||||
    // frame
 | 
			
		||||
    drawline_hr(x + 1, y + 2, 8, true);
 | 
			
		||||
    oled_write_pixel(x + 8, y + 1, true);
 | 
			
		||||
    drawline_hr(x + 8, y, 23, true);
 | 
			
		||||
 | 
			
		||||
    drawline_hr(x + 1, y + 20, 10, true);
 | 
			
		||||
    oled_write_pixel(x + 10, y + 21, true);
 | 
			
		||||
    drawline_hr(x + 10, y + 22, 16, true);
 | 
			
		||||
 | 
			
		||||
    drawline_vb(x, y + 3, 17, true);
 | 
			
		||||
    drawline_vb(x + 31, y + 1, 20, true);
 | 
			
		||||
    oled_write_pixel(x + 30, y + 21, true);
 | 
			
		||||
    oled_write_pixel(x + 29, y + 22, true);
 | 
			
		||||
    oled_write_pixel(x + 28, y + 23, true);
 | 
			
		||||
    oled_write_pixel(x + 27, y + 24, true);
 | 
			
		||||
    oled_write_pixel(x + 26, y + 23, true);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if IS_RIGHT
 | 
			
		||||
    uint8_t i_key_number = 0;
 | 
			
		||||
 | 
			
		||||
    for (uint8_t i = 0; i < 4; i++) {
 | 
			
		||||
        draw_lily_key_row(7, 58 + (i * 4), 4, &i_key_number, key_state, true);
 | 
			
		||||
        draw_lily_key_row(23, 60 + (i * 4), 2, &i_key_number, key_state, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    draw_lily_key_row(9, 74, 3, &i_key_number, key_state, true);
 | 
			
		||||
 | 
			
		||||
    draw_lily_key(3, 68, &i_key_number, key_state, true);
 | 
			
		||||
    draw_lily_key(3, 74, &i_key_number, key_state, true);
 | 
			
		||||
 | 
			
		||||
    // screen
 | 
			
		||||
    draw_rectangle(2, 58, 4, 8, true);
 | 
			
		||||
 | 
			
		||||
    // frame
 | 
			
		||||
    drawline_hr(23, 58, 8, true);
 | 
			
		||||
    oled_write_pixel(23, 57, true);
 | 
			
		||||
    drawline_hr(1, 56, 23, true);
 | 
			
		||||
 | 
			
		||||
    drawline_hr(21, 76, 10, true);
 | 
			
		||||
    oled_write_pixel(21, 77, true);
 | 
			
		||||
    drawline_hr(6, 78, 16, true);
 | 
			
		||||
 | 
			
		||||
    drawline_vb(31, 59, 17, true);
 | 
			
		||||
    drawline_vb(0, 57, 20, true);
 | 
			
		||||
    oled_write_pixel(1, 77, true);
 | 
			
		||||
    oled_write_pixel(2, 78, true);
 | 
			
		||||
    oled_write_pixel(3, 79, true);
 | 
			
		||||
    oled_write_pixel(4, 80, true);
 | 
			
		||||
    oled_write_pixel(5, 79, true);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void draw_lily(uint8_t f) {
 | 
			
		||||
    // frame for the events
 | 
			
		||||
    uint8_t tres_stroke = 10;
 | 
			
		||||
    uint8_t tres_boom   = 30;
 | 
			
		||||
    uint8_t y_start     = 56;
 | 
			
		||||
 | 
			
		||||
    if (f == 0 || f == tres_stroke || f == tres_boom) {
 | 
			
		||||
        // clean screen
 | 
			
		||||
        oled_clear();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // simple lily58 with all the keys
 | 
			
		||||
    if (f < tres_stroke) {
 | 
			
		||||
        draw_lily_render(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // increase number of random keys pressed
 | 
			
		||||
    if (f >= tres_stroke && f < tres_boom) {
 | 
			
		||||
        int inter_f = interpo_pourcent(tres_stroke, tres_boom, f);
 | 
			
		||||
 | 
			
		||||
        unsigned long key_state = fastrand_long();
 | 
			
		||||
        for (int r = 100 - inter_f; r > 0; r = r - 10) {
 | 
			
		||||
            key_state &= fastrand_long();
 | 
			
		||||
        }
 | 
			
		||||
        draw_lily_render(key_state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // statir explosion
 | 
			
		||||
    if (f >= tres_boom) {
 | 
			
		||||
        oled_clear();
 | 
			
		||||
        uint8_t density = (f - tres_boom);
 | 
			
		||||
        if (density > 4) density = 4;
 | 
			
		||||
        draw_static(0, y_start - 8, 32, 32, true, density);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void draw_startup_navi(uint8_t f) {
 | 
			
		||||
    // text
 | 
			
		||||
    oled_write_cursor(0, 5, "HELL0", false);
 | 
			
		||||
    oled_write_cursor(0, 7, "NAVI.", false);
 | 
			
		||||
 | 
			
		||||
    // prompt
 | 
			
		||||
    if ((f % 8) > 4) {
 | 
			
		||||
        oled_write_cursor(0, 12, "> ", false);
 | 
			
		||||
    } else {
 | 
			
		||||
        oled_write_cursor(0, 12, ">_", false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // frame threshold
 | 
			
		||||
    uint8_t tres_shell = 15;
 | 
			
		||||
    uint8_t tres_load  = 35;
 | 
			
		||||
 | 
			
		||||
    // rand text to init display
 | 
			
		||||
    if (f > tres_shell) {
 | 
			
		||||
        int inter_f = interpo_pourcent(tres_shell, tres_load, f);
 | 
			
		||||
 | 
			
		||||
        draw_random_char(1, 12, 'i', 60 + inter_f, 0);
 | 
			
		||||
        draw_random_char(2, 12, 'n', 20 + inter_f, 0);
 | 
			
		||||
        draw_random_char(3, 12, 'i', inter_f, 0);
 | 
			
		||||
        draw_random_char(4, 12, 't', 20 + inter_f, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // loading propress bar
 | 
			
		||||
    if (f > tres_load) {
 | 
			
		||||
        int inter_f = interpo_pourcent(tres_load, 50, f);
 | 
			
		||||
 | 
			
		||||
        // ease
 | 
			
		||||
        float fv = inter_f / 100.00;
 | 
			
		||||
        fv       = fv * fv * fv * fv;
 | 
			
		||||
        inter_f  = fv * 100;
 | 
			
		||||
 | 
			
		||||
        draw_rectangle(0, (15 * 8), 32, 8, 1);
 | 
			
		||||
        draw_progress(0 + 3, (15 * 8) + 3, 26, 2, inter_f, 0, 1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// text dispayed on terminal
 | 
			
		||||
static char *boot_ref[TERMINAL_LINE_NUMBER] = {"LT:", "RT:", "M :", "    ", "cnx:", "A0:", "B0:", "    ", "0x40", "0x60", "0x85", "0x0F", "    ", "> run", "x ", "y ", " 100%", "    ", "> key"};
 | 
			
		||||
 | 
			
		||||
// prompt style for char in the font
 | 
			
		||||
char scan_font[5] = {'>', 1, 1, 1, 1};
 | 
			
		||||
 | 
			
		||||
static char *get_terminal_line(uint8_t i) {
 | 
			
		||||
    // display text
 | 
			
		||||
    if (i < TERMINAL_LINE_NUMBER) {
 | 
			
		||||
        return boot_ref[i];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // blank line every 3 lines
 | 
			
		||||
    if (i % 3 == 0) {
 | 
			
		||||
        return "     ";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // display consecutive chars in the font
 | 
			
		||||
    i = (i - TERMINAL_LINE_NUMBER) * 4;
 | 
			
		||||
 | 
			
		||||
    scan_font[1] = i;
 | 
			
		||||
    scan_font[2] = i + 1;
 | 
			
		||||
    scan_font[3] = i + 2;
 | 
			
		||||
    scan_font[4] = i + 3;
 | 
			
		||||
 | 
			
		||||
    return scan_font;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void draw_startup_terminal(uint8_t f) {
 | 
			
		||||
    // ease for printing on screen
 | 
			
		||||
    f = f * 2;
 | 
			
		||||
    f += (f / 5);
 | 
			
		||||
 | 
			
		||||
    // scroll text
 | 
			
		||||
    uint8_t i_start   = 0;
 | 
			
		||||
    uint8_t i_nb_char = f;
 | 
			
		||||
 | 
			
		||||
    if (f > TERMINAL_LINE_MAX) {
 | 
			
		||||
        i_start   = f - TERMINAL_LINE_MAX;
 | 
			
		||||
        i_nb_char = TERMINAL_LINE_MAX;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // display lines
 | 
			
		||||
    oled_clear();
 | 
			
		||||
    for (uint8_t i = 0; i < i_nb_char; i++) {
 | 
			
		||||
        char *s = get_terminal_line(i + i_start);
 | 
			
		||||
        oled_write_cursor(0, i, s, false);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool render_boot(void) {
 | 
			
		||||
    // end of the boot sequence
 | 
			
		||||
    if (anim_boot_current_frame >= NAVI_DURATION + TERMINAL_DURATION + LILY_DURATION) {
 | 
			
		||||
        anim_boot_current_frame = 0;
 | 
			
		||||
        oled_clear();
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (timer_elapsed(anim_boot_timer) > ANIM_BOOT_FRAME_DURATION) {
 | 
			
		||||
        anim_boot_timer = timer_read();
 | 
			
		||||
        if (anim_boot_current_frame < NAVI_DURATION) {
 | 
			
		||||
            // 55 frames
 | 
			
		||||
            draw_startup_navi(anim_boot_current_frame);
 | 
			
		||||
        } else {
 | 
			
		||||
            if (anim_boot_current_frame >= NAVI_DURATION && anim_boot_current_frame < NAVI_DURATION + TERMINAL_DURATION) {
 | 
			
		||||
                // 25
 | 
			
		||||
                draw_startup_terminal(anim_boot_current_frame - NAVI_DURATION);
 | 
			
		||||
            } else {
 | 
			
		||||
                if (anim_boot_current_frame >= NAVI_DURATION + TERMINAL_DURATION) {
 | 
			
		||||
                    // 25
 | 
			
		||||
                    draw_lily(anim_boot_current_frame - NAVI_DURATION - TERMINAL_DURATION);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        anim_boot_current_frame++;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render_halt(void) {
 | 
			
		||||
    if (timer_elapsed(anim_halt_timer) > ANIM_HALT_FRAME_DURATION) {
 | 
			
		||||
        anim_halt_timer = timer_read();
 | 
			
		||||
 | 
			
		||||
        // comb glitch for all the screen
 | 
			
		||||
        draw_glitch_comb(0, 0, 32, 128, 3, true);
 | 
			
		||||
 | 
			
		||||
        // random moving blocks of pixels
 | 
			
		||||
        for (uint8_t i = 0; i < 6; i++) {
 | 
			
		||||
            int     r  = fastrand();
 | 
			
		||||
            int     rr = fastrand();
 | 
			
		||||
            uint8_t x  = 4 + r % 28;
 | 
			
		||||
            uint8_t y  = rr % 128;
 | 
			
		||||
 | 
			
		||||
            uint8_t w = 7 + r % 20;
 | 
			
		||||
            uint8_t h = 3 + rr % 10;
 | 
			
		||||
            int     s = (fastrand() % 20) - 10;
 | 
			
		||||
            move_block(x, y, w, h, s);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								keyboards/lily58/keymaps/druotoni/boot.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								keyboards/lily58/keymaps/druotoni/boot.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
bool render_boot(void);
 | 
			
		||||
void render_halt(void);
 | 
			
		||||
 | 
			
		||||
void reset_boot(void);
 | 
			
		||||
							
								
								
									
										252
									
								
								keyboards/lily58/keymaps/druotoni/burst.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								keyboards/lily58/keymaps/druotoni/burst.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,252 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// Copyright 2020 Richard Sutherland (rich@brickbots.com)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include QMK_KEYBOARD_H
 | 
			
		||||
 | 
			
		||||
#include "gui_state.h"
 | 
			
		||||
#include "fast_random.h"
 | 
			
		||||
#include "burst.h"
 | 
			
		||||
#include "draw_helper.h"
 | 
			
		||||
 | 
			
		||||
// burst stuff
 | 
			
		||||
static int      current_burst = 0;
 | 
			
		||||
static uint16_t burst_timer   = 0;
 | 
			
		||||
 | 
			
		||||
// WPM stuff
 | 
			
		||||
static int      current_wpm = 0;
 | 
			
		||||
static uint16_t wpm_timer   = 0;
 | 
			
		||||
 | 
			
		||||
// This smoothing is 40 keystrokes
 | 
			
		||||
static const float wpm_smoothing = WPM_SMOOTHING;
 | 
			
		||||
 | 
			
		||||
// store values
 | 
			
		||||
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};
 | 
			
		||||
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};
 | 
			
		||||
 | 
			
		||||
// current max wpm
 | 
			
		||||
int max_wpm = MAX_WPM_INIT;
 | 
			
		||||
 | 
			
		||||
// scope animation stuff
 | 
			
		||||
#define ANIM_SCOPE_FRAME_DURATION 40
 | 
			
		||||
#define ANIM_SLEEP_SCOPE_FRAME_NUMBER 10
 | 
			
		||||
 | 
			
		||||
uint16_t anim_scope_timer       = 0;
 | 
			
		||||
uint16_t anim_scope_idle_timer  = 0;
 | 
			
		||||
uint16_t anim_sleep_scope_timer = 0;
 | 
			
		||||
 | 
			
		||||
uint8_t anim_sleep_scope_duration[ANIM_SLEEP_SCOPE_FRAME_NUMBER] = {30, 30, 30, 30, 20, 20, 30, 30, 32, 35};
 | 
			
		||||
uint8_t current_sleep_scope_frame                                = 0;
 | 
			
		||||
uint8_t sleep_scope_frame_destination                            = ANIM_SLEEP_SCOPE_FRAME_NUMBER - 1;
 | 
			
		||||
 | 
			
		||||
// glitch animation
 | 
			
		||||
int      current_glitch_scope_time  = 150;
 | 
			
		||||
uint32_t glitch_scope_timer         = 0;
 | 
			
		||||
uint8_t  current_glitch_scope_index = 0;
 | 
			
		||||
 | 
			
		||||
static void update_wpm(void) {
 | 
			
		||||
    if (wpm_timer > 0) {
 | 
			
		||||
        current_wpm += ((60000 / timer_elapsed(wpm_timer) / WPM_ESTIMATED_WORD_SIZE) - current_wpm) * wpm_smoothing;
 | 
			
		||||
        if (current_wpm > LIMIT_MAX_WPM) {
 | 
			
		||||
            current_wpm = LIMIT_MAX_WPM;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    wpm_timer = timer_read();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void update_scope(void) {
 | 
			
		||||
    update_wpm();
 | 
			
		||||
 | 
			
		||||
    uint16_t temps_ecoule = timer_elapsed(burst_timer);
 | 
			
		||||
 | 
			
		||||
    if (temps_ecoule > BURST_FENETRE) {
 | 
			
		||||
        // 1er frappe après longtemps
 | 
			
		||||
        current_burst = 40;
 | 
			
		||||
    } else {
 | 
			
		||||
        int time_pourcent = ((100 * (temps_ecoule)) / (BURST_FENETRE));
 | 
			
		||||
        current_burst     = 100 - time_pourcent;
 | 
			
		||||
    }
 | 
			
		||||
    burst_timer = timer_read();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void update_scope_array(void) {
 | 
			
		||||
    // shift array
 | 
			
		||||
    for (uint8_t i = 0; i < SIZE_SCOPE - 1; i++) {
 | 
			
		||||
        burst_scope[i] = burst_scope[i + 1];
 | 
			
		||||
        wpm_scope[i]   = wpm_scope[i + 1];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int burst = current_burst;
 | 
			
		||||
    int wpm   = current_wpm;
 | 
			
		||||
 | 
			
		||||
    // compute max wpm
 | 
			
		||||
    max_wpm = (wpm == 0) ? MAX_WPM_INIT : ((wpm > max_wpm) ? wpm : max_wpm);
 | 
			
		||||
 | 
			
		||||
    // current wpm ratio VS max
 | 
			
		||||
    wpm = (100 * wpm) / max_wpm;
 | 
			
		||||
    if (wpm > 100) wpm = 100;
 | 
			
		||||
 | 
			
		||||
    // update last slot of the arrays
 | 
			
		||||
    burst_scope[SIZE_SCOPE - 1] = burst;
 | 
			
		||||
    wpm_scope[SIZE_SCOPE - 1]   = wpm;
 | 
			
		||||
 | 
			
		||||
    // apply decay to burst chart
 | 
			
		||||
    uint8_t pBaisse = 0;
 | 
			
		||||
    for (uint8_t i = 0; i < SIZE_SCOPE - (SIZE_SCOPE / 4); i++) {
 | 
			
		||||
        pBaisse = 2 + ((SIZE_SCOPE - 1 - i)) / 2;
 | 
			
		||||
        burst_scope[i] -= ((burst_scope[i] * pBaisse) / 100);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void RenderScopeBlack(void) {
 | 
			
		||||
    // clean central zone
 | 
			
		||||
    draw_rectangle_fill(3, 82, 28, 120, false);
 | 
			
		||||
 | 
			
		||||
    // redraw some parts of the frame
 | 
			
		||||
    drawline_hr(1, SCOPE_Y_BOTTOM, 32, 1);
 | 
			
		||||
    drawline_vt(0, SCOPE_Y_BOTTOM - 1, 42, 1);
 | 
			
		||||
    drawline_vt(31, SCOPE_Y_BOTTOM - 1, 47, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_scope_white(void) {
 | 
			
		||||
    static const char PROGMEM raw_logo[] = {
 | 
			
		||||
        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,
 | 
			
		||||
    };
 | 
			
		||||
    oled_write_raw_P_cursor(0, 10, raw_logo, sizeof(raw_logo));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_scope_chart(void) {
 | 
			
		||||
    // clean the frame
 | 
			
		||||
    render_scope_white();
 | 
			
		||||
 | 
			
		||||
    uint8_t y_offset = SCOPE_Y_BOTTOM - 3;
 | 
			
		||||
 | 
			
		||||
    for (uint8_t i = 0; i < SIZE_SCOPE; i++) {
 | 
			
		||||
        // offset
 | 
			
		||||
        uint8_t x = 3 + i;
 | 
			
		||||
 | 
			
		||||
        // new black vertical line for burst
 | 
			
		||||
        uint8_t iCurrentBurst = burst_scope[i];
 | 
			
		||||
        drawline_vt(x, y_offset, (iCurrentBurst * 4) / 10, 0);
 | 
			
		||||
 | 
			
		||||
        // new black point for wpm, white if it's on the burst line
 | 
			
		||||
        uint8_t iCurrentWpm = wpm_scope[i];
 | 
			
		||||
        uint8_t yWpm        = y_offset - ((iCurrentWpm * 4) / 10);
 | 
			
		||||
        oled_write_pixel(x, yWpm, !(iCurrentWpm > iCurrentBurst));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void reset_scope(void) {
 | 
			
		||||
    // scope need wakeup
 | 
			
		||||
    anim_sleep_scope_timer    = timer_read();
 | 
			
		||||
    current_sleep_scope_frame = ANIM_SLEEP_SCOPE_FRAME_NUMBER - 1;
 | 
			
		||||
 | 
			
		||||
    sleep_scope_frame_destination = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_glitch_square(void) {
 | 
			
		||||
    if (timer_elapsed(anim_scope_idle_timer) > 60) {
 | 
			
		||||
        anim_scope_idle_timer = timer_read();
 | 
			
		||||
        RenderScopeBlack();
 | 
			
		||||
 | 
			
		||||
        uint8_t color = 0;
 | 
			
		||||
        uint8_t size  = 0;
 | 
			
		||||
        for (uint8_t i = 0; i < 4; i++) {
 | 
			
		||||
            size = 4 + (fastrand() % 6);
 | 
			
		||||
 | 
			
		||||
            draw_gradient(3 + (fastrand() % 19), 85 + (fastrand() % 20), size, size, 255, 255, 4);
 | 
			
		||||
 | 
			
		||||
            size  = (fastrand() % 6);
 | 
			
		||||
            color = 100 + (fastrand() % 100);
 | 
			
		||||
            draw_gradient(3 + (fastrand() % 19), 100 + (fastrand() % 20), size, size, color, color, 4);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render_scope_idle(void) {
 | 
			
		||||
    uint8_t glitch_prob = get_glitch_probability();
 | 
			
		||||
    get_glitch_index(&glitch_scope_timer, ¤t_glitch_scope_time, ¤t_glitch_scope_index, 150, 350, glitch_prob, 2);
 | 
			
		||||
 | 
			
		||||
    switch (current_glitch_scope_index) {
 | 
			
		||||
        case 0:
 | 
			
		||||
            RenderScopeBlack();
 | 
			
		||||
            return;
 | 
			
		||||
        case 1:
 | 
			
		||||
            render_glitch_square();
 | 
			
		||||
            return;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void RenderScopeSleep(void) {
 | 
			
		||||
    if (current_sleep_scope_frame == sleep_scope_frame_destination) {
 | 
			
		||||
        // animation finished
 | 
			
		||||
        render_scope_idle();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (timer_elapsed(anim_sleep_scope_timer) > anim_sleep_scope_duration[current_sleep_scope_frame]) {
 | 
			
		||||
        anim_sleep_scope_timer = timer_read();
 | 
			
		||||
 | 
			
		||||
        // clean scope
 | 
			
		||||
        RenderScopeBlack();
 | 
			
		||||
 | 
			
		||||
        // render animation
 | 
			
		||||
        render_tv_animation(current_sleep_scope_frame, 3, 80, 25, 48);
 | 
			
		||||
 | 
			
		||||
        // update frame number
 | 
			
		||||
        if (sleep_scope_frame_destination > current_sleep_scope_frame) {
 | 
			
		||||
            current_sleep_scope_frame++;
 | 
			
		||||
        } else {
 | 
			
		||||
            current_sleep_scope_frame--;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render_scope(gui_state_t t) {
 | 
			
		||||
    if (timer_elapsed(anim_scope_timer) > ANIM_SCOPE_FRAME_DURATION) {
 | 
			
		||||
        anim_scope_timer = timer_read();
 | 
			
		||||
 | 
			
		||||
        // shift arrays
 | 
			
		||||
        update_scope_array();
 | 
			
		||||
 | 
			
		||||
        // oled_set_cursor(0, 10);
 | 
			
		||||
 | 
			
		||||
        if (t == _WAKINGUP) {
 | 
			
		||||
            RenderScopeSleep();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (t == _IDLE) {
 | 
			
		||||
            sleep_scope_frame_destination = ANIM_SLEEP_SCOPE_FRAME_NUMBER - 1;
 | 
			
		||||
            RenderScopeSleep();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        render_scope_chart();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void decay_burst(void) {
 | 
			
		||||
    uint16_t temps_ecoule = timer_elapsed(burst_timer);
 | 
			
		||||
 | 
			
		||||
    int poucentageEcoule = 100;
 | 
			
		||||
 | 
			
		||||
    if (temps_ecoule <= BURST_FENETRE * 4) {
 | 
			
		||||
        poucentageEcoule = ((100 * (temps_ecoule)) / (BURST_FENETRE * 4));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    current_burst = current_burst - poucentageEcoule;
 | 
			
		||||
    if (current_burst <= 0) current_burst = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void decay_wpm(void) {
 | 
			
		||||
    if (timer_elapsed(wpm_timer) > 1000) {
 | 
			
		||||
        wpm_timer = timer_read();
 | 
			
		||||
        current_wpm += (-current_wpm) * wpm_smoothing;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void decay_scope(void) {
 | 
			
		||||
    decay_burst();
 | 
			
		||||
    decay_wpm();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								keyboards/lily58/keymaps/druotoni/burst.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								keyboards/lily58/keymaps/druotoni/burst.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// Copyright 2020 Richard Sutherland (rich@brickbots.com)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// burst
 | 
			
		||||
#define MAX_WPM_INIT 40
 | 
			
		||||
#define BURST_FENETRE 500
 | 
			
		||||
 | 
			
		||||
// wpm
 | 
			
		||||
#define LIMIT_MAX_WPM 150
 | 
			
		||||
#define WPM_ESTIMATED_WORD_SIZE 5
 | 
			
		||||
#define WPM_SMOOTHING 0.0487
 | 
			
		||||
 | 
			
		||||
// scope
 | 
			
		||||
#define SIZE_SCOPE 26
 | 
			
		||||
#define SCOPE_Y_BOTTOM 127
 | 
			
		||||
 | 
			
		||||
void update_scope(void);
 | 
			
		||||
void render_scope(gui_state_t t);
 | 
			
		||||
 | 
			
		||||
void reset_scope(void);
 | 
			
		||||
void decay_scope(void);
 | 
			
		||||
							
								
								
									
										55
									
								
								keyboards/lily58/keymaps/druotoni/config.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								keyboards/lily58/keymaps/druotoni/config.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// Copyright 2012 Jun Wako <wakojun@gmail.com>
 | 
			
		||||
// Copyright 2015 Jack Humbert
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#define MASTER_LEFT
 | 
			
		||||
#define OLED_DRIVER_ENABLE
 | 
			
		||||
 | 
			
		||||
// tapping toggle for my layers
 | 
			
		||||
#define TAPPING_TOGGLE 2
 | 
			
		||||
 | 
			
		||||
// choose IS_LEFT or IS_RIGHT for compilation and flash firmware
 | 
			
		||||
#define IS_LEFT 1
 | 
			
		||||
//#define IS_RIGHT 1
 | 
			
		||||
 | 
			
		||||
// logo glitch
 | 
			
		||||
#define WITH_GLITCH
 | 
			
		||||
// boot sequence
 | 
			
		||||
#define WITH_BOOT
 | 
			
		||||
 | 
			
		||||
// custom transport for displaying on both side
 | 
			
		||||
#define SPLIT_TRANSACTION_IDS_USER USER_SYNC_A
 | 
			
		||||
 | 
			
		||||
// custom font
 | 
			
		||||
#ifdef OLED_FONT_H
 | 
			
		||||
#    undef OLED_FONT_H
 | 
			
		||||
#endif
 | 
			
		||||
#define OLED_FONT_H "navi_font.c"
 | 
			
		||||
#undef OLED_FONT_END
 | 
			
		||||
#define OLED_FONT_END 125
 | 
			
		||||
 | 
			
		||||
// more space
 | 
			
		||||
#define NO_ACTION_MACRO
 | 
			
		||||
#define NO_ACTION_FUNCTION
 | 
			
		||||
#define NO_ACTION_ONESHOT
 | 
			
		||||
#define DISABLE_LEADER
 | 
			
		||||
 | 
			
		||||
// ???
 | 
			
		||||
#undef LOCKING_SUPPORT_ENABLE
 | 
			
		||||
#undef LOCKING_RESYNC_ENABLE
 | 
			
		||||
 | 
			
		||||
// small layer state
 | 
			
		||||
#define LAYER_STATE_8BIT
 | 
			
		||||
 | 
			
		||||
// no debug or trace
 | 
			
		||||
#ifndef NO_DEBUG
 | 
			
		||||
#    define NO_DEBUG
 | 
			
		||||
#endif
 | 
			
		||||
#if !defined(NO_PRINT) && !defined(CONSOLE_ENABLE)
 | 
			
		||||
#    define NO_PRINT
 | 
			
		||||
#endif 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										768
									
								
								keyboards/lily58/keymaps/druotoni/draw_helper.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										768
									
								
								keyboards/lily58/keymaps/druotoni/draw_helper.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,768 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// Copyright 2021 ugfx
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include QMK_KEYBOARD_H
 | 
			
		||||
 | 
			
		||||
#include "draw_helper.h"
 | 
			
		||||
#include "fast_random.h"
 | 
			
		||||
 | 
			
		||||
void drawline(uint8_t x, uint8_t y, uint8_t width, bool bHorizontal, bool bPositiveDirection, bool color) {
 | 
			
		||||
    if (width <= 0) return;
 | 
			
		||||
    uint8_t yPlus  = 0;
 | 
			
		||||
    uint8_t yMois  = 0;
 | 
			
		||||
    uint8_t nbtour = 0;
 | 
			
		||||
 | 
			
		||||
    if (!bPositiveDirection) {
 | 
			
		||||
        if (bHorizontal) {
 | 
			
		||||
            x -= width;
 | 
			
		||||
        } else {
 | 
			
		||||
            y -= width;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    yMois = (width / 2) - 1 + (width % 2);
 | 
			
		||||
 | 
			
		||||
    yPlus  = (width / 2);
 | 
			
		||||
    nbtour = (width / 4) + 1;
 | 
			
		||||
 | 
			
		||||
    bool bWhite = color;
 | 
			
		||||
 | 
			
		||||
    if (bHorizontal) {
 | 
			
		||||
        for (uint8_t i = 0; i < nbtour; i++) {
 | 
			
		||||
            oled_write_pixel(x + yPlus + i, y, bWhite);
 | 
			
		||||
            oled_write_pixel(x + yMois - i, y, bWhite);
 | 
			
		||||
 | 
			
		||||
            oled_write_pixel(x + i, y, bWhite);
 | 
			
		||||
            oled_write_pixel(x + width - 1 - i, y, bWhite);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        for (uint8_t i = 0; i < nbtour; i++) {
 | 
			
		||||
            oled_write_pixel(x, y + yPlus + i, bWhite);
 | 
			
		||||
            oled_write_pixel(x, y + yMois - i, bWhite);
 | 
			
		||||
 | 
			
		||||
            oled_write_pixel(x, y + i, bWhite);
 | 
			
		||||
 | 
			
		||||
            oled_write_pixel(x, y + width - 1 - i, bWhite);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drawline_vb(uint8_t x, uint8_t y, uint8_t width, bool color) { drawline(x, y, width, false, true, color); }
 | 
			
		||||
 | 
			
		||||
void drawline_vt(uint8_t x, uint8_t y, uint8_t width, bool color) { drawline(x, y, width, false, false, color); }
 | 
			
		||||
 | 
			
		||||
void drawline_hr(uint8_t x, uint8_t y, uint8_t width, bool color) { drawline(x, y, width, true, true, color); }
 | 
			
		||||
 | 
			
		||||
void drawline_hl(uint8_t x, uint8_t y, uint8_t width, bool color) { drawline(x, y, width, true, false, color); }
 | 
			
		||||
 | 
			
		||||
void draw_rectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color) {
 | 
			
		||||
    drawline_hr(x, y, width, color);
 | 
			
		||||
    drawline_hr(x, y + heigth - 1, width, color);
 | 
			
		||||
    drawline_vb(x, y, heigth, color);
 | 
			
		||||
    drawline_vb(x + width - 1, y, heigth, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void draw_rectangle_fill(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color) {
 | 
			
		||||
    for (uint8_t i = 0; i < heigth; i++) {
 | 
			
		||||
        drawline_hr(x, y + i, width, color);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drawline_hr_heigth(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color) {
 | 
			
		||||
    for (int i = 0; i < heigth; i++) {
 | 
			
		||||
        drawline_hr(x, y - i, width, color);
 | 
			
		||||
        drawline_hr(x, y + i, width, color);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drawline_point_hr(short x, short y, short x1, bool color) {
 | 
			
		||||
    if (y < 0 || y > 127) return;
 | 
			
		||||
 | 
			
		||||
    if (x1 < x) {
 | 
			
		||||
        short iTemp = x;
 | 
			
		||||
        x           = x1;
 | 
			
		||||
        x1          = iTemp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (x1 > 31) x1 = 31;
 | 
			
		||||
    if (x < 0) x = 0;
 | 
			
		||||
    if (x > 31) x = 31;
 | 
			
		||||
 | 
			
		||||
    drawline(x, y, x1 - x, true, true, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void flip_flap_x(short px, short py, uint8_t val, bool color) {
 | 
			
		||||
    oled_write_pixel(px + val, py, color);
 | 
			
		||||
    oled_write_pixel(px - val, py, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void draw_circle(uint8_t x, uint8_t y, uint8_t radius, bool color) {
 | 
			
		||||
    short a, b, P;
 | 
			
		||||
 | 
			
		||||
    // Calculate intermediates
 | 
			
		||||
    a = 1;
 | 
			
		||||
    b = radius;
 | 
			
		||||
    P = 4 - radius;
 | 
			
		||||
 | 
			
		||||
    short py, px;
 | 
			
		||||
 | 
			
		||||
    // Away we go using Bresenham's circle algorithm
 | 
			
		||||
    // Optimized to prevent double drawing
 | 
			
		||||
    px = x;
 | 
			
		||||
    py = y + b;
 | 
			
		||||
    oled_write_pixel(px, py, color);
 | 
			
		||||
    px = x;
 | 
			
		||||
    py = y - b;
 | 
			
		||||
    oled_write_pixel(px, py, color);
 | 
			
		||||
 | 
			
		||||
    flip_flap_x(x, y, b, color);
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        flip_flap_x(x, y + b, a, color);
 | 
			
		||||
        flip_flap_x(x, y - b, a, color);
 | 
			
		||||
        flip_flap_x(x, y + a, b, color);
 | 
			
		||||
        flip_flap_x(x, y - a, b, color);
 | 
			
		||||
 | 
			
		||||
        if (P < 0)
 | 
			
		||||
            P += 3 + 2 * a++;
 | 
			
		||||
        else
 | 
			
		||||
            P += 5 + 2 * (a++ - b--);
 | 
			
		||||
    } while (a < b);
 | 
			
		||||
 | 
			
		||||
    flip_flap_x(x, y + b, a, color);
 | 
			
		||||
    flip_flap_x(x, y - b, a, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void draw_ellipse(uint8_t x, uint8_t y, uint8_t a, uint8_t b, bool color) {
 | 
			
		||||
    int dx, dy;
 | 
			
		||||
    int a2, b2;
 | 
			
		||||
    int err, e2;
 | 
			
		||||
 | 
			
		||||
    //  short py, px;
 | 
			
		||||
    // Calculate intermediates
 | 
			
		||||
    dx  = 0;
 | 
			
		||||
    dy  = b;
 | 
			
		||||
    a2  = a * a;
 | 
			
		||||
    b2  = b * b;
 | 
			
		||||
    err = b2 - (2 * b - 1) * a2;
 | 
			
		||||
 | 
			
		||||
    // Away we go using Bresenham's ellipse algorithm
 | 
			
		||||
    do {
 | 
			
		||||
        flip_flap_x(x, y + dy, dx, color);
 | 
			
		||||
        flip_flap_x(x, y - dy, dx, color);
 | 
			
		||||
 | 
			
		||||
        e2 = 2 * err;
 | 
			
		||||
        if (e2 < (2 * dx + 1) * b2) {
 | 
			
		||||
            dx++;
 | 
			
		||||
            err += (2 * dx + 1) * b2;
 | 
			
		||||
        }
 | 
			
		||||
        if (e2 > -(2 * dy - 1) * a2) {
 | 
			
		||||
            dy--;
 | 
			
		||||
            err -= (2 * dy - 1) * a2;
 | 
			
		||||
        }
 | 
			
		||||
    } while (dy >= 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void draw_ellipse_fill(uint8_t x, uint8_t y, uint8_t a, uint8_t b, bool color) { return; }
 | 
			
		||||
// void draw_ellipse_fill(uint8_t x, uint8_t y, uint8_t a, uint8_t b, uint8_t color) {
 | 
			
		||||
//     int dx, dy;
 | 
			
		||||
//     int a2, b2;
 | 
			
		||||
//     int err, e2;
 | 
			
		||||
 | 
			
		||||
//     // Calculate intermediates
 | 
			
		||||
//     dx  = 0;
 | 
			
		||||
//     dy  = b;
 | 
			
		||||
//     a2  = a * a;
 | 
			
		||||
//     b2  = b * b;
 | 
			
		||||
//     err = b2 - (2 * b - 1) * a2;
 | 
			
		||||
 | 
			
		||||
//     short py, px, px1;
 | 
			
		||||
 | 
			
		||||
//     // Away we go using Bresenham's ellipse algorithm
 | 
			
		||||
//     // This is optimized to prevent overdrawing by drawing a line only when a y is about to change value
 | 
			
		||||
//     do {
 | 
			
		||||
//         e2 = 2 * err;
 | 
			
		||||
//         if (e2 < (2 * dx + 1) * b2) {
 | 
			
		||||
//             dx++;
 | 
			
		||||
//             err += (2 * dx + 1) * b2;
 | 
			
		||||
//         }
 | 
			
		||||
//         if (e2 > -(2 * dy - 1) * a2) {
 | 
			
		||||
//             py  = y + dy;
 | 
			
		||||
//             px  = x - dx;
 | 
			
		||||
//             px1 = x + dx;
 | 
			
		||||
//             drawline_point_hr(px, py, px1, color);
 | 
			
		||||
//             if (y) {
 | 
			
		||||
//                 py  = y - dy;
 | 
			
		||||
//                 px  = x - dx;
 | 
			
		||||
//                 px1 = x + dx;
 | 
			
		||||
//                 drawline_point_hr(px, py, px1, color);
 | 
			
		||||
//             }
 | 
			
		||||
//             dy--;
 | 
			
		||||
//             err -= (2 * dy - 1) * a2;
 | 
			
		||||
//         }
 | 
			
		||||
//     } while (dy >= 0);
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
bool test_limit(short x, short y) { return !(y < 0 || y > 127 || x < 0 || x > 31); }
 | 
			
		||||
 | 
			
		||||
void flip_flap_y_point(short px, short py, short px1, uint8_t val, bool color) {
 | 
			
		||||
    // firmware size optimisation : one fonction for 2 lines of code
 | 
			
		||||
    drawline_point_hr(px, py + val, px1, color);
 | 
			
		||||
    drawline_point_hr(px, py - val, px1, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void draw_fill_circle(short x, short y, uint8_t radius, bool color) {
 | 
			
		||||
    short a, b, P;
 | 
			
		||||
 | 
			
		||||
    // Calculate intermediates
 | 
			
		||||
    a = 1;
 | 
			
		||||
    b = radius;
 | 
			
		||||
    P = 4 - radius;
 | 
			
		||||
 | 
			
		||||
    // Away we go using Bresenham's circle algorithm
 | 
			
		||||
    // This is optimized to prevent overdrawing by drawing a line only when a variable is about to change value
 | 
			
		||||
    short py, px, px1;
 | 
			
		||||
 | 
			
		||||
    py  = y;
 | 
			
		||||
    px  = x - b;
 | 
			
		||||
    px1 = x + b;
 | 
			
		||||
    drawline_point_hr(px, py, px1, color);
 | 
			
		||||
 | 
			
		||||
    py = y + b;
 | 
			
		||||
    px = x;
 | 
			
		||||
    if (test_limit(px, py)) oled_write_pixel(px, py, color);
 | 
			
		||||
    py = y - b;
 | 
			
		||||
    px = x;
 | 
			
		||||
    if (test_limit(px, py)) oled_write_pixel(px, py, color);
 | 
			
		||||
    do {
 | 
			
		||||
        flip_flap_y_point(x - b, y, x + b, a, color);
 | 
			
		||||
 | 
			
		||||
        if (P < 0) {
 | 
			
		||||
            P += 3 + 2 * a++;
 | 
			
		||||
        } else {
 | 
			
		||||
            flip_flap_y_point(x - a, y, x + a, b, color);
 | 
			
		||||
 | 
			
		||||
            P += 5 + 2 * (a++ - b--);
 | 
			
		||||
        }
 | 
			
		||||
    } while (a < b);
 | 
			
		||||
 | 
			
		||||
    flip_flap_y_point(x - b, y, x + b, a, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool apres_moitie(int a, int b) { return (a > b / 2); }
 | 
			
		||||
bool arrive_moitie(int a, int b) { return (a > b / 2); }
 | 
			
		||||
bool avant_moitie(int a, int b) { return (a <= b / 2 && !apres_moitie(a, b)); }
 | 
			
		||||
 | 
			
		||||
void draw_arc_sector(uint8_t x, uint8_t y, uint8_t radius, unsigned char sectors, unsigned char half, bool color) {
 | 
			
		||||
    short a, b, P;
 | 
			
		||||
    short py, px;
 | 
			
		||||
    // Calculate intermediates
 | 
			
		||||
    a = 1;       // x in many explanations
 | 
			
		||||
    b = radius;  // y in many explanations
 | 
			
		||||
    P = 4 - radius;
 | 
			
		||||
 | 
			
		||||
    if (half != 2) {
 | 
			
		||||
        // Away we go using Bresenham's circle algorithm
 | 
			
		||||
        // Optimized to prevent double drawing
 | 
			
		||||
        if (sectors & 0x06) {
 | 
			
		||||
            px = x;
 | 
			
		||||
            py = y - b;
 | 
			
		||||
            oled_write_pixel(px, py, color);
 | 
			
		||||
        }  // Upper upper
 | 
			
		||||
        if (sectors & 0x60) {
 | 
			
		||||
            px = x;
 | 
			
		||||
            py = y + b;
 | 
			
		||||
            oled_write_pixel(px, py, color);
 | 
			
		||||
        }  // Lower lower
 | 
			
		||||
        if (sectors & 0x81) {
 | 
			
		||||
            px = x + b;
 | 
			
		||||
            py = y;
 | 
			
		||||
            oled_write_pixel(px, py, color);
 | 
			
		||||
        }  // Right right
 | 
			
		||||
        if (sectors & 0x18) {
 | 
			
		||||
            px = x - b;
 | 
			
		||||
            py = y;
 | 
			
		||||
            oled_write_pixel(px, py, color);
 | 
			
		||||
        }  // Left left
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool dessiner = false;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        if (half == 1 && arrive_moitie(a, b)) break;
 | 
			
		||||
 | 
			
		||||
        if (half == 2 && avant_moitie(a, b)) {
 | 
			
		||||
            dessiner = false;
 | 
			
		||||
        } else {
 | 
			
		||||
            dessiner = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (dessiner) {
 | 
			
		||||
            if (sectors & 0x01) {
 | 
			
		||||
                px = x + b;
 | 
			
		||||
                py = y - a;
 | 
			
		||||
                oled_write_pixel(px, py, color);
 | 
			
		||||
            }  // Upper right right
 | 
			
		||||
            if (sectors & 0x02) {
 | 
			
		||||
                px = x + a;
 | 
			
		||||
                py = y - b;
 | 
			
		||||
                oled_write_pixel(px, py, color);
 | 
			
		||||
            }  // Upper upper right
 | 
			
		||||
            if (sectors & 0x04) {
 | 
			
		||||
                px = x - a;
 | 
			
		||||
                py = y - b;
 | 
			
		||||
                oled_write_pixel(px, py, color);
 | 
			
		||||
            }  // Upper upper left
 | 
			
		||||
            if (sectors & 0x08) {
 | 
			
		||||
                px = x - b;
 | 
			
		||||
                py = y - a;
 | 
			
		||||
                oled_write_pixel(px, py, color);
 | 
			
		||||
            }  // Upper left  left
 | 
			
		||||
            if (sectors & 0x10) {
 | 
			
		||||
                px = x - b;
 | 
			
		||||
                py = y + a;
 | 
			
		||||
                oled_write_pixel(px, py, color);
 | 
			
		||||
            }  // Lower left  left
 | 
			
		||||
            if (sectors & 0x20) {
 | 
			
		||||
                px = x - a;
 | 
			
		||||
                py = y + b;
 | 
			
		||||
                oled_write_pixel(px, py, color);
 | 
			
		||||
            }  // Lower lower left
 | 
			
		||||
            if (sectors & 0x40) {
 | 
			
		||||
                px = x + a;
 | 
			
		||||
                py = y + b;
 | 
			
		||||
                oled_write_pixel(px, py, color);
 | 
			
		||||
            }  // Lower lower right
 | 
			
		||||
            if (sectors & 0x80) {
 | 
			
		||||
                px = x + b;
 | 
			
		||||
                py = y + a;
 | 
			
		||||
                oled_write_pixel(px, py, color);
 | 
			
		||||
            }  // Lower right right
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (P < 0)
 | 
			
		||||
            P += 3 + 2 * a++;
 | 
			
		||||
        else
 | 
			
		||||
            P += 5 + 2 * (a++ - b--);
 | 
			
		||||
    } while (a < b);
 | 
			
		||||
 | 
			
		||||
    if (half != 1) {
 | 
			
		||||
        if (sectors & 0xC0) {
 | 
			
		||||
            px = x + a;
 | 
			
		||||
            py = y + b;
 | 
			
		||||
            oled_write_pixel(px, py, color);
 | 
			
		||||
        }  // Lower right
 | 
			
		||||
        if (sectors & 0x03) {
 | 
			
		||||
            px = x + a;
 | 
			
		||||
            py = y - b;
 | 
			
		||||
            oled_write_pixel(px, py, color);
 | 
			
		||||
        }  // Upper right
 | 
			
		||||
        if (sectors & 0x30) {
 | 
			
		||||
            px = x - a;
 | 
			
		||||
            py = y + b;
 | 
			
		||||
            oled_write_pixel(px, py, color);
 | 
			
		||||
        }  // Lower left
 | 
			
		||||
        if (sectors & 0x0C) {
 | 
			
		||||
            px = x - a;
 | 
			
		||||
            py = y - b;
 | 
			
		||||
            oled_write_pixel(px, py, color);
 | 
			
		||||
        }  // Upper left
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void draw_static(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int color, uint8_t density) {
 | 
			
		||||
    unsigned long rx        = fastrand_long();
 | 
			
		||||
    unsigned long ry        = fastrand_long();
 | 
			
		||||
    unsigned long maskx     = 1;
 | 
			
		||||
    unsigned long masky     = 1;
 | 
			
		||||
    unsigned long mask_base = 1;
 | 
			
		||||
 | 
			
		||||
    // more 1 in the octet
 | 
			
		||||
    for (int r = 0; r < density; r++) {
 | 
			
		||||
        rx &= fastrand_long();
 | 
			
		||||
        ry &= fastrand_long();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    color = ((rx >> 1) % 2) == 0;
 | 
			
		||||
 | 
			
		||||
    for (uint8_t i = 0; i < width; i++) {
 | 
			
		||||
        for (uint8_t j = 0; j < heigth; j++) {
 | 
			
		||||
            // new mask based on ij loop
 | 
			
		||||
            maskx = (mask_base << i);
 | 
			
		||||
            masky = (mask_base << j);
 | 
			
		||||
 | 
			
		||||
            // logic AND with the masks
 | 
			
		||||
            if (((rx & maskx) == maskx) && ((ry & masky) == masky)) {
 | 
			
		||||
                oled_write_pixel(x + i, y + j, color);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void copy_pixel(int from, int shift, unsigned char mask) {
 | 
			
		||||
    if (shift == 0) return;
 | 
			
		||||
 | 
			
		||||
    // pixel cluster from
 | 
			
		||||
    char c_from  = get_oled_char(from);
 | 
			
		||||
    char extract = c_from & mask;
 | 
			
		||||
 | 
			
		||||
    // pixel cluster shift
 | 
			
		||||
    char c_from_shift = get_oled_char(from + shift);
 | 
			
		||||
    c_from_shift &= ~(mask);
 | 
			
		||||
    c_from_shift |= extract;
 | 
			
		||||
    oled_write_raw_byte(c_from_shift, from + shift);
 | 
			
		||||
 | 
			
		||||
    // fill blank with black
 | 
			
		||||
    c_from &= ~(mask);
 | 
			
		||||
    oled_write_raw_byte(c_from, from);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void draw_glitch_comb(uint8_t x, uint8_t y, uint8_t width, uint16_t height, uint8_t iSize, bool odd) {
 | 
			
		||||
    // work only on row
 | 
			
		||||
    uint16_t y_start = (y / 8) * 32;
 | 
			
		||||
    uint8_t  nb_h    = height / 8;
 | 
			
		||||
 | 
			
		||||
    uint8_t  w_max = width;
 | 
			
		||||
    uint16_t index = y_start + x;
 | 
			
		||||
 | 
			
		||||
    // shift pair even pixel
 | 
			
		||||
    int mask_1 = 85;
 | 
			
		||||
    int mask_2 = 170;
 | 
			
		||||
 | 
			
		||||
    if (!odd) {
 | 
			
		||||
        // shift odd pixel
 | 
			
		||||
        mask_1 = 170;
 | 
			
		||||
        mask_2 = 85;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //  wobble
 | 
			
		||||
    uint16_t pos = 0;
 | 
			
		||||
    for (uint16_t j = 0; j < nb_h; j++) {
 | 
			
		||||
        // next line
 | 
			
		||||
        index = (y_start + x) + (j * 32);
 | 
			
		||||
 | 
			
		||||
        for (uint16_t i = 0; i < w_max; i++) {
 | 
			
		||||
            if (i + iSize < w_max) {
 | 
			
		||||
                pos = index + i;
 | 
			
		||||
                copy_pixel(pos + iSize, iSize * -1, mask_1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (w_max - 1 - i - iSize >= 0) {
 | 
			
		||||
                pos = (index + w_max - 1) - i;
 | 
			
		||||
                copy_pixel(pos - iSize, iSize, mask_2);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void draw_random_char(uint8_t column, uint8_t row, char final_char, int value, uint8_t style) {
 | 
			
		||||
    if (value < 0) return;
 | 
			
		||||
 | 
			
		||||
    char c = final_char;
 | 
			
		||||
 | 
			
		||||
    if (value < 100) {
 | 
			
		||||
        c = ((fastrand() % 15) + 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oled_set_cursor(column, row);
 | 
			
		||||
    oled_write_char(c, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
    if (timer_elapsed(*glitch_timer) > *current_glitch_scope_time) {
 | 
			
		||||
        // end of the last glitch period
 | 
			
		||||
        *glitch_timer = timer_read();
 | 
			
		||||
 | 
			
		||||
        // new random glich period
 | 
			
		||||
        *current_glitch_scope_time = min_time + fastrand() % (max_time - min_time);
 | 
			
		||||
 | 
			
		||||
        bool bGenerateGlitch = (fastrand() % 100) < glitch_probobility;
 | 
			
		||||
        if (!bGenerateGlitch) {
 | 
			
		||||
            // no glitch
 | 
			
		||||
            *glitch_index = 0;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // get a new glitch index
 | 
			
		||||
        *glitch_index = fastrand() % glitch_frame_number;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t get_glitch_frame_index(uint8_t glitch_probobility, uint8_t glitch_frame_number) {
 | 
			
		||||
    bool bGenerateGlitch = (fastrand() % 100) < glitch_probobility;
 | 
			
		||||
    if (!bGenerateGlitch) {
 | 
			
		||||
        // no glitch
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // get a new glitch index
 | 
			
		||||
    return fastrand() % glitch_frame_number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t get_glitch_duration(uint8_t min_time, uint16_t max_time) { return min_time + fastrand() % (max_time - min_time); }
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
    if (timer_elapsed32(*glitch_timer) > *current_glitch_scope_time) {
 | 
			
		||||
        // end of the last glitch period
 | 
			
		||||
        *glitch_timer = timer_read32();
 | 
			
		||||
 | 
			
		||||
        // new random glich period
 | 
			
		||||
        *current_glitch_scope_time = min_time + fastrand() % (max_time - min_time);
 | 
			
		||||
 | 
			
		||||
        bool bGenerateGlitch = (fastrand() % 100) < glitch_probobility;
 | 
			
		||||
        if (!bGenerateGlitch) {
 | 
			
		||||
            // no glitch
 | 
			
		||||
            *glitch_index = 0;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // get a new glitch index
 | 
			
		||||
        *glitch_index = fastrand() % glitch_frame_number;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void draw_progress(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int value, uint8_t style, bool color) {
 | 
			
		||||
    if (value > 100) {
 | 
			
		||||
        value = 100;
 | 
			
		||||
    }
 | 
			
		||||
    int lenght = (width * value) / 100;
 | 
			
		||||
    for (uint8_t i = 0; i < lenght; i++) {
 | 
			
		||||
        switch (style) {
 | 
			
		||||
            case 0:
 | 
			
		||||
                drawline_vb(x + i, y, heigth - 1, color);
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
                // case 1:
 | 
			
		||||
                //     drawline_vb(x + i, y + 1, heigth - 3, ((i % 3) < 2));
 | 
			
		||||
                //     break;
 | 
			
		||||
                // case 2:
 | 
			
		||||
                //     // . . . . .
 | 
			
		||||
                //     drawline_vb(x + i, y + 3, 2, ((i % 2) == 0));
 | 
			
		||||
                //     break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void oled_write_raw_P_cursor(uint8_t col, uint8_t line, const char *data, uint16_t size) {
 | 
			
		||||
    // raw_P at cursor position
 | 
			
		||||
    oled_set_cursor(col, line);
 | 
			
		||||
    oled_write_raw_P(data, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void oled_write_cursor(uint8_t col, uint8_t line, const char *data, bool invert) {
 | 
			
		||||
    // write at cursor position
 | 
			
		||||
    oled_set_cursor(col, line);
 | 
			
		||||
    oled_write(data, invert);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void draw_label(const char *data, uint8_t len, uint8_t row, int value) {
 | 
			
		||||
    if (value < 0) return;
 | 
			
		||||
    if (row >= 16 || row < 0) return;
 | 
			
		||||
    oled_write_cursor(0, row, data, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void draw_box(const char *data, uint8_t len, uint8_t row, long value, uint8_t style) {
 | 
			
		||||
    if (value < 0) return;
 | 
			
		||||
    if (row >= 16 || row < 0) return;
 | 
			
		||||
 | 
			
		||||
    oled_write_cursor(0, row, data, false);
 | 
			
		||||
 | 
			
		||||
    uint8_t y = row * 8;
 | 
			
		||||
 | 
			
		||||
    uint8_t x = 6 * len;
 | 
			
		||||
    uint8_t w = 32 - x;
 | 
			
		||||
 | 
			
		||||
    if (value < 0) value = 0;
 | 
			
		||||
    if (value > 100) value = 100;
 | 
			
		||||
    draw_progress(x, y, w, 7, value, style, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char get_oled_char(uint16_t start_index) {
 | 
			
		||||
    oled_buffer_reader_t reader;
 | 
			
		||||
    reader = oled_read_raw(start_index);
 | 
			
		||||
    return *reader.current_element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_index_first_block(uint8_t y) { return ((y / 8) * 32); }
 | 
			
		||||
 | 
			
		||||
void move_block(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int shift) {
 | 
			
		||||
    // clip
 | 
			
		||||
    if (x >= 31) return;
 | 
			
		||||
    if (y >= 127) return;
 | 
			
		||||
 | 
			
		||||
    int max_screen = 32 - 1;
 | 
			
		||||
    if ((width + x) > max_screen + 1) width = max_screen + 1 - x;
 | 
			
		||||
 | 
			
		||||
    if (width <= 1) return;
 | 
			
		||||
 | 
			
		||||
    if ((heigth + y) > 127) heigth = 127 - y;
 | 
			
		||||
    if (heigth <= 1) return;
 | 
			
		||||
 | 
			
		||||
    // [-32 & +32]
 | 
			
		||||
    if (shift > max_screen) shift = max_screen;
 | 
			
		||||
    if (shift < -1 * max_screen) shift = -1 * max_screen;
 | 
			
		||||
 | 
			
		||||
    if ((width + x + shift) > max_screen) width = width - shift;
 | 
			
		||||
 | 
			
		||||
    int pixelTop    = 8 - (y % 8);
 | 
			
		||||
    int pixelBottom = (y + heigth) % 8;
 | 
			
		||||
 | 
			
		||||
    unsigned char cMastTop    = ~((unsigned)255 >> (pixelTop));
 | 
			
		||||
    unsigned char cMastBottom = ~((unsigned)255 << (pixelBottom));
 | 
			
		||||
 | 
			
		||||
    int indexFirstBloc     = get_index_first_block(y) + x;
 | 
			
		||||
    int indexFirstBlocFull = get_index_first_block(y + pixelTop) + x;
 | 
			
		||||
    int indexFirstBlocEnd  = get_index_first_block(y + heigth) + x;
 | 
			
		||||
 | 
			
		||||
    int nbBlockHeigth = (heigth - pixelTop - pixelBottom) / 8;
 | 
			
		||||
 | 
			
		||||
    if (nbBlockHeigth < 0) {
 | 
			
		||||
        // just single row
 | 
			
		||||
        nbBlockHeigth = 0;
 | 
			
		||||
        cMastBottom   = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (shift < 0) {
 | 
			
		||||
        for (uint16_t i = 0; i < width; i++) {
 | 
			
		||||
            copy_pixel(indexFirstBloc + i, shift, cMastTop);
 | 
			
		||||
            copy_pixel(indexFirstBlocEnd + i, shift, cMastBottom);
 | 
			
		||||
 | 
			
		||||
            for (uint16_t j = 0; j < nbBlockHeigth; j++) {
 | 
			
		||||
                copy_pixel(indexFirstBlocFull + i + (j * 32), shift, 255);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        for (int i = width - 1; i >= 0; i--) {
 | 
			
		||||
            copy_pixel(indexFirstBloc + i, shift, cMastTop);
 | 
			
		||||
            copy_pixel(indexFirstBlocEnd + i, shift, cMastBottom);
 | 
			
		||||
 | 
			
		||||
            for (uint16_t j = 0; j < nbBlockHeigth; j++) {
 | 
			
		||||
                copy_pixel(indexFirstBlocFull + i + (j * 32), shift, 255);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int interpo_pourcent(int min, int max, int v) {
 | 
			
		||||
    // interpolation
 | 
			
		||||
    float x0 = min;
 | 
			
		||||
    float x1 = max;
 | 
			
		||||
    float y0 = 0;
 | 
			
		||||
    float y1 = 100;
 | 
			
		||||
    float xp = v;
 | 
			
		||||
    float yp = y0 + ((y1 - y0) / (x1 - x0)) * (xp - x0);
 | 
			
		||||
 | 
			
		||||
    return (int)yp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t BAYER_PATTERN_4[4][4] = {{15, 135, 45, 165}, {195, 75, 225, 105}, {60, 180, 30, 150}, {240, 120, 210, 90}};
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
    bool invert = color_start > color_end;
 | 
			
		||||
 | 
			
		||||
    if (invert) {
 | 
			
		||||
        color_start = 255 - color_start;
 | 
			
		||||
        color_end   = 255 - color_end;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int step       = (100 / tres);
 | 
			
		||||
    int step_minus = (100 / (tres - 1));
 | 
			
		||||
    int distance   = color_end - color_start;
 | 
			
		||||
 | 
			
		||||
    for (uint8_t i = 0; i < width; i++) {
 | 
			
		||||
        int position = interpo_pourcent(0, width, i);
 | 
			
		||||
 | 
			
		||||
        float color = position;
 | 
			
		||||
        color       = ((int)(color / step)) * step_minus;
 | 
			
		||||
 | 
			
		||||
        color = color_start + ((distance * color) / 100);
 | 
			
		||||
 | 
			
		||||
        for (uint8_t j = 0; j < heigth; j++) {
 | 
			
		||||
            uint8_t       m       = BAYER_PATTERN_4[i % 4][j % 4];
 | 
			
		||||
            unsigned char color_d = (color > m) ? !invert : invert;
 | 
			
		||||
 | 
			
		||||
            oled_write_pixel(x + i, y + j, color_d);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render_tv_animation(uint8_t frame_number, uint8_t x, uint8_t y, uint8_t width, uint8_t heigth) {
 | 
			
		||||
    uint8_t xCenter = x + (width / 2);
 | 
			
		||||
    uint8_t yCenter = y + (heigth / 2);
 | 
			
		||||
 | 
			
		||||
    switch (frame_number) {
 | 
			
		||||
        case 0:
 | 
			
		||||
            // a fond : allume
 | 
			
		||||
            drawline_hr_heigth(x, yCenter, width, 17, true);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 1:
 | 
			
		||||
            drawline_hr_heigth(x, yCenter, width, 12, true);
 | 
			
		||||
            draw_ellipse_fill(xCenter, yCenter, 7, 15, true);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 2:
 | 
			
		||||
            drawline_hr_heigth(x, yCenter, width, 5, true);
 | 
			
		||||
            draw_ellipse_fill(xCenter, yCenter, 5, 8, true);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 3:
 | 
			
		||||
            drawline_hr_heigth(x, yCenter, width, 3, true);
 | 
			
		||||
            draw_ellipse_fill(xCenter, yCenter, 3, 4, true);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 4:
 | 
			
		||||
            drawline_hr_heigth(x, yCenter, width, 2, true);
 | 
			
		||||
            draw_fill_circle(xCenter, yCenter, 3, true);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 5:
 | 
			
		||||
            // central line
 | 
			
		||||
            drawline_hr(x, yCenter, width, true);
 | 
			
		||||
            draw_fill_circle(xCenter, yCenter, 2, true);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 6:
 | 
			
		||||
            // cross
 | 
			
		||||
            drawline_hr(xCenter, yCenter + 1, 2, true);
 | 
			
		||||
            drawline_hr(xCenter, yCenter - 1, 2, true);
 | 
			
		||||
 | 
			
		||||
            // central line
 | 
			
		||||
            drawline_hr(x, yCenter, width, true);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 7:
 | 
			
		||||
            // cross
 | 
			
		||||
            drawline_hr(xCenter, yCenter + 1, 2, true);
 | 
			
		||||
            drawline_hr(xCenter, yCenter - 1, 2, true);
 | 
			
		||||
            // central line
 | 
			
		||||
            drawline_hr(xCenter - 8, yCenter, 18, true);
 | 
			
		||||
            // static
 | 
			
		||||
            oled_write_pixel(xCenter - 11, yCenter, true);
 | 
			
		||||
            oled_write_pixel(xCenter + 12, yCenter, true);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 8:
 | 
			
		||||
            // cross
 | 
			
		||||
            drawline_hr(xCenter, yCenter + 1, 2, true);
 | 
			
		||||
            drawline_hr(xCenter, yCenter - 1, 2, true);
 | 
			
		||||
            // central line
 | 
			
		||||
            drawline_hr(xCenter - 2, yCenter, 4, true);
 | 
			
		||||
            // static
 | 
			
		||||
            drawline_hr(xCenter - 7, yCenter, 2, true);
 | 
			
		||||
            drawline_hr(xCenter + 6, yCenter, 3, true);
 | 
			
		||||
 | 
			
		||||
            //  oled_write_pixel(xCenter - 11, yCenter, true);
 | 
			
		||||
            oled_write_pixel(xCenter - 9, yCenter, true);
 | 
			
		||||
            oled_write_pixel(xCenter + 12, yCenter, true);
 | 
			
		||||
            oled_write_pixel(xCenter + 14, yCenter, true);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 9:
 | 
			
		||||
            // central line
 | 
			
		||||
            drawline_hr(xCenter, yCenter, 2, true);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								keyboards/lily58/keymaps/druotoni/draw_helper.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								keyboards/lily58/keymaps/druotoni/draw_helper.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// Copyright 2021 ugfx
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// line
 | 
			
		||||
void drawline_vb(uint8_t x, uint8_t y, uint8_t width, bool color);
 | 
			
		||||
void drawline_vt(uint8_t x, uint8_t y, uint8_t width, bool color);
 | 
			
		||||
void drawline_hr(uint8_t x, uint8_t y, uint8_t width, bool color);
 | 
			
		||||
void drawline_hl(uint8_t x, uint8_t y, uint8_t width, bool color);
 | 
			
		||||
void drawline_hr_heigth(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color);
 | 
			
		||||
 | 
			
		||||
// rectangle
 | 
			
		||||
void draw_rectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color);
 | 
			
		||||
void draw_rectangle_fill(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color);
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
// circle
 | 
			
		||||
void draw_fill_circle(short x, short y, uint8_t radius, bool color);
 | 
			
		||||
void draw_circle(uint8_t x, uint8_t y, uint8_t radius, bool color);
 | 
			
		||||
void draw_ellipse(uint8_t x, uint8_t y, uint8_t a, uint8_t b, bool color);
 | 
			
		||||
void draw_ellipse_fill(uint8_t x, uint8_t y, uint8_t a, uint8_t b, bool color);
 | 
			
		||||
void draw_arc_sector(uint8_t x, uint8_t y, uint8_t radius, unsigned char sectors, unsigned char half, bool color);
 | 
			
		||||
void draw_static(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int color, uint8_t density);
 | 
			
		||||
 | 
			
		||||
// text
 | 
			
		||||
void draw_random_char(uint8_t column, uint8_t row, char final_char, int value, uint8_t style);
 | 
			
		||||
void draw_label(const char *data, uint8_t len, uint8_t row, int value);
 | 
			
		||||
void draw_box(const char *data, uint8_t len, uint8_t row, long value, uint8_t style);
 | 
			
		||||
void draw_progress(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int value, uint8_t style, bool color);
 | 
			
		||||
 | 
			
		||||
// oled drivers stuff
 | 
			
		||||
char get_oled_char(uint16_t start_index);
 | 
			
		||||
void oled_write_cursor(uint8_t col, uint8_t line, const char *data, bool invert);
 | 
			
		||||
void oled_write_raw_P_cursor(uint8_t col, uint8_t line, const char *data, uint16_t size);
 | 
			
		||||
 | 
			
		||||
// pixel manipulation
 | 
			
		||||
void copy_pixel(int from, int shift, unsigned char mask);
 | 
			
		||||
void move_block(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int shift);
 | 
			
		||||
void draw_glitch_comb(uint8_t x, uint8_t y, uint8_t width, uint16_t height, uint8_t iSize, bool odd);
 | 
			
		||||
 | 
			
		||||
// misc
 | 
			
		||||
void render_tv_animation(uint8_t frame_number, uint8_t x, uint8_t y, uint8_t width, uint8_t heigth);
 | 
			
		||||
int  interpo_pourcent(int min, int max, int v);
 | 
			
		||||
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);
 | 
			
		||||
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);
 | 
			
		||||
							
								
								
									
										17
									
								
								keyboards/lily58/keymaps/druotoni/fast_random.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								keyboards/lily58/keymaps/druotoni/fast_random.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
#include "fast_random.h"
 | 
			
		||||
 | 
			
		||||
// seed for random
 | 
			
		||||
static unsigned long g_seed = 0;
 | 
			
		||||
 | 
			
		||||
int fastrand(void) {
 | 
			
		||||
    // todo : try with random16();
 | 
			
		||||
    g_seed = (214013 * g_seed + 2531011);
 | 
			
		||||
    return (g_seed >> 16) & 0x7FFF;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned long fastrand_long(void) {
 | 
			
		||||
    g_seed = (214013 * g_seed + 2531011);
 | 
			
		||||
    return g_seed;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								keyboards/lily58/keymaps/druotoni/fast_random.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								keyboards/lily58/keymaps/druotoni/fast_random.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
int           fastrand(void);
 | 
			
		||||
unsigned long fastrand_long(void);
 | 
			
		||||
							
								
								
									
										71
									
								
								keyboards/lily58/keymaps/druotoni/gui_state.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								keyboards/lily58/keymaps/druotoni/gui_state.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,71 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include QMK_KEYBOARD_H
 | 
			
		||||
 | 
			
		||||
#include "gui_state.h"
 | 
			
		||||
#include "draw_helper.h"
 | 
			
		||||
 | 
			
		||||
// timer for the gui state
 | 
			
		||||
uint32_t global_sleep_timer     = 0;
 | 
			
		||||
uint32_t global_waking_up_timer = 0;
 | 
			
		||||
uint32_t global_booting_timer   = 0;
 | 
			
		||||
 | 
			
		||||
// timers test for states
 | 
			
		||||
#ifdef WITH_BOOT
 | 
			
		||||
static bool IsBooting(void) { return (timer_elapsed32(global_booting_timer) < BOOTING_TIME_TRESHOLD); }
 | 
			
		||||
#else
 | 
			
		||||
static bool IsBooting(void) { return false; }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// state test
 | 
			
		||||
static bool IsWakingUp(void) { return (timer_elapsed32(global_waking_up_timer) < WAKING_UP_TIME_TRESHOLD); }
 | 
			
		||||
static bool IsIdle(void) { return (timer_elapsed32(global_sleep_timer) > IDLE_TIME_TRESHOLD && timer_elapsed32(global_sleep_timer) < HALTING_TIME_TRESHOLD); }
 | 
			
		||||
static bool IsSleep(void) { return (timer_elapsed32(global_sleep_timer) >= SLEEP_TIME_TRESHOLD); }
 | 
			
		||||
static bool IsHalting(void) { return (timer_elapsed32(global_sleep_timer) >= HALTING_TIME_TRESHOLD && timer_elapsed32(global_sleep_timer) < SLEEP_TIME_TRESHOLD); }
 | 
			
		||||
 | 
			
		||||
gui_state_t get_gui_state(void) {
 | 
			
		||||
    // get gui states by testing timers
 | 
			
		||||
    if (IsBooting()) return _BOOTING;
 | 
			
		||||
    if (IsWakingUp()) return _WAKINGUP;
 | 
			
		||||
    if (IsIdle()) return _IDLE;
 | 
			
		||||
    if (IsHalting()) return _HALTING;
 | 
			
		||||
    if (IsSleep()) return _SLEEP;
 | 
			
		||||
 | 
			
		||||
    return _UP;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void update_gui_state(void) {
 | 
			
		||||
    // what to do when a key is pressed
 | 
			
		||||
    gui_state_t t = get_gui_state();
 | 
			
		||||
 | 
			
		||||
#ifdef WITH_BOOT
 | 
			
		||||
    if (t == _SLEEP) {
 | 
			
		||||
        // booting
 | 
			
		||||
        global_booting_timer = timer_read32();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (t == _BOOTING) {
 | 
			
		||||
        // cancel booting
 | 
			
		||||
        global_booting_timer = 1000000;
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    if (t == _SLEEP) {
 | 
			
		||||
        // waking up
 | 
			
		||||
        global_waking_up_timer = timer_read32();
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if (t == _IDLE || t == _HALTING || t == _BOOTING) {
 | 
			
		||||
        // waking up
 | 
			
		||||
        global_waking_up_timer = timer_read32();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // no sleep
 | 
			
		||||
    global_sleep_timer = timer_read32();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t get_glitch_probability(void) {
 | 
			
		||||
    // more gliches could occur when halting time is near
 | 
			
		||||
    return interpo_pourcent(IDLE_TIME_TRESHOLD, HALTING_TIME_TRESHOLD, timer_elapsed32(global_sleep_timer));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								keyboards/lily58/keymaps/druotoni/gui_state.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								keyboards/lily58/keymaps/druotoni/gui_state.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// states timing
 | 
			
		||||
#define BOOTING_TIME_TRESHOLD 7000
 | 
			
		||||
#define WAKING_UP_TIME_TRESHOLD 300
 | 
			
		||||
#define IDLE_TIME_TRESHOLD 4000
 | 
			
		||||
#define HALTING_TIME_TRESHOLD IDLE_TIME_TRESHOLD + 6000
 | 
			
		||||
#define SLEEP_TIME_TRESHOLD HALTING_TIME_TRESHOLD + 8000
 | 
			
		||||
 | 
			
		||||
typedef uint8_t gui_state_t;
 | 
			
		||||
enum gui_state { _WAKINGUP = 0, _IDLE, _SLEEP, _UP, _BOOTING, _HALTING };
 | 
			
		||||
 | 
			
		||||
gui_state_t get_gui_state(void);
 | 
			
		||||
void        update_gui_state(void);
 | 
			
		||||
uint8_t     get_glitch_probability(void);
 | 
			
		||||
							
								
								
									
										253
									
								
								keyboards/lily58/keymaps/druotoni/keymap.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								keyboards/lily58/keymaps/druotoni/keymap.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,253 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include QMK_KEYBOARD_H
 | 
			
		||||
#include "keymap_french.h"
 | 
			
		||||
#include "transactions.h"
 | 
			
		||||
 | 
			
		||||
// global
 | 
			
		||||
#include "gui_state.h"
 | 
			
		||||
#include "boot.h"
 | 
			
		||||
#include "navi_logo.h"
 | 
			
		||||
 | 
			
		||||
#include "draw_helper.h"
 | 
			
		||||
#include "fast_random.h"
 | 
			
		||||
 | 
			
		||||
// left side
 | 
			
		||||
#include "layer_frame.h"
 | 
			
		||||
#include "burst.h"
 | 
			
		||||
 | 
			
		||||
// right side
 | 
			
		||||
#include "ring.h"
 | 
			
		||||
 | 
			
		||||
// clang-format off
 | 
			
		||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 | 
			
		||||
/* QWERTY
 | 
			
		||||
* ,-----------------------------------------.                    ,-----------------------------------------.
 | 
			
		||||
* | ESC  |   1  |   2  |   3  |   4  |   5  |                    |   6  |   7  |   8  |   9  |   0  |  DEL |
 | 
			
		||||
* |------+------+------+------+------+------|                    |------+------+------+------+------+------|
 | 
			
		||||
* | Tab  |   Q  |   W  |   E  |   R  |   T  |                    |   Y  |   U  |   I  |   O  |   P  |  ^   |
 | 
			
		||||
* |------+------+------+------+------+------|                    |------+------+------+------+------+------|
 | 
			
		||||
* |LShift|   A  |   S  |   D  |   F  |   G  |-------.    ,-------|   H  |   J  |   K  |   L  |   ;  |RShift|
 | 
			
		||||
* |------+------+------+------+------+------|  "    |    |  )    |------+------+------+------+------+------|
 | 
			
		||||
* |LCTRL |   Z  |   X  |   C  |   V  |   B  |-------|    |-------|   N  |   M  |   ,  |   .  |   /  |  $   |
 | 
			
		||||
* `-----------------------------------------/       /     \      \-----------------------------------------'
 | 
			
		||||
*                   | LAlt |  SPE | Space| /  NAV  /       \Enter \  |BackSP| ]    | RGUI |
 | 
			
		||||
*                   |      |      |      |/       /         \      \ |      |      |      |
 | 
			
		||||
*                   `----------------------------'           '------''--------------------'
 | 
			
		||||
*/
 | 
			
		||||
    [_QWERTY] = LAYOUT(
 | 
			
		||||
    KC_ESC,   KC_1,   KC_2,    KC_3,          KC_4,    KC_5,                              KC_6,    KC_7,    KC_8,    KC_9,    KC_0,    KC_DELETE, 
 | 
			
		||||
    KC_TAB,   KC_Q,   KC_W,    KC_E,          KC_R,    KC_T,                              KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    FR_CIRC, 
 | 
			
		||||
    KC_LSFT,  KC_A,   KC_S,    KC_D,          KC_F,    KC_G,                              KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_RSFT, 
 | 
			
		||||
    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, 
 | 
			
		||||
    KC_LALT, TT(_RAISE),    KC_SPC, TT(_LOWER),                                           KC_ENT,  KC_BSPC, KC_RBRC, KC_RGUI 
 | 
			
		||||
    ),
 | 
			
		||||
 | 
			
		||||
 /* LOWER      
 | 
			
		||||
* ,---------------------------------------------.                   ,------------------------------------------------.
 | 
			
		||||
* |  ESC |  F1   |  F2   |  F3  |  F4   |  F5   |                   |   F6   |  F7    |  F8    |  F9   | F10  |  DEL | 
 | 
			
		||||
* |------+-------+-------+------+-------+-------|                   |--------+--------+--------+-------+------+------|
 | 
			
		||||
* |  RST |  F11  |  F12  | DEL  | paste | copy  |                   |  home  | pg up  |  print | redo  | w    |      |
 | 
			
		||||
* |------+-------+-------+------+-------+-------|                   |--------+--------+--------+-------+------+------|
 | 
			
		||||
* |      |  all  |       | SAV  | undo  | BackSP|-------.   ,-------|  left  | down   |  up    | right |      |      |
 | 
			
		||||
* |------+-------+-------+------+-------+-------|  enter|   |       |--------+--------+--------+-------+------+------|
 | 
			
		||||
* |  F9  |  F11  |  F10  | F5   | TAB   | cut   |-------|   |-------|  end   | pg dw  |        |       |      |      |
 | 
			
		||||
* `---------------------------------------------/       /    \       \-----------------------------------------------'
 | 
			
		||||
*                   |      | SPE  |          | /       /      \       \  |      | MENU |      |
 | 
			
		||||
*                   |      |      |          |/       /        \       \ |      |      |      |
 | 
			
		||||
*                   `--------------------------------'          '-------''--------------------'
 | 
			
		||||
*/
 | 
			
		||||
    [_LOWER] =  LAYOUT(
 | 
			
		||||
    KC_ESC, KC_F1,      KC_F2,  KC_F3,      KC_F4,          KC_F5,                          KC_F6,      KC_F7,      KC_F8,      KC_F9,      KC_F10,         KC_DELETE,
 | 
			
		||||
    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), _______,
 | 
			
		||||
    _______,RCTL(FR_A), _______,RCTL(FR_S), RCTL(FR_Z),     KC_BSPC,                        KC_LEFT,    KC_DOWN,    KC_UP,      KC_RIGHT,   _______,        _______,
 | 
			
		||||
    KC_F9,  KC_F11,     KC_F10, KC_F5,      LALT(KC_TAB),   RCTL(FR_X), KC_ENT, _______,    KC_END,     KC_PGDN,    _______,    _______,    _______,        _______,
 | 
			
		||||
    _______,TT(_RAISE), _______, _______,                                                   _______,    _______,    KC_APP,     _______),
 | 
			
		||||
 | 
			
		||||
/* RAISE
 | 
			
		||||
* ,-----------------------------------------.                    ,-------------------------------------------.
 | 
			
		||||
* |      |      |      |      |      |      |                    |      |     |   /   |   *  |  -  | RGB TOG|
 | 
			
		||||
* |------+------+------+------+------+------|                    |------+------+------+------+-----+--------|
 | 
			
		||||
* |   `  |   [  |   ]  |      |      |      |                    |   ^  |   7  |   8  |   9  |  +  | RGB HUI|
 | 
			
		||||
* |------+------+------+------+------+------|                    |------+------+------+------+-----+--------|
 | 
			
		||||
* |      |  @   |  |   |  &   |  €   |  #   |-------.    ,-------|   $  |   4  |   5  |   6  |     |        |
 | 
			
		||||
* |------+------+------+------+------+------|       |    |       |------+------+------+------+-----+--------|
 | 
			
		||||
* |  F7  |  F8  |  F9  | F10  |  #   | F12  |-------|    |-------|      |   1  |   2  |   3  |     |        |
 | 
			
		||||
* `-----------------------------------------/       /     \      \------------------------------------------'
 | 
			
		||||
*                   |      |      |      | /       /       \      \  |       |   0  |  .   |
 | 
			
		||||
*                   |      |      |      |/       /         \      \ |       |      |      |
 | 
			
		||||
*                   `----------------------------'           '------''---------------------'
 | 
			
		||||
*/
 | 
			
		||||
    [_RAISE] = LAYOUT(
 | 
			
		||||
    _______, _______,    _______,    _______,    _______, _______,                   _______,    _______, KC_PSLS, KC_PAST, KC_PMNS, RGB_TOG,
 | 
			
		||||
    KC_GRV,  FR_LBRC,    FR_RBRC,    _______,    _______, _______,                   FR_EQL,     KC_KP_7, KC_KP_8, KC_KP_9, KC_PPLS, RGB_HUI, 
 | 
			
		||||
    _______, FR_AT,      FR_PIPE,    ALGR(KC_1), FR_EURO, FR_HASH,                   S(FR_EQL),  KC_KP_4, KC_KP_5, KC_KP_6, _______, _______,
 | 
			
		||||
    KC_F7,   KC_F8,      KC_F9,      KC_F10,     FR_HASH, KC_F12, _______, _______,  _______,    KC_KP_1, KC_KP_2, KC_KP_3, _______, _______,
 | 
			
		||||
    _______, _______,    _______,    _______,                                        _______,    _______, KC_KP_0, KC_KP_DOT)
 | 
			
		||||
};
 | 
			
		||||
// clang-format on
 | 
			
		||||
 | 
			
		||||
// sync transport
 | 
			
		||||
typedef struct _sync_keycode_t {
 | 
			
		||||
    uint16_t keycode;
 | 
			
		||||
} sync_keycode_t;
 | 
			
		||||
 | 
			
		||||
// force rigth side to update
 | 
			
		||||
bool b_sync_need_send = false;
 | 
			
		||||
 | 
			
		||||
// last keycode typed
 | 
			
		||||
sync_keycode_t last_keycode;
 | 
			
		||||
 | 
			
		||||
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
 | 
			
		||||
    // vertical orientation
 | 
			
		||||
    return OLED_ROTATION_270;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render(gui_state_t t) {
 | 
			
		||||
    // logo
 | 
			
		||||
    render_logo(t);
 | 
			
		||||
 | 
			
		||||
#if IS_LEFT
 | 
			
		||||
    // left side
 | 
			
		||||
    render_layer_frame(t);
 | 
			
		||||
    render_gears();
 | 
			
		||||
 | 
			
		||||
    decay_scope();
 | 
			
		||||
    render_scope(t);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if IS_RIGHT
 | 
			
		||||
    // right side
 | 
			
		||||
    render_circle(t);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void update(uint16_t keycode) {
 | 
			
		||||
#if IS_LEFT
 | 
			
		||||
    update_scope();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if IS_RIGHT
 | 
			
		||||
    update_circle(keycode);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void reset(void) {
 | 
			
		||||
#if IS_LEFT
 | 
			
		||||
    reset_scope();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if IS_RIGHT
 | 
			
		||||
    reset_ring();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void set_wackingup_mode_clean(void) {
 | 
			
		||||
    oled_clear();
 | 
			
		||||
    reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool oled_task_user(void) {
 | 
			
		||||
    gui_state_t t = get_gui_state();
 | 
			
		||||
 | 
			
		||||
    // in sleep mode => turn display off
 | 
			
		||||
    if (t == _SLEEP) {
 | 
			
		||||
        oled_off();
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // not in sleep mode => screen is on
 | 
			
		||||
    oled_on();
 | 
			
		||||
 | 
			
		||||
#ifdef WITH_BOOT
 | 
			
		||||
    // in booting mode => display booting animation
 | 
			
		||||
    if (t == _BOOTING) {
 | 
			
		||||
        bool boot_finished = render_boot();
 | 
			
		||||
        if (boot_finished) {
 | 
			
		||||
            // end of the boot : wacking up
 | 
			
		||||
            set_wackingup_mode_clean();
 | 
			
		||||
            update_gui_state();
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // in halting mode => display booting animation
 | 
			
		||||
    if (t == _HALTING) {
 | 
			
		||||
        render_halt();
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(t);
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void process_key(uint16_t keycode) {
 | 
			
		||||
    // update screen with the new key
 | 
			
		||||
    update(keycode);
 | 
			
		||||
 | 
			
		||||
    gui_state_t t = get_gui_state();
 | 
			
		||||
 | 
			
		||||
    if (t == _IDLE) {
 | 
			
		||||
        // wake up animation
 | 
			
		||||
        reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (t == _BOOTING || t == _HALTING) {
 | 
			
		||||
        // cancel booting or halting : waking_up
 | 
			
		||||
        set_wackingup_mode_clean();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (t == _SLEEP) {
 | 
			
		||||
        // boot sequence
 | 
			
		||||
        set_wackingup_mode_clean();
 | 
			
		||||
        reset_boot();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    update_gui_state();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void user_sync_a_slave_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) {
 | 
			
		||||
    const sync_keycode_t* m2s = (const sync_keycode_t*)in_data;
 | 
			
		||||
    // get the last char typed on left side and update the right side
 | 
			
		||||
    process_key(m2s->keycode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void keyboard_post_init_user(void) {
 | 
			
		||||
    // callback for tranport sync data
 | 
			
		||||
    transaction_register_rpc(USER_SYNC_A, user_sync_a_slave_handler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void housekeeping_task_user(void) {
 | 
			
		||||
    // only for master side
 | 
			
		||||
    if (!is_keyboard_master()) return;
 | 
			
		||||
 | 
			
		||||
    // only if a new char was typed
 | 
			
		||||
    if (!b_sync_need_send) return;
 | 
			
		||||
 | 
			
		||||
    // send the char to the slave side : sync is done
 | 
			
		||||
    if (transaction_rpc_send(USER_SYNC_A, sizeof(last_keycode), &last_keycode)) {
 | 
			
		||||
        b_sync_need_send = false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
 | 
			
		||||
    if (record->event.pressed) {
 | 
			
		||||
        // master : store keycode to sent to the other side to be process_key
 | 
			
		||||
        last_keycode.keycode = keycode;
 | 
			
		||||
        b_sync_need_send     = true;
 | 
			
		||||
 | 
			
		||||
        // gui process the input
 | 
			
		||||
        process_key(keycode);
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if IS_LEFT
 | 
			
		||||
layer_state_t layer_state_set_user(layer_state_t state) {
 | 
			
		||||
    // update the frame with the layer name
 | 
			
		||||
    update_layer_frame(state);
 | 
			
		||||
    return state;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										105
									
								
								keyboards/lily58/keymaps/druotoni/layer_frame.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								keyboards/lily58/keymaps/druotoni/layer_frame.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,105 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include QMK_KEYBOARD_H
 | 
			
		||||
 | 
			
		||||
#include "gui_state.h"
 | 
			
		||||
#include "layer_frame.h"
 | 
			
		||||
#include "draw_helper.h"
 | 
			
		||||
 | 
			
		||||
#define ANIM_LAYER_FRAME_DURATION 2
 | 
			
		||||
#define ANIM_LAYER_FRAME_MAX 7
 | 
			
		||||
 | 
			
		||||
// current layer
 | 
			
		||||
uint8_t current_layer = _QWERTY;
 | 
			
		||||
 | 
			
		||||
// layer animation stuff
 | 
			
		||||
uint16_t anim_layer_frame_timer  = 0;
 | 
			
		||||
uint8_t  current_layer_frame     = ANIM_LAYER_FRAME_MAX;
 | 
			
		||||
uint8_t  layer_frame_destination = ANIM_LAYER_FRAME_MAX;
 | 
			
		||||
 | 
			
		||||
// layer name for display
 | 
			
		||||
const char*        layer_name;
 | 
			
		||||
static const char* layer_ref[3] = {LAYER_NAME_0, LAYER_NAME_1, LAYER_NAME_2};
 | 
			
		||||
 | 
			
		||||
void update_layer_frame(layer_state_t state) {
 | 
			
		||||
    // reset timer
 | 
			
		||||
    anim_layer_frame_timer = timer_read();
 | 
			
		||||
 | 
			
		||||
    // direction for animation base on layer selected
 | 
			
		||||
    current_layer = get_highest_layer(state);
 | 
			
		||||
    if (current_layer == _QWERTY) {
 | 
			
		||||
        layer_frame_destination = 0;
 | 
			
		||||
    } else {
 | 
			
		||||
        layer_frame_destination = ANIM_LAYER_FRAME_MAX;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void draw_black_screen(void) {
 | 
			
		||||
    // clean frame center
 | 
			
		||||
    draw_rectangle_fill(3, 42, 26, 20, false);
 | 
			
		||||
    drawline_hr(17, 62, 12, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render_gears(void) {
 | 
			
		||||
    // 64 bytes, 8x8 font, 8 characters, 32x16 image, 4 columns, 2 rows
 | 
			
		||||
    static const char PROGMEM raw_logo[] = {
 | 
			
		||||
        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,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // extra line for complete the gui
 | 
			
		||||
    oled_write_raw_P_cursor(0, 8, raw_logo, sizeof(raw_logo));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render_layer_frame(gui_state_t t) {
 | 
			
		||||
    // 96 bytes, 8x8 font, 12 characters, 32x24 image, 4 columns, 3 rows
 | 
			
		||||
    static const char PROGMEM raw_logo[] = {
 | 
			
		||||
        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,
 | 
			
		||||
    };
 | 
			
		||||
    oled_write_raw_P_cursor(0, 5, raw_logo, sizeof(raw_logo));
 | 
			
		||||
 | 
			
		||||
    // extra line for complete the gui
 | 
			
		||||
    drawline_hr(2, 39, 25, 1);
 | 
			
		||||
 | 
			
		||||
    if (current_layer_frame != layer_frame_destination) {
 | 
			
		||||
        if (timer_elapsed(anim_layer_frame_timer) > ANIM_LAYER_FRAME_DURATION) {
 | 
			
		||||
            anim_layer_frame_timer = timer_read();
 | 
			
		||||
 | 
			
		||||
            if (layer_frame_destination > current_layer_frame) {
 | 
			
		||||
                current_layer_frame++;
 | 
			
		||||
            } else {
 | 
			
		||||
                current_layer_frame--;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // black screen
 | 
			
		||||
        draw_black_screen();
 | 
			
		||||
 | 
			
		||||
        // gradient animation on layer selection
 | 
			
		||||
        draw_gradient(3, 42, current_layer_frame * 4, 10, 0, 255, 7);
 | 
			
		||||
        draw_gradient(3 + (27 - current_layer_frame * 4), 57, current_layer_frame * 4, 6, 255, 0, 7);
 | 
			
		||||
 | 
			
		||||
        drawline_hr(3, 46, 22, false);
 | 
			
		||||
        drawline_hr(3, 47, 23, false);
 | 
			
		||||
 | 
			
		||||
        draw_rectangle_fill(3, 55, 24, 2, false);
 | 
			
		||||
        draw_rectangle_fill(24, 48, 3, 7, false);
 | 
			
		||||
 | 
			
		||||
        draw_rectangle_fill(3, 60, 12, 2, false);
 | 
			
		||||
        oled_write_pixel(15, 61, false);
 | 
			
		||||
        drawline_hr(14, 62, 3, false);
 | 
			
		||||
        drawline_hr(14, 62, 3, false);
 | 
			
		||||
        drawline_hr(3, 62, 11, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // get current layer name
 | 
			
		||||
    layer_name = layer_ref[current_layer];
 | 
			
		||||
 | 
			
		||||
    // gui on pause : no layer name on screen
 | 
			
		||||
    if (t == _IDLE || t == _SLEEP || t == _WAKINGUP) {
 | 
			
		||||
        layer_name = "   ";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // display layer name in the frame
 | 
			
		||||
    oled_write_cursor(1, 6, layer_name, false);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								keyboards/lily58/keymaps/druotoni/layer_frame.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								keyboards/lily58/keymaps/druotoni/layer_frame.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// layer name : must be 3 chars
 | 
			
		||||
#define LAYER_NAME_0 "ABC"
 | 
			
		||||
#define LAYER_NAME_1 "NAV"
 | 
			
		||||
#define LAYER_NAME_2 "SPE"
 | 
			
		||||
 | 
			
		||||
enum layer_number { _QWERTY = 0, _LOWER, _RAISE };
 | 
			
		||||
 | 
			
		||||
void render_gears(void);
 | 
			
		||||
void render_layer_frame(gui_state_t t);
 | 
			
		||||
void update_layer_frame(layer_state_t state);
 | 
			
		||||
							
								
								
									
										139
									
								
								keyboards/lily58/keymaps/druotoni/navi_font.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								keyboards/lily58/keymaps/druotoni/navi_font.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,139 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0.
 | 
			
		||||
// See gfxfont.h for newer custom bitmap font info.
 | 
			
		||||
 | 
			
		||||
#include "progmem.h"
 | 
			
		||||
 | 
			
		||||
// Standard ASCII 5x7 font
 | 
			
		||||
const unsigned char font[] PROGMEM = {
 | 
			
		||||
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x42, 0x3A, 0x12, 0x12, 0x0E, 0x00,
 | 
			
		||||
    0x0C, 0x44, 0x47, 0x24, 0x1C, 0x00,
 | 
			
		||||
    0x24, 0x24, 0x14, 0x7F, 0x04, 0x00,
 | 
			
		||||
    0x42, 0x3F, 0x02, 0x22, 0x1E, 0x00,
 | 
			
		||||
    0x0A, 0x0A, 0x7F, 0x0A, 0x0A, 0x00,
 | 
			
		||||
    0x02, 0x47, 0x42, 0x22, 0x1F, 0x00,
 | 
			
		||||
    0x21, 0x15, 0x09, 0x15, 0x63, 0x00,
 | 
			
		||||
    0x44, 0x44, 0x3F, 0x04, 0x04, 0x00,
 | 
			
		||||
    0x22, 0x1A, 0x02, 0x7F, 0x12, 0x00,
 | 
			
		||||
    0x22, 0x22, 0x12, 0x0A, 0x06, 0x00,
 | 
			
		||||
    0x08, 0x47, 0x42, 0x22, 0x1E, 0x00,
 | 
			
		||||
    0x10, 0x52, 0x54, 0x30, 0x16, 0x00,
 | 
			
		||||
    0x40, 0x3A, 0x02, 0x3E, 0x42, 0x00,
 | 
			
		||||
    0x5E, 0x52, 0x52, 0x52, 0x5E, 0x00,
 | 
			
		||||
    0x04, 0x27, 0x44, 0x44, 0x3C, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x77, 0x00, 0x77, 0x00, 0x77, 0x00,
 | 
			
		||||
    0x14, 0x22, 0x7F, 0x22, 0x14, 0x00,
 | 
			
		||||
    0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x00,
 | 
			
		||||
    0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00,
 | 
			
		||||
    0x00, 0x66, 0x89, 0x95, 0x6A, 0x00,
 | 
			
		||||
    0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
 | 
			
		||||
    0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x00,
 | 
			
		||||
    0x08, 0x04, 0x7E, 0x04, 0x08, 0x00,
 | 
			
		||||
    0x10, 0x20, 0x7E, 0x20, 0x10, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x1C, 0x1C, 0x1C, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x08, 0x1C, 0x08, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x5F, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
 | 
			
		||||
    0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00,
 | 
			
		||||
    0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00,
 | 
			
		||||
    0x23, 0x13, 0x08, 0x64, 0x62, 0x00,
 | 
			
		||||
    0x36, 0x49, 0x56, 0x20, 0x50, 0x00,
 | 
			
		||||
    0x00, 0x08, 0x07, 0x03, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x1C, 0x22, 0x41, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x41, 0x22, 0x1C, 0x00, 0x00,
 | 
			
		||||
    0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00,
 | 
			
		||||
    0x08, 0x08, 0x3E, 0x08, 0x08, 0x00,
 | 
			
		||||
    0x00, 0x80, 0x70, 0x30, 0x00, 0x00,
 | 
			
		||||
    0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x60, 0x60, 0x00, 0x00,
 | 
			
		||||
    0x20, 0x10, 0x08, 0x04, 0x02, 0x00,
 | 
			
		||||
    0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00,
 | 
			
		||||
    0x00, 0x42, 0x7F, 0x40, 0x00, 0x00,
 | 
			
		||||
    0x72, 0x49, 0x49, 0x49, 0x46, 0x00,
 | 
			
		||||
    0x21, 0x41, 0x49, 0x4D, 0x33, 0x00,
 | 
			
		||||
    0x18, 0x14, 0x12, 0x7F, 0x10, 0x00,
 | 
			
		||||
    0x27, 0x45, 0x45, 0x45, 0x39, 0x00,
 | 
			
		||||
    0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00,
 | 
			
		||||
    0x41, 0x21, 0x11, 0x09, 0x07, 0x00,
 | 
			
		||||
    0x36, 0x49, 0x49, 0x49, 0x36, 0x00,
 | 
			
		||||
    0x46, 0x49, 0x49, 0x29, 0x1E, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x40, 0x34, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x08, 0x14, 0x22, 0x41, 0x00,
 | 
			
		||||
    0x14, 0x14, 0x14, 0x14, 0x14, 0x00,
 | 
			
		||||
    0x00, 0x41, 0x22, 0x14, 0x08, 0x00,
 | 
			
		||||
    0x02, 0x01, 0x59, 0x09, 0x06, 0x00,
 | 
			
		||||
    0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00,
 | 
			
		||||
    0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00,
 | 
			
		||||
    0x7F, 0x49, 0x49, 0x49, 0x36, 0x00,
 | 
			
		||||
    0x3E, 0x41, 0x41, 0x41, 0x22, 0x00,
 | 
			
		||||
    0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00,
 | 
			
		||||
    0x7F, 0x49, 0x49, 0x49, 0x41, 0x00,
 | 
			
		||||
    0x7F, 0x09, 0x09, 0x09, 0x01, 0x00,
 | 
			
		||||
    0x3E, 0x41, 0x41, 0x51, 0x73, 0x00,
 | 
			
		||||
    0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00,
 | 
			
		||||
    0x00, 0x41, 0x7F, 0x41, 0x00, 0x00,
 | 
			
		||||
    0x20, 0x40, 0x41, 0x3F, 0x01, 0x00,
 | 
			
		||||
    0x7F, 0x08, 0x14, 0x22, 0x41, 0x00,
 | 
			
		||||
    0x7F, 0x40, 0x40, 0x40, 0x40, 0x00,
 | 
			
		||||
    0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00,
 | 
			
		||||
    0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00,
 | 
			
		||||
    0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00,
 | 
			
		||||
    0x7F, 0x09, 0x09, 0x09, 0x06, 0x00,
 | 
			
		||||
    0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00,
 | 
			
		||||
    0x7F, 0x09, 0x19, 0x29, 0x46, 0x00,
 | 
			
		||||
    0x26, 0x49, 0x49, 0x49, 0x32, 0x00,
 | 
			
		||||
    0x03, 0x01, 0x7F, 0x01, 0x03, 0x00,
 | 
			
		||||
    0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00,
 | 
			
		||||
    0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00,
 | 
			
		||||
    0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00,
 | 
			
		||||
    0x63, 0x14, 0x08, 0x14, 0x63, 0x00,
 | 
			
		||||
    0x03, 0x04, 0x78, 0x04, 0x03, 0x00,
 | 
			
		||||
    0x61, 0x59, 0x49, 0x4D, 0x43, 0x00,
 | 
			
		||||
    0x00, 0x7F, 0x41, 0x41, 0x41, 0x00,
 | 
			
		||||
    0x02, 0x04, 0x08, 0x10, 0x20, 0x00,
 | 
			
		||||
    0x00, 0x41, 0x41, 0x41, 0x7F, 0x00,
 | 
			
		||||
    0x04, 0x02, 0x01, 0x02, 0x04, 0x00,
 | 
			
		||||
    0x40, 0x40, 0x40, 0x40, 0x40, 0x00,
 | 
			
		||||
    0x00, 0x03, 0x07, 0x08, 0x00, 0x00,
 | 
			
		||||
    0x20, 0x54, 0x54, 0x78, 0x40, 0x00,
 | 
			
		||||
    0x7F, 0x28, 0x44, 0x44, 0x38, 0x00,
 | 
			
		||||
    0x38, 0x44, 0x44, 0x44, 0x28, 0x00,
 | 
			
		||||
    0x38, 0x44, 0x44, 0x28, 0x7F, 0x00,
 | 
			
		||||
    0x38, 0x54, 0x54, 0x54, 0x18, 0x00,
 | 
			
		||||
    0x00, 0x08, 0x7E, 0x09, 0x02, 0x00,
 | 
			
		||||
    0x18, 0x24, 0x24, 0x1C, 0x78, 0x00,
 | 
			
		||||
    0x7F, 0x08, 0x04, 0x04, 0x78, 0x00,
 | 
			
		||||
    0x00, 0x44, 0x7D, 0x40, 0x00, 0x00,
 | 
			
		||||
    0x20, 0x40, 0x40, 0x3D, 0x00, 0x00,
 | 
			
		||||
    0x7F, 0x10, 0x28, 0x44, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x41, 0x7F, 0x40, 0x00, 0x00,
 | 
			
		||||
    0x7C, 0x04, 0x78, 0x04, 0x78, 0x00,
 | 
			
		||||
    0x7C, 0x08, 0x04, 0x04, 0x78, 0x00,
 | 
			
		||||
    0x38, 0x44, 0x44, 0x44, 0x38, 0x00,
 | 
			
		||||
    0x7C, 0x18, 0x24, 0x24, 0x18, 0x00,
 | 
			
		||||
    0x18, 0x24, 0x24, 0x18, 0x7C, 0x00,
 | 
			
		||||
    0x7C, 0x08, 0x04, 0x04, 0x08, 0x00,
 | 
			
		||||
    0x48, 0x54, 0x54, 0x54, 0x24, 0x00,
 | 
			
		||||
    0x04, 0x04, 0x3F, 0x44, 0x24, 0x00,
 | 
			
		||||
    0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00,
 | 
			
		||||
    0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00,
 | 
			
		||||
    0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00,
 | 
			
		||||
    0x44, 0x28, 0x10, 0x28, 0x44, 0x00,
 | 
			
		||||
    0x4C, 0x90, 0x90, 0x90, 0x7C, 0x00,
 | 
			
		||||
    0x44, 0x64, 0x54, 0x4C, 0x44, 0x00,
 | 
			
		||||
    0x00, 0x08, 0x36, 0x41, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x77, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x41, 0x36, 0x08, 0x00, 0x00,
 | 
			
		||||
    0x02, 0x01, 0x02, 0x04, 0x02, 0x00,
 | 
			
		||||
    0x3C, 0x26, 0x23, 0x26, 0x3C, 0x00
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										117
									
								
								keyboards/lily58/keymaps/druotoni/navi_logo.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								keyboards/lily58/keymaps/druotoni/navi_logo.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,117 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include QMK_KEYBOARD_H
 | 
			
		||||
 | 
			
		||||
#include "gui_state.h"
 | 
			
		||||
#include "navi_logo.h"
 | 
			
		||||
#include "fast_random.h"
 | 
			
		||||
#include "draw_helper.h"
 | 
			
		||||
 | 
			
		||||
#define LOGO_SIZE 128
 | 
			
		||||
 | 
			
		||||
// glitch stuff
 | 
			
		||||
#define GLITCH_FRAME_NUMBER 11
 | 
			
		||||
 | 
			
		||||
uint8_t  current_glitch_index = 0;
 | 
			
		||||
int      current_glitch_time  = 150;
 | 
			
		||||
uint32_t glitch_timer         = 0;
 | 
			
		||||
 | 
			
		||||
static void render_logo_clean(void) {
 | 
			
		||||
    // your logo here
 | 
			
		||||
    static const char PROGMEM raw_logo[] = {
 | 
			
		||||
        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,
 | 
			
		||||
    };
 | 
			
		||||
    oled_write_raw_P(raw_logo, sizeof(raw_logo));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render_glitch_bar(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t iProb) {
 | 
			
		||||
    // random horizontal scanlines
 | 
			
		||||
    for (uint8_t i = 0; i < height; i++) {
 | 
			
		||||
        bool bGenerateGlitch = (fastrand() % 100) < iProb;
 | 
			
		||||
 | 
			
		||||
        if (bGenerateGlitch) {
 | 
			
		||||
            drawline_hr(x, y + i, width, true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render_misc_glitch(uint8_t algo) {
 | 
			
		||||
    char c = 0;
 | 
			
		||||
    switch (algo) {
 | 
			
		||||
        case 7:
 | 
			
		||||
            // invert
 | 
			
		||||
            for (uint8_t i = 0; i < LOGO_SIZE; i++) {
 | 
			
		||||
                c = get_oled_char(i);
 | 
			
		||||
                oled_write_raw_byte(~(c), i);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 8:
 | 
			
		||||
            //  wobble
 | 
			
		||||
            for (uint8_t i = 0; i < LOGO_SIZE; i++) {
 | 
			
		||||
                if (i < LOGO_SIZE - 1) {
 | 
			
		||||
                    copy_pixel(i + 1, -1, 85);
 | 
			
		||||
 | 
			
		||||
                    copy_pixel(LOGO_SIZE - 1 - 1 - i, 1, 170);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_logo_glitch(void) {
 | 
			
		||||
#ifdef WITH_GLITCH
 | 
			
		||||
    // get a random glitch index
 | 
			
		||||
    uint8_t glitch_prob = get_glitch_probability();
 | 
			
		||||
    get_glitch_index(&glitch_timer, ¤t_glitch_time, ¤t_glitch_index, 0, 150, glitch_prob, GLITCH_FRAME_NUMBER);
 | 
			
		||||
 | 
			
		||||
    // no glitch
 | 
			
		||||
    if (current_glitch_index <= 3) {
 | 
			
		||||
        render_logo_clean();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // glitch time !
 | 
			
		||||
    switch (current_glitch_index) {
 | 
			
		||||
        case 4:
 | 
			
		||||
            move_block(1, 11, 24, 3, 5);
 | 
			
		||||
            move_block(2, 19, 14, 3, 4);
 | 
			
		||||
            move_block(9, 22, 7, 4, 4);
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        case 5:
 | 
			
		||||
            move_block(6, 25, 20, 7, 4);
 | 
			
		||||
            move_block(0, 8, 32, 8, 7);
 | 
			
		||||
            return;
 | 
			
		||||
        case 6:
 | 
			
		||||
            move_block(3, 7, 27, 4, -3);
 | 
			
		||||
            move_block(13, 23, 19, 4, -4);
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        case 7:
 | 
			
		||||
        case 8:
 | 
			
		||||
            render_misc_glitch(current_glitch_index);
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        case 9:
 | 
			
		||||
            render_glitch_bar(0, 0, 32, 32, 25);
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        case 10:
 | 
			
		||||
            draw_static(0, 0, 32, 32, true, 0);
 | 
			
		||||
            return;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render_logo(gui_state_t t) {
 | 
			
		||||
    if (t == _IDLE) {
 | 
			
		||||
        // on idle : glitch time !
 | 
			
		||||
        render_logo_glitch();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // standart logo
 | 
			
		||||
    render_logo_clean();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								keyboards/lily58/keymaps/druotoni/navi_logo.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								keyboards/lily58/keymaps/druotoni/navi_logo.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
void render_logo(gui_state_t t);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										133
									
								
								keyboards/lily58/keymaps/druotoni/readme.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								keyboards/lily58/keymaps/druotoni/readme.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,133 @@
 | 
			
		|||
# HELL0 NAVI. Interface
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Ready to dive into the Wired ?
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
HELL0 NAVI provides interactive animations for both sides :
 | 
			
		||||
- a scope on left side for burst, WPM and active layer
 | 
			
		||||
- a ring on right side for the last key stroke
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Typing animation
 | 
			
		||||
 | 
			
		||||
The scope displays your burst time on a chart. The WPM is represented by an horizontal line.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
<img src="https://imgur.com/Yf7D6UN.gif" height="400" >
 | 
			
		||||
 | 
			
		||||
## Startup animation
 | 
			
		||||
 | 
			
		||||
Your Navi boots when it leaves the sleep mode. The animation can be canceled by typing.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<img src="https://imgur.com/EXU92Ev.gif" height="400" >
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Waking up animation
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<img src="https://imgur.com/9GWa7rR.gif" height="400" >
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Idle animation
 | 
			
		||||
 | 
			
		||||
The Copland OS is still in beta test. After a while, some visual glitches will occur. 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<img src="https://imgur.com/eKZ7qgC.gif" height="400" >
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Shutdown animation
 | 
			
		||||
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. 
 | 
			
		||||
 | 
			
		||||
# How to build & flash
 | 
			
		||||
 | 
			
		||||
You need to flash each side with a specific version based on config.h configuration.
 | 
			
		||||
 | 
			
		||||
 ## Left side (master)
 | 
			
		||||
 | 
			
		||||
IS_RIGHT needs to be commented in config.h
 | 
			
		||||
```
 | 
			
		||||
#define IS_LEFT 1
 | 
			
		||||
//#define IS_RIGHT 1
 | 
			
		||||
```
 | 
			
		||||
Connect the left side and flash
 | 
			
		||||
 | 
			
		||||
 ## Right side (slave)
 | 
			
		||||
 | 
			
		||||
Comment IS_LEFT and uncomment IS_RIGHT  in config.h
 | 
			
		||||
```
 | 
			
		||||
//#define IS_LEFT 1
 | 
			
		||||
#define IS_RIGHT 1
 | 
			
		||||
```
 | 
			
		||||
Connect the right side and flash
 | 
			
		||||
 | 
			
		||||
# Customization
 | 
			
		||||
 | 
			
		||||
## Logo
 | 
			
		||||
Logo can be change in navi_logo.c.
 | 
			
		||||
The new logo must be 32x32 pixels.
 | 
			
		||||
```
 | 
			
		||||
static void render_logo_clean(void) {
 | 
			
		||||
    // your logo here
 | 
			
		||||
    static const char PROGMEM logo_raw[] = {
 | 
			
		||||
        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,
 | 
			
		||||
    };
 | 
			
		||||
    oled_write_raw_P(logo_raw, sizeof(logo_raw));
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
## Layer names
 | 
			
		||||
 | 
			
		||||
The current version handle 3 differents layers. Names can be changed in layer_frame.h.
 | 
			
		||||
```
 | 
			
		||||
// layer name : must be 3 chars
 | 
			
		||||
#define LAYER_NAME_0 "ABC"
 | 
			
		||||
#define LAYER_NAME_1 "NAV"
 | 
			
		||||
#define LAYER_NAME_2 "SPE"
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Timing
 | 
			
		||||
 | 
			
		||||
You can tweak states timing in gui_state.h.
 | 
			
		||||
```
 | 
			
		||||
// states timing
 | 
			
		||||
#define BOOTING_TIME_TRESHOLD 7000
 | 
			
		||||
#define WAKING_UP_TIME_TRESHOLD 300
 | 
			
		||||
#define IDLE_TIME_TRESHOLD 4000
 | 
			
		||||
#define HALTING_TIME_TRESHOLD IDLE_TIME_TRESHOLD + 6000
 | 
			
		||||
#define SLEEP_TIME_TRESHOLD HALTING_TIME_TRESHOLD + 8000
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Need space ?
 | 
			
		||||
Boot and gliches can be commented in config.h
 | 
			
		||||
```
 | 
			
		||||
// states timing
 | 
			
		||||
// logo glitch
 | 
			
		||||
//#define WITH_GLITCH
 | 
			
		||||
// boot sequence
 | 
			
		||||
//#define WITH_BOOT
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
> Keyboard : https://github.com/kata0510/Lily58
 | 
			
		||||
> 
 | 
			
		||||
> Case : https://github.com/BoardSodie/Lily58-Acrylic-Case
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										494
									
								
								keyboards/lily58/keymaps/druotoni/ring.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										494
									
								
								keyboards/lily58/keymaps/druotoni/ring.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,494 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include QMK_KEYBOARD_H
 | 
			
		||||
#include "gui_state.h"
 | 
			
		||||
#include "ring.h"
 | 
			
		||||
 | 
			
		||||
#include "fast_random.h"
 | 
			
		||||
#include "draw_helper.h"
 | 
			
		||||
 | 
			
		||||
char tListeTotal[SIZE_ARRAY_1]  = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'};
 | 
			
		||||
char tListeTotal2[SIZE_ARRAY_1] = {'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ',', '.', '/', '1', '2', '3'};
 | 
			
		||||
 | 
			
		||||
static char tRefArc[SIZE_ARRAY_1]  = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'};
 | 
			
		||||
static char tRefArc2[SIZE_ARRAY_1] = {'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ',', '.', '/', '1', '2', '3'};
 | 
			
		||||
 | 
			
		||||
// ring target and previous char
 | 
			
		||||
char c_target   = 'A';
 | 
			
		||||
char c_target2  = 'Q';
 | 
			
		||||
char c_last     = ' ';
 | 
			
		||||
char c_previous = ' ';
 | 
			
		||||
 | 
			
		||||
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', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ';', '\'', ' ', ',', '.', '/', ' ', ' ', ' '};
 | 
			
		||||
 | 
			
		||||
// main circle
 | 
			
		||||
#define CIRCLE_ANIM_FRAME_DURATION 40
 | 
			
		||||
uint16_t circle_timer = 0;
 | 
			
		||||
 | 
			
		||||
// special animation for special keys
 | 
			
		||||
#define ANIM_CENTER_FRAME_NUMBER 5
 | 
			
		||||
#define ANIM_CENTER_FRAME_DURATION 40
 | 
			
		||||
uint16_t anim_center_timer         = 0;
 | 
			
		||||
uint8_t  anim_center_current_frame = 0;
 | 
			
		||||
 | 
			
		||||
// sleep animation
 | 
			
		||||
#define ANIM_SLEEP_RING_FRAME_NUMBER 9
 | 
			
		||||
#define ANIM_SLEEP_RING_FRAME_DURATION 20
 | 
			
		||||
uint16_t anim_sleep_ring_timer        = 0;
 | 
			
		||||
uint8_t  current_sleep_ring_frame     = 0;
 | 
			
		||||
uint8_t  sleep_ring_frame_destination = ANIM_SLEEP_RING_FRAME_NUMBER - 1;
 | 
			
		||||
 | 
			
		||||
// glitch animation
 | 
			
		||||
uint16_t anim_ring_idle_timer      = 0;
 | 
			
		||||
int      current_glitch_ring_time  = 150;
 | 
			
		||||
uint32_t glitch_ring_timer         = 0;
 | 
			
		||||
uint8_t  current_glitch_ring_index = 0;
 | 
			
		||||
 | 
			
		||||
// central frame keylog animation
 | 
			
		||||
#define ANIM_KEYLOG_FRAME_NUMBER 8
 | 
			
		||||
#define ANIM_KEYLOG_FRAME_DURATION 20
 | 
			
		||||
uint8_t  anim_keylog_current_frame = 0;
 | 
			
		||||
uint16_t anim_keylog_timer         = 0;
 | 
			
		||||
 | 
			
		||||
static const char PROGMEM raw_ring_sleep[4][64] = {{
 | 
			
		||||
                                                       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,
 | 
			
		||||
                                                   },
 | 
			
		||||
 | 
			
		||||
                                                   {
 | 
			
		||||
                                                       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,
 | 
			
		||||
                                                   },
 | 
			
		||||
 | 
			
		||||
                                                   {
 | 
			
		||||
                                                       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,
 | 
			
		||||
                                                   },
 | 
			
		||||
 | 
			
		||||
                                                   {
 | 
			
		||||
                                                       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,
 | 
			
		||||
                                                   }};
 | 
			
		||||
 | 
			
		||||
static const char PROGMEM raw_circle[4][128] = {{
 | 
			
		||||
                                                    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,
 | 
			
		||||
                                                },
 | 
			
		||||
                                                {
 | 
			
		||||
                                                    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,
 | 
			
		||||
                                                },
 | 
			
		||||
                                                {
 | 
			
		||||
                                                    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,
 | 
			
		||||
                                                },
 | 
			
		||||
                                                {
 | 
			
		||||
                                                    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,
 | 
			
		||||
                                                }};
 | 
			
		||||
 | 
			
		||||
static const char PROGMEM raw_bottom[] = {
 | 
			
		||||
    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,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char PROGMEM raw_middle[] = {
 | 
			
		||||
    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,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void rotate_right(char str[]) {
 | 
			
		||||
    uint8_t iSize = SIZE_ARRAY_1;
 | 
			
		||||
    char    cFist = str[0];
 | 
			
		||||
 | 
			
		||||
    // rotate array to the right
 | 
			
		||||
    for (uint8_t i = 0; i < iSize - 1; i++) {
 | 
			
		||||
        str[i] = str[i + 1];
 | 
			
		||||
    }
 | 
			
		||||
    str[iSize - 1] = cFist;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rotate_left(char str[]) {
 | 
			
		||||
    uint8_t iSize = SIZE_ARRAY_1;
 | 
			
		||||
    char    cLast = str[iSize - 1];
 | 
			
		||||
 | 
			
		||||
    // rotate array to the left
 | 
			
		||||
    for (uint8_t i = iSize - 1; i > 0; i--) {
 | 
			
		||||
        str[i] = str[i - 1];
 | 
			
		||||
    }
 | 
			
		||||
    str[0] = cLast;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static signed char GetPosition(char c, char tListe[]) {
 | 
			
		||||
    uint8_t iSize = SIZE_ARRAY_1;
 | 
			
		||||
 | 
			
		||||
    // find position of c in the array
 | 
			
		||||
    for (uint8_t i = 0; i < iSize; i++) {
 | 
			
		||||
        if (tListe[i] == c) return i;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // not found
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static signed char GetDistance(char cNew, char tListe[]) {
 | 
			
		||||
    signed char iPositionNew = GetPosition(cNew, tListe);
 | 
			
		||||
    if (iPositionNew == -1) {
 | 
			
		||||
        // not found
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return iPositionNew - CURSOR_1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool TesterEstDansListe(char c, char tListe[]) {
 | 
			
		||||
    // char in the list ?
 | 
			
		||||
    return GetPosition(c, tListe) != -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void SmartRotation(char c, char tListe[]) {
 | 
			
		||||
    signed char i = GetDistance(c, tListe);
 | 
			
		||||
    if (i == 0) return;
 | 
			
		||||
 | 
			
		||||
    // rotate in the shorter way
 | 
			
		||||
    if (i < 0) {
 | 
			
		||||
        rotate_left(tListe);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (i > 0) {
 | 
			
		||||
        rotate_right(tListe);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void update_list(char cNouveau, char tListe[]) {
 | 
			
		||||
    signed char iDistance = GetDistance(cNouveau, tListe);
 | 
			
		||||
    if (iDistance != 0) {
 | 
			
		||||
        // the new char is in the list : rotation
 | 
			
		||||
        SmartRotation(cNouveau, tListe);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void draw_arc_sector_16(uint8_t x, uint8_t y, uint8_t radius, int position, bool color) {
 | 
			
		||||
    unsigned int s = 1;
 | 
			
		||||
    s              = s << (position / 2);
 | 
			
		||||
 | 
			
		||||
    if (position % 4 == 0 || position % 4 == 3) {
 | 
			
		||||
        draw_arc_sector(x, y, radius, s, 1, color);
 | 
			
		||||
    } else {
 | 
			
		||||
        draw_arc_sector(x, y, radius, s, 2, color);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_set(uint8_t x, uint8_t y, uint8_t r, int p, bool color) {
 | 
			
		||||
    // 2 pixels arc sector
 | 
			
		||||
    draw_arc_sector_16(x, y, r, p, color);
 | 
			
		||||
    draw_arc_sector_16(x, y, r - 1, p, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void draw_letter_circle(char t[], char tRef[], char ct, uint8_t x, uint8_t y, uint8_t r, bool invert) {
 | 
			
		||||
    char c = t[CURSOR_1];
 | 
			
		||||
 | 
			
		||||
    signed char p  = GetPosition(c, tRef);
 | 
			
		||||
    signed char pt = GetPosition(ct, tRef);
 | 
			
		||||
 | 
			
		||||
    if (!invert) {
 | 
			
		||||
        draw_fill_circle(x, y, r, false);
 | 
			
		||||
        draw_circle(x, y, r, false);
 | 
			
		||||
        draw_circle(x, y, r - 1, false);
 | 
			
		||||
        draw_circle(x, y, r - 2, false);
 | 
			
		||||
        draw_circle(x, y, r - 4, true);
 | 
			
		||||
        draw_circle(x, y, r - 5, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int pafter  = (pt + 1) % SIZE_ARRAY_1;
 | 
			
		||||
    int pbefore = (pt + SIZE_ARRAY_1 - 1) % SIZE_ARRAY_1;
 | 
			
		||||
    render_set(x, y, r, pt, true);
 | 
			
		||||
    render_set(x, y, r, pafter, true);
 | 
			
		||||
    render_set(x, y, r, pbefore, true);
 | 
			
		||||
 | 
			
		||||
    pafter  = (pt + 2) % SIZE_ARRAY_1;
 | 
			
		||||
    pbefore = (pt + SIZE_ARRAY_1 - 2) % SIZE_ARRAY_1;
 | 
			
		||||
    render_set(x, y, r, pafter, true);
 | 
			
		||||
    render_set(x, y, r, pbefore, true);
 | 
			
		||||
 | 
			
		||||
    r -= 4;
 | 
			
		||||
 | 
			
		||||
    pafter  = (p + 1) % SIZE_ARRAY_1;
 | 
			
		||||
    pbefore = (p + SIZE_ARRAY_1 - 1) % SIZE_ARRAY_1;
 | 
			
		||||
 | 
			
		||||
    render_set(x, y, r, p, false);
 | 
			
		||||
    render_set(x, y, r, pafter, false);
 | 
			
		||||
    render_set(x, y, r, pbefore, false);
 | 
			
		||||
 | 
			
		||||
    draw_circle(x, y, r - 6, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void draw_center_circle_frame(uint8_t x, uint8_t y, uint8_t r, uint8_t f) {
 | 
			
		||||
    draw_fill_circle(x, y, r, 0);
 | 
			
		||||
    draw_circle(x, y, r, 0);
 | 
			
		||||
 | 
			
		||||
    if (f == 0) {
 | 
			
		||||
        draw_circle(x, y, r, 1);
 | 
			
		||||
    } else {
 | 
			
		||||
        // animation
 | 
			
		||||
        oled_write_raw_P_cursor(0, 11, raw_circle[f - 1], sizeof(raw_circle[f - 1]));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_anim_center_circle(uint8_t x, uint8_t y, uint8_t r) {
 | 
			
		||||
    if (anim_center_current_frame == ANIM_CENTER_FRAME_NUMBER) {
 | 
			
		||||
        // last frame : no animation
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (timer_elapsed(anim_center_timer) > ANIM_CENTER_FRAME_DURATION) {
 | 
			
		||||
        anim_center_timer = timer_read();
 | 
			
		||||
 | 
			
		||||
        draw_center_circle_frame(x, y, r, anim_center_current_frame);
 | 
			
		||||
 | 
			
		||||
        anim_center_current_frame++;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_char(char c) {
 | 
			
		||||
    // write keylog char in the frame then offset to center
 | 
			
		||||
    oled_set_cursor(2, 6);
 | 
			
		||||
    oled_write_char(c, false);
 | 
			
		||||
    move_block(12, 48, 6, 8, 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_keylog(gui_state_t t) {
 | 
			
		||||
    if (anim_keylog_current_frame != ANIM_KEYLOG_FRAME_NUMBER) {
 | 
			
		||||
        if (timer_elapsed(anim_keylog_timer) > ANIM_KEYLOG_FRAME_DURATION) {
 | 
			
		||||
            // update frame number
 | 
			
		||||
            anim_keylog_timer = timer_read();
 | 
			
		||||
            anim_keylog_current_frame++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // clean frame
 | 
			
		||||
        draw_rectangle_fill(7, 46, 21, 11, false);
 | 
			
		||||
 | 
			
		||||
        // comb motion to merge current and previous
 | 
			
		||||
        if (anim_keylog_current_frame < ANIM_KEYLOG_FRAME_NUMBER / 2) {
 | 
			
		||||
            // expand the previous char
 | 
			
		||||
            write_char(c_previous);
 | 
			
		||||
            draw_glitch_comb(9, 6 * 8, 18, 8, anim_keylog_current_frame + 1, true);
 | 
			
		||||
        } else {
 | 
			
		||||
            // shrink the current char
 | 
			
		||||
            write_char(c_last);
 | 
			
		||||
            draw_glitch_comb(9, 6 * 8, 18, 8, ANIM_KEYLOG_FRAME_NUMBER - anim_keylog_current_frame, false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    write_char(c_last);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void reset_ring(void) {
 | 
			
		||||
    // need to open
 | 
			
		||||
    anim_sleep_ring_timer        = timer_read();
 | 
			
		||||
    current_sleep_ring_frame     = ANIM_SLEEP_RING_FRAME_NUMBER - 1;
 | 
			
		||||
    sleep_ring_frame_destination = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_tv_circle(uint8_t x, uint8_t y, uint8_t r, uint8_t f) {
 | 
			
		||||
    // raw image
 | 
			
		||||
    if (f == 2 || f == 3) {
 | 
			
		||||
        oled_write_raw_P_cursor(0, 12, raw_ring_sleep[f - 2], sizeof(raw_ring_sleep[f - 2]));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // raw image
 | 
			
		||||
    if (f == 5 || f == 6) {
 | 
			
		||||
        oled_write_raw_P_cursor(0, 12, raw_ring_sleep[f - 3], sizeof(raw_ring_sleep[f - 3]));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // other frames : lighter to draw than using raw image
 | 
			
		||||
    switch (f) {
 | 
			
		||||
        case 1:
 | 
			
		||||
            draw_circle(x, y, r, 1);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 4:
 | 
			
		||||
            drawline_hr(1, y, 12, 1);
 | 
			
		||||
            drawline_hr(19, y, 12, 1);
 | 
			
		||||
            drawline_vb(0, y - 1, 3, true);
 | 
			
		||||
            drawline_vb(31, y - 1, 3, true);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 7:
 | 
			
		||||
 | 
			
		||||
            oled_write_pixel(1, y, true);
 | 
			
		||||
            oled_write_pixel(3, y, true);
 | 
			
		||||
            oled_write_pixel(28, y, true);
 | 
			
		||||
            oled_write_pixel(30, y, true);
 | 
			
		||||
 | 
			
		||||
            drawline_vb(0, y - 12, 26, true);
 | 
			
		||||
            drawline_vb(31, y - 12, 26, true);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 8:
 | 
			
		||||
            drawline_vb(0, 88, 32, true);
 | 
			
		||||
            drawline_vb(31, 88, 32, true);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_circle_white(void) {
 | 
			
		||||
    // top
 | 
			
		||||
    oled_write_raw_P_cursor(0, 5, raw_middle, sizeof(raw_middle));
 | 
			
		||||
    drawline_hr(5, 39, 25, 1);
 | 
			
		||||
 | 
			
		||||
    // clean center
 | 
			
		||||
    draw_rectangle_fill(0, 80, 32, 40, false);
 | 
			
		||||
 | 
			
		||||
    // bottom
 | 
			
		||||
    drawline_vb(0, 80, 8, 1);
 | 
			
		||||
    drawline_vb(31, 80, 8, 1);
 | 
			
		||||
    oled_write_pixel(1, 80, true);
 | 
			
		||||
    oled_write_pixel(30, 80, true);
 | 
			
		||||
 | 
			
		||||
    oled_write_raw_P_cursor(0, 15, raw_bottom, sizeof(raw_bottom));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_ring_clean_close(void) {
 | 
			
		||||
    render_circle_white();
 | 
			
		||||
    drawline_vb(0, 88, 32, true);
 | 
			
		||||
    drawline_vb(31, 88, 32, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_glitch_square(void) {
 | 
			
		||||
    if (timer_elapsed(anim_ring_idle_timer) > 60) {
 | 
			
		||||
        anim_ring_idle_timer = timer_read();
 | 
			
		||||
 | 
			
		||||
        render_ring_clean_close();
 | 
			
		||||
 | 
			
		||||
        uint8_t size = 0;
 | 
			
		||||
        for (uint8_t i = 0; i < 4; i++) {
 | 
			
		||||
            size = 4 + (fastrand() % 6);
 | 
			
		||||
            draw_rectangle_fill(3 + (fastrand() % 19), 85 + (fastrand() % 20), size, size, true);
 | 
			
		||||
 | 
			
		||||
            size = (fastrand() % 6);
 | 
			
		||||
            draw_rectangle_fill(3 + (fastrand() % 19), 100 + (fastrand() % 20), size, size, true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_ring_idle(void) {
 | 
			
		||||
    uint8_t glitch_prob = get_glitch_probability();
 | 
			
		||||
    get_glitch_index(&glitch_ring_timer, ¤t_glitch_ring_time, ¤t_glitch_ring_index, 150, 350, glitch_prob, 2);
 | 
			
		||||
 | 
			
		||||
    switch (current_glitch_ring_index) {
 | 
			
		||||
        case 0:
 | 
			
		||||
            // no glitch
 | 
			
		||||
            render_ring_clean_close();
 | 
			
		||||
            return;
 | 
			
		||||
        case 1:
 | 
			
		||||
            // square gliches
 | 
			
		||||
            render_glitch_square();
 | 
			
		||||
            return;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_ring_sleep(void) {
 | 
			
		||||
    if (current_sleep_ring_frame == sleep_ring_frame_destination) {
 | 
			
		||||
        // no more animation needes : render the idle animation
 | 
			
		||||
        render_ring_idle();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // display wacking up / sleep animation
 | 
			
		||||
    if (timer_elapsed(anim_sleep_ring_timer) > ANIM_SLEEP_RING_FRAME_DURATION) {
 | 
			
		||||
        anim_sleep_ring_timer = timer_read();
 | 
			
		||||
 | 
			
		||||
        // clean + new frame
 | 
			
		||||
        render_circle_white();
 | 
			
		||||
        render_tv_circle(15, 103, 11, current_sleep_ring_frame);
 | 
			
		||||
 | 
			
		||||
        // update frame number
 | 
			
		||||
        if (sleep_ring_frame_destination > current_sleep_ring_frame) {
 | 
			
		||||
            current_sleep_ring_frame++;
 | 
			
		||||
        } else {
 | 
			
		||||
            current_sleep_ring_frame--;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void render_circle_middle(void) {
 | 
			
		||||
    // clean
 | 
			
		||||
    render_circle_white();
 | 
			
		||||
 | 
			
		||||
    // center special animation
 | 
			
		||||
    if (anim_center_current_frame < ANIM_CENTER_FRAME_NUMBER) {
 | 
			
		||||
        render_anim_center_circle(15, 103, 15 - 4);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // ring render
 | 
			
		||||
    if (anim_center_current_frame == ANIM_CENTER_FRAME_NUMBER) {
 | 
			
		||||
        draw_letter_circle(tListeTotal, tRefArc, c_target, 15, 103, 15, false);
 | 
			
		||||
        draw_letter_circle(tListeTotal2, tRefArc2, c_target2, 15, 103, 15, true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render_circle(gui_state_t t) {
 | 
			
		||||
    if (timer_elapsed(circle_timer) > CIRCLE_ANIM_FRAME_DURATION) {
 | 
			
		||||
        // new frame
 | 
			
		||||
        circle_timer = timer_read();
 | 
			
		||||
 | 
			
		||||
        // shift rings
 | 
			
		||||
        update_list(c_target, tListeTotal);
 | 
			
		||||
        update_list(c_target2, tListeTotal2);
 | 
			
		||||
 | 
			
		||||
        // waking up animation
 | 
			
		||||
        if (t == _WAKINGUP) {
 | 
			
		||||
            render_ring_sleep();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // idle animation
 | 
			
		||||
        if (t == _IDLE) {
 | 
			
		||||
            sleep_ring_frame_destination = ANIM_SLEEP_RING_FRAME_NUMBER - 1;
 | 
			
		||||
            render_ring_sleep();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // render on display
 | 
			
		||||
        render_circle_middle();
 | 
			
		||||
        render_keylog(t);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void update_circle(uint16_t keycode) {
 | 
			
		||||
    // special animation for special keys
 | 
			
		||||
    if (keycode == KC_ESC || keycode == KC_SPACE || keycode == KC_ENTER) {
 | 
			
		||||
        anim_center_timer         = timer_read();
 | 
			
		||||
        anim_center_current_frame = 0;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // cancel special animation on a new key
 | 
			
		||||
    anim_center_current_frame = ANIM_CENTER_FRAME_NUMBER;
 | 
			
		||||
 | 
			
		||||
    // out of scope key
 | 
			
		||||
    if (keycode >= 60) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // keycode to char
 | 
			
		||||
    char c = pgm_read_byte(&code_to_name[keycode]);
 | 
			
		||||
 | 
			
		||||
    // stock previous char
 | 
			
		||||
    c_previous = c_last;
 | 
			
		||||
    c_last     = c;
 | 
			
		||||
 | 
			
		||||
    // start keylog animation
 | 
			
		||||
    anim_keylog_current_frame = 0;
 | 
			
		||||
 | 
			
		||||
    // update target in ring #1 position
 | 
			
		||||
    if (TesterEstDansListe(c, tListeTotal)) {
 | 
			
		||||
        c_target = c;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // update target in #2 position
 | 
			
		||||
    if (TesterEstDansListe(c, tListeTotal2)) {
 | 
			
		||||
        c_target2 = c;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								keyboards/lily58/keymaps/druotoni/ring.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								keyboards/lily58/keymaps/druotoni/ring.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
// Copyright 2021 Nicolas Druoton (druotoni)
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#define SIZE_ARRAY_1 16
 | 
			
		||||
#define CURSOR_1 9
 | 
			
		||||
 | 
			
		||||
void update_circle(uint16_t);
 | 
			
		||||
void render_circle(gui_state_t t);
 | 
			
		||||
void reset_ring(void);
 | 
			
		||||
							
								
								
									
										28
									
								
								keyboards/lily58/keymaps/druotoni/rules.mk
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								keyboards/lily58/keymaps/druotoni/rules.mk
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
# Build Options
 | 
			
		||||
#   change to "no" to disable the options, or define them in the Makefile in
 | 
			
		||||
#   the appropriate keymap folder that will get included automatically
 | 
			
		||||
#
 | 
			
		||||
RGBLIGHT_ENABLE = yes       # Enable WS2812 RGB underlight. 
 | 
			
		||||
 | 
			
		||||
# Bootloader selection
 | 
			
		||||
BOOTLOADER = atmel-dfu
 | 
			
		||||
 | 
			
		||||
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
 | 
			
		||||
SLEEP_LED_ENABLE = no    # Breathing sleep LED during USB suspend
 | 
			
		||||
# EXTRAFLAGS += -flto
 | 
			
		||||
LTO_ENABLE = yes
 | 
			
		||||
SPACE_CADET_ENABLE = no
 | 
			
		||||
GRAVE_ESC_ENABLE = no
 | 
			
		||||
MAGIC_ENABLE  = no
 | 
			
		||||
 | 
			
		||||
# If you want to change the display of OLED, you need to change here
 | 
			
		||||
SRC +=  ./lib/rgb_state_reader.c \
 | 
			
		||||
        ./burst.c \
 | 
			
		||||
        ./navi_logo.c \
 | 
			
		||||
        ./gui_state.c \
 | 
			
		||||
        ./fast_random.c \
 | 
			
		||||
        ./layer_frame.c \
 | 
			
		||||
        ./ring.c \
 | 
			
		||||
        ./boot.c \
 | 
			
		||||
        ./draw_helper.c \
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue