mirror of
https://github.com/mon/PocketVoltex.git
synced 2026-09-27 09:23:12 +03:00
Knob lights are now gorgeous
This commit is contained in:
@@ -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),
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user