Skip to content

Commit

Permalink
Add option to turn off RGB & OLED on host suspend (#526)
Browse files Browse the repository at this point in the history
  • Loading branch information
deeebug authored Sep 18, 2023
1 parent 69a20ee commit e90c448
Show file tree
Hide file tree
Showing 16 changed files with 114 additions and 2 deletions.
5 changes: 5 additions & 0 deletions headers/addons/i2cdisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@
#define SPLASH_DURATION 7500 // Duration in milliseconds
#endif

#ifndef DISPLAY_TURN_OFF_WHEN_SUSPENDED
#define DISPLAY_TURN_OFF_WHEN_SUSPENDED 0
#endif

#ifndef DEFAULT_SPLASH
#define DEFAULT_SPLASH \
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, \
Expand Down Expand Up @@ -211,6 +215,7 @@ class I2CDisplayAddon : public GPAddon
uint16_t prevButtonState;
bool isFocusModeEnabled;
bool focusModePrevState;
bool turnOffWhenSuspended;
};

#endif
5 changes: 5 additions & 0 deletions headers/addons/neopicoleds.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@
#define LEDS_BUTTON_A2 -1
#endif

#ifndef LEDS_TURN_OFF_WHEN_SUSPENDED
#define LEDS_TURN_OFF_WHEN_SUSPENDED 0
#endif

void configureAnimations(AnimationStation *as);
AnimationHotkey animationHotkeys(Gamepad *gamepad);
PixelMatrix createLedButtonLayout(ButtonLayout layout, int ledsPerPixel);
Expand Down Expand Up @@ -192,6 +196,7 @@ class NeoPicoLEDAddon : public GPAddon {
std::map<std::string, int> buttonPositions;
bool isFocusModeEnabled;
bool focusModePrevState;
bool turnOffWhenSuspended;
};

#endif
3 changes: 3 additions & 0 deletions headers/addons/pleds.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ class PlayerLEDAddon : public GPAddon
PLEDType type;
PWMPlayerLEDs *pwmLEDs = nullptr;
PLEDAnimationState animationState;

private:
bool turnOffWhenSuspended;
};

#endif
10 changes: 9 additions & 1 deletion lib/TinyUSB_Gamepad/src/tusb_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@

UsbMode usb_mode = USB_MODE_HID;
InputMode input_mode = INPUT_MODE_XINPUT;
bool usb_mounted = false;
static bool usb_mounted = false;
static bool usb_suspended = false;

InputMode get_input_mode(void)
{
Expand All @@ -32,6 +33,11 @@ bool get_usb_mounted(void)
return usb_mounted;
}

bool get_usb_suspended(void)
{
return usb_suspended;
}

void initialize_driver(InputMode mode)
{
input_mode = mode;
Expand Down Expand Up @@ -191,9 +197,11 @@ void tud_umount_cb(void)
void tud_suspend_cb(bool remote_wakeup_en)
{
(void)remote_wakeup_en;
usb_suspended = true;
}

// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
usb_suspended = false;
}
1 change: 1 addition & 0 deletions lib/TinyUSB_Gamepad/src/usb_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ typedef enum

InputMode get_input_mode(void);
bool get_usb_mounted(void);
bool get_usb_suspended(void);
void initialize_driver(InputMode mode);
void receive_report(uint8_t *buffer);
bool send_report(void *report, uint16_t report_size);
Expand Down
3 changes: 3 additions & 0 deletions proto/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ message DisplayOptions
optional bool invert = 16;

optional int32 displaySaverTimeout = 17;
optional bool turnOffWhenSuspended = 18;
}

message LEDOptions
Expand Down Expand Up @@ -200,6 +201,8 @@ message LEDOptions
optional int32 pledPin3 = 28;
optional int32 pledPin4 = 29;
optional uint32 pledColor = 30;

optional bool turnOffWhenSuspended = 31;
};

// This has to be kept in sync with AnimationOptions in AnimationStation.hpp
Expand Down
9 changes: 9 additions & 0 deletions src/addons/i2cdisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "ps4_driver.h"
#include "helper.h"
#include "config.pb.h"
#include "usb_driver.h"

