diff --git a/headers/addons/neopicoleds.h b/headers/addons/neopicoleds.h index 0bffaa7e8..0092efc79 100644 --- a/headers/addons/neopicoleds.h +++ b/headers/addons/neopicoleds.h @@ -199,6 +199,7 @@ class NeoPicoLEDAddon : public GPAddon { AnimationStation as; std::map buttonPositions; bool turnOffWhenSuspended; + PLEDType ledType; }; #endif diff --git a/headers/addons/turbo.h b/headers/addons/turbo.h index b0dc258e6..3909d25e8 100644 --- a/headers/addons/turbo.h +++ b/headers/addons/turbo.h @@ -22,6 +22,18 @@ #define TURBO_LED_PIN -1 #endif +#ifndef TURBO_LED_INDEX +#define TURBO_LED_INDEX -1 +#endif + +#ifndef TURBO_LED_TYPE +#define TURBO_LED_TYPE PLED_TYPE_NONE +#endif + +#ifndef TURBO_LED_COLOR +#define TURBO_LED_COLOR ColorRed +#endif + // TURBO SHMUP MODE #ifndef TURBO_SHMUP_MODE #define TURBO_SHMUP_MODE 0 diff --git a/headers/gamepad/GamepadAuxState.h b/headers/gamepad/GamepadAuxState.h index d6e34fb67..8daf75436 100644 --- a/headers/gamepad/GamepadAuxState.h +++ b/headers/gamepad/GamepadAuxState.h @@ -110,6 +110,13 @@ struct GamepadAuxHapticChannel uint16_t intensity = 0; }; +struct GamepadAuxTurbo +{ + bool enabled = false; + bool active = false; + uint8_t activity = 0; +}; + struct GamepadAuxSensors { GamepadAux3DRelativeSensor mouse; @@ -142,4 +149,6 @@ struct GamepadAuxState GamepadAuxSensors sensors; GamepadAuxHaptics haptics; + + GamepadAuxTurbo turbo; }; diff --git a/proto/config.proto b/proto/config.proto index b081f01ce..851eda73b 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -397,6 +397,10 @@ message TurboOptions optional uint32 shmupBtnMask3 = 17; optional uint32 shmupBtnMask4 = 18; optional ShmupMixMode shmupMixMode = 19; + + optional PLEDType turboLedType = 20; + optional int32 turboLedIndex = 21; + optional uint32 turboLedColor = 22; } message SliderOptions diff --git a/src/addons/neopicoleds.cpp b/src/addons/neopicoleds.cpp index 6571a05b7..2fc5fe5d0 100644 --- a/src/addons/neopicoleds.cpp +++ b/src/addons/neopicoleds.cpp @@ -42,324 +42,340 @@ uint32_t rgbPLEDValues[4]; // Move to Proto Enums typedef enum { - XINPUT_PLED_OFF = 0x00, // All off - XINPUT_PLED_BLINKALL = 0x01, // All blinking - XINPUT_PLED_FLASH1 = 0x02, // 1 flashes, then on - XINPUT_PLED_FLASH2 = 0x03, // 2 flashes, then on - XINPUT_PLED_FLASH3 = 0x04, // 3 flashes, then on - XINPUT_PLED_FLASH4 = 0x05, // 4 flashes, then on - XINPUT_PLED_ON1 = 0x06, // 1 on - XINPUT_PLED_ON2 = 0x07, // 2 on - XINPUT_PLED_ON3 = 0x08, // 3 on - XINPUT_PLED_ON4 = 0x09, // 4 on - XINPUT_PLED_ROTATE = 0x0A, // Rotating (e.g. 1-2-4-3) - XINPUT_PLED_BLINK = 0x0B, // Blinking* - XINPUT_PLED_SLOWBLINK = 0x0C, // Slow blinking* - XINPUT_PLED_ALTERNATE = 0x0D, // Alternating (e.g. 1+4-2+3), then back to previous* + XINPUT_PLED_OFF = 0x00, // All off + XINPUT_PLED_BLINKALL = 0x01, // All blinking + XINPUT_PLED_FLASH1 = 0x02, // 1 flashes, then on + XINPUT_PLED_FLASH2 = 0x03, // 2 flashes, then on + XINPUT_PLED_FLASH3 = 0x04, // 3 flashes, then on + XINPUT_PLED_FLASH4 = 0x05, // 4 flashes, then on + XINPUT_PLED_ON1 = 0x06, // 1 on + XINPUT_PLED_ON2 = 0x07, // 2 on + XINPUT_PLED_ON3 = 0x08, // 3 on + XINPUT_PLED_ON4 = 0x09, // 4 on + XINPUT_PLED_ROTATE = 0x0A, // Rotating (e.g. 1-2-4-3) + XINPUT_PLED_BLINK = 0x0B, // Blinking* + XINPUT_PLED_SLOWBLINK = 0x0C, // Slow blinking* + XINPUT_PLED_ALTERNATE = 0x0D, // Alternating (e.g. 1+4-2+3), then back to previous* } XInputPLEDPattern; // TODO: Make this a helper function // Animation Helper for Player LEDs PLEDAnimationState getXInputAnimationNEOPICO(uint16_t ledState) { - PLEDAnimationState animationState = - { - .state = 0, - .animation = PLED_ANIM_NONE, - .speed = PLED_SPEED_OFF, - }; - - switch (ledState) - { - case XINPUT_PLED_BLINKALL: - case XINPUT_PLED_ROTATE: - case XINPUT_PLED_BLINK: - case XINPUT_PLED_SLOWBLINK: - case XINPUT_PLED_ALTERNATE: - animationState.state = (PLED_STATE_LED1 | PLED_STATE_LED2 | PLED_STATE_LED3 | PLED_STATE_LED4); - animationState.animation = PLED_ANIM_BLINK; - animationState.speed = PLED_SPEED_FAST; - break; - - case XINPUT_PLED_FLASH1: - case XINPUT_PLED_ON1: - animationState.state = PLED_STATE_LED1; - animationState.animation = PLED_ANIM_SOLID; - animationState.speed = PLED_SPEED_OFF; - break; - - case XINPUT_PLED_FLASH2: - case XINPUT_PLED_ON2: - animationState.state = PLED_STATE_LED2; - animationState.animation = PLED_ANIM_SOLID; - animationState.speed = PLED_SPEED_OFF; - break; - - case XINPUT_PLED_FLASH3: - case XINPUT_PLED_ON3: - animationState.state = PLED_STATE_LED3; - animationState.animation = PLED_ANIM_SOLID; - animationState.speed = PLED_SPEED_OFF; - break; - - case XINPUT_PLED_FLASH4: - case XINPUT_PLED_ON4: - animationState.state = PLED_STATE_LED4; - animationState.animation = PLED_ANIM_SOLID; - animationState.speed = PLED_SPEED_OFF; - break; - - default: - break; - } - - return animationState; + PLEDAnimationState animationState = + { + .state = 0, + .animation = PLED_ANIM_NONE, + .speed = PLED_SPEED_OFF, + }; + + switch (ledState) + { + case XINPUT_PLED_BLINKALL: + case XINPUT_PLED_ROTATE: + case XINPUT_PLED_BLINK: + case XINPUT_PLED_SLOWBLINK: + case XINPUT_PLED_ALTERNATE: + animationState.state = (PLED_STATE_LED1 | PLED_STATE_LED2 | PLED_STATE_LED3 | PLED_STATE_LED4); + animationState.animation = PLED_ANIM_BLINK; + animationState.speed = PLED_SPEED_FAST; + break; + + case XINPUT_PLED_FLASH1: + case XINPUT_PLED_ON1: + animationState.state = PLED_STATE_LED1; + animationState.animation = PLED_ANIM_SOLID; + animationState.speed = PLED_SPEED_OFF; + break; + + case XINPUT_PLED_FLASH2: + case XINPUT_PLED_ON2: + animationState.state = PLED_STATE_LED2; + animationState.animation = PLED_ANIM_SOLID; + animationState.speed = PLED_SPEED_OFF; + break; + + case XINPUT_PLED_FLASH3: + case XINPUT_PLED_ON3: + animationState.state = PLED_STATE_LED3; + animationState.animation = PLED_ANIM_SOLID; + animationState.speed = PLED_SPEED_OFF; + break; + + case XINPUT_PLED_FLASH4: + case XINPUT_PLED_ON4: + animationState.state = PLED_STATE_LED4; + animationState.animation = PLED_ANIM_SOLID; + animationState.speed = PLED_SPEED_OFF; + break; + + default: + break; + } + + return animationState; } PLEDAnimationState getXBoneAnimationNEOPICO(Gamepad * gamepad) { - PLEDAnimationState animationState = - { - .state = (PLED_STATE_LED1 | PLED_STATE_LED2 | PLED_STATE_LED3 | PLED_STATE_LED4), - .animation = PLED_ANIM_OFF - }; + PLEDAnimationState animationState = + { + .state = (PLED_STATE_LED1 | PLED_STATE_LED2 | PLED_STATE_LED3 | PLED_STATE_LED4), + .animation = PLED_ANIM_OFF + }; - if ( gamepad->auxState.playerID.ledValue == 1 ) { - animationState.animation = PLED_ANIM_SOLID; - } + if ( gamepad->auxState.playerID.ledValue == 1 ) { + animationState.animation = PLED_ANIM_SOLID; + } - return animationState; + return animationState; } PLEDAnimationState getPS3AnimationNEOPICO(uint16_t ledState) { - const uint8_t ps3LEDs[10][4] = { - { 0x01, 0x00, 0x00, 0x00 }, - { 0x00, 0x01, 0x00, 0x00 }, - { 0x00, 0x00, 0x01, 0x00 }, - { 0x00, 0x00, 0x00, 0x01 }, - { 0x01, 0x00, 0x00, 0x01 }, - { 0x00, 0x01, 0x00, 0x01 }, - { 0x00, 0x00, 0x01, 0x01 }, - { 0x01, 0x00, 0x01, 0x01 }, - { 0x00, 0x01, 0x01, 0x01 }, - { 0x01, 0x01, 0x01, 0x01 } - }; - - PLEDAnimationState animationState = - { - .state = 0, - .animation = PLED_ANIM_NONE, - .speed = PLED_SPEED_OFF, - }; - - if (ledState != 0) { - uint8_t ledNumber = ledState & 0x0F; - if (ps3LEDs[ledNumber-1][0] == 0x01) animationState.state |= PLED_STATE_LED1; - if (ps3LEDs[ledNumber-1][1] == 0x01) animationState.state |= PLED_STATE_LED2; - if (ps3LEDs[ledNumber-1][2] == 0x01) animationState.state |= PLED_STATE_LED3; - if (ps3LEDs[ledNumber-1][3] == 0x01) animationState.state |= PLED_STATE_LED4; - } - - if (animationState.state != 0) { - animationState.animation = PLED_ANIM_SOLID; - animationState.speed = PLED_SPEED_OFF; - } else { - animationState.state = 0; - animationState.animation = PLED_ANIM_OFF; - animationState.speed = PLED_SPEED_OFF; - } - - return animationState; + const uint8_t ps3LEDs[10][4] = { + { 0x01, 0x00, 0x00, 0x00 }, + { 0x00, 0x01, 0x00, 0x00 }, + { 0x00, 0x00, 0x01, 0x00 }, + { 0x00, 0x00, 0x00, 0x01 }, + { 0x01, 0x00, 0x00, 0x01 }, + { 0x00, 0x01, 0x00, 0x01 }, + { 0x00, 0x00, 0x01, 0x01 }, + { 0x01, 0x00, 0x01, 0x01 }, + { 0x00, 0x01, 0x01, 0x01 }, + { 0x01, 0x01, 0x01, 0x01 } + }; + + PLEDAnimationState animationState = + { + .state = 0, + .animation = PLED_ANIM_NONE, + .speed = PLED_SPEED_OFF, + }; + + if (ledState != 0) { + uint8_t ledNumber = ledState & 0x0F; + if (ps3LEDs[ledNumber-1][0] == 0x01) animationState.state |= PLED_STATE_LED1; + if (ps3LEDs[ledNumber-1][1] == 0x01) animationState.state |= PLED_STATE_LED2; + if (ps3LEDs[ledNumber-1][2] == 0x01) animationState.state |= PLED_STATE_LED3; + if (ps3LEDs[ledNumber-1][3] == 0x01) animationState.state |= PLED_STATE_LED4; + } + + if (animationState.state != 0) { + animationState.animation = PLED_ANIM_SOLID; + animationState.speed = PLED_SPEED_OFF; + } else { + animationState.state = 0; + animationState.animation = PLED_ANIM_OFF; + animationState.speed = PLED_SPEED_OFF; + } + + return animationState; } PLEDAnimationState getPS4AnimationNEOPICO(uint32_t flashOn, uint32_t flashOff) { - PLEDAnimationState animationState = - { - .state = (PLED_STATE_LED1 | PLED_STATE_LED2 | PLED_STATE_LED3 | PLED_STATE_LED4), - .animation = PLED_ANIM_SOLID, - .speed = PLED_SPEED_OFF, - }; - - if (flashOn > 0 || flashOff > 0) { - animationState.animation = PLED_ANIM_BLINK_CUSTOM; - animationState.speedOn = flashOn; - animationState.speedOff = flashOff; - } - - return animationState; + PLEDAnimationState animationState = + { + .state = (PLED_STATE_LED1 | PLED_STATE_LED2 | PLED_STATE_LED3 | PLED_STATE_LED4), + .animation = PLED_ANIM_SOLID, + .speed = PLED_SPEED_OFF, + }; + + if (flashOn > 0 || flashOff > 0) { + animationState.animation = PLED_ANIM_BLINK_CUSTOM; + animationState.speedOn = flashOn; + animationState.speedOff = flashOff; + } + + return animationState; } bool NeoPicoLEDAddon::available() { - const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); - return isValidPin(ledOptions.dataPin); + const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); + return isValidPin(ledOptions.dataPin); } void NeoPicoLEDAddon::setup() { - // Set Default LED Options - const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); - turnOffWhenSuspended = ledOptions.turnOffWhenSuspended; + // Set Default LED Options + const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); + turnOffWhenSuspended = ledOptions.turnOffWhenSuspended; - Gamepad * gamepad = Storage::getInstance().GetProcessedGamepad(); - gamepad->auxState.playerID.enabled = true; - gamepad->auxState.sensors.statusLight.enabled = true; + // Get turbo options (turbo RGB led) + const TurboOptions& turboOptions = Storage::getInstance().getAddonOptions().turboOptions; - if ( ledOptions.pledType == PLED_TYPE_RGB ) { - neoPLEDs = new NeoPicoPlayerLEDs(); - } + Gamepad * gamepad = Storage::getInstance().GetProcessedGamepad(); + gamepad->auxState.playerID.enabled = true; + gamepad->auxState.sensors.statusLight.enabled = true; - neopico = nullptr; // set neopico to null + if ( ledOptions.pledType == PLED_TYPE_RGB || + turboOptions.turboLedType == PLED_TYPE_RGB) { + neoPLEDs = new NeoPicoPlayerLEDs(); + } - // Create a dummy Neo Pico for the initial configuration - neopico = new NeoPico(-1, 0); - configureLEDs(); + neopico = nullptr; // set neopico to null - nextRunTime = make_timeout_time_ms(0); // Reset timeout + // Create a dummy Neo Pico for the initial configuration + neopico = new NeoPico(-1, 0); + configureLEDs(); + + nextRunTime = make_timeout_time_ms(0); // Reset timeout } void NeoPicoLEDAddon::process() { - const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); - if (!isValidPin(ledOptions.dataPin) || !time_reached(this->nextRunTime)) - return; - - Gamepad * gamepad = Storage::getInstance().GetProcessedGamepad(); - AnimationHotkey action = animationHotkeys(gamepad); - if (ledOptions.pledType == PLED_TYPE_RGB) { - inputMode = gamepad->getOptions().inputMode; // HACK - if (gamepad->auxState.playerID.enabled && gamepad->auxState.playerID.active) { - switch (inputMode) { - case INPUT_MODE_XINPUT: - animationState = getXInputAnimationNEOPICO(gamepad->auxState.playerID.ledValue); - break; - case INPUT_MODE_PS3: - animationState = getPS3AnimationNEOPICO(gamepad->auxState.playerID.ledValue); - break; - case INPUT_MODE_PS4: - case INPUT_MODE_PS5: - animationState = getPS4AnimationNEOPICO(gamepad->auxState.playerID.ledBlinkOn, gamepad->auxState.playerID.ledBlinkOff); - break; - case INPUT_MODE_XBONE: - animationState = getXBoneAnimationNEOPICO(gamepad); - break; - default: - break; - } - } - - if (neoPLEDs != nullptr && animationState.animation != PLED_ANIM_NONE) { - neoPLEDs->animate(animationState); - } - } - - if ( action != HOTKEY_LEDS_NONE ) { - as.HandleEvent(action); - } - - uint32_t buttonState = gamepad->state.dpad << 16 | gamepad->state.buttons; - vector pressed; - for (auto row : matrix.pixels) - { - for (auto pixel : row) - { - if (buttonState & pixel.mask) - pressed.push_back(pixel); - } - } - if (pressed.size() > 0) - as.HandlePressed(pressed); - else - as.ClearPressed(); - - as.Animate(); - - if (turnOffWhenSuspended && get_usb_suspended()) { - as.DimBrightnessTo0(); - } else { - as.SetBrightness(AnimationStation::GetBrightness()); - } - - as.ApplyBrightness(frame); - - // Apply the player LEDs to our first 4 leds if we're in NEOPIXEL mode - if (ledOptions.pledType == PLED_TYPE_RGB) { - LEDOptions & ledOptions = Storage::getInstance().getLedOptions(); - int32_t pledIndexes[] = { ledOptions.pledIndex1, ledOptions.pledIndex2, ledOptions.pledIndex3, ledOptions.pledIndex4 }; - for (int i = 0; i < PLED_COUNT; i++) { - if (pledIndexes[i] < 0) - continue; - - float level = (static_cast(PLED_MAX_LEVEL - neoPLEDs->getLedLevels()[i]) / static_cast(PLED_MAX_LEVEL)); - float brightness = as.GetBrightnessX() * level; - if (gamepad->auxState.sensors.statusLight.enabled && gamepad->auxState.sensors.statusLight.active) { - rgbPLEDValues[i] = (RGB(gamepad->auxState.sensors.statusLight.color.red, gamepad->auxState.sensors.statusLight.color.green, gamepad->auxState.sensors.statusLight.color.blue)).value(neopico->GetFormat(), brightness); - } else { - rgbPLEDValues[i] = ((RGB)ledOptions.pledColor).value(neopico->GetFormat(), brightness); - } - frame[pledIndexes[i]] = rgbPLEDValues[i]; - } - } - - neopico->SetFrame(frame); - neopico->Show(); - AnimationStore.save(); - - this->nextRunTime = make_timeout_time_ms(NeoPicoLEDAddon::intervalMS); + const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); + if (!isValidPin(ledOptions.dataPin) || !time_reached(this->nextRunTime)) + return; + + // Get turbo options (turbo RGB led) + const TurboOptions& turboOptions = Storage::getInstance().getAddonOptions().turboOptions; + + Gamepad * gamepad = Storage::getInstance().GetProcessedGamepad(); + AnimationHotkey action = animationHotkeys(gamepad); + if (ledOptions.pledType == PLED_TYPE_RGB) { + inputMode = gamepad->getOptions().inputMode; // HACK + if (gamepad->auxState.playerID.enabled && gamepad->auxState.playerID.active) { + switch (inputMode) { + case INPUT_MODE_XINPUT: + animationState = getXInputAnimationNEOPICO(gamepad->auxState.playerID.ledValue); + break; + case INPUT_MODE_PS3: + animationState = getPS3AnimationNEOPICO(gamepad->auxState.playerID.ledValue); + break; + case INPUT_MODE_PS4: + case INPUT_MODE_PS5: + animationState = getPS4AnimationNEOPICO(gamepad->auxState.playerID.ledBlinkOn, gamepad->auxState.playerID.ledBlinkOff); + break; + case INPUT_MODE_XBONE: + animationState = getXBoneAnimationNEOPICO(gamepad); + break; + default: + break; + } + } + + if (neoPLEDs != nullptr && animationState.animation != PLED_ANIM_NONE) { + neoPLEDs->animate(animationState); + } + } + + if ( action != HOTKEY_LEDS_NONE ) { + as.HandleEvent(action); + } + + uint32_t buttonState = gamepad->state.dpad << 16 | gamepad->state.buttons; + vector pressed; + for (auto row : matrix.pixels) + { + for (auto pixel : row) + { + if (buttonState & pixel.mask) + pressed.push_back(pixel); + } + } + if (pressed.size() > 0) + as.HandlePressed(pressed); + else + as.ClearPressed(); + + as.Animate(); + + if (turnOffWhenSuspended && get_usb_suspended()) { + as.DimBrightnessTo0(); + } else { + as.SetBrightness(AnimationStation::GetBrightness()); + } + + as.ApplyBrightness(frame); + + // Apply the player LEDs to our first 4 leds if we're in NEOPIXEL mode + if (ledOptions.pledType == PLED_TYPE_RGB) { + int32_t pledIndexes[] = { ledOptions.pledIndex1, ledOptions.pledIndex2, ledOptions.pledIndex3, ledOptions.pledIndex4 }; + for (int i = 0; i < PLED_COUNT; i++) { + if (pledIndexes[i] < 0 || pledIndexes[i] > 99) + continue; + + float level = (static_cast(PLED_MAX_LEVEL - neoPLEDs->getLedLevels()[i]) / static_cast(PLED_MAX_LEVEL)); + float brightness = as.GetBrightnessX() * level; + if (gamepad->auxState.sensors.statusLight.enabled && gamepad->auxState.sensors.statusLight.active) { + rgbPLEDValues[i] = (RGB(gamepad->auxState.sensors.statusLight.color.red, gamepad->auxState.sensors.statusLight.color.green, gamepad->auxState.sensors.statusLight.color.blue)).value(neopico->GetFormat(), brightness); + } else { + rgbPLEDValues[i] = ((RGB)ledOptions.pledColor).value(neopico->GetFormat(), brightness); + } + frame[pledIndexes[i]] = rgbPLEDValues[i]; + } + } + + // Turbo LED is a separate RGB that is on if turbo is on, and off if its off + if ( turboOptions.turboLedType == PLED_TYPE_RGB ) { // RGB or PWM? + if ( gamepad->auxState.turbo.activity == 1) { // Turbo is on (active sensor) + if (turboOptions.turboLedIndex >= 0 && turboOptions.turboLedIndex < 100) { // Double check index value + float brightness = as.GetBrightnessX(); + frame[turboOptions.turboLedIndex] = ((RGB)turboOptions.turboLedColor).value(neopico->GetFormat(), brightness); + } + } + } + + neopico->SetFrame(frame); + neopico->Show(); + AnimationStore.save(); + + this->nextRunTime = make_timeout_time_ms(NeoPicoLEDAddon::intervalMS); } std::vector * NeoPicoLEDAddon::getLEDPositions(string button, std::vector> *positions) { - int buttonPosition = buttonPositions[button]; - if (buttonPosition < 0) - return &EMPTY_VECTOR; - else - return &positions->at(buttonPosition); + int buttonPosition = buttonPositions[button]; + if (buttonPosition < 0) + return &EMPTY_VECTOR; + else + return &positions->at(buttonPosition); } // Macro for Pixel() declarations #define PIXEL(BUTTON, MASK) \ - Pixel(buttonPositions[BUTTON], MASK, *getLEDPositions(BUTTON, positions)) + Pixel(buttonPositions[BUTTON], MASK, *getLEDPositions(BUTTON, positions)) /** * @brief Create an LED layout using a 2x4 matrix. */ std::vector> NeoPicoLEDAddon::generatedLEDButtons(std::vector> *positions) { - std::vector> pixels = - { - { - PIXEL(BUTTON_LABEL_B3, GAMEPAD_MASK_B3), - PIXEL(BUTTON_LABEL_B1, GAMEPAD_MASK_B1), - }, - { - PIXEL(BUTTON_LABEL_B4, GAMEPAD_MASK_B4), - PIXEL(BUTTON_LABEL_B2, GAMEPAD_MASK_B2), - }, - { - PIXEL(BUTTON_LABEL_R1, GAMEPAD_MASK_R1), - PIXEL(BUTTON_LABEL_R2, GAMEPAD_MASK_R2), - }, - { - PIXEL(BUTTON_LABEL_L1, GAMEPAD_MASK_L1), - PIXEL(BUTTON_LABEL_L2, GAMEPAD_MASK_L2), - }, - { - PIXEL(BUTTON_LABEL_LEFT, GAMEPAD_MASK_DL), - PIXEL(BUTTON_LABEL_DOWN, GAMEPAD_MASK_DD), - PIXEL(BUTTON_LABEL_RIGHT, GAMEPAD_MASK_DR), - PIXEL(BUTTON_LABEL_UP, GAMEPAD_MASK_DU), - PIXEL(BUTTON_LABEL_S1, GAMEPAD_MASK_S1), - PIXEL(BUTTON_LABEL_S2, GAMEPAD_MASK_S2), - PIXEL(BUTTON_LABEL_L3, GAMEPAD_MASK_L3), - PIXEL(BUTTON_LABEL_R3, GAMEPAD_MASK_R3), - PIXEL(BUTTON_LABEL_A1, GAMEPAD_MASK_A1), - PIXEL(BUTTON_LABEL_A2, GAMEPAD_MASK_A2), - }, - }; - - return pixels; + std::vector> pixels = + { + { + PIXEL(BUTTON_LABEL_B3, GAMEPAD_MASK_B3), + PIXEL(BUTTON_LABEL_B1, GAMEPAD_MASK_B1), + }, + { + PIXEL(BUTTON_LABEL_B4, GAMEPAD_MASK_B4), + PIXEL(BUTTON_LABEL_B2, GAMEPAD_MASK_B2), + }, + { + PIXEL(BUTTON_LABEL_R1, GAMEPAD_MASK_R1), + PIXEL(BUTTON_LABEL_R2, GAMEPAD_MASK_R2), + }, + { + PIXEL(BUTTON_LABEL_L1, GAMEPAD_MASK_L1), + PIXEL(BUTTON_LABEL_L2, GAMEPAD_MASK_L2), + }, + { + PIXEL(BUTTON_LABEL_LEFT, GAMEPAD_MASK_DL), + PIXEL(BUTTON_LABEL_DOWN, GAMEPAD_MASK_DD), + PIXEL(BUTTON_LABEL_RIGHT, GAMEPAD_MASK_DR), + PIXEL(BUTTON_LABEL_UP, GAMEPAD_MASK_DU), + PIXEL(BUTTON_LABEL_S1, GAMEPAD_MASK_S1), + PIXEL(BUTTON_LABEL_S2, GAMEPAD_MASK_S2), + PIXEL(BUTTON_LABEL_L3, GAMEPAD_MASK_L3), + PIXEL(BUTTON_LABEL_R3, GAMEPAD_MASK_R3), + PIXEL(BUTTON_LABEL_A1, GAMEPAD_MASK_A1), + PIXEL(BUTTON_LABEL_A2, GAMEPAD_MASK_A2), + }, + }; + + return pixels; } /** @@ -367,59 +383,59 @@ std::vector> NeoPicoLEDAddon::generatedLEDButtons(std::vector */ std::vector> NeoPicoLEDAddon::generatedLEDStickless(vector> *positions) { - std::vector> pixels = - { - { - PIXEL(BUTTON_LABEL_LEFT, GAMEPAD_MASK_DL), - NO_PIXEL, - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_DOWN, GAMEPAD_MASK_DD), - NO_PIXEL, - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_RIGHT, GAMEPAD_MASK_DR), - NO_PIXEL, - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_UP, GAMEPAD_MASK_DU), - NO_PIXEL, - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_B3, GAMEPAD_MASK_B3), - PIXEL(BUTTON_LABEL_B1, GAMEPAD_MASK_B1), - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_B4, GAMEPAD_MASK_B4), - PIXEL(BUTTON_LABEL_B2, GAMEPAD_MASK_B2), - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_R1, GAMEPAD_MASK_R1), - PIXEL(BUTTON_LABEL_R2, GAMEPAD_MASK_R2), - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_L1, GAMEPAD_MASK_L1), - PIXEL(BUTTON_LABEL_L2, GAMEPAD_MASK_L2), - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_S1, GAMEPAD_MASK_S1), - PIXEL(BUTTON_LABEL_S2, GAMEPAD_MASK_S2), - PIXEL(BUTTON_LABEL_L3, GAMEPAD_MASK_L3), - PIXEL(BUTTON_LABEL_R3, GAMEPAD_MASK_R3), - PIXEL(BUTTON_LABEL_A1, GAMEPAD_MASK_A1), - PIXEL(BUTTON_LABEL_A2, GAMEPAD_MASK_A2), - }, - }; - - return pixels; + std::vector> pixels = + { + { + PIXEL(BUTTON_LABEL_LEFT, GAMEPAD_MASK_DL), + NO_PIXEL, + NO_PIXEL, + }, + { + PIXEL(BUTTON_LABEL_DOWN, GAMEPAD_MASK_DD), + NO_PIXEL, + NO_PIXEL, + }, + { + PIXEL(BUTTON_LABEL_RIGHT, GAMEPAD_MASK_DR), + NO_PIXEL, + NO_PIXEL, + }, + { + PIXEL(BUTTON_LABEL_UP, GAMEPAD_MASK_DU), + NO_PIXEL, + NO_PIXEL, + }, + { + PIXEL(BUTTON_LABEL_B3, GAMEPAD_MASK_B3), + PIXEL(BUTTON_LABEL_B1, GAMEPAD_MASK_B1), + NO_PIXEL, + }, + { + PIXEL(BUTTON_LABEL_B4, GAMEPAD_MASK_B4), + PIXEL(BUTTON_LABEL_B2, GAMEPAD_MASK_B2), + NO_PIXEL, + }, + { + PIXEL(BUTTON_LABEL_R1, GAMEPAD_MASK_R1), + PIXEL(BUTTON_LABEL_R2, GAMEPAD_MASK_R2), + NO_PIXEL, + }, + { + PIXEL(BUTTON_LABEL_L1, GAMEPAD_MASK_L1), + PIXEL(BUTTON_LABEL_L2, GAMEPAD_MASK_L2), + NO_PIXEL, + }, + { + PIXEL(BUTTON_LABEL_S1, GAMEPAD_MASK_S1), + PIXEL(BUTTON_LABEL_S2, GAMEPAD_MASK_S2), + PIXEL(BUTTON_LABEL_L3, GAMEPAD_MASK_L3), + PIXEL(BUTTON_LABEL_R3, GAMEPAD_MASK_R3), + PIXEL(BUTTON_LABEL_A1, GAMEPAD_MASK_A1), + PIXEL(BUTTON_LABEL_A2, GAMEPAD_MASK_A2), + }, + }; + + return pixels; } /** @@ -427,47 +443,47 @@ std::vector> NeoPicoLEDAddon::generatedLEDStickless(vector> NeoPicoLEDAddon::generatedLEDWasd(std::vector> *positions) { - std::vector> pixels = - { - { - NO_PIXEL, - PIXEL(BUTTON_LABEL_LEFT, GAMEPAD_MASK_DL), - }, - { - PIXEL(BUTTON_LABEL_UP, GAMEPAD_MASK_DU), - PIXEL(BUTTON_LABEL_DOWN, GAMEPAD_MASK_DD), - }, - { - NO_PIXEL, - PIXEL(BUTTON_LABEL_RIGHT, GAMEPAD_MASK_DR), - }, - { - PIXEL(BUTTON_LABEL_B3, GAMEPAD_MASK_B3), - PIXEL(BUTTON_LABEL_B1, GAMEPAD_MASK_B1), - }, - { - PIXEL(BUTTON_LABEL_B4, GAMEPAD_MASK_B4), - PIXEL(BUTTON_LABEL_B2, GAMEPAD_MASK_B2), - }, - { - PIXEL(BUTTON_LABEL_R1, GAMEPAD_MASK_R1), - PIXEL(BUTTON_LABEL_R2, GAMEPAD_MASK_R2), - }, - { - PIXEL(BUTTON_LABEL_L1, GAMEPAD_MASK_L1), - PIXEL(BUTTON_LABEL_L2, GAMEPAD_MASK_L2), - }, - { - PIXEL(BUTTON_LABEL_S1, GAMEPAD_MASK_S1), - PIXEL(BUTTON_LABEL_S2, GAMEPAD_MASK_S2), - PIXEL(BUTTON_LABEL_L3, GAMEPAD_MASK_L3), - PIXEL(BUTTON_LABEL_R3, GAMEPAD_MASK_R3), - PIXEL(BUTTON_LABEL_A1, GAMEPAD_MASK_A1), - PIXEL(BUTTON_LABEL_A2, GAMEPAD_MASK_A2), - }, - }; - - return pixels; + std::vector> pixels = + { + { + NO_PIXEL, + PIXEL(BUTTON_LABEL_LEFT, GAMEPAD_MASK_DL), + }, + { + PIXEL(BUTTON_LABEL_UP, GAMEPAD_MASK_DU), + PIXEL(BUTTON_LABEL_DOWN, GAMEPAD_MASK_DD), + }, + { + NO_PIXEL, + PIXEL(BUTTON_LABEL_RIGHT, GAMEPAD_MASK_DR), + }, + { + PIXEL(BUTTON_LABEL_B3, GAMEPAD_MASK_B3), + PIXEL(BUTTON_LABEL_B1, GAMEPAD_MASK_B1), + }, + { + PIXEL(BUTTON_LABEL_B4, GAMEPAD_MASK_B4), + PIXEL(BUTTON_LABEL_B2, GAMEPAD_MASK_B2), + }, + { + PIXEL(BUTTON_LABEL_R1, GAMEPAD_MASK_R1), + PIXEL(BUTTON_LABEL_R2, GAMEPAD_MASK_R2), + }, + { + PIXEL(BUTTON_LABEL_L1, GAMEPAD_MASK_L1), + PIXEL(BUTTON_LABEL_L2, GAMEPAD_MASK_L2), + }, + { + PIXEL(BUTTON_LABEL_S1, GAMEPAD_MASK_S1), + PIXEL(BUTTON_LABEL_S2, GAMEPAD_MASK_S2), + PIXEL(BUTTON_LABEL_L3, GAMEPAD_MASK_L3), + PIXEL(BUTTON_LABEL_R3, GAMEPAD_MASK_R3), + PIXEL(BUTTON_LABEL_A1, GAMEPAD_MASK_A1), + PIXEL(BUTTON_LABEL_A2, GAMEPAD_MASK_A2), + }, + }; + + return pixels; } /** @@ -475,203 +491,207 @@ std::vector> NeoPicoLEDAddon::generatedLEDWasd(std::vector> NeoPicoLEDAddon::generatedLEDWasdFBM(std::vector> *positions) { - std::vector> pixels = - { - { - PIXEL(BUTTON_LABEL_L1, GAMEPAD_MASK_L1), - PIXEL(BUTTON_LABEL_L2, GAMEPAD_MASK_L2), - }, - { - PIXEL(BUTTON_LABEL_R1, GAMEPAD_MASK_R1), - PIXEL(BUTTON_LABEL_R2, GAMEPAD_MASK_R2), - }, - { - PIXEL(BUTTON_LABEL_B4, GAMEPAD_MASK_B4), - PIXEL(BUTTON_LABEL_B2, GAMEPAD_MASK_B2), - }, - { - PIXEL(BUTTON_LABEL_B3, GAMEPAD_MASK_B3), - PIXEL(BUTTON_LABEL_B1, GAMEPAD_MASK_B1), - }, - { - NO_PIXEL, - PIXEL(BUTTON_LABEL_LEFT, GAMEPAD_MASK_DL), - }, - { - PIXEL(BUTTON_LABEL_UP, GAMEPAD_MASK_DU), - PIXEL(BUTTON_LABEL_DOWN, GAMEPAD_MASK_DD), - }, - { - NO_PIXEL, - PIXEL(BUTTON_LABEL_RIGHT, GAMEPAD_MASK_DR), - }, - { - PIXEL(BUTTON_LABEL_S1, GAMEPAD_MASK_S1), - PIXEL(BUTTON_LABEL_S2, GAMEPAD_MASK_S2), - PIXEL(BUTTON_LABEL_L3, GAMEPAD_MASK_L3), - PIXEL(BUTTON_LABEL_R3, GAMEPAD_MASK_R3), - PIXEL(BUTTON_LABEL_A1, GAMEPAD_MASK_A1), - PIXEL(BUTTON_LABEL_A2, GAMEPAD_MASK_A2), - }, - }; - - return pixels; + std::vector> pixels = + { + { + PIXEL(BUTTON_LABEL_L1, GAMEPAD_MASK_L1), + PIXEL(BUTTON_LABEL_L2, GAMEPAD_MASK_L2), + }, + { + PIXEL(BUTTON_LABEL_R1, GAMEPAD_MASK_R1), + PIXEL(BUTTON_LABEL_R2, GAMEPAD_MASK_R2), + }, + { + PIXEL(BUTTON_LABEL_B4, GAMEPAD_MASK_B4), + PIXEL(BUTTON_LABEL_B2, GAMEPAD_MASK_B2), + }, + { + PIXEL(BUTTON_LABEL_B3, GAMEPAD_MASK_B3), + PIXEL(BUTTON_LABEL_B1, GAMEPAD_MASK_B1), + }, + { + NO_PIXEL, + PIXEL(BUTTON_LABEL_LEFT, GAMEPAD_MASK_DL), + }, + { + PIXEL(BUTTON_LABEL_UP, GAMEPAD_MASK_DU), + PIXEL(BUTTON_LABEL_DOWN, GAMEPAD_MASK_DD), + }, + { + NO_PIXEL, + PIXEL(BUTTON_LABEL_RIGHT, GAMEPAD_MASK_DR), + }, + { + PIXEL(BUTTON_LABEL_S1, GAMEPAD_MASK_S1), + PIXEL(BUTTON_LABEL_S2, GAMEPAD_MASK_S2), + PIXEL(BUTTON_LABEL_L3, GAMEPAD_MASK_L3), + PIXEL(BUTTON_LABEL_R3, GAMEPAD_MASK_R3), + PIXEL(BUTTON_LABEL_A1, GAMEPAD_MASK_A1), + PIXEL(BUTTON_LABEL_A2, GAMEPAD_MASK_A2), + }, + }; + + return pixels; } std::vector> NeoPicoLEDAddon::createLEDLayout(ButtonLayout layout, uint8_t ledsPerPixel, uint8_t ledButtonCount) { - vector> positions(ledButtonCount); - for (int i = 0; i != ledButtonCount; i++) - { - positions[i].resize(ledsPerPixel); - for (int l = 0; l != ledsPerPixel; l++) - positions[i][l] = (i * ledsPerPixel) + l; - } - - switch (static_cast(layout)) - { - case BUTTON_LAYOUT_STICKLESS: - case BUTTON_LAYOUT_OPENCORE0WASDA: - case BUTTON_LAYOUT_STICKLESS_13: - case BUTTON_LAYOUT_STICKLESS_14: - case BUTTON_LAYOUT_STICKLESS_16: - case BUTTON_LAYOUT_STICKLESS_R16: - case BUTTON_LAYOUT_BOARD_DEFINED_A: - return generatedLEDStickless(&positions); - case BUTTON_LAYOUT_FIGHTBOARD_MIRRORED: - return generatedLEDWasdFBM(&positions); - case BUTTON_LAYOUT_BUTTONS_ANGLED: - case BUTTON_LAYOUT_FIGHTBOARD_STICK: - return generatedLEDWasd(&positions); - case BUTTON_LAYOUT_BLANKA: - case BUTTON_LAYOUT_BUTTONS_BASIC: - case BUTTON_LAYOUT_KEYBOARD_ANGLED: - case BUTTON_LAYOUT_KEYBOARDA: - case BUTTON_LAYOUT_DANCEPADA: - case BUTTON_LAYOUT_TWINSTICKA: - case BUTTON_LAYOUT_ARCADE: - case BUTTON_LAYOUT_VLXA: - default: - return generatedLEDButtons(&positions); - } - - assert(false); - return std::vector>(); + vector> positions(ledButtonCount); + for (int i = 0; i != ledButtonCount; i++) + { + positions[i].resize(ledsPerPixel); + for (int l = 0; l != ledsPerPixel; l++) + positions[i][l] = (i * ledsPerPixel) + l; + } + + switch (static_cast(layout)) + { + case BUTTON_LAYOUT_STICKLESS: + case BUTTON_LAYOUT_OPENCORE0WASDA: + case BUTTON_LAYOUT_STICKLESS_13: + case BUTTON_LAYOUT_STICKLESS_14: + case BUTTON_LAYOUT_STICKLESS_16: + case BUTTON_LAYOUT_STICKLESS_R16: + case BUTTON_LAYOUT_BOARD_DEFINED_A: + return generatedLEDStickless(&positions); + case BUTTON_LAYOUT_FIGHTBOARD_MIRRORED: + return generatedLEDWasdFBM(&positions); + case BUTTON_LAYOUT_BUTTONS_ANGLED: + case BUTTON_LAYOUT_FIGHTBOARD_STICK: + return generatedLEDWasd(&positions); + case BUTTON_LAYOUT_BLANKA: + case BUTTON_LAYOUT_BUTTONS_BASIC: + case BUTTON_LAYOUT_KEYBOARD_ANGLED: + case BUTTON_LAYOUT_KEYBOARDA: + case BUTTON_LAYOUT_DANCEPADA: + case BUTTON_LAYOUT_TWINSTICKA: + case BUTTON_LAYOUT_ARCADE: + case BUTTON_LAYOUT_VLXA: + default: + return generatedLEDButtons(&positions); + } + + assert(false); + return std::vector>(); } uint8_t NeoPicoLEDAddon::setupButtonPositions() { - const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); - buttonPositions.clear(); - buttonPositions.emplace(BUTTON_LABEL_UP, ledOptions.indexUp); - buttonPositions.emplace(BUTTON_LABEL_DOWN, ledOptions.indexDown); - buttonPositions.emplace(BUTTON_LABEL_LEFT, ledOptions.indexLeft); - buttonPositions.emplace(BUTTON_LABEL_RIGHT, ledOptions.indexRight); - buttonPositions.emplace(BUTTON_LABEL_B1, ledOptions.indexB1); - buttonPositions.emplace(BUTTON_LABEL_B2, ledOptions.indexB2); - buttonPositions.emplace(BUTTON_LABEL_B3, ledOptions.indexB3); - buttonPositions.emplace(BUTTON_LABEL_B4, ledOptions.indexB4); - buttonPositions.emplace(BUTTON_LABEL_L1, ledOptions.indexL1); - buttonPositions.emplace(BUTTON_LABEL_R1, ledOptions.indexR1); - buttonPositions.emplace(BUTTON_LABEL_L2, ledOptions.indexL2); - buttonPositions.emplace(BUTTON_LABEL_R2, ledOptions.indexR2); - buttonPositions.emplace(BUTTON_LABEL_S1, ledOptions.indexS1); - buttonPositions.emplace(BUTTON_LABEL_S2, ledOptions.indexS2); - buttonPositions.emplace(BUTTON_LABEL_L3, ledOptions.indexL3); - buttonPositions.emplace(BUTTON_LABEL_R3, ledOptions.indexR3); - buttonPositions.emplace(BUTTON_LABEL_A1, ledOptions.indexA1); - buttonPositions.emplace(BUTTON_LABEL_A2, ledOptions.indexA2); - uint8_t buttonCount = 0; - for (auto const& buttonPosition : buttonPositions) - { - if (buttonPosition.second > -1) - buttonCount++; - } - - return buttonCount; + const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); + buttonPositions.clear(); + buttonPositions.emplace(BUTTON_LABEL_UP, ledOptions.indexUp); + buttonPositions.emplace(BUTTON_LABEL_DOWN, ledOptions.indexDown); + buttonPositions.emplace(BUTTON_LABEL_LEFT, ledOptions.indexLeft); + buttonPositions.emplace(BUTTON_LABEL_RIGHT, ledOptions.indexRight); + buttonPositions.emplace(BUTTON_LABEL_B1, ledOptions.indexB1); + buttonPositions.emplace(BUTTON_LABEL_B2, ledOptions.indexB2); + buttonPositions.emplace(BUTTON_LABEL_B3, ledOptions.indexB3); + buttonPositions.emplace(BUTTON_LABEL_B4, ledOptions.indexB4); + buttonPositions.emplace(BUTTON_LABEL_L1, ledOptions.indexL1); + buttonPositions.emplace(BUTTON_LABEL_R1, ledOptions.indexR1); + buttonPositions.emplace(BUTTON_LABEL_L2, ledOptions.indexL2); + buttonPositions.emplace(BUTTON_LABEL_R2, ledOptions.indexR2); + buttonPositions.emplace(BUTTON_LABEL_S1, ledOptions.indexS1); + buttonPositions.emplace(BUTTON_LABEL_S2, ledOptions.indexS2); + buttonPositions.emplace(BUTTON_LABEL_L3, ledOptions.indexL3); + buttonPositions.emplace(BUTTON_LABEL_R3, ledOptions.indexR3); + buttonPositions.emplace(BUTTON_LABEL_A1, ledOptions.indexA1); + buttonPositions.emplace(BUTTON_LABEL_A2, ledOptions.indexA2); + uint8_t buttonCount = 0; + for (auto const& buttonPosition : buttonPositions) + { + if (buttonPosition.second > -1) + buttonCount++; + } + + return buttonCount; } void NeoPicoLEDAddon::configureLEDs() { - const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); - uint8_t buttonCount = setupButtonPositions(); - vector> pixels = createLEDLayout(static_cast(ledOptions.ledLayout), ledOptions.ledsPerButton, buttonCount); - matrix.setup(pixels, ledOptions.ledsPerButton); - ledCount = matrix.getLedCount(); - if (ledOptions.pledType == PLED_TYPE_RGB && PLED_COUNT > 0) - ledCount += PLED_COUNT; - - // Remove the old neopico (config can call this) - delete neopico; - neopico = new NeoPico(ledOptions.dataPin, ledCount, static_cast(ledOptions.ledFormat)); - neopico->Off(); - - Animation::format = static_cast(ledOptions.ledFormat); - as.ConfigureBrightness(ledOptions.brightnessMaximum, ledOptions.brightnessSteps); - AnimationOptions animationOptions = AnimationStore.getAnimationOptions(); - addStaticThemes(ledOptions, animationOptions); - as.SetOptions(animationOptions); - as.SetMatrix(matrix); - as.SetMode(as.options.baseAnimationIndex); + const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); + const TurboOptions& turboOptions = Storage::getInstance().getAddonOptions().turboOptions; + uint8_t buttonCount = setupButtonPositions(); + vector> pixels = createLEDLayout(static_cast(ledOptions.ledLayout), ledOptions.ledsPerButton, buttonCount); + matrix.setup(pixels, ledOptions.ledsPerButton); + ledCount = matrix.getLedCount(); + if (ledOptions.pledType == PLED_TYPE_RGB && PLED_COUNT > 0) + ledCount += PLED_COUNT; + + if (turboOptions.turboLedType == PLED_TYPE_RGB) + ledCount += 1; + + // Remove the old neopico (config can call this) + delete neopico; + neopico = new NeoPico(ledOptions.dataPin, ledCount, static_cast(ledOptions.ledFormat)); + neopico->Off(); + + Animation::format = static_cast(ledOptions.ledFormat); + as.ConfigureBrightness(ledOptions.brightnessMaximum, ledOptions.brightnessSteps); + AnimationOptions animationOptions = AnimationStore.getAnimationOptions(); + addStaticThemes(ledOptions, animationOptions); + as.SetOptions(animationOptions); + as.SetMatrix(matrix); + as.SetMode(as.options.baseAnimationIndex); } AnimationHotkey animationHotkeys(Gamepad *gamepad) { - AnimationHotkey action = HOTKEY_LEDS_NONE; - - if (gamepad->pressedS1() && gamepad->pressedS2()) - { - if (gamepad->pressedB3()) - { - action = HOTKEY_LEDS_ANIMATION_UP; - gamepad->state.buttons &= ~(GAMEPAD_MASK_B3 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); - } - else if (gamepad->pressedB1()) - { - action = HOTKEY_LEDS_ANIMATION_DOWN; - gamepad->state.buttons &= ~(GAMEPAD_MASK_B1 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); - } - else if (gamepad->pressedB4()) - { - action = HOTKEY_LEDS_BRIGHTNESS_UP; - gamepad->state.buttons &= ~(GAMEPAD_MASK_B4 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); - } - else if (gamepad->pressedB2()) - { - action = HOTKEY_LEDS_BRIGHTNESS_DOWN; - gamepad->state.buttons &= ~(GAMEPAD_MASK_B2 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); - } - else if (gamepad->pressedR1()) - { - action = HOTKEY_LEDS_PARAMETER_UP; - gamepad->state.buttons &= ~(GAMEPAD_MASK_R1 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); - } - else if (gamepad->pressedR2()) - { - action = HOTKEY_LEDS_PARAMETER_DOWN; - gamepad->state.buttons &= ~(GAMEPAD_MASK_R2 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); - } - else if (gamepad->pressedL1()) - { - action = HOTKEY_LEDS_PRESS_PARAMETER_UP; - gamepad->state.buttons &= ~(GAMEPAD_MASK_L1 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); - } - else if (gamepad->pressedL2()) - { - action = HOTKEY_LEDS_PRESS_PARAMETER_DOWN; - gamepad->state.buttons &= ~(GAMEPAD_MASK_L2 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); - } - else if (gamepad->pressedL3()) - { - action = HOTKEY_LEDS_FADETIME_DOWN; - gamepad->state.buttons &= ~(GAMEPAD_MASK_L3 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); - } - else if (gamepad->pressedR3()) - { - action = HOTKEY_LEDS_FADETIME_UP; - gamepad->state.buttons &= ~(GAMEPAD_MASK_R3 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); - } - } - - return action; + AnimationHotkey action = HOTKEY_LEDS_NONE; + + if (gamepad->pressedS1() && gamepad->pressedS2()) + { + if (gamepad->pressedB3()) + { + action = HOTKEY_LEDS_ANIMATION_UP; + gamepad->state.buttons &= ~(GAMEPAD_MASK_B3 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); + } + else if (gamepad->pressedB1()) + { + action = HOTKEY_LEDS_ANIMATION_DOWN; + gamepad->state.buttons &= ~(GAMEPAD_MASK_B1 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); + } + else if (gamepad->pressedB4()) + { + action = HOTKEY_LEDS_BRIGHTNESS_UP; + gamepad->state.buttons &= ~(GAMEPAD_MASK_B4 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); + } + else if (gamepad->pressedB2()) + { + action = HOTKEY_LEDS_BRIGHTNESS_DOWN; + gamepad->state.buttons &= ~(GAMEPAD_MASK_B2 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); + } + else if (gamepad->pressedR1()) + { + action = HOTKEY_LEDS_PARAMETER_UP; + gamepad->state.buttons &= ~(GAMEPAD_MASK_R1 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); + } + else if (gamepad->pressedR2()) + { + action = HOTKEY_LEDS_PARAMETER_DOWN; + gamepad->state.buttons &= ~(GAMEPAD_MASK_R2 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); + } + else if (gamepad->pressedL1()) + { + action = HOTKEY_LEDS_PRESS_PARAMETER_UP; + gamepad->state.buttons &= ~(GAMEPAD_MASK_L1 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); + } + else if (gamepad->pressedL2()) + { + action = HOTKEY_LEDS_PRESS_PARAMETER_DOWN; + gamepad->state.buttons &= ~(GAMEPAD_MASK_L2 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); + } + else if (gamepad->pressedL3()) + { + action = HOTKEY_LEDS_FADETIME_DOWN; + gamepad->state.buttons &= ~(GAMEPAD_MASK_L3 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); + } + else if (gamepad->pressedR3()) + { + action = HOTKEY_LEDS_FADETIME_UP; + gamepad->state.buttons &= ~(GAMEPAD_MASK_R3 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); + } + } + + return action; } diff --git a/src/addons/turbo.cpp b/src/addons/turbo.cpp index 3869bb3c1..4f702f057 100644 --- a/src/addons/turbo.cpp +++ b/src/addons/turbo.cpp @@ -55,14 +55,18 @@ void TurboInput::setup() dialValue = 0; } - // Setup Turbo LED if available - if (isValidPin(options.ledPin)) { + // Setup Turbo PWM LED if available (RGB is handled in neopicoleds.cpp) + if (isValidPin(options.ledPin) && options.turboLedType == PLED_TYPE_PWM) { hasLedPin = true; gpio_init(options.ledPin); gpio_set_dir(options.ledPin, GPIO_OUT); gpio_put(options.ledPin, 1); } + Gamepad * gamepad = Storage::getInstance().GetProcessedGamepad(); + gamepad->auxState.turbo.enabled = true; + gamepad->auxState.turbo.active = 1; + // SHMUP Mode if ( options.shmupModeEnabled ) { shmupBtnPin[0] = options.shmupBtn1Pin; // Charge Buttons Pins @@ -192,15 +196,21 @@ void TurboInput::process() // OFF: No turbo buttons enabled // ON: 1 or more turbo buttons enabled // BLINK: OFF on turbo shot, ON on turbo flicker - if (hasLedPin) { - // Turbo toggled on - if (turboButtonsMask) { - if (gamepad->state.buttons & turboButtonsMask) - gpio_put(options.ledPin, bTurboFlicker ? TURBO_LED_STATE_ON : TURBO_LED_STATE_OFF); - else - gpio_put(options.ledPin, TURBO_LED_STATE_ON); - } - else { + Gamepad * processedGamepad = Storage::getInstance().GetProcessedGamepad(); + if (turboButtonsMask) { + if (gamepad->state.buttons & turboButtonsMask) + processedGamepad->auxState.turbo.activity = bTurboFlicker ? TURBO_LED_STATE_ON : TURBO_LED_STATE_OFF; + else + processedGamepad->auxState.turbo.activity = TURBO_LED_STATE_ON; + } else { + processedGamepad->auxState.turbo.activity = TURBO_LED_STATE_OFF; + } + + // PWM LED Pin + if ( hasLedPin ) { + if ( processedGamepad->auxState.turbo.activity == TURBO_LED_STATE_ON ) { + gpio_put(options.ledPin, TURBO_LED_STATE_ON); + } else { gpio_put(options.ledPin, TURBO_LED_STATE_OFF); } } diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 37aa209f2..d8dd5fbf4 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -565,6 +565,9 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY(config.addonOptions.turboOptions, shmupBtnMask3, SHMUP_BUTTON3); INIT_UNSET_PROPERTY(config.addonOptions.turboOptions, shmupBtnMask4, SHMUP_BUTTON4); INIT_UNSET_PROPERTY(config.addonOptions.turboOptions, shmupMixMode, SHMUP_MIX_MODE); + INIT_UNSET_PROPERTY(config.addonOptions.turboOptions, turboLedType, TURBO_LED_TYPE); + INIT_UNSET_PROPERTY(config.addonOptions.turboOptions, turboLedIndex, TURBO_LED_INDEX); + INIT_UNSET_PROPERTY(config.addonOptions.turboOptions, turboLedColor, static_cast(TURBO_LED_COLOR.r) << 16 | static_cast(TURBO_LED_COLOR.g) << 8 | static_cast(TURBO_LED_COLOR.b)); // addonOptions.reverseOptions INIT_UNSET_PROPERTY(config.addonOptions.reverseOptions, enabled, !!REVERSE_ENABLED); @@ -1320,6 +1323,11 @@ void migrateTurboPinToGpio(Config& config) { } turboOptions.deprecatedButtonPin = -1; // set our turbo options to -1 for subsequent calls } + + // Make sure we set PWM mode if we are using led pin + if ( turboOptions.turboLedType == PLED_TYPE_NONE && isValidPin(turboOptions.ledPin) ) { + turboOptions.turboLedType = PLED_TYPE_PWM; + } } void migrateAuthenticationMethods(Config& config) { diff --git a/src/configs/webconfig.cpp b/src/configs/webconfig.cpp index 78291030d..4b6754f3d 100644 --- a/src/configs/webconfig.cpp +++ b/src/configs/webconfig.cpp @@ -1539,6 +1539,9 @@ std::string setAddonOptions() docToValue(turboOptions.shmupBtnMask3, doc, "shmupBtnMask3"); docToValue(turboOptions.shmupBtnMask4, doc, "shmupBtnMask4"); docToPin(turboOptions.shmupDialPin, doc, "pinShmupDial"); + docToValue(turboOptions.turboLedType, doc, "turboLedType"); + docToValue(turboOptions.turboLedIndex, doc, "turboLedIndex"); + docToValue(turboOptions.turboLedColor, doc, "turboLedColor"); docToValue(turboOptions.enabled, doc, "TurboInputEnabled"); WiiOptions& wiiOptions = Storage::getInstance().getAddonOptions().wiiOptions; @@ -1952,6 +1955,9 @@ std::string getAddonOptions() writeDoc(doc, "shmupBtnMask3", turboOptions.shmupBtnMask3); writeDoc(doc, "shmupBtnMask4", turboOptions.shmupBtnMask4); writeDoc(doc, "pinShmupDial", cleanPin(turboOptions.shmupDialPin)); + writeDoc(doc, "turboLedType", turboOptions.turboLedType); + writeDoc(doc, "turboLedIndex", turboOptions.turboLedIndex); + writeDoc(doc, "turboLedColor", ((RGB)turboOptions.turboLedColor).value(LED_FORMAT_RGB)); writeDoc(doc, "TurboInputEnabled", turboOptions.enabled); const WiiOptions& wiiOptions = Storage::getInstance().getAddonOptions().wiiOptions; diff --git a/www/server/app.js b/www/server/app.js index f5ebf7d60..c47c3f970 100644 --- a/www/server/app.js +++ b/www/server/app.js @@ -472,6 +472,9 @@ app.get('/api/getAddonsOptions', (req, res) => { shmupBtnMask3: 0, shmupBtnMask4: 0, pinShmupDial: -1, + turboLedType: 1, + turboLedIndex: 16, + turboLedColor: 16711680, sliderSOCDModeDefault: 1, snesPadClockPin: -1, snesPadLatchPin: -1, diff --git a/www/src/Addons/Rotary.tsx b/www/src/Addons/Rotary.tsx index be7a30a7c..81a6d31e4 100644 --- a/www/src/Addons/Rotary.tsx +++ b/www/src/Addons/Rotary.tsx @@ -43,7 +43,7 @@ export const rotaryScheme = { .number() .required() .label('Rotary Encoder Add-On Enabled'), - encoderOneEnabled: yup.boolean().required().label('Encoder One Enabled'), + encoderOneEnabled: yup.number().required().label('Encoder One Enabled'), encoderOnePinA: yup .number() .label('Encoder One Pin A') @@ -61,11 +61,11 @@ export const rotaryScheme = { .label('Encoder One Reset After') .required(), encoderOneAllowWrapAround: yup - .boolean() + .number() .required() .label('Encoder One Allow Wrap Around'), encoderOneMultiplier: yup.number().label('Encoder One Multiplier').required(), - encoderTwoEnabled: yup.boolean().required().label('Encoder Two Enabled'), + encoderTwoEnabled: yup.number().required().label('Encoder Two Enabled'), encoderTwoPinA: yup .number() .label('Encoder Two Pin A') @@ -83,7 +83,7 @@ export const rotaryScheme = { .label('Encoder Two Reset After') .required(), encoderTwoAllowWrapAround: yup - .boolean() + .number() .required() .label('Encoder Two Allow Wrap Around'), encoderTwoMultiplier: yup.number().label('Encoder Two Multiplier').required(), diff --git a/www/src/Addons/Turbo.tsx b/www/src/Addons/Turbo.tsx index 1c596e981..defcc415c 100644 --- a/www/src/Addons/Turbo.tsx +++ b/www/src/Addons/Turbo.tsx @@ -1,14 +1,17 @@ -import React from 'react'; +import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { FormCheck, Row } from 'react-bootstrap'; import * as yup from 'yup'; +import { AppContext } from '../Contexts/AppContext'; +import ColorPicker from '../Components/ColorPicker'; import Section from '../Components/Section'; import FormSelect from '../Components/FormSelect'; import FormControl from '../Components/FormControl'; import AnalogPinOptions from '../Components/AnalogPinOptions'; import { BUTTON_MASKS_OPTIONS } from '../Data/Buttons'; import { DUAL_STICK_MODES } from '../Data/Addons'; +import LEDColors from '../Data/LEDColors'; const SHMUP_MIXED_MODES = [ { label: 'Turbo Priority', value: 0 }, @@ -99,6 +102,12 @@ export const turboScheme = { .number() .label('Charge Shot Button 4 Map') .validateSelectionWhenValue('TurboInputEnabled', BUTTON_MASKS_OPTIONS), + turboLedType: yup.number().required().label('Turbo LED Type'), + turboLedIndex: yup + .number() + .label('Turbo LED Index') + .validateMinWhenEqualTo('turboLedType', 1, 0), + turboLedColor: yup.string().label('RGB Turbo LED').validateColor(), }; export const turboState = { @@ -120,18 +129,54 @@ export const turboState = { TurboInputEnabled: 0, turboPinLED: -1, turboShotCount: 5, + turboLedType: 0, + turboLedIndex: 0, + turboLedColor: '#000000' }; -const Turbo = ({ values, errors, handleChange, handleCheckbox }) => { +const Turbo = ({ values, errors, handleChange, handleCheckbox, handleBlur, setFieldValue}) => { const { t } = useTranslation(); + + const [colorPickerTarget, setColorPickerTarget] = useState(null); + const [showPicker, setShowPicker] = useState(false); + + const toggleRgbPledPicker = (e) => { + e.stopPropagation(); + setColorPickerTarget(e.target); + setShowPicker(!showPicker); + }; + return (