summaryrefslogtreecommitdiff
path: root/keyboards/lily58/keymaps/druotoni/burst.c
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/lily58/keymaps/druotoni/burst.c')
-rw-r--r--keyboards/lily58/keymaps/druotoni/burst.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/keyboards/lily58/keymaps/druotoni/burst.c b/keyboards/lily58/keymaps/druotoni/burst.c
new file mode 100644
index 0000000000..6dd6579e73
--- /dev/null
+++ b/keyboards/lily58/keymaps/druotoni/burst.c
@@ -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, &current_glitch_scope_time, &current_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();
+}