From d7aa200addcab4e5ed4e7156b7c1fe4d5fb28111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kir=C3=A1ly=20D=C3=A1vid?= Date: Sat, 18 Nov 2023 19:05:17 +0100 Subject: [PATCH 1/6] Re-implement input history #602 --- CMakeLists.txt | 1 + headers/addons/i2cdisplay.h | 5 + headers/addons/inputhistory.h | 54 +++++ proto/config.proto | 9 + site/docs/add-ons/input-history.mdx | 30 +++ .../images/gpc-add-ons-input-history.png | Bin 0 -> 6963 bytes .../menu-pages/08-add-ons-configuration.mdx | 1 + src/addons/i2cdisplay.cpp | 60 +++--- src/addons/inputhistory.cpp | 197 ++++++++++++++++++ src/config_utils.cpp | 6 + src/configs/webconfig.cpp | 12 ++ src/gp2040aux.cpp | 5 +- www/server/app.js | 4 + www/src/Addons/InputHistory.tsx | 102 +++++++++ www/src/Locales/en/AddonsConfig.jsx | 4 + www/src/Locales/pt-BR/AddonsConfig.jsx | 4 + www/src/Locales/zh-CN/AddonsConfig.jsx | 4 + www/src/Pages/AddonsConfigPage.jsx | 4 + 18 files changed, 477 insertions(+), 25 deletions(-) create mode 100644 headers/addons/inputhistory.h create mode 100644 site/docs/add-ons/input-history.mdx create mode 100644 site/docs/assets/images/gpc-add-ons-input-history.png create mode 100644 src/addons/inputhistory.cpp create mode 100644 www/src/Addons/InputHistory.tsx diff --git a/CMakeLists.txt b/CMakeLists.txt index 36d7ff1fc..d21735dd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,6 +156,7 @@ src/addons/slider_socd.cpp src/addons/wiiext.cpp src/addons/input_macro.cpp src/addons/snes_input.cpp +src/addons/inputhistory.cpp src/gamepad/GamepadDebouncer.cpp src/gamepad/GamepadDescriptors.cpp src/addons/tilt.cpp diff --git a/headers/addons/i2cdisplay.h b/headers/addons/i2cdisplay.h index 4fd996070..33d830101 100644 --- a/headers/addons/i2cdisplay.h +++ b/headers/addons/i2cdisplay.h @@ -13,6 +13,7 @@ #include "gpaddon.h" #include "gamepad.h" #include "storagemanager.h" +#include "addons/inputhistory.h" #ifndef HAS_I2C_DISPLAY #define HAS_I2C_DISPLAY -1 @@ -141,6 +142,8 @@ class I2CDisplayAddon : public GPAddon { public: + I2CDisplayAddon(InputHistoryAddon*); + ~I2CDisplayAddon() {} virtual bool available(); virtual void setup(); virtual void preprocess() {} @@ -219,6 +222,8 @@ class I2CDisplayAddon : public GPAddon bool isFocusModeEnabled; bool focusModePrevState; bool turnOffWhenSuspended; + bool isInputHistoryEnabled; + InputHistoryAddon* inputHistoryAddon; }; #endif diff --git a/headers/addons/inputhistory.h b/headers/addons/inputhistory.h new file mode 100644 index 000000000..fc875292a --- /dev/null +++ b/headers/addons/inputhistory.h @@ -0,0 +1,54 @@ +#ifndef INPUT_HISTORY_H_ +#define INPUT_HISTORY_H_ + +#include "OneBitDisplay.h" + +#include +#include +#include "gpaddon.h" +#include +#include + +#ifndef INPUT_HISTORY_ENABLED +#define INPUT_HISTORY_ENABLED 0 +#endif + +#ifndef INPUT_HISTORY_LENGTH +#define INPUT_HISTORY_LENGTH 21 +#endif + +#ifndef INPUT_HISTORY_COL +#define INPUT_HISTORY_COL 0 +#endif + +#ifndef INPUT_HISTORY_ROW +#define INPUT_HISTORY_ROW 7 +#endif + +#define InputHistoryName "InputHistory" + +class InputHistoryAddon : public GPAddon +{ +public: + virtual bool available(); + virtual void setup(); + virtual void preprocess() {} + virtual void process(); + virtual std::string name() { return InputHistoryName; } + virtual void drawHistory(OBDISP *pOBD); +private: + uint32_t historyLength; + uint32_t col; + uint32_t row; + std::string historyString; + std::deque inputHistory; + std::array lastInput; + Gamepad* gamepad; + Gamepad* pGamepad; + bool pressedUp(); + bool pressedDown(); + bool pressedLeft(); + bool pressedRight(); +}; + +#endif \ No newline at end of file diff --git a/proto/config.proto b/proto/config.proto index 568aebc36..3b988b63e 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -653,6 +653,14 @@ message MacroOptions repeated Macro macroList = 3 [(nanopb).max_count = 6]; } +message InputHistoryOptions +{ + optional bool enabled = 1; + optional uint32 length = 2; + optional uint32 col = 3; + optional uint32 row = 4; +} + message AddonOptions { optional BootselButtonOptions bootselButtonOptions = 1; @@ -675,6 +683,7 @@ message AddonOptions optional TiltOptions tiltOptions = 18; optional PSPassthroughOptions psPassthroughOptions = 19; optional MacroOptions macroOptions = 20; + optional InputHistoryOptions inputHistoryOptions = 21; } message MigrationHistory diff --git a/site/docs/add-ons/input-history.mdx b/site/docs/add-ons/input-history.mdx new file mode 100644 index 000000000..eb8dfa740 --- /dev/null +++ b/site/docs/add-ons/input-history.mdx @@ -0,0 +1,30 @@ +--- +title: Input History +# tags: +# - +pagination_next: null +pagination_prev: null +description: "Add-on to show input history" +--- + +# Input History + +Purpose: This add-on is intended to allow you to display input history + +![GP2040-CE Configurator - Add-Ons Input History](../assets/images/gpc-add-ons-input-history.png) + +## Web Configurator Options + +- `History Length` - Set the max character length of the history. +- `Column` - Specify the column at which the history begins on the display. ( 0 - left, 20 - right ) +- `Row` - Specify the row on which the history appears on the display. ( 0 - top, 7 - bottom ) + +## Hardware + +### Requirements + +An already configured [monochrome display](../web-configurator/menu-pages/07-display-configuration.mdx). + +## Miscellaneous Notes + +None diff --git a/site/docs/assets/images/gpc-add-ons-input-history.png b/site/docs/assets/images/gpc-add-ons-input-history.png new file mode 100644 index 0000000000000000000000000000000000000000..c49d1e3a628f6da300f9a77cb2204da58994ede6 GIT binary patch literal 6963 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 literal 0 HcmV?d00001 diff --git a/site/docs/web-configurator/menu-pages/08-add-ons-configuration.mdx b/site/docs/web-configurator/menu-pages/08-add-ons-configuration.mdx index 5a6a77c1e..23157104e 100644 --- a/site/docs/web-configurator/menu-pages/08-add-ons-configuration.mdx +++ b/site/docs/web-configurator/menu-pages/08-add-ons-configuration.mdx @@ -26,6 +26,7 @@ Some of these add-ons are experimental and not all add-ons are interoperable wit - [Extra Button Configuration](../../add-ons/extra-button.mdx) - [Focus Mode Configuration](../../add-ons/focus-mode.mdx) - [I2C Analog ADS1219](../../add-ons/i2c-analog-ads1219.mdx) +- [Input History](../../add-ons/input-history.mdx) - [Input Reverse](../../add-ons/input-reverse.mdx) - [Joystick Selection Slider](../../add-ons/joystick-selection-slider.mdx) - [Keyboard Host Configuration](../../add-ons/keyboard-host.mdx) diff --git a/src/addons/i2cdisplay.cpp b/src/addons/i2cdisplay.cpp index 1af67cd79..ee53df6a3 100644 --- a/src/addons/i2cdisplay.cpp +++ b/src/addons/i2cdisplay.cpp @@ -15,6 +15,10 @@ #include "config.pb.h" #include "usb_driver.h" +I2CDisplayAddon::I2CDisplayAddon(InputHistoryAddon* pInputHistoryAddon) { + inputHistoryAddon = pInputHistoryAddon; +} + bool I2CDisplayAddon::available() { const DisplayOptions& options = Storage::getInstance().getDisplayOptions(); return options.enabled && @@ -58,6 +62,9 @@ void I2CDisplayAddon::setup() { displaySaverTimeout = displaySaverTimer; configMode = Storage::getInstance().GetConfigMode(); turnOffWhenSuspended = options.turnOffWhenSuspended; + + const InputHistoryOptions& inputHistoryOptions = Storage::getInstance().getAddonOptions().inputHistoryOptions; + isInputHistoryEnabled = inputHistoryOptions.enabled; } bool I2CDisplayAddon::isDisplayPowerOff() @@ -135,37 +142,37 @@ void I2CDisplayAddon::process() { switch (options.buttonLayout) { case BUTTON_LAYOUT_STICK: - drawArcadeStick(8, 28, 8, 2); + drawArcadeStick(8, (isInputHistoryEnabled ? 22 : 28), 8, 2); break; case BUTTON_LAYOUT_STICKLESS: drawStickless(8, 20, 8, 2); break; case BUTTON_LAYOUT_BUTTONS_ANGLED: - drawWasdBox(8, 28, 7, 3); + drawWasdBox(8, (isInputHistoryEnabled ? 22 : 28), 7, 3); break; case BUTTON_LAYOUT_BUTTONS_BASIC: - drawUDLR(8, 28, 8, 2); + drawUDLR(8, (isInputHistoryEnabled ? 22 : 28), 8, 2); break; case BUTTON_LAYOUT_KEYBOARD_ANGLED: - drawKeyboardAngled(18, 28, 5, 2); + drawKeyboardAngled(18, (isInputHistoryEnabled ? 24 : 28), 5, 2); break; case BUTTON_LAYOUT_KEYBOARDA: - drawMAMEA(8, 28, 10, 1); + drawMAMEA(8, (isInputHistoryEnabled ? 22 : 28), 10, 1); break; case BUTTON_LAYOUT_OPENCORE0WASDA: - drawOpenCore0WASDA(16, 28, 10, 1); + drawOpenCore0WASDA(16, (isInputHistoryEnabled ? 22 : 28), 10, 1); break; case BUTTON_LAYOUT_DANCEPADA: - drawDancepadA(39, 12, 15, 2); + drawDancepadA(39, (isInputHistoryEnabled ? 10 : 12), (isInputHistoryEnabled ? 13 : 15), 2); break; case BUTTON_LAYOUT_TWINSTICKA: - drawTwinStickA(8, 28, 8, 2); + drawTwinStickA(8, (isInputHistoryEnabled ? 22 : 28), 8, 2); break; case BUTTON_LAYOUT_BLANKA: drawBlankA(0, 0, 0, 0); break; case BUTTON_LAYOUT_VLXA: - drawVLXA(7, 28, 7, 2); + drawVLXA(7, (isInputHistoryEnabled ? 22 : 28), 7, 2); break; case BUTTON_LAYOUT_CUSTOMA: drawButtonLayoutLeft(buttonLayoutCustomOptions.paramsLeft); @@ -180,52 +187,52 @@ void I2CDisplayAddon::process() { switch (options.buttonLayoutRight) { case BUTTON_LAYOUT_ARCADE: - drawArcadeButtons(8, 28, 8, 2); + drawArcadeButtons(8, (isInputHistoryEnabled ? 22 : 28), 8, 2); break; case BUTTON_LAYOUT_STICKLESSB: drawSticklessButtons(8, 20, 8, 2); break; case BUTTON_LAYOUT_BUTTONS_ANGLEDB: - drawWasdButtons(8, 28, 7, 3); + drawWasdButtons(8, (isInputHistoryEnabled ? 22 : 28), 7, 3); break; case BUTTON_LAYOUT_VEWLIX: - drawVewlix(8, 28, 8, 2); + drawVewlix(8, (isInputHistoryEnabled ? 22 : 28), 8, 2); break; case BUTTON_LAYOUT_VEWLIX7: - drawVewlix7(8, 28, 8, 2); + drawVewlix7(8, (isInputHistoryEnabled ? 22 : 28), 8, 2); break; case BUTTON_LAYOUT_CAPCOM: - drawCapcom(6, 28, 8, 2); + drawCapcom(6, (isInputHistoryEnabled ? 22 : 28), 8, 2); break; case BUTTON_LAYOUT_CAPCOM6: - drawCapcom6(16, 28, 8, 2); + drawCapcom6(16, (isInputHistoryEnabled ? 22 : 28), 8, 2); break; case BUTTON_LAYOUT_SEGA2P: - drawSega2p(8, 28, 8, 2); + drawSega2p(8, (isInputHistoryEnabled ? 22 : 28), 8, 2); break; case BUTTON_LAYOUT_NOIR8: - drawNoir8(8, 28, 8, 2); + drawNoir8(8, (isInputHistoryEnabled ? 22 : 28), 8, 2); break; case BUTTON_LAYOUT_KEYBOARDB: - drawMAMEB(68, 28, 10, 1); + drawMAMEB(68, (isInputHistoryEnabled ? 22 : 28), 10, 1); break; case BUTTON_LAYOUT_KEYBOARD8B: - drawMAME8B(68, 28, 10, 1); + drawMAME8B(68, (isInputHistoryEnabled ? 22 : 28), 10, 1); break; case BUTTON_LAYOUT_OPENCORE0WASDB: - drawOpenCore0WASDB(68, 28, 10, 1); + drawOpenCore0WASDB(68, (isInputHistoryEnabled ? 22 : 28), 10, 1); break; case BUTTON_LAYOUT_DANCEPADB: - drawDancepadB(39, 12, 15, 2); + drawDancepadB(39, (isInputHistoryEnabled ? 10 : 12), (isInputHistoryEnabled ? 13 : 15), 2); break; case BUTTON_LAYOUT_TWINSTICKB: - drawTwinStickB(100, 28, 8, 2); + drawTwinStickB(100, (isInputHistoryEnabled ? 22 : 28), 8, 2); break; case BUTTON_LAYOUT_BLANKB: drawSticklessButtons(0, 0, 0, 0); break; case BUTTON_LAYOUT_VLXB: - drawVLXB(6, 28, 7, 2); + drawVLXB(6, (isInputHistoryEnabled ? 22 : 28), 7, 2); break; case BUTTON_LAYOUT_CUSTOMB: drawButtonLayoutRight(buttonLayoutCustomOptions.paramsRight); @@ -237,6 +244,11 @@ void I2CDisplayAddon::process() { drawArcadeStick(90, 22, 8, 2); break; } + + if(isInputHistoryEnabled) { + inputHistoryAddon->drawHistory(&obd); + } + break; } @@ -494,7 +506,7 @@ void I2CDisplayAddon::drawStickless(int startX, int startY, int buttonRadius, in obdPreciseEllipse(&obd, startX, startY, buttonRadius, buttonRadius, 1, pressedLeft()); obdPreciseEllipse(&obd, startX + buttonMargin, startY, buttonRadius, buttonRadius, 1, pressedDown()); obdPreciseEllipse(&obd, startX + (buttonMargin * 1.875), startY + (buttonMargin / 2), buttonRadius, buttonRadius, 1, pressedRight()); - obdPreciseEllipse(&obd, startX + (buttonMargin * 2.25), startY + buttonMargin * 1.875, buttonRadius, buttonRadius, 1, pressedUp()); + obdPreciseEllipse(&obd, startX + (buttonMargin * (isInputHistoryEnabled ? 1.875 : 2.25)), startY + buttonMargin * (isInputHistoryEnabled ? 1.5 : 1.875), buttonRadius, buttonRadius, 1, pressedUp()); } void I2CDisplayAddon::drawWasdBox(int startX, int startY, int buttonRadius, int buttonPadding) diff --git a/src/addons/inputhistory.cpp b/src/addons/inputhistory.cpp new file mode 100644 index 000000000..88aea6b10 --- /dev/null +++ b/src/addons/inputhistory.cpp @@ -0,0 +1,197 @@ +#include "addons/inputhistory.h" +#include "storagemanager.h" +#include "math.h" +#include "usb_driver.h" +#include "helper.h" +#include "config.pb.h" + +static const std::string displayNames[][18] = { + { // HID / DINPUT + "U", "D", "L", "R", + "X", "O", "#", "^", + "L1", "R1", "L2", "R2", + "SL", "ST", "LS", "RS", "H", "A2" + }, + { // Switch + "U", "D", "L", "R", + "B", "A", "Y", "X", + "L", "R", "ZL", "ZR", + "-", "+", "LS", "RS", "H", "C" + }, + { // XInput + "U", "D", "L", "R", + "A", "B", "X", "Y", + "LB", "RB", "LT", "RT", + "S1", "S2", "L3", "R3", "A1", "A2" + }, + { // Keyboard / HID-KB + "U", "D", "L", "R", + "B1", "B2", "B3", "B4", + "L1", "R1", "L2", "R2", + "S1", "S2", "L3", "R3", "A1", "A2" + }, + { // PS4 + "U", "D", "L", "R", + "X", "O", "#", "^", + "L1", "R1", "L2", "R2", + "SL", "ST", "LS", "RS", "H", "A2" + }, + { // Config + "U", "D", "L", "R", + "B1", "B2", "B3", "B4", + "L1", "R1", "L2", "R2", + "S1", "S2", "L3", "R3", "A1", "A2" + } +}; + +bool InputHistoryAddon::available() { + const InputHistoryOptions& options = Storage::getInstance().getAddonOptions().inputHistoryOptions; + return options.enabled; +} + +void InputHistoryAddon::setup() { + const InputHistoryOptions& options = Storage::getInstance().getAddonOptions().inputHistoryOptions; + historyLength = options.length; + col = options.col; + row = options.row; + + gamepad = Storage::getInstance().GetGamepad(); + pGamepad = Storage::getInstance().GetProcessedGamepad(); +} + +void InputHistoryAddon::process() { + std::deque pressed; + + // Get key states + std::array currentInput = { + pressedUp(), + pressedDown(), + pressedLeft(), + pressedRight(), + gamepad->pressedB1(), + gamepad->pressedB2(), + gamepad->pressedB3(), + gamepad->pressedB4(), + gamepad->pressedL1(), + gamepad->pressedR1(), + gamepad->pressedL2(), + gamepad->pressedR2(), + gamepad->pressedS1(), + gamepad->pressedS2(), + gamepad->pressedL3(), + gamepad->pressedR3(), + gamepad->pressedA1(), + gamepad->pressedA2(), + }; + + uint8_t mode; + switch (gamepad->getOptions().inputMode) + { + case INPUT_MODE_HID: mode=0; break; + case INPUT_MODE_SWITCH: mode=1; break; + case INPUT_MODE_XINPUT: mode=2; break; + case INPUT_MODE_KEYBOARD: mode=3; break; + case INPUT_MODE_PS4: mode=4; break; + case INPUT_MODE_CONFIG: mode=5; break; + default: mode=0; break; + } + + // Check if any new keys have been pressed + if (lastInput != currentInput) { + // Iterate through array + for (uint8_t x=0; x<18; x++) { + // Add any pressed keys to deque + if (currentInput[x]) pressed.push_back(displayNames[mode][x]); + } + // Update the last keypress array + lastInput = currentInput; + } + + if (pressed.size() > 0) { + std::string newInput; + for(const auto &s : pressed) { + if(!newInput.empty()) + newInput += "+"; + newInput += s; + } + + inputHistory.push_back(newInput); + } + + if (inputHistory.size() > (historyLength / 2) + 1) { + inputHistory.pop_front(); + } + + std::string ret; + + for (auto it = inputHistory.crbegin(); it != inputHistory.crend(); ++it) { + std::string newRet = ret; + if (!newRet.empty()) + newRet = " " + newRet; + + newRet = *it + newRet; + ret = newRet; + + if (ret.size() >= historyLength) { + break; + } + } + + if(ret.size() >= historyLength) { + historyString = ret.substr(ret.size() - historyLength); + } else { + historyString = ret; + } +} + +void InputHistoryAddon::drawHistory(OBDISP *pOBD) { + obdWriteString(pOBD, 0, col * 6, row, (char *)historyString.c_str(), FONT_6x8, 0, 0); +} + +bool InputHistoryAddon::pressedUp() +{ + switch (gamepad->getOptions().dpadMode) + { + case DPAD_MODE_DIGITAL: return pGamepad->pressedUp(); + case DPAD_MODE_LEFT_ANALOG: return pGamepad->state.ly == GAMEPAD_JOYSTICK_MIN; + case DPAD_MODE_RIGHT_ANALOG: return pGamepad->state.ry == GAMEPAD_JOYSTICK_MIN; + } + + return false; +} + +bool InputHistoryAddon::pressedDown() +{ + switch (gamepad->getOptions().dpadMode) + { + case DPAD_MODE_DIGITAL: return pGamepad->pressedDown(); + case DPAD_MODE_LEFT_ANALOG: return pGamepad->state.ly == GAMEPAD_JOYSTICK_MAX; + case DPAD_MODE_RIGHT_ANALOG: return pGamepad->state.ry == GAMEPAD_JOYSTICK_MAX; + } + + return false; +} + +bool InputHistoryAddon::pressedLeft() +{ + switch (gamepad->getOptions().dpadMode) + { + case DPAD_MODE_DIGITAL: return pGamepad->pressedLeft(); + case DPAD_MODE_LEFT_ANALOG: return pGamepad->state.lx == GAMEPAD_JOYSTICK_MIN; + case DPAD_MODE_RIGHT_ANALOG: return pGamepad->state.rx == GAMEPAD_JOYSTICK_MIN; + } + + return false; +} + +bool InputHistoryAddon::pressedRight() +{ + switch (gamepad->getOptions().dpadMode) + { + case DPAD_MODE_DIGITAL: return pGamepad->pressedRight(); + case DPAD_MODE_LEFT_ANALOG: return pGamepad->state.lx == GAMEPAD_JOYSTICK_MAX; + case DPAD_MODE_RIGHT_ANALOG: return pGamepad->state.rx == GAMEPAD_JOYSTICK_MAX; + } + + return false; +} \ No newline at end of file diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 4ea89e404..8b0d09e45 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -445,6 +445,12 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY(config.addonOptions.buzzerOptions, pin, BUZZER_PIN); INIT_UNSET_PROPERTY(config.addonOptions.buzzerOptions, volume, BUZZER_VOLUME); + // addonOptions.inputHistoryOptions + INIT_UNSET_PROPERTY(config.addonOptions.inputHistoryOptions, enabled, !!INPUT_HISTORY_ENABLED); + INIT_UNSET_PROPERTY(config.addonOptions.inputHistoryOptions, length, INPUT_HISTORY_LENGTH); + INIT_UNSET_PROPERTY(config.addonOptions.inputHistoryOptions, col, INPUT_HISTORY_COL); + INIT_UNSET_PROPERTY(config.addonOptions.inputHistoryOptions, row, INPUT_HISTORY_ROW); + // addonOptions.playerNumberOptions INIT_UNSET_PROPERTY(config.addonOptions.playerNumberOptions, enabled, !!PLAYERNUM_ADDON_ENABLED); INIT_UNSET_PROPERTY(config.addonOptions.playerNumberOptions, number, PLAYER_NUMBER); diff --git a/src/configs/webconfig.cpp b/src/configs/webconfig.cpp index fc0c38946..58484e3d9 100644 --- a/src/configs/webconfig.cpp +++ b/src/configs/webconfig.cpp @@ -1098,6 +1098,12 @@ std::string setAddonOptions() docToPin(snesOptions.latchPin, doc, "snesPadLatchPin"); docToPin(snesOptions.dataPin, doc, "snesPadDataPin"); + InputHistoryOptions& inputHistoryOptions = Storage::getInstance().getAddonOptions().inputHistoryOptions; + docToValue(inputHistoryOptions.length, doc, "inputHistoryLength"); + docToValue(inputHistoryOptions.enabled, doc, "InputHistoryAddonEnabled"); + docToValue(inputHistoryOptions.col, doc, "inputHistoryCol"); + docToValue(inputHistoryOptions.row, doc, "inputHistoryRow"); + KeyboardHostOptions& keyboardHostOptions = Storage::getInstance().getAddonOptions().keyboardHostOptions; docToValue(keyboardHostOptions.enabled, doc, "KeyboardHostAddonEnabled"); Pin_t oldKbPinDplus = keyboardHostOptions.pinDplus; @@ -1505,6 +1511,12 @@ std::string getAddonOptions() writeDoc(doc, "snesPadDataPin", cleanPin(snesOptions.dataPin)); writeDoc(doc, "SNESpadAddonEnabled", snesOptions.enabled); + const InputHistoryOptions& inputHistoryOptions = Storage::getInstance().getAddonOptions().inputHistoryOptions; + writeDoc(doc, "inputHistoryLength", inputHistoryOptions.length); + writeDoc(doc, "InputHistoryAddonEnabled", inputHistoryOptions.enabled); + writeDoc(doc, "inputHistoryCol", inputHistoryOptions.col); + writeDoc(doc, "inputHistoryRow", inputHistoryOptions.row); + const KeyboardHostOptions& keyboardHostOptions = Storage::getInstance().getAddonOptions().keyboardHostOptions; writeDoc(doc, "KeyboardHostAddonEnabled", keyboardHostOptions.enabled); writeDoc(doc, "keyboardHostPinDplus", keyboardHostOptions.pinDplus); diff --git a/src/gp2040aux.cpp b/src/gp2040aux.cpp index 3ddcc58ac..f0076dbe9 100644 --- a/src/gp2040aux.cpp +++ b/src/gp2040aux.cpp @@ -13,6 +13,7 @@ #include "addons/ps4mode.h" #include "addons/pspassthrough.h" #include "addons/neopicoleds.h" +#include "addons/inputhistory.h" #include @@ -25,7 +26,9 @@ GP2040Aux::~GP2040Aux() { void GP2040Aux::setup() { // Setup Add-ons addons.LoadUSBAddon(new PSPassthroughAddon(), CORE1_LOOP); - addons.LoadAddon(new I2CDisplayAddon(), CORE1_LOOP); + InputHistoryAddon* inputHistoryAddon = new InputHistoryAddon(); + addons.LoadAddon(inputHistoryAddon, CORE1_LOOP); + addons.LoadAddon(new I2CDisplayAddon(inputHistoryAddon), CORE1_LOOP); addons.LoadAddon(new NeoPicoLEDAddon(), CORE1_LOOP); addons.LoadAddon(new PlayerLEDAddon(), CORE1_LOOP); addons.LoadAddon(new BoardLedAddon(), CORE1_LOOP); diff --git a/www/server/app.js b/www/server/app.js index 6496a046c..469f9005d 100644 --- a/www/server/app.js +++ b/www/server/app.js @@ -461,6 +461,10 @@ app.get('/api/getAddonsOptions', (req, res) => { WiiExtensionAddonEnabled: 1, SNESpadAddonEnabled: 1, PSPassthroughAddonEnabled: 1, + InputHistoryAddonEnabled: 1, + inputHistoryLength: 21, + inputHistoryCol: 0, + inputHistoryRow: 7, usedPins: Object.values(picoController), }); }); diff --git a/www/src/Addons/InputHistory.tsx b/www/src/Addons/InputHistory.tsx new file mode 100644 index 000000000..512259109 --- /dev/null +++ b/www/src/Addons/InputHistory.tsx @@ -0,0 +1,102 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { FormCheck, Row } from 'react-bootstrap'; +import * as yup from 'yup'; + +import Section from '../Components/Section'; + +import FormControl from '../Components/FormControl'; + +export const inputHistoryScheme = { + InputHistoryAddonEnabled: yup + .number() + .required() + .label('Input History Enabled'), + inputHistoryLength: yup + .number() + .label('Input History Length') + .validateRangeWhenValue('InputHistoryAddonEnabled', 1, 21), + inputHistoryCol: yup + .number() + .label('Col') + .validateRangeWhenValue('InputHistoryAddonEnabled', 0, 20), + inputHistoryRow: yup + .number() + .label('Row') + .validateRangeWhenValue('InputHistoryAddonEnabled', 0, 7), +}; + +export const inputHistoryState = { + InputHistoryAddonEnabled: 0, + inputHistoryLength: 21, + inputHistoryCol: 0, + inputHistoryRow: 7, +}; + +const InputHistory = ({ values, errors, handleChange, handleCheckbox }) => { + const { t } = useTranslation(); + return ( +
+ + { + handleCheckbox('InputHistoryAddonEnabled', values); + handleChange(e); + }} + /> +
+ ); +}; + +export default InputHistory; diff --git a/www/src/Locales/en/AddonsConfig.jsx b/www/src/Locales/en/AddonsConfig.jsx index 1e22f0e28..5c748efda 100644 --- a/www/src/Locales/en/AddonsConfig.jsx +++ b/www/src/Locales/en/AddonsConfig.jsx @@ -144,4 +144,8 @@ export default { 'pspassthrough-d-minus-label': 'D-', 'pspassthrough-five-v-label': '5V Power (optional)', 'pin-config-moved-to-core-text': 'Note: the pins for this add-on are now configured on the Pin Mapping page.', + 'input-history-header-text': 'Input History', + 'input-history-length-label': 'History length (characters)', + 'input-history-col-label': 'Column', + 'input-history-row-label': 'Row' }; diff --git a/www/src/Locales/pt-BR/AddonsConfig.jsx b/www/src/Locales/pt-BR/AddonsConfig.jsx index 931020d6c..df9d9b40c 100644 --- a/www/src/Locales/pt-BR/AddonsConfig.jsx +++ b/www/src/Locales/pt-BR/AddonsConfig.jsx @@ -154,4 +154,8 @@ export default { 'pspassthrough-d-plus-label': 'D+', 'pspassthrough-d-minus-label': 'D-', 'pspassthrough-five-v-label': 'Alimentação 5V (opcional)', + 'input-history-header-text': 'Histórico de Entrada', + 'input-history-length-label': 'Comprimento do histórico (caracteres)', + 'input-history-col-label': 'Coluna', + 'input-history-row-label': 'Linha', }; diff --git a/www/src/Locales/zh-CN/AddonsConfig.jsx b/www/src/Locales/zh-CN/AddonsConfig.jsx index fc86a9769..65b1ed946 100644 --- a/www/src/Locales/zh-CN/AddonsConfig.jsx +++ b/www/src/Locales/zh-CN/AddonsConfig.jsx @@ -138,4 +138,8 @@ export default { 'pspassthrough-d-plus-label': 'D+', 'pspassthrough-d-minus-label': 'D-', 'pspassthrough-five-v-label': '5V 电源(可选)', + 'input-history-header-text': '输入历史', + 'input-history-length-label': '历史长度(字符)', + 'input-history-col-label': '列', + 'input-history-row-label': '行' }; diff --git a/www/src/Pages/AddonsConfigPage.jsx b/www/src/Pages/AddonsConfigPage.jsx index 25fba6a52..f92d69173 100644 --- a/www/src/Pages/AddonsConfigPage.jsx +++ b/www/src/Pages/AddonsConfigPage.jsx @@ -43,6 +43,7 @@ import FocusMode, { focusModeState, } from '../Addons/FocusMode'; import Keyboard, { keyboardScheme, keyboardState } from '../Addons/Keyboard'; +import InputHistory, { inputHistoryScheme, inputHistoryState } from '../Addons/InputHistory'; const schema = yup.object().shape({ ...analogScheme, @@ -62,6 +63,7 @@ const schema = yup.object().shape({ ...wiiScheme, ...focusModeScheme, ...keyboardScheme, + ...inputHistoryScheme, }); const defaultValues = { @@ -83,6 +85,7 @@ const defaultValues = { ...snesState, ...focusModeState, ...keyboardState, + ...inputHistoryState, }; const ADDONS = [ @@ -104,6 +107,7 @@ const ADDONS = [ SNES, FocusMode, Keyboard, + InputHistory ]; const FormContext = ({ setStoredData }) => { From f4e01ade2be1ca5aab50964c2316eedb4b765dac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kir=C3=A1ly=20D=C3=A1vid?= Date: Sat, 18 Nov 2023 19:47:49 +0100 Subject: [PATCH 2/6] Fix formatting --- headers/addons/inputhistory.h | 8 +- src/addons/inputhistory.cpp | 186 +++++++++++++++++----------------- 2 files changed, 97 insertions(+), 97 deletions(-) diff --git a/headers/addons/inputhistory.h b/headers/addons/inputhistory.h index fc875292a..13f4d2a33 100644 --- a/headers/addons/inputhistory.h +++ b/headers/addons/inputhistory.h @@ -31,7 +31,7 @@ class InputHistoryAddon : public GPAddon { public: virtual bool available(); - virtual void setup(); + virtual void setup(); virtual void preprocess() {} virtual void process(); virtual std::string name() { return InputHistoryName; } @@ -40,15 +40,15 @@ class InputHistoryAddon : public GPAddon uint32_t historyLength; uint32_t col; uint32_t row; - std::string historyString; + std::string historyString; std::deque inputHistory; std::array lastInput; Gamepad* gamepad; Gamepad* pGamepad; - bool pressedUp(); + bool pressedUp(); bool pressedDown(); bool pressedLeft(); bool pressedRight(); }; -#endif \ No newline at end of file +#endif diff --git a/src/addons/inputhistory.cpp b/src/addons/inputhistory.cpp index 88aea6b10..f2acf4ace 100644 --- a/src/addons/inputhistory.cpp +++ b/src/addons/inputhistory.cpp @@ -5,95 +5,95 @@ #include "helper.h" #include "config.pb.h" -static const std::string displayNames[][18] = { - { // HID / DINPUT - "U", "D", "L", "R", - "X", "O", "#", "^", - "L1", "R1", "L2", "R2", - "SL", "ST", "LS", "RS", "H", "A2" - }, - { // Switch - "U", "D", "L", "R", - "B", "A", "Y", "X", - "L", "R", "ZL", "ZR", - "-", "+", "LS", "RS", "H", "C" - }, - { // XInput - "U", "D", "L", "R", - "A", "B", "X", "Y", - "LB", "RB", "LT", "RT", - "S1", "S2", "L3", "R3", "A1", "A2" - }, - { // Keyboard / HID-KB - "U", "D", "L", "R", - "B1", "B2", "B3", "B4", - "L1", "R1", "L2", "R2", - "S1", "S2", "L3", "R3", "A1", "A2" - }, - { // PS4 - "U", "D", "L", "R", - "X", "O", "#", "^", - "L1", "R1", "L2", "R2", - "SL", "ST", "LS", "RS", "H", "A2" - }, - { // Config - "U", "D", "L", "R", - "B1", "B2", "B3", "B4", - "L1", "R1", "L2", "R2", - "S1", "S2", "L3", "R3", "A1", "A2" - } +static const std::string displayNames[][18] = { + { // HID / DINPUT + "U", "D", "L", "R", + "X", "O", "#", "^", + "L1", "R1", "L2", "R2", + "SL", "ST", "LS", "RS", "H", "A2" + }, + { // Switch + "U", "D", "L", "R", + "B", "A", "Y", "X", + "L", "R", "ZL", "ZR", + "-", "+", "LS", "RS", "H", "C" + }, + { // XInput + "U", "D", "L", "R", + "A", "B", "X", "Y", + "LB", "RB", "LT", "RT", + "S1", "S2", "L3", "R3", "A1", "A2" + }, + { // Keyboard / HID-KB + "U", "D", "L", "R", + "B1", "B2", "B3", "B4", + "L1", "R1", "L2", "R2", + "S1", "S2", "L3", "R3", "A1", "A2" + }, + { // PS4 + "U", "D", "L", "R", + "X", "O", "#", "^", + "L1", "R1", "L2", "R2", + "SL", "ST", "LS", "RS", "H", "A2" + }, + { // Config + "U", "D", "L", "R", + "B1", "B2", "B3", "B4", + "L1", "R1", "L2", "R2", + "S1", "S2", "L3", "R3", "A1", "A2" + } }; bool InputHistoryAddon::available() { - const InputHistoryOptions& options = Storage::getInstance().getAddonOptions().inputHistoryOptions; + const InputHistoryOptions& options = Storage::getInstance().getAddonOptions().inputHistoryOptions; return options.enabled; } void InputHistoryAddon::setup() { const InputHistoryOptions& options = Storage::getInstance().getAddonOptions().inputHistoryOptions; historyLength = options.length; - col = options.col; - row = options.row; - + col = options.col; + row = options.row; + gamepad = Storage::getInstance().GetGamepad(); pGamepad = Storage::getInstance().GetProcessedGamepad(); } void InputHistoryAddon::process() { - std::deque pressed; + std::deque pressed; - // Get key states + // Get key states std::array currentInput = { - pressedUp(), - pressedDown(), - pressedLeft(), - pressedRight(), - gamepad->pressedB1(), - gamepad->pressedB2(), - gamepad->pressedB3(), - gamepad->pressedB4(), - gamepad->pressedL1(), - gamepad->pressedR1(), - gamepad->pressedL2(), - gamepad->pressedR2(), - gamepad->pressedS1(), - gamepad->pressedS2(), - gamepad->pressedL3(), - gamepad->pressedR3(), - gamepad->pressedA1(), - gamepad->pressedA2(), - }; - - uint8_t mode; + pressedUp(), + pressedDown(), + pressedLeft(), + pressedRight(), + gamepad->pressedB1(), + gamepad->pressedB2(), + gamepad->pressedB3(), + gamepad->pressedB4(), + gamepad->pressedL1(), + gamepad->pressedR1(), + gamepad->pressedL2(), + gamepad->pressedR2(), + gamepad->pressedS1(), + gamepad->pressedS2(), + gamepad->pressedL3(), + gamepad->pressedR3(), + gamepad->pressedA1(), + gamepad->pressedA2(), + }; + + uint8_t mode; switch (gamepad->getOptions().inputMode) { - case INPUT_MODE_HID: mode=0; break; - case INPUT_MODE_SWITCH: mode=1; break; - case INPUT_MODE_XINPUT: mode=2; break; - case INPUT_MODE_KEYBOARD: mode=3; break; - case INPUT_MODE_PS4: mode=4; break; - case INPUT_MODE_CONFIG: mode=5; break; - default: mode=0; break; + case INPUT_MODE_HID: mode=0; break; + case INPUT_MODE_SWITCH: mode=1; break; + case INPUT_MODE_XINPUT: mode=2; break; + case INPUT_MODE_KEYBOARD: mode=3; break; + case INPUT_MODE_PS4: mode=4; break; + case INPUT_MODE_CONFIG: mode=5; break; + default: mode=0; break; } // Check if any new keys have been pressed @@ -108,14 +108,14 @@ void InputHistoryAddon::process() { } if (pressed.size() > 0) { - std::string newInput; - for(const auto &s : pressed) { - if(!newInput.empty()) - newInput += "+"; - newInput += s; - } - - inputHistory.push_back(newInput); + std::string newInput; + for(const auto &s : pressed) { + if(!newInput.empty()) + newInput += "+"; + newInput += s; + } + + inputHistory.push_back(newInput); } if (inputHistory.size() > (historyLength / 2) + 1) { @@ -125,23 +125,23 @@ void InputHistoryAddon::process() { std::string ret; for (auto it = inputHistory.crbegin(); it != inputHistory.crend(); ++it) { - std::string newRet = ret; - if (!newRet.empty()) - newRet = " " + newRet; + std::string newRet = ret; + if (!newRet.empty()) + newRet = " " + newRet; - newRet = *it + newRet; - ret = newRet; + newRet = *it + newRet; + ret = newRet; - if (ret.size() >= historyLength) { - break; - } + if (ret.size() >= historyLength) { + break; + } } - if(ret.size() >= historyLength) { - historyString = ret.substr(ret.size() - historyLength); - } else { - historyString = ret; - } + if(ret.size() >= historyLength) { + historyString = ret.substr(ret.size() - historyLength); + } else { + historyString = ret; + } } void InputHistoryAddon::drawHistory(OBDISP *pOBD) { @@ -194,4 +194,4 @@ bool InputHistoryAddon::pressedRight() } return false; -} \ No newline at end of file +} From 032560a900d3fc397d6f777393f3a6bf8424c3b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kir=C3=A1ly=20D=C3=A1vid?= Date: Sat, 18 Nov 2023 21:35:59 +0100 Subject: [PATCH 3/6] Installation header in docs --- site/docs/add-ons/input-history.mdx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/site/docs/add-ons/input-history.mdx b/site/docs/add-ons/input-history.mdx index eb8dfa740..1aa298f2b 100644 --- a/site/docs/add-ons/input-history.mdx +++ b/site/docs/add-ons/input-history.mdx @@ -25,6 +25,10 @@ Purpose: This add-on is intended to allow you to display input history An already configured [monochrome display](../web-configurator/menu-pages/07-display-configuration.mdx). +### Installation + +None. + ## Miscellaneous Notes -None +None. From 53242adccf9080daaa23ee318b27a87bb3f633b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kir=C3=A1ly=20D=C3=A1vid?= Date: Sat, 18 Nov 2023 22:35:30 +0100 Subject: [PATCH 4/6] Check if display is enabled --- src/addons/inputhistory.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/addons/inputhistory.cpp b/src/addons/inputhistory.cpp index f2acf4ace..20cbd6ca7 100644 --- a/src/addons/inputhistory.cpp +++ b/src/addons/inputhistory.cpp @@ -45,8 +45,9 @@ static const std::string displayNames[][18] = { }; bool InputHistoryAddon::available() { + const DisplayOptions& displayOptions = Storage::getInstance().getDisplayOptions(); const InputHistoryOptions& options = Storage::getInstance().getAddonOptions().inputHistoryOptions; - return options.enabled; + return displayOptions.enabled && options.enabled; } void InputHistoryAddon::setup() { From c147ae9f8a2a7b5c66f839af37b0431ce1887116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kir=C3=A1ly=20D=C3=A1vid?= Date: Sat, 18 Nov 2023 23:43:38 +0100 Subject: [PATCH 5/6] Fixing input - symbol mapping --- site/docs/add-ons/input-history.mdx | 23 ++++++++++++++++++++++- src/addons/inputhistory.cpp | 6 +++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/site/docs/add-ons/input-history.mdx b/site/docs/add-ons/input-history.mdx index 1aa298f2b..b593fa186 100644 --- a/site/docs/add-ons/input-history.mdx +++ b/site/docs/add-ons/input-history.mdx @@ -31,4 +31,25 @@ None. ## Miscellaneous Notes -None. +Input - Symbol mapping: + +| GP2040-CE | PS3 | Switch | XINPUT | KEYBOARD | PS4 | CONFIG | +|-----------|:---:|:------:|:------:|:--------:|:---:|:------:| +| Up | U | U | U | U | U | U | +| Down | D | D | D | D | D | D | +| Left | L | L | L | L | L | L | +| Right | R | R | R | R | R | R | +| B1 | X | B | A | B1 | X | B1 | +| B2 | O | A | B | B2 | O | B2 | +| B3 | # | Y | X | B3 | # | B3 | +| B4 | ^ | X | Y | B4 | ^ | B4 | +| L1 | L1 | L | LB | L1 | L1 | L1 | +| R1 | R1 | R | RB | R1 | R1 | R1 | +| L2 | L2 | ZL | LT | L2 | L2 | L2 | +| R2 | R2 | ZR | RT | R2 | R2 | R2 | +| S1 | SL | - | BK | S1 | SH | S1 | +| S2 | ST | + | ST | S2 | OP | S2 | +| L3 | L3 | LS | LS | L3 | L3 | L3 | +| R3 | R3 | RS | RS | R3 | R3 | R3 | +| A1 | PS | H | G | A1 | PS | A1 | +| A2 | A2 | C | A2 | A2 | T | A2 | diff --git a/src/addons/inputhistory.cpp b/src/addons/inputhistory.cpp index 20cbd6ca7..daef24bb4 100644 --- a/src/addons/inputhistory.cpp +++ b/src/addons/inputhistory.cpp @@ -10,7 +10,7 @@ static const std::string displayNames[][18] = { "U", "D", "L", "R", "X", "O", "#", "^", "L1", "R1", "L2", "R2", - "SL", "ST", "LS", "RS", "H", "A2" + "SL", "ST", "L3", "R3", "PS", "A2" }, { // Switch "U", "D", "L", "R", @@ -22,7 +22,7 @@ static const std::string displayNames[][18] = { "U", "D", "L", "R", "A", "B", "X", "Y", "LB", "RB", "LT", "RT", - "S1", "S2", "L3", "R3", "A1", "A2" + "BK", "ST", "LS", "RS", "G", "A2" }, { // Keyboard / HID-KB "U", "D", "L", "R", @@ -34,7 +34,7 @@ static const std::string displayNames[][18] = { "U", "D", "L", "R", "X", "O", "#", "^", "L1", "R1", "L2", "R2", - "SL", "ST", "LS", "RS", "H", "A2" + "SH", "OP", "L3", "R3", "PS", "T" }, { // Config "U", "D", "L", "R", From 8510b7c26365b0672d09f0a41667b197e0415323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kir=C3=A1ly=20D=C3=A1vid?= Date: Sun, 19 Nov 2023 02:23:35 +0100 Subject: [PATCH 6/6] Attaching history addon only if available --- headers/addons/i2cdisplay.h | 3 +-- src/addons/i2cdisplay.cpp | 20 ++++++++++---------- src/gp2040aux.cpp | 9 +++++++-- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/headers/addons/i2cdisplay.h b/headers/addons/i2cdisplay.h index 33d830101..38b61c60e 100644 --- a/headers/addons/i2cdisplay.h +++ b/headers/addons/i2cdisplay.h @@ -142,13 +142,12 @@ class I2CDisplayAddon : public GPAddon { public: - I2CDisplayAddon(InputHistoryAddon*); - ~I2CDisplayAddon() {} virtual bool available(); virtual void setup(); virtual void preprocess() {} virtual void process(); virtual std::string name() { return I2CDisplayName; } + virtual void attachInputHistoryAddon(InputHistoryAddon*); private: int initDisplay(int typeOverride); bool isSH1106(int detectedDisplay); diff --git a/src/addons/i2cdisplay.cpp b/src/addons/i2cdisplay.cpp index ee53df6a3..fcce523aa 100644 --- a/src/addons/i2cdisplay.cpp +++ b/src/addons/i2cdisplay.cpp @@ -15,14 +15,10 @@ #include "config.pb.h" #include "usb_driver.h" -I2CDisplayAddon::I2CDisplayAddon(InputHistoryAddon* pInputHistoryAddon) { - inputHistoryAddon = pInputHistoryAddon; -} - bool I2CDisplayAddon::available() { const DisplayOptions& options = Storage::getInstance().getDisplayOptions(); - return options.enabled && - isValidPin(options.i2cSDAPin) && + return options.enabled && + isValidPin(options.i2cSDAPin) && isValidPin(options.i2cSCLPin); } @@ -86,7 +82,7 @@ bool I2CDisplayAddon::isDisplayPowerOff() } else if (!!displaySaverTimeout && displaySaverTimer <= 0) { setDisplayPower(0); } - + if (isFocusModeEnabled) { const FocusModeOptions& focusModeOptions = Storage::getInstance().getAddonOptions().focusModeOptions; bool isFocusModeActive = !gpio_get(focusModeOptions.pin); @@ -221,7 +217,7 @@ void I2CDisplayAddon::process() { break; case BUTTON_LAYOUT_OPENCORE0WASDB: drawOpenCore0WASDB(68, (isInputHistoryEnabled ? 22 : 28), 10, 1); - break; + break; case BUTTON_LAYOUT_DANCEPADB: drawDancepadB(39, (isInputHistoryEnabled ? 10 : 12), (isInputHistoryEnabled ? 13 : 15), 2); break; @@ -245,7 +241,7 @@ void I2CDisplayAddon::process() { break; } - if(isInputHistoryEnabled) { + if(isInputHistoryEnabled && inputHistoryAddon != nullptr) { inputHistoryAddon->drawHistory(&obd); } @@ -394,7 +390,7 @@ void I2CDisplayAddon::drawButtonLayoutLeft(ButtonLayoutParamsLeft& options) break; case BUTTON_LAYOUT_OPENCORE0WASDA: drawOpenCore0WASDA(startX, startY, buttonRadius, buttonPadding); - break; + break; case BUTTON_LAYOUT_DANCEPADA: drawDancepadA(startX, startY, buttonRadius, buttonPadding); break; @@ -1121,3 +1117,7 @@ bool I2CDisplayAddon::pressedRight() return false; } + +void I2CDisplayAddon::attachInputHistoryAddon(InputHistoryAddon* pInputHistoryAddon) { + inputHistoryAddon = pInputHistoryAddon; +} diff --git a/src/gp2040aux.cpp b/src/gp2040aux.cpp index f0076dbe9..c425e2089 100644 --- a/src/gp2040aux.cpp +++ b/src/gp2040aux.cpp @@ -24,11 +24,16 @@ GP2040Aux::~GP2040Aux() { } void GP2040Aux::setup() { + InputHistoryAddon* inputHistoryAddon = new InputHistoryAddon(); + I2CDisplayAddon* i2CDisplayAddon = new I2CDisplayAddon(); + + if(inputHistoryAddon->available() && i2CDisplayAddon->available()) + i2CDisplayAddon->attachInputHistoryAddon(inputHistoryAddon); + // Setup Add-ons addons.LoadUSBAddon(new PSPassthroughAddon(), CORE1_LOOP); - InputHistoryAddon* inputHistoryAddon = new InputHistoryAddon(); addons.LoadAddon(inputHistoryAddon, CORE1_LOOP); - addons.LoadAddon(new I2CDisplayAddon(inputHistoryAddon), CORE1_LOOP); + addons.LoadAddon(i2CDisplayAddon, CORE1_LOOP); addons.LoadAddon(new NeoPicoLEDAddon(), CORE1_LOOP); addons.LoadAddon(new PlayerLEDAddon(), CORE1_LOOP); addons.LoadAddon(new BoardLedAddon(), CORE1_LOOP);