RGB Refactor Cleanup, turbocharger mode from 4yn

This commit is contained in:
Nicholas Gadjali
2022-07-04 02:44:12 -07:00
parent 5e33a3d3a5
commit c6567d0b9b
7 changed files with 183 additions and 49 deletions
Binary file not shown.
+1 -1
View File
@@ -6,7 +6,7 @@
#define ENC_GPIO_SIZE 2 // Number of encoders
#define ENC_PPR 600 // Encoder PPR
#define MOUSE_SENS 1 // Mouse sensitivity multiplier
#define ENC_DEBOUNCE true // Encoder Debouncing
#define ENC_DEBOUNCE false // Encoder Debouncing
#define SW_DEBOUNCE_TIME_US 4000 // Switch debounce delay in us
#define ENC_PULSE (ENC_PPR * 4) // 4 pulses per PPR
#define REACTIVE_TIMEOUT_MAX 1000000 // HID to reactive timeout in us
+11 -48
View File
@@ -17,9 +17,9 @@
#include "hardware/pio.h"
#include "pico/multicore.h"
#include "pico/stdlib.h"
#include "rgb/rgb_include.h"
#include "tusb.h"
#include "usb_descriptors.h"
#include "ws2812.pio.h"
PIO pio, pio_1;
uint32_t enc_val[ENC_GPIO_SIZE];
@@ -33,13 +33,10 @@ bool kbm_report;
uint64_t reactive_timeout_timestamp;
void (*ws2812b_mode)();
void (*loop_mode)();
bool joy_mode_check = true;
typedef struct {
uint8_t r, g, b;
} RGB_t;
union {
struct {
uint8_t buttons[LED_GPIO_SIZE];
@@ -48,54 +45,13 @@ union {
uint8_t raw[LED_GPIO_SIZE + WS2812B_LED_ZONES * 3];
} lights_report;
/**
* WS2812B RGB Assignment
* @param pixel_grb The pixel color to set
**/
static inline void put_pixel(uint32_t pixel_grb) {
pio_sm_put_blocking(pio1, ENC_GPIO_SIZE, pixel_grb << 8u);
}
/**
* WS2812B RGB Format Helper
**/
static inline uint32_t urgb_u32(uint8_t r, uint8_t g, uint8_t b) {
return ((uint32_t)(r) << 8) | ((uint32_t)(g) << 16) | (uint32_t)(b);
}
/**
* 768 Color Wheel Picker
* @param wheel_pos Color value, r->g->b->r...
**/
uint32_t color_wheel(uint16_t wheel_pos) {
wheel_pos %= 768;
if (wheel_pos < 256) {
return urgb_u32(wheel_pos, 255 - wheel_pos, 0);
} else if (wheel_pos < 512) {
wheel_pos -= 256;
return urgb_u32(255 - wheel_pos, 0, wheel_pos);
} else {
wheel_pos -= 512;
return urgb_u32(0, wheel_pos, 255 - wheel_pos);
}
}
/**
* Color cycle effect
**/
void ws2812b_color_cycle(uint32_t counter) {
for (int i = 0; i < WS2812B_LED_SIZE; ++i) {
put_pixel(color_wheel((counter + i * (int)(768 / WS2812B_LED_SIZE)) % 768));
}
}
/**
* WS2812B Lighting
* @param counter Current number of WS2812B cycles
**/
void ws2812b_update(uint32_t counter) {
if (time_us_64() - reactive_timeout_timestamp >= REACTIVE_TIMEOUT_MAX) {
ws2812b_color_cycle(counter);
ws2812b_mode(counter);
} else {
for (int i = 0; i < WS2812B_LED_ZONES; i++) {
for (int j = 0; j < WS2812B_LEDS_PER_ZONE; j++) {
@@ -275,7 +231,7 @@ void init() {
channel_config_set_dreq(&c, pio_get_dreq(pio, i, false));
dma_channel_configure(i, &c,
&enc_val[i], // Destinatinon pointer
&enc_val[i], // Destination pointer
&pio->rxf[i], // Source pointer
0x10, // Number of transfers
true // Start immediately
@@ -321,6 +277,13 @@ void init() {
joy_mode_check = true;
}
// RGB Mode Switching
if (!gpio_get(SW_GPIO[1])) {
ws2812b_mode = &turbocharger_color_cycle;
} else {
ws2812b_mode = &ws2812b_color_cycle;
}
// Disable RGB
if (gpio_get(SW_GPIO[8])) {
multicore_launch_core1(core1_entry);
+9
View File
@@ -0,0 +1,9 @@
/**
* Color cycle effect
* @author SpeedyPotato
**/
void ws2812b_color_cycle(uint32_t counter) {
for (int i = 0; i < WS2812B_LED_SIZE; ++i) {
put_pixel(color_wheel((counter + i * (int)(768 / WS2812B_LED_SIZE)) % 768));
}
}
+10
View File
@@ -0,0 +1,10 @@
/**
* Simple header file to include all files in the folder
* @author SpeedyPotato
*
* To add a lighting mode, create a function which accepts a uint32_t as a parameter.
* Create lighting mode as desired and then add the #include here.
**/
#include "ws2812b_util.c"
#include "color_cycle.c"
#include "turbocharger.c"
+111
View File
@@ -0,0 +1,111 @@
/**
* @author 4yn, SpeedyPotato
* Turbocharger chasing laser effect
*
* Move 2 lighting areas around the controller depending on knob input.
*
* For each knob, calculate every 5 ms:
* - Add any knob delta to a counter
* - Clamp counter to some "maximum speed"
* - If counter is far enough from 0, knob is moving
* - If counter is too near 0 and has been there for a while, fade out
* - Move the lighting area in the correct direction at a constant speed
* - Decay the counter
*
* Curent values are tuned for
* - Lights sampled at 200 Hz
* - 0.1 rotations for lights to activate
* - Lighting areas take 0.75s to make one full rotation
* - Movement takes 0.5s to decay to stop
* - Fade out takes another 0.2s samples to disappear
*
* LEDs are positioned as:
* - 0, 1 as dummy leds on top of controller
* - 2-6 LEDs on right edge, top to bottom
* - 7-9 as dummy leds on bottom of controller
* - 10-14 LEDs on left edge, bottom to top
* - 15 as dummy led on top of controller
*
* Lighting areas start at position 0 and will light up the 3 nearest LEDs.
* By strategically positioning led 0 at the top, this avoids lighting areas
* from suddenly appeaering.
**/
extern uint32_t enc_val[ENC_GPIO_SIZE];
#define TURBO_LIGHTS_CLAMP 0.1f
#define TURBO_LIGHTS_THRESHOLD 0.05f
#define TURBO_LIGHTS_DECAY 0.0005f
#define TURBO_LIGHTS_VEL 0.12f
#define TURBO_LIGHTS_MAX (WS2812B_LED_SIZE + 6.0f)
#define TURBO_LIGHTS_FADE 40
#define TURBO_LIGHTS_FADE_VEL 0.025f
int i_clamp(int d, int min, int max) {
const int t = d < min ? min : d;
return t > max ? max : t;
}
float f_clamp(float d, float min, float max) {
const float t = d < min ? min : d;
return t > max ? max : t;
}
float f_one_mod(float d, float mod) {
const float t = d < 0 ? d + mod : d;
return t > mod ? t - mod : t;
}
float f_abs(float d) {
return d < 0 ? -d : d;
}
uint32_t turbo_prev_enc_val[ENC_GPIO_SIZE];
float turbo_cur_enc_val[ENC_GPIO_SIZE];
float turbo_lights_pos[ENC_GPIO_SIZE];
float turbo_lights_brightness[ENC_GPIO_SIZE];
int turbo_lights_idle[ENC_GPIO_SIZE];
void turbocharger_color_cycle(uint32_t unused) {
for (int i = 0; i < ENC_GPIO_SIZE; i++) {
int enc_delta = (enc_val[i] - turbo_prev_enc_val[i]) * (ENC_REV[i] ? 1 : -1);
turbo_prev_enc_val[i] = enc_val[i];
turbo_cur_enc_val[i] = f_clamp(turbo_cur_enc_val[i] + (float)(enc_delta) / ENC_PULSE, -TURBO_LIGHTS_CLAMP, TURBO_LIGHTS_CLAMP);
if (turbo_cur_enc_val[i] < -TURBO_LIGHTS_THRESHOLD) {
turbo_lights_idle[i] = 0;
turbo_lights_pos[i] += TURBO_LIGHTS_VEL;
turbo_lights_brightness[i] = 1.0f;
} else if (turbo_cur_enc_val[i] > TURBO_LIGHTS_THRESHOLD) {
turbo_lights_idle[i] = 0;
turbo_lights_pos[i] -= TURBO_LIGHTS_VEL;
turbo_lights_brightness[i] = 1.0f;
} else {
turbo_lights_idle[i]++;
if (turbo_lights_idle[i] > TURBO_LIGHTS_FADE) {
turbo_lights_pos[i] = 0;
} else {
turbo_lights_brightness[i] = f_clamp(turbo_lights_brightness[i] - TURBO_LIGHTS_FADE_VEL, 0.0f, 1.0f);
}
}
turbo_lights_pos[i] = f_one_mod(turbo_lights_pos[i], TURBO_LIGHTS_MAX);
if (turbo_cur_enc_val[i] < -TURBO_LIGHTS_DECAY) {
turbo_cur_enc_val[i] += TURBO_LIGHTS_DECAY;
} else if (turbo_cur_enc_val[i] > TURBO_LIGHTS_DECAY) {
turbo_cur_enc_val[i] -= TURBO_LIGHTS_DECAY;
}
}
for (int i = 0; i < WS2812B_LED_SIZE; i++) {
float pos = 2.0f + i + (i >= WS2812B_LED_SIZE / 2 ? 3.0f : 0.0f);
float l_strength = (1.0f - f_clamp(f_abs(turbo_lights_pos[0] - pos), 0.0f, 2.0f) / 2) * turbo_lights_brightness[0];
float r_strength = (1.0f - f_clamp(f_abs(turbo_lights_pos[1] - pos), 0.0f, 2.0f) / 2) * turbo_lights_brightness[1];
put_pixel(urgb_u32(
i_clamp(l_strength * 70 + r_strength * 250, 0, 255),
i_clamp(l_strength * 230 + r_strength * 60, 0, 255),
i_clamp(l_strength * 250 + r_strength * 200, 0, 255)
));
}
}
+41
View File
@@ -0,0 +1,41 @@
/*
* ws2812b utility class
* @author SpeedyPotato
*/
#include "ws2812.pio.h"
typedef struct {
uint8_t r, g, b;
} RGB_t;
/**
* WS2812B RGB Format Helper
**/
static inline uint32_t urgb_u32(uint8_t r, uint8_t g, uint8_t b) {
return ((uint32_t)(r) << 8) | ((uint32_t)(g) << 16) | (uint32_t)(b);
}
/**
* 768 Color Wheel Picker
* @param wheel_pos Color value, r->g->b->r...
**/
static inline uint32_t color_wheel(uint16_t wheel_pos) {
wheel_pos %= 768;
if (wheel_pos < 256) {
return urgb_u32(wheel_pos, 255 - wheel_pos, 0);
} else if (wheel_pos < 512) {
wheel_pos -= 256;
return urgb_u32(255 - wheel_pos, 0, wheel_pos);
} else {
wheel_pos -= 512;
return urgb_u32(0, wheel_pos, 255 - wheel_pos);
}
}
/**
* WS2812B RGB Assignment
* @param pixel_grb The pixel color to set
**/
static inline void put_pixel(uint32_t pixel_grb) {
pio_sm_put_blocking(pio1, ENC_GPIO_SIZE, pixel_grb << 8u);
}