From 61cd76dca7b955dec40d9b13013b71d5ebe875f9 Mon Sep 17 00:00:00 2001 From: William Toohey Date: Fri, 10 Feb 2017 20:37:21 +1000 Subject: [PATCH] Knob lights are now gorgeous --- Firmware/PocketVoltex/Descriptors.c | 7 +--- Firmware/PocketVoltex/LED.c | 6 +++- Firmware/PocketVoltex/LED.h | 2 +- Firmware/PocketVoltex/LEDPatterns.c | 53 +++++++++++++++++++++++----- Firmware/PocketVoltex/LEDPatterns.h | 13 ++++--- Firmware/PocketVoltex/PocketVoltex.c | 20 ++++++----- Software/HidLights.au3 | 2 +- 7 files changed, 72 insertions(+), 31 deletions(-) diff --git a/Firmware/PocketVoltex/Descriptors.c b/Firmware/PocketVoltex/Descriptors.c index e850225..96b70d9 100644 --- a/Firmware/PocketVoltex/Descriptors.c +++ b/Firmware/PocketVoltex/Descriptors.c @@ -25,12 +25,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM LEDReport[] = // at least 1 INPUT is also needed to be recognised by Bemanitools HID_RI_USAGE_MINIMUM(8, 1), HID_RI_USAGE_MAXIMUM(8, 1), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), - //0x79, STRING_ID_LED_Indiv, //HID_RI_STRING_MINIMUM(8, STRING_ID_LED_Indiv), - //0x89, STRING_ID_LED_Indiv + LED_TOTAL_COUNT, //HID_RI_STRING_MAXIMUM(8, STRING_ID_LED_Indiv + LED_COUNT), - //HID_RI_USAGE_MINIMUM(8, 1), // LED 1 - //HID_RI_USAGE_MAXIMUM(8, LED_TOTAL_COUNT), // LED 8 + buttons - //HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), + HID_RI_INPUT(8, HID_IOF_CONSTANT), HID_RI_END_COLLECTION(0), }; diff --git a/Firmware/PocketVoltex/LED.c b/Firmware/PocketVoltex/LED.c index 306ba8e..ee6781a 100644 --- a/Firmware/PocketVoltex/LED.c +++ b/Firmware/PocketVoltex/LED.c @@ -19,7 +19,7 @@ #define UPDATE_HZ 100 // prescaler is the div8 -#define TIMER_COMPARE ((F_CPU / 8 / UPDATE_HZ / GND_COUNT / BRIGHTNESS_LEVELS)-1) +#define TIMER_COMPARE ((F_CPU / 8 / UPDATE_HZ / GND_COUNT / BRIGHTNESS_DOWNSCALE)-1) #if TIMER_COMPARE > 255 #error timer compare too large for timer register #endif @@ -158,6 +158,10 @@ ISR(TIMER0_COMPA_vect) { offset = &leds_frontbuffer[0]; brightness += BRIGHTNESS_INCREMENT; // brightness rolls over cleanly due to being a multiple + #if BRIGHTNESS_LEVELS != 256 + if(brightness > BRIGHTNESS_MAX) + brightness = 0; + #endif } // Faster than loops diff --git a/Firmware/PocketVoltex/LED.h b/Firmware/PocketVoltex/LED.h index 8f323a9..21bf877 100644 --- a/Firmware/PocketVoltex/LED.h +++ b/Firmware/PocketVoltex/LED.h @@ -13,7 +13,7 @@ #define LED_VIRTUAL_COUNT 6 #define LED_TOTAL_COUNT (LED_PHYSICAL_COUNT + LED_VIRTUAL_COUNT) // Internally how many brightness levels you can use - for higher res fades -#define BRIGHTNESS_LEVELS 256 +#define BRIGHTNESS_LEVELS 128 #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 diff --git a/Firmware/PocketVoltex/LEDPatterns.c b/Firmware/PocketVoltex/LEDPatterns.c index 4592015..a371338 100644 --- a/Firmware/PocketVoltex/LEDPatterns.c +++ b/Firmware/PocketVoltex/LEDPatterns.c @@ -36,26 +36,32 @@ typedef struct { const uint8_t rgb[3]; uint8_t leds[2]; uint8_t levels[2]; + uint16_t fadeTimer; + uint8_t fadeOut; + int8_t fadeBuffer; } KnobLights; // OPTIONS SHOULD BE: blue, pink, green, yellow static KnobLights knobs[2] = { // Aqua, mid left LEDs - {{0,BRIGHTNESS_MAX,BRIGHTNESS_MAX}, {2,3}, {BRIGHTNESS_LEVELS/2, BRIGHTNESS_LEVELS/2}}, + {{0,BRIGHTNESS_MAX,BRIGHTNESS_MAX}, {2,3}, {BRIGHTNESS_MAX, 0}}, // Pink, mid right LEDs - {{BRIGHTNESS_MAX,0,BRIGHTNESS_MAX}, {0,1}, {BRIGHTNESS_LEVELS/2, BRIGHTNESS_LEVELS/2}} + {{BRIGHTNESS_MAX,0,BRIGHTNESS_MAX}, {0,1}, {0, BRIGHTNESS_MAX}} }; void led_knob_light_indiv(KnobLights* knob, const uint8_t* map); uint8_t led_on_frame(void) { - return ++frameCounter >= LED_MS_PER_FRAME; + if(++frameCounter >= LED_MS_PER_FRAME) { + frameCounter = 0; + return 1; + } else { + return 0; + } } // Called every 1ms void led_animate(void) { - frameCounter = 0; - switch(animMode) { case INIT_FLASH: if(pattern.flash.dir) { @@ -70,6 +76,7 @@ void led_animate(void) { pattern.flash.level = 0; led_set_all(0,0,0); led_anim_follower(); + break; } else { pattern.flash.level -= FLASH_SPEED; } @@ -112,24 +119,54 @@ void led_animate(void) { default: break; } - +} + +void led_knob_lights(void) { led_knob_light_indiv(&knobs[0], ledLeftCircleMap); led_knob_light_indiv(&knobs[1], ledRightCircleMap); } void led_knob_light_indiv(KnobLights* knob, const uint8_t* map) { + if(knob->fadeOut >= BRIGHTNESS_MAX) { + return; + } for(uint8_t led = 0; led < 2; led++) { uint8_t r = knob->rgb[0]; uint8_t g = knob->rgb[1]; uint8_t b = knob->rgb[2]; + uint8_t power = knob->levels[led]; + if(knob->fadeOut > power) { + power = 0; + } else { + power -= knob->fadeOut; + } //led_set_max(ledCircleMap[knobs[i].leds[led]], r, g, b); - led_fade_over(pgm_read_byte(&map[knob->leds[led]]), r, g, b, knob->levels[led]); + led_fade_over(pgm_read_byte(&map[knob->leds[led]]), r, g, b, power); } } void led_knob_indiv(KnobLights* knob, int8_t value) { - if(value == 0) + if(value == 0) { + // hold before fadeout + if(knob->fadeTimer > 0) { + knob->fadeTimer--; + if(knob->fadeTimer == 0) + knob->fadeBuffer = 0; + // actually fade out + } else if(knob->fadeOut < BRIGHTNESS_MAX - LED_KNOB_FADE) { + knob->fadeOut += LED_KNOB_FADE; + // completely faded + } else { + knob->fadeOut = BRIGHTNESS_MAX; + } return; + } + knob->fadeBuffer += value; + // bumped it enough to reenable lights, or the timeout has yet to occur + if(knob->fadeTimer || knob->fadeBuffer > LED_KNOB_SENSITIVITY || knob->fadeBuffer < -LED_KNOB_SENSITIVITY) { + knob->fadeTimer = LED_KNOB_HOLD; + knob->fadeOut = 0; + } /* This is annoying and repetitive but don't think there's a nicer way */ value *= LED_KNOB_SPEED; if(value > 0) { diff --git a/Firmware/PocketVoltex/LEDPatterns.h b/Firmware/PocketVoltex/LEDPatterns.h index 820082a..d19d3af 100644 --- a/Firmware/PocketVoltex/LEDPatterns.h +++ b/Firmware/PocketVoltex/LEDPatterns.h @@ -8,11 +8,13 @@ #define LED_MS_PER_FRAME (1000 / LED_FRAMERATE) // brightness levels per frame -#define FLASH_SPEED 12 -#define FOLLOW_SPEED 4 -#define LED_KNOB_SPEED 4 -#define LED_KNOB_HOLD 200 -#define LED_KNOB_FADE 12 +#define FLASH_SPEED (BRIGHTNESS_LEVELS/21) +#define FOLLOW_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 3 + enum LEDMode { NONE = 0, @@ -26,6 +28,7 @@ uint8_t led_on_frame(void); void led_animate(void); void led_anim_flash(void); void led_anim_follower(void); +void led_knob_lights(void); void led_knobs_update(int8_t left, int8_t right); #endif \ No newline at end of file diff --git a/Firmware/PocketVoltex/PocketVoltex.c b/Firmware/PocketVoltex/PocketVoltex.c index ff656e4..062b836 100644 --- a/Firmware/PocketVoltex/PocketVoltex.c +++ b/Firmware/PocketVoltex/PocketVoltex.c @@ -18,7 +18,7 @@ #define BOOTLOADER_START_ADDRESS (0x1c00 * 2) // How long to wait before moving to internal lighting -#define HID_LED_TIMEOUT 5000 +#define HID_LED_TIMEOUT 2000 typedef struct { @@ -185,7 +185,9 @@ int main(void) if(updateLEDs) { updateLEDs = 0; - led_animate(); + if(hidTimeout >= HID_LED_TIMEOUT) + led_animate(); + led_knob_lights(); led_commit(); } } @@ -378,16 +380,16 @@ void EVENT_USB_Device_StartOfFrame(void) HID_Device_MillisecondElapsed(&Inputs_HID_Interface); HID_Device_MillisecondElapsed(&LED_HID_Interface); - if(hidTimeout > HID_LED_TIMEOUT) { - // we use a sentinel since this is actually inside an interrupt! - // less LED flicker if ran outside - if(led_on_frame()) { - updateLEDs = 1; - } - } else { + if(hidTimeout < HID_LED_TIMEOUT) { hidTimeout++; } + // we use a sentinel since this is actually inside an interrupt! + // less LED flicker if ran outside + if(led_on_frame()) { + updateLEDs = 1; + } + macro_on_frame(&switches[SWITCH_COUNT-1]); for(int i = 0; i < SWITCH_COUNT; i++) { diff --git a/Software/HidLights.au3 b/Software/HidLights.au3 index 6c664c4..dc27b85 100644 --- a/Software/HidLights.au3 +++ b/Software/HidLights.au3 @@ -13,7 +13,7 @@ Local $lights[8] = [ _ "Woofer", "Woofer", "Controller", "Controller" _ ] -Local $colours[3] = ["B", "G", "R"] +Local $colours[3] = ["R", "G", "B"] Local $bt[6] = ["Button A", "Button B", "Button C", "Button D", "FX-L", "FX-R"] WinWait("BemaniPC Input Configuration")