From 3df59dd1f1eabcf43c24d628f693211155d3456c Mon Sep 17 00:00:00 2001 From: William Toohey Date: Fri, 17 Feb 2017 16:03:33 +1000 Subject: [PATCH] Breathe mode, LED cleanup and brightness levels increase --- Firmware/PocketVoltex/Config.c | 6 ++- Firmware/PocketVoltex/Config.h | 8 ++-- Firmware/PocketVoltex/LED.c | 57 +++++++++++++++++------- Firmware/PocketVoltex/LED.h | 12 +++-- Firmware/PocketVoltex/LEDPatterns.c | 69 ++++++++++++++++++----------- Firmware/PocketVoltex/LEDPatterns.h | 22 +++++---- 6 files changed, 113 insertions(+), 61 deletions(-) diff --git a/Firmware/PocketVoltex/Config.c b/Firmware/PocketVoltex/Config.c index 5598b27..2259150 100644 --- a/Firmware/PocketVoltex/Config.c +++ b/Firmware/PocketVoltex/Config.c @@ -1,8 +1,9 @@ -#include - #include #include +#include "Config.h" +#include "Macro.h" + #define MAGIC_NUMBER 42 uint8_t firstRun EEMEM; // init to 255 @@ -22,6 +23,7 @@ static const PROGMEM sdvx_config_t defaults = { HID_KEYBOARD_SC_KEYPAD_PLUS}, // macro .btColour = {BRIGHTNESS_MAX, BRIGHTNESS_MAX, BRIGHTNESS_MAX}, // white .fxColour = {BRIGHTNESS_MAX, BRIGHTNESS_MAX/4, 0}, // orange + .breatheColour = {BRIGHTNESS_MAX/2, BRIGHTNESS_MAX/8, 0}, // dim orange .knobColours = { {0,BRIGHTNESS_MAX,BRIGHTNESS_MAX}, // aqua {BRIGHTNESS_MAX,0,BRIGHTNESS_MAX} // pink diff --git a/Firmware/PocketVoltex/Config.h b/Firmware/PocketVoltex/Config.h index 5c7d68e..37641b1 100644 --- a/Firmware/PocketVoltex/Config.h +++ b/Firmware/PocketVoltex/Config.h @@ -4,14 +4,14 @@ #include #include #include -#include "LED.h" +#include "LEDPatterns.h" // 7 gameplay switches + macro combo switch #define SWITCH_COUNT 8 #define JOYSTICK_PPR (24 * 4) #define MAGIC_RESET_NUMBER 42 // divide by 10 for actual version -#define FIRMWARE_VERSION 1 +#define FIRMWARE_VERSION 10 // not configurable since they're all the same switches #define SWITCH_DEBOUNCE 30 @@ -21,6 +21,7 @@ typedef struct { uint8_t switches[SWITCH_COUNT]; RGB_t btColour; RGB_t fxColour; + RGB_t breatheColour; RGB_t knobColours[2]; uint8_t lightsOn; uint8_t hidLights; @@ -37,13 +38,14 @@ typedef struct { #define CONFIG_BYTES sizeof(sdvx_config_t) typedef struct { - uint8_t version; + uint16_t version; uint16_t serial; } version_t; typedef enum { GETCONFIG = 1, SETCONFIG = 2, + VERSION = 3, RESET = MAGIC_RESET_NUMBER } command_action_t; diff --git a/Firmware/PocketVoltex/LED.c b/Firmware/PocketVoltex/LED.c index 1eb70b4..cb638d0 100644 --- a/Firmware/PocketVoltex/LED.c +++ b/Firmware/PocketVoltex/LED.c @@ -69,20 +69,6 @@ void led_set(uint8_t num, uint8_t r, uint8_t g, uint8_t b) { leds[offset+B] = b; } -void led_set_rgb(uint8_t num, RGB_t* colour) { - led_set(num, colour->r, colour->g, colour->b); -} - -void led_set_max(uint8_t num, uint8_t r, uint8_t g, uint8_t b) { - uint8_t offset = num * 3; - if(r > leds[offset+R]) - leds[offset+R] = r; - if(g > leds[offset+G]) - leds[offset+G] = g; - if(b > leds[offset+B]) - leds[offset+B] = b; -} - // Applies a crossfade between the current colour and an overlay colour with a given strength void led_fade_over(uint8_t num, uint8_t r, uint8_t g, uint8_t b, uint8_t strength) { uint8_t offset = num * 3; @@ -110,8 +96,31 @@ void led_fade_over(uint8_t num, uint8_t r, uint8_t g, uint8_t b, uint8_t strengt } } -void led_fade_over_rgb(uint8_t num, RGB_t* colour, uint8_t strength) { - led_fade_over(num, colour->r, colour->g, colour->b, strength); +// goes from a setpoint of 0 instead +void led_fade_all(uint8_t r, uint8_t g, uint8_t b, uint8_t strength) { + // going outside max val for a signed int8 + int16_t scales[3]; + // colour distances from setpoint of 0 + scales[R] = r; + scales[G] = g; + scales[B] = b; + for(uint8_t i = 0; i < 3; i++) { + // perform scaling with div0 check + if(scales[i] == 0) { + scales[i] = BRIGHTNESS_LEVELS; + } else { + // won't ever be 0, don't check later + scales[i] = BRIGHTNESS_LEVELS / scales[i]; + } + int16_t new = strength/scales[i]; + // Integer division strikes again + if(new > BRIGHTNESS_MAX) + new = BRIGHTNESS_MAX; + if(new < 0) + new = 0; + scales[i] = new; + } + led_set_all(scales[0], scales[1], scales[2]); } void led_set_all(uint8_t r, uint8_t g, uint8_t b) { @@ -124,6 +133,22 @@ void led_set_indiv(uint8_t num, uint8_t val) { leds[num] = val; } +void led_set_rgb(uint8_t num, RGB_t* colour) { + led_set(num, colour->r, colour->g, colour->b); +} + +void led_fade_over_rgb(uint8_t num, RGB_t* colour, uint8_t strength) { + led_fade_over(num, colour->r, colour->g, colour->b, strength); +} + +void led_fade_all_rgb(RGB_t* colour, uint8_t strength) { + led_fade_all(colour->r, colour->g, colour->b, strength); +} + +void led_set_all_rgb(RGB_t* colour) { + led_set_all(colour->r, colour->g, colour->b); +} + /* Straight voodoo magic, consult the Inline Assembler Cookbook Equivalent to: if(*led++ > brightness) diff --git a/Firmware/PocketVoltex/LED.h b/Firmware/PocketVoltex/LED.h index 16e8668..c3c700e 100644 --- a/Firmware/PocketVoltex/LED.h +++ b/Firmware/PocketVoltex/LED.h @@ -17,7 +17,7 @@ #define BRIGHTNESS_MAX (BRIGHTNESS_LEVELS-1) // How many are actually PWM'd, because the chip isn't that quick // MUST be a multiple of BRIGHTNESS_LEVELS -#define BRIGHTNESS_DOWNSCALE 64 +#define BRIGHTNESS_DOWNSCALE 128 typedef struct { uint8_t r, g, b; @@ -39,13 +39,17 @@ static const PROGMEM uint8_t ledRightCircleMap[] = {7, 5, 3, 1}; void led_init(void); void led_commit(void); void led_set(uint8_t num, uint8_t r, uint8_t g, uint8_t b); -void led_set_rgb(uint8_t num, RGB_t* colour); -void led_set_max(uint8_t num, uint8_t r, uint8_t g, uint8_t b); void led_fade_over(uint8_t num, uint8_t r, uint8_t g, uint8_t b, uint8_t strength); -void led_fade_over_rgb(uint8_t num, RGB_t* colour, uint8_t strength); +void led_fade_all(uint8_t r, uint8_t g, uint8_t b, uint8_t strength); void led_set_all(uint8_t r, uint8_t g, uint8_t b); void led_set_indiv(uint8_t num, uint8_t val); +void led_set_rgb(uint8_t num, RGB_t* colour); +void led_fade_over_rgb(uint8_t num, RGB_t* colour, uint8_t strength); +void led_fade_all_rgb(RGB_t* colour, uint8_t strength); +void led_set_all_rgb(RGB_t* colour); + + // http://electronics.stackexchange.com/a/11100/95969 PROGMEM const static uint8_t ledLogCurve[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, diff --git a/Firmware/PocketVoltex/LEDPatterns.c b/Firmware/PocketVoltex/LEDPatterns.c index dbd7143..a1b83cd 100644 --- a/Firmware/PocketVoltex/LEDPatterns.c +++ b/Firmware/PocketVoltex/LEDPatterns.c @@ -16,15 +16,17 @@ typedef union { struct { uint8_t level; int8_t dir; + RGB_t colour; } flash; - - RGB_t singleColour; - + struct { uint8_t level; + uint8_t dir; RGB_t colour; } breathe; + RGB_t singleColour; + RGBFader followers[LED_COUNT]; } Patterns_t; @@ -49,6 +51,7 @@ static KnobLights knobs[2] = { }; void led_knob_light_indiv(KnobLights* knob, RGB_t* colour, const uint8_t* map); +void led_update_breather(uint8_t speed); uint8_t led_on_frame(void) { if(++frameCounter >= LED_MS_PER_FRAME) { @@ -63,29 +66,11 @@ uint8_t led_on_frame(void) { void led_animate(void) { switch(animMode) { case INIT_FLASH: - if(pattern.flash.dir) { - if(pattern.flash.level >= BRIGHTNESS_LEVELS - FLASH_SPEED) { - pattern.flash.level = BRIGHTNESS_MAX; - pattern.flash.dir = 0; - } else { - pattern.flash.level += FLASH_SPEED; - } - } else { - if(pattern.flash.level <= FLASH_SPEED) { - pattern.flash.level = 0; - led_set_all(0,0,0); - led_anim_follower(); - break; - } else { - pattern.flash.level -= FLASH_SPEED; - } + led_update_breather(FLASH_SPEED); + if(pattern.flash.level == 0) { + led_anim_breathe(); + break; } - - uint8_t bright = pgm_read_byte(&ledLogCurve[pattern.flash.level]); - // yellowy orange - //led_set_all(bright, bright/2, 0); - // I think white looks nicer - led_set_all(bright, bright, bright); break; case FOLLOWER: for(uint8_t led = 0; led < LED_COUNT; led++) { @@ -115,6 +100,8 @@ void led_animate(void) { } break; case BREATHE: + led_update_breather(BREATHE_SPEED); + break; default: break; } @@ -198,12 +185,40 @@ void led_knobs_update(int8_t left, int8_t right) { led_knob_indiv(&knobs[1], right*2); } +void led_update_breather(uint8_t speed) { + if(pattern.flash.dir) { + if(pattern.flash.level >= BRIGHTNESS_LEVELS - speed) { + pattern.flash.level = BRIGHTNESS_MAX; + pattern.flash.dir = 0; + } else { + pattern.flash.level += speed; + } + } else { + if(pattern.flash.level <= speed) { + pattern.flash.level = 0; + pattern.flash.dir = 1; + } else { + pattern.flash.level -= speed; + } + } + + uint8_t bright = pattern.flash.level; + //uint8_t bright = pgm_read_byte(&ledLogCurve[pattern.flash.level]); + led_fade_all_rgb(&pattern.flash.colour, bright); +} + void led_anim_flash(void) { animMode = INIT_FLASH; - // starting at 2 stops us getting a frame of red if you're not doing white flash - //pattern.flash.level = 2; pattern.flash.level = 0; pattern.flash.dir = 1; + pattern.flash.colour = (RGB_t){BRIGHTNESS_MAX, BRIGHTNESS_MAX, BRIGHTNESS_MAX}; +} + +void led_anim_breathe(void) { + animMode = BREATHE; + pattern.flash.level = 0; + pattern.flash.dir = 1; + pattern.flash.colour = sdvxConfig.breatheColour; } void led_anim_follower(void) { diff --git a/Firmware/PocketVoltex/LEDPatterns.h b/Firmware/PocketVoltex/LEDPatterns.h index d29c560..7420728 100644 --- a/Firmware/PocketVoltex/LEDPatterns.h +++ b/Firmware/PocketVoltex/LEDPatterns.h @@ -1,8 +1,18 @@ #ifndef _LED_PATTERNS_H #define _LED_PATTERNS_H +// circular dependency with Config.h requires this to be here +enum LEDMode { + NONE = 0, + INIT_FLASH = 1, + SINGLE_COLOUR = 2, + FOLLOWER = 3, + BREATHE = 4, +}; + #include #include "LED.h" +#include "Config.h" #define LED_FRAMERATE 30 #define LED_MS_PER_FRAME (1000 / LED_FRAMERATE) @@ -10,23 +20,17 @@ // brightness levels per frame #define FLASH_SPEED (BRIGHTNESS_LEVELS/21) #define FOLLOW_SPEED (BRIGHTNESS_LEVELS/64) +#define BREATHE_SPEED (BRIGHTNESS_LEVELS/64) + #define LED_KNOB_SPEED (BRIGHTNESS_LEVELS/42) #define LED_KNOB_HOLD 300 #define LED_KNOB_FADE (BRIGHTNESS_LEVELS/128) #define LED_KNOB_SENSITIVITY 5 - -enum LEDMode { - NONE = 0, - INIT_FLASH, - SINGLE_COLOUR, - FOLLOWER, - BREATHE, -}; - uint8_t led_on_frame(void); void led_animate(void); void led_anim_flash(void); +void led_anim_breathe(void); void led_anim_follower(void); void led_knob_lights(void); void led_knobs_update(int8_t left, int8_t right);