bool I2CDisplayAddon::available() {
const DisplayOptions& options = Storage::getInstance().getDisplayOptions();
Expand Down Expand Up @@ -56,10 +57,18 @@ void I2CDisplayAddon::setup() {
displaySaverTimer = options.displaySaverTimeout;
displaySaverTimeout = displaySaverTimer;
configMode = Storage::getInstance().GetConfigMode();
turnOffWhenSuspended = options.turnOffWhenSuspended;
}

bool I2CDisplayAddon::isDisplayPowerOff()
{
if (turnOffWhenSuspended && get_usb_suspended()) {
if (displayIsPowerOn) setDisplayPower(0);
return true;
} else {
if (!displayIsPowerOn) setDisplayPower(1);
}

if (!displaySaverTimeout && !isFocusModeEnabled) return false;

float diffTime = getMillis() - prevMillis;
Expand Down
9 changes: 9 additions & 0 deletions src/addons/neopicoleds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "addons/neopicoleds.h"
#include "addons/pleds.h"
#include "themes.h"
#include "usb_driver.h"

#include "enums.h"
#include "helper.h"
Expand Down Expand Up @@ -110,6 +111,7 @@ void NeoPicoLEDAddon::setup()
{
// Set Default LED Options
const LEDOptions& ledOptions = Storage::getInstance().getLedOptions();
turnOffWhenSuspended = ledOptions.turnOffWhenSuspended;

if ( ledOptions.pledType == PLED_TYPE_RGB ) {
neoPLEDs = new NeoPicoPlayerLEDs();
Expand Down Expand Up @@ -178,6 +180,13 @@ void NeoPicoLEDAddon::process()
}
}
}

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
Expand Down
5 changes: 5 additions & 0 deletions src/addons/playerleds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "hardware/pwm.h"
#include "GamepadEnums.h"
#include "xinput_driver.h"
#include "usb_driver.h"

// GP2040 Includes
#include "addons/pleds.h"
Expand Down Expand Up @@ -83,6 +84,8 @@ bool PlayerLEDAddon::available() {

void PlayerLEDAddon::setup() {
const LEDOptions& ledOptions = Storage::getInstance().getLedOptions();
turnOffWhenSuspended = ledOptions.turnOffWhenSuspended;

switch (ledOptions.pledType)
{
case PLED_TYPE_PWM:
Expand All @@ -99,6 +102,8 @@ void PlayerLEDAddon::setup() {

void PlayerLEDAddon::process()
{
if (turnOffWhenSuspended && get_usb_suspended()) return;

Gamepad * gamepad = Storage::getInstance().GetProcessedGamepad();
const LEDOptions& ledOptions = Storage::getInstance().getLedOptions();

Expand Down
2 changes: 2 additions & 0 deletions src/config_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config)
INIT_UNSET_PROPERTY(config.displayOptions, i2cSpeed, I2C_SPEED);
INIT_UNSET_PROPERTY(config.displayOptions, buttonLayout, BUTTON_LAYOUT);
INIT_UNSET_PROPERTY(config.displayOptions, buttonLayoutRight, BUTTON_LAYOUT_RIGHT);
INIT_UNSET_PROPERTY(config.displayOptions, turnOffWhenSuspended, DISPLAY_TURN_OFF_WHEN_SUSPENDED);

ButtonLayoutParamsLeft& paramsLeft = config.displayOptions.buttonLayoutCustomOptions.paramsLeft;
INIT_UNSET_PROPERTY(paramsLeft, layout, BUTTON_LAYOUT);
Expand Down Expand Up @@ -277,6 +278,7 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config)
INIT_UNSET_PROPERTY(config.ledOptions, ledsPerButton, LEDS_PER_PIXEL);
INIT_UNSET_PROPERTY(config.ledOptions, brightnessMaximum, LED_BRIGHTNESS_MAXIMUM);
INIT_UNSET_PROPERTY(config.ledOptions, brightnessSteps, LED_BRIGHTNESS_STEPS);
INIT_UNSET_PROPERTY(config.ledOptions, turnOffWhenSuspended, LEDS_TURN_OFF_WHEN_SUSPENDED);

INIT_UNSET_PROPERTY(config.ledOptions, indexUp, LEDS_DPAD_UP);
INIT_UNSET_PROPERTY(config.ledOptions, indexDown, LEDS_DPAD_DOWN);
Expand Down
4 changes: 4 additions & 0 deletions src/configs/webconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ std::string setDisplayOptions(DisplayOptions& displayOptions)
readDoc(displayOptions.splashChoice, doc, "splashChoice");
readDoc(displayOptions.splashDuration, doc, "splashDuration");
readDoc(displayOptions.displaySaverTimeout, doc, "displaySaverTimeout");
readDoc(displayOptions.turnOffWhenSuspended, doc, "turnOffWhenSuspended");

readDoc(displayOptions.buttonLayoutCustomOptions.paramsLeft.layout, doc, "buttonLayoutCustomOptions", "params", "layout");
readDoc(displayOptions.buttonLayoutCustomOptions.paramsLeft.common.startX, doc, "buttonLayoutCustomOptions", "params", "startX");
Expand Down Expand Up @@ -461,6 +462,7 @@ std::string getDisplayOptions() // Manually set Document Attributes for the disp
writeDoc(doc, "splashChoice", displayOptions.splashChoice);
writeDoc(doc, "splashDuration", displayOptions.splashDuration);
writeDoc(doc, "displaySaverTimeout", displayOptions.displaySaverTimeout);
writeDoc(doc, "turnOffWhenSuspended", displayOptions.turnOffWhenSuspended);

writeDoc(doc, "buttonLayoutCustomOptions", "params", "layout", displayOptions.buttonLayoutCustomOptions.paramsLeft.layout);
writeDoc(doc, "buttonLayoutCustomOptions", "params", "startX", displayOptions.buttonLayoutCustomOptions.paramsLeft.common.startX);
Expand Down Expand Up @@ -655,6 +657,7 @@ std::string setLedOptions()
readDoc(ledOptions.ledsPerButton, doc, "ledsPerButton");
readDoc(ledOptions.brightnessMaximum, doc, "brightnessMaximum");
readDoc(ledOptions.brightnessSteps, doc, "brightnessSteps");
readDoc(ledOptions.turnOffWhenSuspended, doc, "turnOffWhenSuspended");
readIndex(ledOptions.indexUp, "ledButtonMap", "Up");
readIndex(ledOptions.indexDown, "ledButtonMap", "Down");
readIndex(ledOptions.indexLeft, "ledButtonMap", "Left");
Expand Down Expand Up @@ -694,6 +697,7 @@ std::string getLedOptions()
writeDoc(doc, "ledsPerButton", ledOptions.ledsPerButton);
writeDoc(doc, "brightnessMaximum", ledOptions.brightnessMaximum);
writeDoc(doc, "brightnessSteps", ledOptions.brightnessSteps);
writeDoc(doc, "turnOffWhenSuspended", ledOptions.turnOffWhenSuspended);

const auto writeIndex = [&](const char* key0, const char* key1, int var)
{
Expand Down
2 changes: 2 additions & 0 deletions www/server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ app.get('/api/getDisplayOptions', (req, res) => {
},

displaySaverTimeout: 0,
turnOffWhenSuspended: 0,
};
console.log('data', data);
return res.send(data);
Expand Down Expand Up @@ -192,6 +193,7 @@ app.get('/api/getLedOptions', (req, res) => {
pledPin3: 14,
pledPin4: 15,
pledColor: 65280,
turnOffWhenSuspended: 0,
});
});

Expand Down
1 change: 1 addition & 0 deletions www/src/Locales/en/DisplayConfig.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ export default {
'splash-duration-label': 'Splash Duration (seconds, 0 for Always On)',
'display-saver-timeout-label': 'Display Saver Timeout (minutes)',
'inverted-label': 'Inverted',
'turn-off-when-suspended': 'Turn Off When Suspended'
},
};
1 change: 1 addition & 0 deletions www/src/Locales/en/LedConfig.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ export default {
'available-header-text': 'Available Buttons',
'assigned-header-text': 'Assigned Buttons',
},
'turn-off-when-suspended': 'Turn Off When Suspended'
};
22 changes: 21 additions & 1 deletion www/src/Pages/DisplayConfig.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ const schema = yup.object().shape({
.oneOf(DISPLAY_FLIP_MODES.map((o) => o.value))
.label('Flip Display'),
invertDisplay: yup.number().label('Invert Display'),
turnOffWhenSuspended: yup.number().label('Turn Off When Suspended'),
buttonLayout: buttonLayoutSchema,
buttonLayoutRight: buttonLayoutRightSchema,
splashMode: yup
Expand Down Expand Up @@ -226,6 +227,8 @@ const FormContext = () => {
values.splashChoice = parseInt(values.splashChoice);
if (!!values.splashDuration)
values.splashDuration = parseInt(values.splashDuration);
if (!!values.turnOffWhenSuspended)
values.turnOffWhenSuspended = parseInt(values.turnOffWhenSuspended);

await WebApi.setDisplayOptions(values, true);
}
Expand All @@ -241,6 +244,8 @@ const FormContext = () => {
values.flipDisplay = parseInt(values.flipDisplay);
if (!!values.invertDisplay)
values.invertDisplay = parseInt(values.invertDisplay);
if (!!values.turnOffWhenSuspended)
values.turnOffWhenSuspended = parseInt(values.turnOffWhenSuspended);
if (!!values.buttonLayout)
values.buttonLayout = parseInt(values.buttonLayout);
if (!!values.buttonLayoutRight)
Expand Down Expand Up @@ -291,7 +296,7 @@ export default function DisplayConfigPage() {
onSubmit={onSuccess}
initialValues={defaultValues}
>
{({ handleSubmit, handleChange, handleBlur, values, touched, errors }) =>
{({ handleSubmit, handleChange, handleBlur, values, touched, errors, setFieldValue }) =>
console.log('errors', errors) ||
console.log('values', values) || (
<Section title={t('DisplayConfig:header-text')}>
Expand Down Expand Up @@ -511,6 +516,21 @@ export default function DisplayConfigPage() {
</option>
))}
</FormSelect>
<div className="col-sm-3">
<Form.Check
label={t('DisplayConfig:form.turn-off-when-suspended')}
type="switch"
name="turnOffWhenSuspended"
isInvalid={false}
checked={Boolean(values.turnOffWhenSuspended)}
onChange={(e) => {
setFieldValue(
'turnOffWhenSuspended',
e.target.checked ? 1 : 0,
);
}}
/>
</div>
</Row>
<Row className="mb-3">
<FormSelect
Expand Down
34 changes: 34 additions & 0 deletions www/src/Pages/LEDConfigPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ const schema = yup.object().shape({
.number()
.label('PLED Index 4')
.validateMinWhenEqualTo('pledType', 1, 0),
turnOffWhenSuspended: yup.number().label('Turn Off When Suspended'),
});

const getLedButtons = (buttonLabels, map, excludeNulls, swapTpShareLabels) => {
Expand Down Expand Up @@ -314,6 +315,8 @@ export default function LEDConfigPage() {
const data = { ...values };
data.pledType = parseInt(values.pledType);
if (data.pledColor) data.pledColor = hexToInt(values.pledColor);
if (!!data.turnOffWhenSuspended)
data.turnOffWhenSuspended = parseInt(values.turnOffWhenSuspended);

const success = await WebApi.setLedOptions(data);
if (success) updateUsedPins();
Expand Down Expand Up @@ -369,6 +372,7 @@ export default function LEDConfigPage() {
setValues,
values,
errors,
setFieldValue,
}) => (
<Form
noValidate
Expand Down Expand Up @@ -461,6 +465,21 @@ export default function LEDConfigPage() {
min={1}
max={10}
/>
<div className="col-sm-3">
<Form.Check
label={t('LedConfig:turn-off-when-suspended')}
type="switch"
name="turnOffWhenSuspended"
isInvalid={false}
checked={Boolean(values.turnOffWhenSuspended)}
onChange={(e) => {
setFieldValue(
'turnOffWhenSuspended',
e.target.checked ? 1 : 0,
);
}}
/>
</div>
</Row>
</Section>
<Section title={t('LedConfig:player.header-text')}>
Expand Down Expand Up @@ -619,6 +638,21 @@ export default function LEDConfigPage() {
show={showPicker}
target={colorPickerTarget}
></ColorPicker>
<div className="col-sm-3 mb-3">
<Form.Check
label={t('LedConfig:turn-off-when-suspended')}
type="switch"
name="turnOffWhenSuspended"
isInvalid={false}
checked={Boolean(values.turnOffWhenSuspended)}
onChange={(e) => {
setFieldValue(
'turnOffWhenSuspended',
e.target.checked ? 1 : 0,
);
}}
/>
</div>
</Row>
<p hidden={parseInt(values.pledType) !== 0}>
{t('LedConfig:player.pwm-sub-header-text')}
Expand Down

0 comments on commit e90c448

Please sign in to comment.