qmk_userspace/keyboards/crkbd/r2g/keymaps/mgallecom/animation-utils.c
2024-11-25 07:48:52 +00:00

99 lines
2.8 KiB
C

/**
* Utilities for QMK oled animations
*
* Copyright (c) Marek Piechut
* MIT License
*/
#pragma once
//-------- CONFIGURATION START --------
#ifndef ANIM_RENDER_WPM
#define ANIM_RENDER_WPM true
#endif
#ifndef FAST_TYPE_WPM
#define FAST_TYPE_WPM 45 //Switch to fast animation when over words per minute
#endif
#ifndef ANIM_INVERT
#define ANIM_INVERT false //Invert animation color and background
#endif
#ifndef ANIM_BG
#define ANIM_BG 0x00
#endif
#ifndef ANIM_FRAME_TIME
#define ANIM_FRAME_TIME 250
#endif
//-------- CONFIGURATION END--------
#define ANIM_WPM_WIDTH 22
#define OLED_ROWS OLED_DISPLAY_HEIGHT / 4
static void oled_render_wpm(void) {
static char wpm_str[4];
sprintf(wpm_str, "%03d", get_current_wpm());
oled_set_cursor(0, 1);
oled_write_P(PSTR("WPM"), false);
oled_set_cursor(0, 2);
oled_write(wpm_str, false);
}
static void oled_render_anim_frame(const char **fast_frames, const char **slow_frames, uint8_t frames_len) {
static uint32_t anim_timer = 0;
static uint8_t current_frame = 0;
static int16_t frame_offset = ANIM_RENDER_WPM ? ANIM_WPM_WIDTH : 0;
static int8_t step = 8;
const uint8_t speed = get_current_wpm();
if (timer_elapsed32(anim_timer) > ANIM_FRAME_TIME && speed > 0) {
oled_set_cursor(0, 0);
anim_timer = timer_read32();
const bool is_fast = speed > FAST_TYPE_WPM;
const char *frame = is_fast ? fast_frames[current_frame] : slow_frames[current_frame];
const int8_t bg = ANIM_BG;
uint8_t frame_start_offset = ANIM_RENDER_WPM ? ANIM_WPM_WIDTH : 0;
current_frame = (current_frame + 1) % frames_len;
for(int offset = 0; offset <= OLED_MATRIX_SIZE; offset++) {
uint16_t col = offset % OLED_DISPLAY_WIDTH;
if(col < frame_start_offset) {
continue;
} else if (col < frame_offset || col > frame_offset + ANIM_FRAME_WIDTH) {
oled_write_raw_byte((ANIM_INVERT ? ~bg : bg), offset);
} else if (col <= OLED_DISPLAY_WIDTH) {
uint8_t row = offset / OLED_DISPLAY_WIDTH;
int frame_data_offset = ANIM_FRAME_WIDTH * row + col - frame_offset;
uint8_t col_data = pgm_read_byte(frame + frame_data_offset);
oled_write_raw_byte(ANIM_INVERT ? ~col_data : col_data, offset );
}
}
#ifdef ANIM_SCROLL
if(is_fast) {
#ifdef ANIM_BOUNCE
if(frame_offset + ANIM_FRAME_WIDTH > OLED_DISPLAY_WIDTH || frame_offset < frame_start_offset) {
step = -step;
}
#endif
frame_offset += step;
if(frame_offset >= OLED_DISPLAY_WIDTH) {
frame_offset = frame_start_offset - ANIM_FRAME_WIDTH + step;
}
} else if (frame_offset > (OLED_DISPLAY_WIDTH - ANIM_FRAME_WIDTH) || frame_offset < frame_start_offset) {
frame_offset = frame_start_offset;
}
#endif
}
if(ANIM_RENDER_WPM) {
oled_render_wpm();
}
}