diff --git a/CMakeLists.txt b/CMakeLists.txt index 6eb6dea45..90661b7b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,10 @@ endif() cmake_minimum_required(VERSION 3.13) include(CMakePrintHelpers) +# enable compile commands for use by IDE autocompletion +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + + # initialize the SDK based on PICO_SDK_PATH # note: this must happen before project() include(pico_sdk_import.cmake) diff --git a/README.md b/README.md index 08652ce3d..f1c7dcbdd 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Full documentation can be found at [https://gp2040-ce.info](https://gp2040-ce.in ## Features - Select from 13 input modes including X-Input, Nintendo Switch, Playstation 4/5, Xbox One, D-Input, and Keyboard -- Input latency average of 0.76ms in Xinput and 0.91ms for Playstation 5. +- Input latency average of 0.76ms in Xinput and 0.90ms for Playstation 5. - Multiple SOCD cleaning modes - Up Priority (a.k.a. Stickless), Neutral, and Second Input Priority. - Left and Right stick emulation via D-pad inputs as well as dedicated toggle switches. - Dual direction via D-pad + LS/RS. @@ -53,17 +53,18 @@ Visit the [GP2040-CE Usage](https://gp2040-ce.info/usage) page for more details. Input latency is tested using the methodology outlined at [WydD's inputlag.science website](https://inputlag.science/controller/methodology), using the default 1000 Hz (1 ms) polling rate in the firmware. You can read more about the setup we use to conduct latency testing [HERE](https://github.com/OpenStickCommunity/Site/blob/main/latency_testing/README.md) if you are interested in testing for yourself or would just like to know more about the devices used to do the testing. -| Version | Mode | Poll Rate | Min | Max | Avg | Stdev | % on time | %1f skip | %2f skip | -| ------- | ------------ | --------- | ------- | ------- | ------- | ------- | --------- | -------- | -------- | -| v0.7.9 | Xinput | 1 ms | 0.45 ms | 1.28 ms | 0.76 ms | 0.24 ms | 98.48% | 1.52% | 0% | -| v0.7.9 | Switch | 1 ms | 0.41 ms | 1.23 ms | 0.72 ms | 0.24 ms | 98.53% | 1.47% | 0% | -| v0.7.9 | Dinput (PS3) | 1 ms | 0.44 ms | 1.27 ms | 0.75 ms | 0.24 ms | 98.49% | 1.51% | 0% | -| v0.7.9 | PS4 | 1 ms | 0.55 ms | 2.26 ms | 0.90 ms | 0.32 ms | 98.21% | 1.79% | 0% | -| v0.7.9 | PS5 | 1 ms | 0.55 ms | 2.33 ms | 0.91 ms | 0.33 ms | 98.18% | 1.82% | 0% | +| Version | Mode | Poll Rate | Min | Max | Avg | Stdev | % on time | %1f skip | %2f skip | +| ------- | ------- | --------- | ------- | ------- | ------- | ------- | --------- | -------- | -------- | +| v0.7.10 | Xinput | 1 ms | 0.45 ms | 1.28 ms | 0.76 ms | 0.24 ms | 98.48% | 1.52% | 0% | +| v0.7.10 | Switch | 1 ms | 0.41 ms | 1.22 ms | 0.73 ms | 0.24 ms | 98.52% | 1.48% | 0% | +| v0.7.10 | HID USB | 1 ms | 0.42 ms | 1.24 ms | 0.73 ms | 0.24 ms | 98.53% | 1.47% | 0% | +| v0.7.10 | PS3 | 1 ms | 0.52 ms | 1.33 ms | 0.82 ms | 0.24 ms | 98.38% | 1.62% | 0% | +| v0.7.10 | PS4 | 1 ms | 0.55 ms | 2.38 ms | 0.91 ms | 0.31 ms | 98.19% | 1.81% | 0% | +| v0.7.10 | PS5 | 1 ms | 0.55 ms | 2.38 ms | 0.90 ms | 0.31 ms | 98.20% | 1.80% | 0% | -Full results can be found in the [GP2040-CE v0.7.9 Firmware Latency Test Results](https://github.com/OpenStickCommunity/Site/raw/main/latency_testing/GP2040-CE_Firmware_Latency_Test_Results_v0.7.9.xlsx) .xlsx Sheet. +Full results can be found in the [GP2040-CE v0.7.10 Firmware Latency Test Results](https://github.com/OpenStickCommunity/Site/raw/main/latency_testing/GP2040-CE_Firmware_Latency_Test_Results_v0.7.10.xlsx) .xlsx Sheet. -Results from v0.7.8 can be found [HERE](https://github.com/OpenStickCommunity/Site/raw/main/latency_testing/GP2040-CE_Firmware_Latency_Test_Results_v0.7.8.xlsx). Previous results can be found in the `latency_testing` folder. +Results from v0.7.9 can be found [HERE](https://github.com/OpenStickCommunity/Site/raw/main/latency_testing/GP2040-CE_Firmware_Latency_Test_Results_v0.7.9.xlsx). Previous results can be found in the `latency_testing` folder. ## Support diff --git a/configs/RP2040AdvancedBreakoutBoardUSBPassthrough/BoardConfig.h b/configs/RP2040AdvancedBreakoutBoardUSBPassthrough/BoardConfig.h index 5f4930c31..9636ff2c3 100644 --- a/configs/RP2040AdvancedBreakoutBoardUSBPassthrough/BoardConfig.h +++ b/configs/RP2040AdvancedBreakoutBoardUSBPassthrough/BoardConfig.h @@ -62,10 +62,21 @@ #define KEY_BUTTON_A2 HID_KEY_F2 // A2 | ~ | Capture | ~ | 14 | ~ | #define KEY_BUTTON_FN -1 // Hotkey Function | -#define BOARD_LEDS_PIN 4 +#define USB_PERIPHERAL_ENABLED 1 + +#define USB_PERIPHERAL_PIN_DPLUS 23 +#define USB_PERIPHERAL_PIN_ORDER 0 -#define LED_BRIGHTNESS_MAXIMUM 50 +#define DEFAULT_INPUT_MODE_R1 INPUT_MODE_XBONE +#define DEFAULT_INPUT_MODE_B4 INPUT_MODE_PS5 +#define DEFAULT_PS5AUTHENTICATION_TYPE INPUT_MODE_AUTH_TYPE_USB +#define BOARD_LEDS_PIN 4 +#define LED_BRIGHTNESS_MAXIMUM 100 +#define LED_BRIGHTNESS_STEPS 5 +#define LED_FORMAT LED_FORMAT_GRB +#define LEDS_PER_PIXEL 1 +#define LEDS_BASE_ANIMATION_INDEX 1 #define LEDS_DPAD_LEFT 0 #define LEDS_DPAD_DOWN 1 #define LEDS_DPAD_RIGHT 2 @@ -78,18 +89,21 @@ #define LEDS_BUTTON_B2 9 #define LEDS_BUTTON_R2 10 #define LEDS_BUTTON_L2 11 +#define LEDS_BUTTON_A1 12 +#define LEDS_BUTTON_L3 13 +#define LEDS_BUTTON_R3 14 +#define LEDS_BUTTON_A2 15 #define HAS_I2C_DISPLAY 1 #define I2C0_ENABLED 1 #define I2C0_PIN_SDA 0 #define I2C0_PIN_SCL 1 -#define DISPLAY_I2C_BLOCK i2c0 - -#define USB_PERIPHERAL_ENABLED 1 -#define USB_PERIPHERAL_PIN_DPLUS 23 +#define BUTTON_LAYOUT BUTTON_LAYOUT_STICKLESS +#define BUTTON_LAYOUT_RIGHT BUTTON_LAYOUT_STICKLESSB +#define SPLASH_MODE SPLASH_MODE_STATIC +#define SPLASH_DURATION 3000 -#define DEFAULT_INPUT_MODE_R1 INPUT_MODE_XBONE -#define DEFAULT_INPUT_MODE_B4 INPUT_MODE_PS5 -#define DEFAULT_PS5AUTHENTICATION_TYPE INPUT_MODE_AUTH_TYPE_USB +// Keyboard Host enabled by default +#define KEYBOARD_HOST_ENABLED 1 #endif \ No newline at end of file diff --git a/headers/addons/keyboard_host_listener.h b/headers/addons/keyboard_host_listener.h index 769d9cca2..c41c6c2f7 100644 --- a/headers/addons/keyboard_host_listener.h +++ b/headers/addons/keyboard_host_listener.h @@ -35,13 +35,10 @@ class KeyboardHostListener : public USBListener { virtual void get_report_complete(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) {} void process(); private: - GamepadState _keyboard_host_state; - bool _keyboard_host_enabled; uint8_t getKeycodeFromModifier(uint8_t modifier); void preprocess_report(); void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const *report); void process_mouse_report(uint8_t dev_addr, hid_mouse_report_t const *report); - KeyboardButtonMapping _keyboard_host_mapDpadUp; KeyboardButtonMapping _keyboard_host_mapDpadDown; KeyboardButtonMapping _keyboard_host_mapDpadLeft; @@ -62,22 +59,20 @@ class KeyboardHostListener : public USBListener { KeyboardButtonMapping _keyboard_host_mapButtonA2; KeyboardButtonMapping _keyboard_host_mapButtonA3; KeyboardButtonMapping _keyboard_host_mapButtonA4; - + GamepadState _keyboard_host_state; + bool _keyboard_host_mounted; uint8_t _keyboard_dev_addr; uint8_t _keyboard_instance; - - bool _mouse_host_enabled; + bool _mouse_host_mounted; uint8_t _mouse_dev_addr; uint8_t _mouse_instance; - uint16_t mouseLeftMapping; uint16_t mouseMiddleMapping; uint16_t mouseRightMapping; - - int16_t mouseX = 0; - int16_t mouseY = 0; - int16_t mouseZ = 0; - bool mouseActive = false; + int16_t mouseX; + int16_t mouseY; + int16_t mouseZ; + bool mouseActive; }; #endif // _KeyboardHost_H_ \ No newline at end of file diff --git a/proto/config.proto b/proto/config.proto index af78fe71b..44593ec4d 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -407,7 +407,7 @@ message SliderOptions optional int32 deprecatedPinSliderTwo = 3 [deprecated = true]; optional DpadMode deprecatedModeOne = 4 [deprecated = true]; optional DpadMode deprecatedModeTwo = 5 [deprecated = true]; - optional DpadMode deprecatedModeDefault = 6; + optional DpadMode deprecatedModeDefault = 6 [deprecated = true]; } message SOCDSliderOptions @@ -794,7 +794,7 @@ message AddonOptions optional OnBoardLedOptions onBoardLedOptions = 2; optional AnalogOptions analogOptions = 3; optional TurboOptions turboOptions = 4; - optional SliderOptions deprecatedSliderOptions = 5; + optional SliderOptions deprecatedSliderOptions = 5 [deprecated = true]; optional ReverseOptions reverseOptions = 6; optional AnalogADS1219Options analogADS1219Options = 7; optional DualDirectionalOptions dualDirectionalOptions = 8; diff --git a/src/addons/analog.cpp b/src/addons/analog.cpp index a59452774..dff9b54aa 100644 --- a/src/addons/analog.cpp +++ b/src/addons/analog.cpp @@ -74,6 +74,12 @@ void AnalogInput::setup() { void AnalogInput::process() { Gamepad * gamepad = Storage::getInstance().GetGamepad(); + + uint16_t joystickMid = GAMEPAD_JOYSTICK_MID; + if ( DriverManager::getInstance().getDriver() != nullptr ) { + joystickMid = DriverManager::getInstance().getDriver()->GetJoystickMidValue(); + } + for(int i = 0; i < ADC_COUNT; i++) { // Read X-Axis if (isValidPin(adc_pairs[i].x_pin)) { @@ -109,7 +115,7 @@ void AnalogInput::process() { } if (adc_pairs[i].analog_dpad == DpadMode::DPAD_MODE_LEFT_ANALOG) { - if ( DriverManager::getInstance().getDriver()->GetJoystickMidValue() == 0x8000 ) { + if ( joystickMid == 0x8000 ) { gamepad->state.lx = static_cast(std::ceil(65535.0f * adc_pairs[i].x_value)); gamepad->state.ly = static_cast(std::ceil(65535.0f * adc_pairs[i].y_value)); } else { // 0x7FFF @@ -117,7 +123,7 @@ void AnalogInput::process() { gamepad->state.ly = static_cast(65535.0f * adc_pairs[i].y_value); } } else if (adc_pairs[i].analog_dpad == DpadMode::DPAD_MODE_RIGHT_ANALOG) { - if ( DriverManager::getInstance().getDriver()->GetJoystickMidValue() == 0x8000 ) { + if ( joystickMid == 0x8000 ) { gamepad->state.rx = static_cast(std::ceil(65535.0f * adc_pairs[i].x_value)); gamepad->state.ry = static_cast(std::ceil(65535.0f * adc_pairs[i].y_value)); } else { // 0x7FFF diff --git a/src/addons/keyboard_host_listener.cpp b/src/addons/keyboard_host_listener.cpp index 4734c48a4..4974e581e 100644 --- a/src/addons/keyboard_host_listener.cpp +++ b/src/addons/keyboard_host_listener.cpp @@ -3,6 +3,8 @@ #include "storagemanager.h" #include "class/hid/hid_host.h" +#define DEV_ADDR_NONE 0xFF + void KeyboardHostListener::setup() { const KeyboardHostOptions& keyboardHostOptions = Storage::getInstance().getAddonOptions().keyboardHostOptions; const KeyboardMapping& keyboardMapping = keyboardHostOptions.mapping; @@ -50,22 +52,23 @@ void KeyboardHostListener::setup() { mouseMiddleMapping = keyboardHostOptions.mouseMiddle; mouseRightMapping = keyboardHostOptions.mouseRight; - _keyboard_host_enabled = false; - _keyboard_dev_addr = 0; + _keyboard_host_mounted = false; + _keyboard_dev_addr = DEV_ADDR_NONE; _keyboard_instance = 0; - _mouse_host_enabled = false; - _mouse_dev_addr = 0; + _mouse_host_mounted = false; + _mouse_dev_addr = DEV_ADDR_NONE; _mouse_instance = 0; mouseX = 0; mouseY = 0; mouseZ = 0; + mouseActive = false; } void KeyboardHostListener::process() { Gamepad *gamepad = Storage::getInstance().GetGamepad(); - if (_keyboard_host_enabled || _mouse_host_enabled) { + if (_keyboard_host_mounted == true || _mouse_host_mounted == true) { gamepad->state.dpad |= _keyboard_host_state.dpad; gamepad->state.buttons |= _keyboard_host_state.buttons; gamepad->state.lx |= _keyboard_host_state.lx; @@ -78,14 +81,16 @@ void KeyboardHostListener::process() { } } - gamepad->auxState.sensors.mouse.enabled = _mouse_host_enabled; - gamepad->auxState.sensors.mouse.active = mouseActive; - if (_mouse_host_enabled && mouseActive) { - gamepad->auxState.sensors.mouse.x = mouseX; - gamepad->auxState.sensors.mouse.y = mouseY; - gamepad->auxState.sensors.mouse.z = mouseZ; + if ( _mouse_host_mounted == true ) { + gamepad->auxState.sensors.mouse.active = mouseActive; + if ( mouseActive == true ) { + gamepad->auxState.sensors.mouse.active = true; + gamepad->auxState.sensors.mouse.x = mouseX; + gamepad->auxState.sensors.mouse.y = mouseY; + gamepad->auxState.sensors.mouse.z = mouseZ; + mouseActive = false; + } } - mouseActive = false; } void KeyboardHostListener::mount(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { @@ -93,51 +98,43 @@ void KeyboardHostListener::mount(uint8_t dev_addr, uint8_t instance, uint8_t con uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); // tuh_hid_report_received_cb() will be invoked when report is available - if (itf_protocol == HID_ITF_PROTOCOL_KEYBOARD) { + if (_keyboard_host_mounted == false && itf_protocol == HID_ITF_PROTOCOL_KEYBOARD) { + _keyboard_host_mounted = true; _keyboard_dev_addr = dev_addr; _keyboard_instance = instance; - _keyboard_host_enabled = true; - } else if (itf_protocol == HID_ITF_PROTOCOL_MOUSE) { + } else if (_mouse_host_mounted == false && itf_protocol == HID_ITF_PROTOCOL_MOUSE) { + Gamepad *gamepad = Storage::getInstance().GetGamepad(); + gamepad->auxState.sensors.mouse.enabled = true; + _mouse_host_mounted = true; _mouse_dev_addr = dev_addr; _mouse_instance = instance; - _mouse_host_enabled = true; - } else { - return; } } void KeyboardHostListener::unmount(uint8_t dev_addr) { - if ( _keyboard_dev_addr == dev_addr ) { - _keyboard_host_enabled = false; - _keyboard_dev_addr = 0; + if ( _keyboard_host_mounted == true && _keyboard_dev_addr == dev_addr ) { + _keyboard_host_mounted = false; + _keyboard_dev_addr = DEV_ADDR_NONE; _keyboard_instance = 0; - } else if ( _mouse_dev_addr == dev_addr ) { - _mouse_host_enabled = false; - _mouse_dev_addr = 0; + } else if ( _mouse_host_mounted == true && _mouse_dev_addr == dev_addr ) { + Gamepad *gamepad = Storage::getInstance().GetGamepad(); + gamepad->auxState.sensors.mouse.enabled = false; + _mouse_host_mounted = false; + _mouse_dev_addr = DEV_ADDR_NONE; _mouse_instance = 0; } } void KeyboardHostListener::report_received(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len){ - if ( - ( _keyboard_host_enabled == false || _keyboard_dev_addr != dev_addr || _keyboard_instance != instance ) - && - ( _mouse_host_enabled == false || _mouse_dev_addr != dev_addr || _mouse_instance != instance ) - ) - return; // do nothing if we haven't mounted - - // Interface protocol (hid_interface_protocol_enum_t) - uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); - - preprocess_report(); + // do nothing if we haven't mounted +if ( _keyboard_host_mounted == false && _mouse_host_mounted == false ) + return; // tuh_hid_report_received_cb() will be invoked when report is available - if (itf_protocol == HID_ITF_PROTOCOL_KEYBOARD) { + if ( _keyboard_host_mounted == true && _keyboard_dev_addr == dev_addr && _keyboard_instance == instance ) { process_kbd_report(dev_addr, (hid_keyboard_report_t const*) report ); - } else if (itf_protocol == HID_ITF_PROTOCOL_MOUSE) { + } else if ( _mouse_host_mounted == true && _mouse_dev_addr == dev_addr && _mouse_instance == instance) { process_mouse_report(dev_addr, (hid_mouse_report_t const*) report ); - } else { - return; } } @@ -171,12 +168,13 @@ void KeyboardHostListener::preprocess_report() _keyboard_host_state.ry = joystickMid; _keyboard_host_state.lt = 0; _keyboard_host_state.rt = 0; - } // convert hid keycode to ascii and print via usb device CDC (ignore non-printable) void KeyboardHostListener::process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const *report) { + preprocess_report(); + // make this 13 instead of 7 to include modifier bitfields from hid_keyboard_modifier_bm_t for(uint8_t i=0; i<13; i++) { @@ -223,6 +221,8 @@ void KeyboardHostListener::process_kbd_report(uint8_t dev_addr, hid_keyboard_rep void KeyboardHostListener::process_mouse_report(uint8_t dev_addr, hid_mouse_report_t const * report) { + preprocess_report(); + //------------- button state -------------// _keyboard_host_state.buttons |= (report->buttons & MOUSE_BUTTON_LEFT ? mouseLeftMapping : _keyboard_host_state.buttons) diff --git a/src/drivers/ps4/PS4Driver.cpp b/src/drivers/ps4/PS4Driver.cpp index 26e44259c..f40134d1d 100644 --- a/src/drivers/ps4/PS4Driver.cpp +++ b/src/drivers/ps4/PS4Driver.cpp @@ -245,13 +245,13 @@ void PS4Driver::process(Gamepad * gamepad) { } else if (pointOneTouched && touchpadData.p1.unpressed) { pointOneTouched = false; } - if (!pointTwoTouched && touchpadData.p2.unpressed) { + if (!pointTwoTouched && !touchpadData.p2.unpressed) { touchCounter = (touchCounter < PS4_TP_MAX_COUNT ? touchCounter+1 : 0); touchpadData.p2.counter = touchCounter; pointTwoTouched = true; - } else if (pointTwoTouched && touchpadData.p1.unpressed) { + } else if (pointTwoTouched && touchpadData.p2.unpressed) { pointTwoTouched = false; } ps4Report.touchpad_data = touchpadData; diff --git a/www/src/Locales/zh-CN/HomePage.jsx b/www/src/Locales/zh-CN/HomePage.jsx index f3195f20d..0732642e4 100644 --- a/www/src/Locales/zh-CN/HomePage.jsx +++ b/www/src/Locales/zh-CN/HomePage.jsx @@ -4,6 +4,7 @@ export default { 'header-text': '欢迎来到 GP2040-CE 网页配置器', 'latest-text': '最新:{{version}}', 'memory-flash-text': '闪存', + 'memory-board-text': '板载闪存', 'memory-header-text': '内存 (KB)', 'memory-heap-text': '堆', 'memory-static-allocations-text': '静态分配', diff --git a/www/src/Locales/zh-CN/SettingsPage.jsx b/www/src/Locales/zh-CN/SettingsPage.jsx index 41042a969..d8bdad500 100644 --- a/www/src/Locales/zh-CN/SettingsPage.jsx +++ b/www/src/Locales/zh-CN/SettingsPage.jsx @@ -79,7 +79,7 @@ export default { 'xbone-mode-text': '补充信息:Xbox One 模式需要 USB 主机(USB Host)连接和 USB 加密狗才能正确认证。', 'xinput-mode-text': - '补充信息: Xbox 360 模式可以在没有身份验证或连接USB加密狗的情况下工作。', + '补充信息:Xinput 可以在没有认证的情况下在PC上运行。如果您想在 Xbox 360 上使用它,请选择USB验证并连接合适的加密狗。', 'hotkey-settings-label': '快捷键设置', 'hotkey-settings-sub-header': 'Fn 组合映射在引脚映射页面提供了一个可映射的Function按键。 要选择 Fn 组合映射选项,请同时按住 Function 按键和其他快捷键。
此外, 可从下拉列表中选择 None 以取消分配按钮', @@ -138,7 +138,7 @@ export default { }, 'forced-setup-mode-modal-title': '强制设置模式警告', 'forced-setup-mode-modal-body': - '如果保存后重新启动到控制器模式,您将无法再访问网页配置。 如果你完全理解并打算解锁保存按钮,请在下方键入 "{{warningCheckText}}" 。 单击取消将还原此设置并保存。', + '如果您在保存后重新启动到控制器模式,您将无法再访问网页配置。如果您完全理解并同意这一点,请在下方键入 "{{warningCheckText}}" 以解锁保存按钮。 点击“取消”将恢复此设置并保存。', '4-way-joystick-mode-label': '4向摇杆模式', 'lock-hotkeys-label': '锁定快捷键', 'keyboard-mapping-header-text': '键盘映射',