Last active
July 22, 2019 19:20
-
-
Save EndingCredits/0355babc2aa8becb11c2ab8aada871ed to your computer and use it in GitHub Desktop.
Ripple effect for HS60 keyboard > https://i.imgur.com/GBUDbji.mp4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# See below for algorithm details | |
# https://web.archive.org/web/20160418004149/http://freespace.virgin.net/hugo.elias/graphics/x_water.htm | |
// GRID_MAX refers to the maximum position of an LED via map_led_to_point | |
#define LED_GRID_MAX_Y 65 | |
#define LED_GRID_MAX_X 255 | |
// Number to shift right by to get to ripple grid | |
#define GRID_COARSE 4 | |
// Width and height of ripple grid | |
#define R_HEIGHT (LED_GRID_MAX_Y>>GRID_COARSE) | |
#define R_WIDTH (LED_GRID_MAX_X>>GRID_COARSE) | |
// Wave persistence, higher = less decay | |
#define R_PERSISTENCE (7 - GRID_COARSE) | |
// Create ripple grid, which has two buffers | |
// uint16 to prevent overflow and to enable 'HDR'ness | |
uint16_t ripple_grid_a[R_WIDTH * R_HEIGHT]; | |
uint16_t ripple_grid_b[R_WIDTH * R_HEIGHT]; | |
uint16_t* ripple_grid_front; | |
uint16_t* ripple_grid_back; | |
void backlight_effect_keypress_ripples( bool initialize ) | |
{ | |
if (initialize) { | |
// Set buffers and zero-init them | |
ripple_grid_front = ripple_grid_a; | |
ripple_grid_back = ripple_grid_b; | |
for (uint16_t i = 0; i < R_WIDTH*R_HEIGHT; i++) { | |
ripple_grid_a[i] = 0; | |
ripple_grid_b[i] = 0; | |
} | |
} | |
Point point; | |
for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ ) | |
{ | |
// Map LED to ripple grid | |
map_led_to_point( i, &point ); | |
uint8_t x = MIN( point.x>>GRID_COARSE, R_WIDTH-1); | |
uint8_t y = MIN( point.y>>GRID_COARSE, R_HEIGHT-1); | |
// If keyhit, set 'height' to some value | |
if (g_key_hit[i]==1) { | |
ripple_grid_front[x + R_WIDTH*y] = 512; | |
} | |
// Get intensity from grid and clip value | |
uint8_t intensity = MIN(ripple_grid_back[x + R_WIDTH*y], 255); | |
// Set LED color from intenisty | |
HSV hsv = { .h = g_config.color_1.h, | |
.s = g_config.color_1.s, | |
.v = (g_config.brightness * intensity) / 255 }; | |
RGB rgb = hsv_to_rgb( hsv ); | |
backlight_set_color( i, rgb.r, rgb.g, rgb.b ); | |
} | |
// Ripples updates | |
if ( g_tick % (0x08 >> g_config.effect_speed) == 0) { | |
// For each cell in the ripple grid | |
for (uint8_t y = 0; y < R_HEIGHT; y++) { | |
for (uint8_t x = 0; x < R_WIDTH; x++) { | |
// Current cell | |
uint16_t* gridcell = &ripple_grid_back[x + R_WIDTH*y]; | |
// Mapping for cells on edges to enable reflections | |
uint8_t x_p = (x == R_WIDTH-1) ? x - 1 : x + 1 ; | |
uint8_t x_n = (x == 0) ? x + 1 : x - 1 ; | |
uint8_t y_p = (y == R_HEIGHT-1) ? y - 1 : y + 1 ; | |
uint8_t y_n = (y == 0) ? y + 1 : y - 1 ; | |
// Apply filter | |
uint16_t neighbours = ripple_grid_front[x_p + R_WIDTH*y]; | |
neighbours = neighbours + ripple_grid_front[x_n + R_WIDTH*y]; | |
neighbours = neighbours + ripple_grid_front[x + R_WIDTH*y_p]; | |
neighbours = neighbours + ripple_grid_front[x + R_WIDTH*y_n]; | |
neighbours = neighbours / 2; | |
*gridcell = (neighbours > *gridcell) ? neighbours - *gridcell : 0; | |
// Decay value | |
*gridcell = *gridcell - (*gridcell >> R_PERSISTENCE); | |
} | |
} | |
// Swap buffers | |
uint16_t* temp = ripple_grid_front; | |
ripple_grid_front = ripple_grid_back; | |
ripple_grid_back = temp; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment