From aabb00f2b5ee8f063974bedf76648b0243d683cd Mon Sep 17 00:00:00 2001 From: wiredopposite Date: Thu, 19 Dec 2024 23:15:27 -0700 Subject: [PATCH] v1.0.0-alpha --- .gitignore | 4 +- .gitmodules | 3 + Firmware/ESP32/main/Bluepad32/Bluepad32.cpp | 322 ++--- Firmware/ESP32/main/Bluepad32/Bluepad32.h | 11 +- Firmware/ESP32/main/Bluepad32/Gamepad.h | 66 +- Firmware/ESP32/main/Board/board_api.h | 1 - Firmware/ESP32/main/I2CDriver/I2CDriver.cpp | 45 +- Firmware/ESP32/main/I2CDriver/I2CDriver.h | 83 +- Firmware/ESP32/main/Reports.h | 134 -- Firmware/ESP32/main/RingBuffer.h | 57 + Firmware/ESP32/main/c_wrapper.cpp | 22 +- Firmware/ESP32/main/c_wrapper.h | 3 +- Firmware/ESP32/main/main.c | 24 +- Firmware/ESP32/sdkconfig | 26 +- Firmware/RP2040/.vscode/settings.json | 69 +- Firmware/RP2040/CMakeLists.txt | 99 +- Firmware/RP2040/src/Bluepad32/Bluepad32.cpp | 37 +- Firmware/RP2040/src/Bluepad32/Bluepad32.h | 1 - .../RP2040/src/Board/Pico_WS2812/WS2812.cpp | 22 +- .../RP2040/src/Board/Pico_WS2812/WS2812.hpp | 7 +- Firmware/RP2040/src/Board/board_api.cpp | 123 +- Firmware/RP2040/src/Board/board_api.h | 9 +- Firmware/RP2040/src/Descriptors/CDCDev.h | 65 +- Firmware/RP2040/src/Descriptors/DInput.h | 5 + Firmware/RP2040/src/Descriptors/PS3.h | 267 ++-- Firmware/RP2040/src/Descriptors/PS5.h | 49 +- Firmware/RP2040/src/Descriptors/XInput.h | 7 +- Firmware/RP2040/src/Descriptors/XboxOG.h | 5 - Firmware/RP2040/src/Gamepad.h | 180 ++- .../RP2040/src/I2CDriver/4Channel/I2CDriver.h | 14 +- .../src/I2CDriver/4Channel/I2CManager.h | 2 +- .../src/I2CDriver/4Channel/I2CMaster.cpp | 148 ++- .../RP2040/src/I2CDriver/4Channel/I2CMaster.h | 15 +- .../src/I2CDriver/4Channel/I2CSlave.cpp | 34 +- .../RP2040/src/I2CDriver/4Channel/I2CSlave.h | 8 +- .../RP2040/src/I2CDriver/ESP32/I2CDriver.cpp | 187 +++ .../{i2c_driver_esp32.h => ESP32/I2CDriver.h} | 5 +- .../RP2040/src/I2CDriver/i2c_4ch_master.cpp | 0 .../RP2040/src/I2CDriver/i2c_driver_4ch.cpp | 627 --------- .../RP2040/src/I2CDriver/i2c_driver_4ch.h | 145 --- .../RP2040/src/I2CDriver/i2c_driver_esp32.cpp | 177 --- Firmware/RP2040/src/OGXMini/Debug.h | 55 + Firmware/RP2040/src/OGXMini/OGXMini.h | 2 - .../{OGXMini_4Ch.cpp => OGXMini_4Channel.cpp} | 96 +- Firmware/RP2040/src/OGXMini/OGXMini_ESP32.cpp | 80 +- Firmware/RP2040/src/OGXMini/OGXMini_PicoW.cpp | 48 +- .../RP2040/src/OGXMini/OGXMini_Standard.cpp | 128 +- Firmware/RP2040/src/TaskQueue/TaskQueue.cpp | 1079 ++++++++++------ Firmware/RP2040/src/TaskQueue/TaskQueue.h | 7 +- .../USBDevice/DeviceDriver/DInput/DInput.cpp | 153 ++- .../USBDevice/DeviceDriver/DeviceDriver.cpp | 2 + .../src/USBDevice/DeviceDriver/DeviceDriver.h | 8 +- .../src/USBDevice/DeviceDriver/PS3/PS3.cpp | 240 ++-- .../src/USBDevice/DeviceDriver/PS3/PS3.h | 6 +- .../DeviceDriver/PSClassic/PSClassic.cpp | 177 ++- .../USBDevice/DeviceDriver/Switch/Switch.cpp | 118 +- .../DeviceDriver/UARTBridge/UARTBridge.cpp | 73 +- .../DeviceDriver/UARTBridge/UARTBridge.h | 2 +- .../UARTBridge/uart_bridge/uart_bridge.c | 129 +- .../UARTBridge/uart_bridge/uart_bridge.h | 6 +- .../USBDevice/DeviceDriver/WebApp/WebApp.cpp | 72 +- .../USBDevice/DeviceDriver/XInput/XInput.h | 4 - .../XInput/tud_xinput/tud_xinput.cpp | 13 +- .../DeviceDriver/XboxOG/XboxOG_SB.cpp | 410 +++--- .../USBDevice/DeviceDriver/XboxOG/XboxOG_SB.h | 17 +- .../DeviceDriver/XboxOG/tud_xid/tud_xid.cpp | 9 + .../RP2040/src/USBDevice/DeviceManager.cpp | 34 +- Firmware/RP2040/src/USBDevice/DeviceManager.h | 13 +- .../src/USBHost/HIDParser/HIDJoystick.cpp | 24 + .../src/USBHost/HIDParser/HIDJoystick.h | 24 + .../USBHost/HIDParser/HIDReportDescriptor.cpp | 24 + .../USBHost/HIDParser/HIDReportDescriptor.h | 24 + .../HIDParser/HIDReportDescriptorElements.cpp | 24 + .../HIDParser/HIDReportDescriptorElements.h | 24 + .../HIDParser/HIDReportDescriptorUsages.cpp | 24 + .../HIDParser/HIDReportDescriptorUsages.h | 24 + .../RP2040/src/USBHost/HIDParser/HIDUtils.cpp | 24 + .../RP2040/src/USBHost/HIDParser/HIDUtils.h | 24 + .../src/USBHost/HostDriver/DInput/DInput.cpp | 2 +- .../src/USBHost/HostDriver/HostDriver.h | 3 + .../RP2040/src/USBHost/HostDriver/PS3/PS3.cpp | 13 +- .../RP2040/src/USBHost/HostDriver/PS5/PS5.cpp | 70 +- .../RP2040/src/USBHost/HostDriver/PS5/PS5.h | 1 - .../USBHost/HostDriver/XInput/Xbox360W.cpp | 76 +- .../src/USBHost/HostDriver/XInput/Xbox360W.h | 16 +- .../src/USBHost/HostDriver/XInput/XboxOG.cpp | 2 +- .../XInput/tuh_xinput/tuh_xinput.cpp | 1127 ++++------------- .../HostDriver/XInput/tuh_xinput/tuh_xinput.h | 8 +- .../XInput/tuh_xinput/tuh_xinput_cmd.h | 4 +- Firmware/RP2040/src/USBHost/HostManager.h | 746 +++++------ Firmware/RP2040/src/USBHost/tuh_callbacks.cpp | 49 +- .../RP2040/src/UserSettings/UserProfile.cpp | 20 +- .../RP2040/src/UserSettings/UserSettings.cpp | 42 +- .../RP2040/src/UserSettings/UserSettings.h | 2 + Firmware/RP2040/src/board_config.h | 44 +- Firmware/RP2040/src/main.cpp | 5 +- Firmware/RP2040/src/tusb_config.h | 9 +- Firmware/external/Pico-PIO-USB | 1 + Firmware/external/patch_libs.cmake | 21 - .../patches/tinyusb_disable_hidh.diff | 25 - README.md | 17 +- Tools/README.md | 4 +- WebApp/constants.js | 4 +- WebApp/start.bat | 1 + hardware/README.md | 10 + .../BOM_OGX-Mini_RP2040-Zero_Interposer.csv | 0 ...Gerber_OGX-Mini_RP2040-Zero_Interposer.zip | Bin ...ematic_OGX-Mini_RP2040-Zero_Interposer.pdf | 0 images/DiagramPico.png | Bin 0 -> 134847 bytes images/DiagramPico2.png | Bin 0 -> 116011 bytes images/DiagramRPZero.png | Bin 0 -> 191990 bytes images/pi_pico_diagram.png | Bin 87029 -> 0 bytes 112 files changed, 3869 insertions(+), 4782 deletions(-) delete mode 100644 Firmware/ESP32/main/Reports.h create mode 100644 Firmware/ESP32/main/RingBuffer.h create mode 100644 Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.cpp rename Firmware/RP2040/src/I2CDriver/{i2c_driver_esp32.h => ESP32/I2CDriver.h} (51%) delete mode 100644 Firmware/RP2040/src/I2CDriver/i2c_4ch_master.cpp delete mode 100644 Firmware/RP2040/src/I2CDriver/i2c_driver_4ch.cpp delete mode 100644 Firmware/RP2040/src/I2CDriver/i2c_driver_4ch.h delete mode 100644 Firmware/RP2040/src/I2CDriver/i2c_driver_esp32.cpp create mode 100644 Firmware/RP2040/src/OGXMini/Debug.h rename Firmware/RP2040/src/OGXMini/{OGXMini_4Ch.cpp => OGXMini_4Channel.cpp} (76%) create mode 160000 Firmware/external/Pico-PIO-USB delete mode 100644 Firmware/external/patches/tinyusb_disable_hidh.diff create mode 100644 WebApp/start.bat rename hardware/{ => RP2040-Zero_PCB}/BOM_OGX-Mini_RP2040-Zero_Interposer.csv (100%) rename hardware/{ => RP2040-Zero_PCB}/Gerber_OGX-Mini_RP2040-Zero_Interposer.zip (100%) rename hardware/{ => RP2040-Zero_PCB}/Schematic_OGX-Mini_RP2040-Zero_Interposer.pdf (100%) create mode 100644 images/DiagramPico.png create mode 100644 images/DiagramPico2.png create mode 100644 images/DiagramRPZero.png delete mode 100644 images/pi_pico_diagram.png diff --git a/.gitignore b/.gitignore index 630fed8..daef46b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,11 @@ +Firmware/.vscode Firmware/RP2040/build Firmware/RP2040/.ignore Firmware/RP2040/src/USBDevice/DeviceDriver/XboxOG/tud_xid/tud_xid_xremote_rom.h - Firmware/ESP32/.ignore Firmware/ESP32/build Firmware/ESP32/components/btstack Firmware/ESP32/sdkconfig.old - Firmware/external/pico-sdk Firmware/external/picotool - Tools/dvd-dongle-rom.bin \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index b830911..39242a9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "Tools/dump-dvd-kit"] path = Tools/dump-dvd-kit url = https://github.com/XboxDev/dump-dvd-kit.git +[submodule "Firmware/external/Pico-PIO-USB"] + path = Firmware/external/Pico-PIO-USB + url = https://github.com/wiredopposite/Pico-PIO-USB.git diff --git a/Firmware/ESP32/main/Bluepad32/Bluepad32.cpp b/Firmware/ESP32/main/Bluepad32/Bluepad32.cpp index 60bfdff..bcd4c10 100644 --- a/Firmware/ESP32/main/Bluepad32/Bluepad32.cpp +++ b/Firmware/ESP32/main/Bluepad32/Bluepad32.cpp @@ -1,12 +1,4 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include "btstack_port_esp32.h" #include "btstack_run_loop.h" @@ -14,60 +6,82 @@ #include "uni.h" #include "sdkconfig.h" -#include "Board/board_api.h" #include "I2CDriver/I2CDriver.h" +#include "Board/board_api.h" #include "Bluepad32/Gamepad.h" #include "Bluepad32/Bluepad32.h" -namespace bluepad32 { - -// I2CDriver i2c_driver; +namespace BP32 { +static constexpr uint8_t MAX_DEVICES = CONFIG_BLUEPAD32_MAX_DEVICES; static constexpr uint32_t FEEDBACK_TIME_MS = 200; static constexpr uint32_t LED_TIME_MS = 500; -struct Device +I2CDriver i2c_driver_; +btstack_timer_source_t feedback_timer_; +std::atomic devs_conn_[MAX_DEVICES]{false}; + +static inline void send_feedback_cb(void* context) { - std::atomic connected{false}; - std::atomic new_report_in{false}; - std::atomic report_in{ReportIn()}; - std::atomic report_out{ReportOut()}; -}; + I2CDriver::PacketOut packet_out = reinterpret_cast*>(context)->load(); + uni_hid_device_t* bp_device = nullptr; -std::array devices_; - -static inline void send_feedback_cb(btstack_timer_source *ts) -{ - uni_hid_device_t* bp_device; - - for (uint8_t i = 0; i < CONFIG_BLUEPAD32_MAX_DEVICES; ++i) + if (!(bp_device = uni_hid_device_get_instance_for_idx(packet_out.index)) || + !uni_bt_conn_is_connected(&bp_device->conn) || + !bp_device->report_parser.play_dual_rumble) { - bp_device = uni_hid_device_get_instance_for_idx(i); - if (!bp_device || !bp_device->report_parser.play_dual_rumble) + return; + } + + if (packet_out.rumble_l || packet_out.rumble_r) + { + bp_device->report_parser.play_dual_rumble( + bp_device, + 0, + FEEDBACK_TIME_MS, + packet_out.rumble_l, + packet_out.rumble_r + ); + } +} + +static inline void feedback_timer_cb(btstack_timer_source *ts) +{ + static btstack_context_callback_registration_t cb_registration[MAX_DEVICES]; + static std::atomic packets_out[MAX_DEVICES]; + + uni_hid_device_t* bp_device = nullptr; + + for (uint8_t i = 0; i < MAX_DEVICES; ++i) + { + if (!(bp_device = uni_hid_device_get_instance_for_idx(i)) || + !uni_bt_conn_is_connected(&bp_device->conn)) { continue; } - ReportOut report_out = devices_[i].report_out.load(); - if (!report_out.rumble_l && !report_out.rumble_r) + cb_registration[i].callback = send_feedback_cb; + cb_registration[i].context = reinterpret_cast(&packets_out[i]); + + //Get i2c rumble packet then register callback on BTStack thread + i2c_driver_.push_task([i] { - continue; - } - // ReportOut report_out; - // report_out.index = i; - // i2c_driver.i2c_read_blocking(i2c_driver.MULTI_SLAVE ? i + 1 : 1, reinterpret_cast(&report_out), sizeof(ReportOut)); - // if (!report_out.rumble_l && !report_out.rumble_r) - // { - // continue; - // } - bp_device->report_parser.play_dual_rumble(bp_device, 0, FEEDBACK_TIME_MS, report_out.rumble_l, report_out.rumble_r); + I2CDriver::PacketOut packet_out; + if (i2c_driver_.i2c_read_blocking( I2CDriver::MULTI_SLAVE ? i + 1 : 0x01, + reinterpret_cast(&packet_out), + sizeof(I2CDriver::PacketOut)) == ESP_OK) + { + packets_out[i].store(packet_out); + btstack_run_loop_execute_on_main_thread(&cb_registration[i]); + } + }); } btstack_run_loop_set_timer(ts, FEEDBACK_TIME_MS); btstack_run_loop_add_timer(ts); } -static inline void check_led_cb(btstack_timer_source *ts) +inline void check_led_cb(btstack_timer_source *ts) { static bool led_state = false; led_state = !led_state; @@ -80,7 +94,7 @@ static inline void check_led_cb(btstack_timer_source *ts) { for (uint8_t i = 0; i < board_api::NUM_LEDS; ++i) { - board_api::set_led(i, devices_[i].connected.load() ? 1 : (led_state ? 1 : 0)); + board_api::set_led(i, devs_conn_[i].load() ? 1 : (led_state ? 1 : 0)); } } @@ -90,24 +104,21 @@ static inline void check_led_cb(btstack_timer_source *ts) //BT Driver -static void init(int argc, const char** arg_V) -{ - -} +static void init(int argc, const char** arg_V) {} static void init_complete_cb(void) { uni_bt_enable_new_connections_unsafe(true); - // // Based on runtime condition, you can delete or list the stored BT keys. - // if (1) - // { + // Based on runtime condition, you can delete or list the stored BT keys. + if (1) + { uni_bt_del_keys_unsafe(); - // } - // else - // { - // uni_bt_list_keys_unsafe(); - // } + } + else + { + uni_bt_list_keys_unsafe(); + } uni_property_dump_all(); } @@ -126,46 +137,59 @@ static void device_connected_cb(uni_hid_device_t* device) #ifdef CONFIG_BLUEPAD32_USB_CONSOLE_ENABLE logd("BP32", "Device connected, addr: %p, index: %i\n", device, uni_hid_device_get_idx_for_instance(device)); #endif - - int idx = uni_hid_device_get_idx_for_instance(device); - if (idx >= CONFIG_BLUEPAD32_MAX_DEVICES || idx < 0) - { - return; - } - devices_[idx].connected.store(true); } -static void device_disconnected_cb(uni_hid_device_t* device) +void device_disconnected_cb(uni_hid_device_t* device) { #ifdef CONFIG_BLUEPAD32_USB_CONSOLE_ENABLE logd("BP32", "Device disconnected, addr: %p, index: %i\n", device, uni_hid_device_get_idx_for_instance(device)); #endif int idx = uni_hid_device_get_idx_for_instance(device); - if (idx >= CONFIG_BLUEPAD32_MAX_DEVICES || idx < 0) + if (idx >= MAX_DEVICES || idx < 0) { return; } - ReportIn report_in = ReportIn(); - report_in.index = static_cast(idx); - devices_[idx].report_in.store(report_in); - devices_[idx].connected.store(false); + devs_conn_[idx].store(false); + if (!any_connected()) + { + btstack_run_loop_remove_timer(&feedback_timer_); + } + + I2CDriver::PacketIn packet_in = I2CDriver::PacketIn(); + packet_in.index = static_cast(idx); + + i2c_driver_.push_task([packet_in] + { + i2c_driver_.i2c_write_blocking( I2CDriver::MULTI_SLAVE ? packet_in.index + 1 : 0x01, + reinterpret_cast(&packet_in), + sizeof(I2CDriver::PacketIn)); + }); } static uni_error_t device_ready_cb(uni_hid_device_t* device) { + int idx = uni_hid_device_get_idx_for_instance(device); + if (idx >= MAX_DEVICES || idx < 0) + { + return UNI_ERROR_IGNORE_DEVICE; + } + + devs_conn_[idx].store(true); + + feedback_timer_.process = feedback_timer_cb; + feedback_timer_.context = nullptr; + + btstack_run_loop_set_timer(&feedback_timer_, FEEDBACK_TIME_MS); + btstack_run_loop_add_timer(&feedback_timer_); + return UNI_ERROR_SUCCESS; } -static void oob_event_cb(uni_platform_oob_event_t event, void* data) +static inline void controller_data_cb(uni_hid_device_t* device, uni_controller_t* controller) { - return; -} - -static void controller_data_cb(uni_hid_device_t* device, uni_controller_t* controller) -{ - static uni_gamepad_t prev_uni_gp[CONFIG_BLUEPAD32_MAX_DEVICES] = {}; + static uni_gamepad_t prev_uni_gps[MAX_DEVICES]{0}; if (controller->klass != UNI_CONTROLLER_CLASS_GAMEPAD) { @@ -175,77 +199,85 @@ static void controller_data_cb(uni_hid_device_t* device, uni_controller_t* contr uni_gamepad_t *uni_gp = &controller->gamepad; int idx = uni_hid_device_get_idx_for_instance(device); - if (idx >= CONFIG_BLUEPAD32_MAX_DEVICES || idx < 0 || std::memcmp(uni_gp, &prev_uni_gp[idx], sizeof(uni_gamepad_t)) == 0) + if (idx < 0 || std::memcmp(uni_gp, &prev_uni_gps[idx], sizeof(uni_gamepad_t)) == 0) { return; } - ReportIn report_in; - report_in.index = static_cast(idx); + I2CDriver::PacketIn packet_in; + packet_in.index = static_cast(idx); switch (uni_gp->dpad) { case DPAD_UP: - report_in.dpad = Gamepad::DPad::UP; + packet_in.dpad = Gamepad::DPad::UP; break; case DPAD_DOWN: - report_in.dpad = Gamepad::DPad::DOWN; + packet_in.dpad = Gamepad::DPad::DOWN; break; case DPAD_LEFT: - report_in.dpad = Gamepad::DPad::LEFT; + packet_in.dpad = Gamepad::DPad::LEFT; break; case DPAD_RIGHT: - report_in.dpad = Gamepad::DPad::RIGHT; + packet_in.dpad = Gamepad::DPad::RIGHT; break; case (DPAD_UP | DPAD_RIGHT): - report_in.dpad = Gamepad::DPad::UP_RIGHT; + packet_in.dpad = Gamepad::DPad::UP_RIGHT; break; case (DPAD_DOWN | DPAD_RIGHT): - report_in.dpad = Gamepad::DPad::DOWN_RIGHT; + packet_in.dpad = Gamepad::DPad::DOWN_RIGHT; break; case (DPAD_DOWN | DPAD_LEFT): - report_in.dpad = Gamepad::DPad::DOWN_LEFT; + packet_in.dpad = Gamepad::DPad::DOWN_LEFT; break; case (DPAD_UP | DPAD_LEFT): - report_in.dpad = Gamepad::DPad::UP_LEFT; + packet_in.dpad = Gamepad::DPad::UP_LEFT; break; default: break; } - if (uni_gp->buttons & BUTTON_A) report_in.buttons |= Gamepad::Button::A; - if (uni_gp->buttons & BUTTON_B) report_in.buttons |= Gamepad::Button::B; - if (uni_gp->buttons & BUTTON_X) report_in.buttons |= Gamepad::Button::X; - if (uni_gp->buttons & BUTTON_Y) report_in.buttons |= Gamepad::Button::Y; - if (uni_gp->buttons & BUTTON_SHOULDER_L) report_in.buttons |= Gamepad::Button::LB; - if (uni_gp->buttons & BUTTON_SHOULDER_R) report_in.buttons |= Gamepad::Button::RB; - if (uni_gp->buttons & BUTTON_THUMB_L) report_in.buttons |= Gamepad::Button::L3; - if (uni_gp->buttons & BUTTON_THUMB_R) report_in.buttons |= Gamepad::Button::R3; - if (uni_gp->misc_buttons & MISC_BUTTON_BACK) report_in.buttons |= Gamepad::Button::BACK; - if (uni_gp->misc_buttons & MISC_BUTTON_START) report_in.buttons |= Gamepad::Button::START; - if (uni_gp->misc_buttons & MISC_BUTTON_SYSTEM) report_in.buttons |= Gamepad::Button::SYS; - if (uni_gp->misc_buttons & MISC_BUTTON_CAPTURE) report_in.buttons |= Gamepad::Button::MISC; + if (uni_gp->buttons & BUTTON_A) packet_in.buttons |= Gamepad::Button::A; + if (uni_gp->buttons & BUTTON_B) packet_in.buttons |= Gamepad::Button::B; + if (uni_gp->buttons & BUTTON_X) packet_in.buttons |= Gamepad::Button::X; + if (uni_gp->buttons & BUTTON_Y) packet_in.buttons |= Gamepad::Button::Y; + if (uni_gp->buttons & BUTTON_SHOULDER_L) packet_in.buttons |= Gamepad::Button::LB; + if (uni_gp->buttons & BUTTON_SHOULDER_R) packet_in.buttons |= Gamepad::Button::RB; + if (uni_gp->buttons & BUTTON_THUMB_L) packet_in.buttons |= Gamepad::Button::L3; + if (uni_gp->buttons & BUTTON_THUMB_R) packet_in.buttons |= Gamepad::Button::R3; + if (uni_gp->misc_buttons & MISC_BUTTON_BACK) packet_in.buttons |= Gamepad::Button::BACK; + if (uni_gp->misc_buttons & MISC_BUTTON_START) packet_in.buttons |= Gamepad::Button::START; + if (uni_gp->misc_buttons & MISC_BUTTON_SYSTEM) packet_in.buttons |= Gamepad::Button::SYS; + if (uni_gp->misc_buttons & MISC_BUTTON_CAPTURE) packet_in.buttons |= Gamepad::Button::MISC; - report_in.trigger_l = Gamepad::scale_trigger(uni_gp->brake); - report_in.trigger_r = Gamepad::scale_trigger(uni_gp->throttle); + packet_in.trigger_l = Scale::uint10_to_uint8(uni_gp->brake); + packet_in.trigger_r = Scale::uint10_to_uint8(uni_gp->throttle); - report_in.joystick_lx = static_cast(uni_gp->axis_x); - report_in.joystick_ly = static_cast(uni_gp->axis_y); - report_in.joystick_rx = static_cast(uni_gp->axis_rx); - report_in.joystick_ry = static_cast(uni_gp->axis_ry); + packet_in.joystick_lx = Scale::int10_to_int16(uni_gp->axis_x); + packet_in.joystick_ly = Scale::int10_to_int16(uni_gp->axis_y); + packet_in.joystick_rx = Scale::int10_to_int16(uni_gp->axis_rx); + packet_in.joystick_ry = Scale::int10_to_int16(uni_gp->axis_ry); - devices_[idx].report_in.store(report_in); - devices_[idx].new_report_in.store(true); - // i2c_driver.i2c_write_blocking(i2c_driver.MULTI_SLAVE ? idx + 1 : 1, reinterpret_cast(&report_in), sizeof(ReportIn)); + i2c_driver_.push_task([packet_in] + { + i2c_driver_.i2c_write_blocking( I2CDriver::MULTI_SLAVE ? packet_in.index + 1 : 0x01, + reinterpret_cast(&packet_in), + sizeof(I2CDriver::PacketIn)); + }); - std::memcpy(uni_gp, &prev_uni_gp[idx], sizeof(uni_gamepad_t)); + std::memcpy(&prev_uni_gps[idx], uni_gp, sizeof(uni_gamepad_t)); } -const uni_property_t* get_property_cb(uni_property_idx_t idx) +static const uni_property_t* get_property_cb(uni_property_idx_t idx) { return nullptr; } +static void oob_event_cb(uni_platform_oob_event_t event, void* data) +{ + return; +} + uni_platform* get_driver() { static uni_platform driver = @@ -264,49 +296,45 @@ uni_platform* get_driver() return &driver; } -//Public +//Public -ReportIn get_report_in(uint8_t index) +bool any_connected() { - devices_[index].new_report_in.store(false); - return devices_[index].report_in.load(); + for (auto& connected : devs_conn_) + { + if (connected.load()) + { + return true; + } + } + return false; } -void set_report_out(const ReportOut& report_out) +bool connected(uint8_t index) { - if (report_out.index >= CONFIG_BLUEPAD32_MAX_DEVICES) - { - return; - } - devices_[report_out.index].report_out.store(report_out); + return devs_conn_[index].load(); } void run_task() { - for (uint8_t i = 0; i < CONFIG_BLUEPAD32_MAX_DEVICES; ++i) - { - ReportIn report_in; - report_in.index = i; - devices_[i].report_in.store(report_in); - devices_[i].report_out.store(ReportOut()); - } - board_api::init_pins(); - - // i2c_driver.initialize_i2c(); + + i2c_driver_.initialize_i2c(); + + xTaskCreatePinnedToCore( + i2c_driver_.run_tasks, + "i2c", + 2048 * 2, + nullptr, + configMAX_PRIORITIES-8, + nullptr, + 1 ); btstack_init(); uni_platform_set_custom(get_driver()); uni_init(0, nullptr); - btstack_timer_source_t feedback_timer; - feedback_timer.process = send_feedback_cb; - feedback_timer.context = nullptr; - - btstack_run_loop_set_timer(&feedback_timer, FEEDBACK_TIME_MS); - btstack_run_loop_add_timer(&feedback_timer); - btstack_timer_source_t led_timer; led_timer.process = check_led_cb; led_timer.context = nullptr; @@ -317,26 +345,4 @@ void run_task() btstack_run_loop_execute(); } -bool any_connected() -{ - for (auto& device : devices_) - { - if (device.connected.load()) - { - return true; - } - } - return false; -} - -bool connected(uint8_t index) -{ - return devices_[index].connected.load(); -} - -bool new_report_in(uint8_t index) -{ - return devices_[index].new_report_in.load(); -} - -} // namespace bluepad32 \ No newline at end of file +} // namespace BP32 \ No newline at end of file diff --git a/Firmware/ESP32/main/Bluepad32/Bluepad32.h b/Firmware/ESP32/main/Bluepad32/Bluepad32.h index 2a9f781..3c7d2cc 100644 --- a/Firmware/ESP32/main/Bluepad32/Bluepad32.h +++ b/Firmware/ESP32/main/Bluepad32/Bluepad32.h @@ -3,18 +3,11 @@ #include -#include "sdkconfig.h" -#include "I2CDriver/I2CDriver.h" -#include "Reports.h" - -namespace bluepad32 +namespace BP32 { void run_task(); - bool connected(uint8_t index); bool any_connected(); - bool new_report_in(uint8_t index); - ReportIn get_report_in(uint8_t index); - void set_report_out(const ReportOut& report); + bool connected(uint8_t index); } #endif // _BLUEPAD32_DRIVER_H_ \ No newline at end of file diff --git a/Firmware/ESP32/main/Bluepad32/Gamepad.h b/Firmware/ESP32/main/Bluepad32/Gamepad.h index 0c6794c..6bcb7f4 100644 --- a/Firmware/ESP32/main/Bluepad32/Gamepad.h +++ b/Firmware/ESP32/main/Bluepad32/Gamepad.h @@ -33,50 +33,68 @@ namespace Gamepad static constexpr uint16_t MISC = 0x0800; } +} // namespace Gamepad + +namespace Scale +{ + namespace INT_16 + { + static constexpr int16_t MIN = INT16_MIN; + static constexpr int16_t MID = 0; + static constexpr int16_t MAX = INT16_MAX; + } + namespace UINT_16 + { + static constexpr uint16_t MIN = 0; + static constexpr uint16_t MID = 0x8000; + static constexpr uint16_t MAX = 0xFFFF; + } namespace UINT_8 { - static constexpr uint8_t MID = 0x80; - static constexpr uint8_t MAX = 0xFF; + static constexpr uint8_t MAX = 0xFF; + static constexpr uint8_t MID = 0x80; + static constexpr uint8_t MIN = 0x00; } - namespace INT_10 { static constexpr int32_t MIN = -512; static constexpr int32_t MAX = 511; } - namespace UINT_10 { static constexpr int32_t MAX = 1023; } - static inline uint8_t scale_joystick(int32_t value) + static inline int16_t int10_to_int16(int32_t value) { - value = value - INT_10::MIN; + constexpr int32_t scale_factor = INT_16::MAX - INT_16::MIN; + constexpr int32_t range = INT_10::MAX - INT_10::MIN; - if (value >= UINT_10::MAX) + if (value >= INT_10::MAX) { - return UINT_8::MAX; + return INT_16::MAX; } - else if (value <= 0) + else if (value <= INT_10::MIN) { - return 0; + return INT_16::MIN; + } + + int32_t scaled_value = (value - INT_10::MIN) * scale_factor; + return static_cast(scaled_value / range + INT_16::MIN); + } + static inline uint8_t uint10_to_uint8(int32_t value) + { + if (value > UINT_10::MAX) + { + value = UINT_10::MAX; + } + else if (value < 0) + { + value = 0; } return static_cast(value >> 2); } - static inline uint8_t scale_trigger(int32_t value) - { - if (value >= UINT_10::MAX) - { - return UINT_8::MAX; - } - else if (value <= 0) - { - return 0; - } - return static_cast(value >> 2); - } - -} // namespace Gamepad + +} // namespace Scale #endif // GAMEPAD_H \ No newline at end of file diff --git a/Firmware/ESP32/main/Board/board_api.h b/Firmware/ESP32/main/Board/board_api.h index 41a2422..37989a3 100644 --- a/Firmware/ESP32/main/Board/board_api.h +++ b/Firmware/ESP32/main/Board/board_api.h @@ -38,7 +38,6 @@ namespace board_api void init_pins(); void set_led(uint8_t index, bool state); void set_led(bool state); - void check_reset_pin(); } #endif // _BOARD_API_H_ \ No newline at end of file diff --git a/Firmware/ESP32/main/I2CDriver/I2CDriver.cpp b/Firmware/ESP32/main/I2CDriver/I2CDriver.cpp index 6a8e13b..ca18fd4 100644 --- a/Firmware/ESP32/main/I2CDriver/I2CDriver.cpp +++ b/Firmware/ESP32/main/I2CDriver/I2CDriver.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -8,6 +7,13 @@ #include "I2CDriver/I2CDriver.h" #include "Bluepad32/Bluepad32.h" +I2CDriver::TaskQueue I2CDriver::task_queue_; + +I2CDriver::~I2CDriver() +{ + i2c_driver_delete(I2C_NUM_0); +} + void I2CDriver::initialize_i2c() { i2c_config_t conf; @@ -18,46 +24,21 @@ void I2CDriver::initialize_i2c() conf.scl_io_num = GPIO_NUM_22; conf.sda_pullup_en = GPIO_PULLUP_ENABLE; conf.scl_pullup_en = GPIO_PULLUP_ENABLE; - conf.master.clk_speed = 400 * 1000; + conf.master.clk_speed = 1000 * 1000; i2c_param_config(I2C_NUM_0, &conf); i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0); } -void I2CDriver::run_task() +void I2CDriver::run_tasks(void* parameter) { - ReportIn report_in; - ReportOut report_out; - - initialize_i2c(); + std::function task; while (true) - { - for (uint8_t i = 0; i < CONFIG_BLUEPAD32_MAX_DEVICES; ++i) + { + while (task_queue_.pop(task)) { - if (!bluepad32::connected(i)) - { - vTaskDelay(1); - continue; - } - - if (bluepad32::new_report_in(i)) - { - report_in = bluepad32::get_report_in(i); - if (i2c_write_blocking(MULTI_SLAVE ? (i + 1) : 0x01, reinterpret_cast(&report_in), sizeof(ReportIn)) != ESP_OK) - { - continue; - } - } - - // vTaskDelay(1); - - if (i2c_read_blocking(MULTI_SLAVE ? (i + 1) : 0x01, reinterpret_cast(&report_out), sizeof(ReportOut)) != ESP_OK) - { - continue; - } - - bluepad32::set_report_out(report_out); + task(); } vTaskDelay(1); diff --git a/Firmware/ESP32/main/I2CDriver/I2CDriver.h b/Firmware/ESP32/main/I2CDriver/I2CDriver.h index b77fd52..6246a9b 100644 --- a/Firmware/ESP32/main/I2CDriver/I2CDriver.h +++ b/Firmware/ESP32/main/I2CDriver/I2CDriver.h @@ -3,12 +3,12 @@ #include #include -#include +#include #include -#include "Reports.h" +#include "sdkconfig.h" +#include "RingBuffer.h" -//Will probably refactor this to be event driven class I2CDriver { public: @@ -19,14 +19,67 @@ public: true; #endif - I2CDriver() = default; - ~I2CDriver() { i2c_driver_delete(I2C_NUM_0); } + enum class PacketID : uint8_t { UNKNOWN = 0, SET_PAD, GET_PAD }; - void run_task(); + #pragma pack(push, 1) + struct PacketIn + { + uint8_t packet_len; + uint8_t packet_id; + uint8_t index; + uint8_t dpad; + uint16_t buttons; + uint8_t trigger_l; + uint8_t trigger_r; + int16_t joystick_lx; + int16_t joystick_ly; + int16_t joystick_rx; + int16_t joystick_ry; + + PacketIn() + { + std::memset(this, 0, sizeof(PacketIn)); + packet_len = sizeof(PacketIn); + packet_id = static_cast(PacketID::SET_PAD); + } + }; + static_assert(sizeof(PacketIn) == 16, "PacketIn is misaligned"); + + struct PacketOut + { + uint8_t packet_len; + uint8_t packet_id; + uint8_t index; + uint8_t rumble_l; + uint8_t rumble_r; + uint8_t reserved[3]; + + PacketOut() + { + std::memset(this, 0, sizeof(PacketOut)); + packet_len = sizeof(PacketOut); + packet_id = static_cast(PacketID::GET_PAD); + } + }; + static_assert(sizeof(PacketOut) == 8, "PacketOut is misaligned"); + #pragma pack(pop) + + I2CDriver() = default; + ~I2CDriver(); void initialize_i2c(); - static inline esp_err_t i2c_write_blocking(uint8_t address, const uint8_t* buffer, size_t len) + //Does not return + static void run_tasks(void* parameter); + + //Thread safe + inline void push_task(std::function task) + { + task_queue_.push(task); + } + + //Don't call directly from another thread, use in push_task + inline esp_err_t i2c_write_blocking(uint8_t address, const uint8_t* buffer, size_t len) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); @@ -39,7 +92,8 @@ public: return ret; } - static inline esp_err_t i2c_read_blocking(uint8_t address, uint8_t* buffer, size_t len) + //Don't call directly from another thread, use in push_task + inline esp_err_t i2c_read_blocking(uint8_t address, uint8_t* buffer, size_t len) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); @@ -59,17 +113,8 @@ public: } private: -// static constexpr bool MULTI_SLAVE = -// #if CONFIG_MULTI_SLAVE_MODE == 0 -// false; -// #else -// true; -// #endif - // std::array report_in_buffer_{}; - // std::array, CONFIG_BLUEPAD32_MAX_DEVICES> new_report_in_{false}; - // std::array report_out_buffer_{}; - - + using TaskQueue = RingBuffer, 6>; + static TaskQueue task_queue_; }; #endif // _I2C_DRIVER_H_ \ No newline at end of file diff --git a/Firmware/ESP32/main/Reports.h b/Firmware/ESP32/main/Reports.h deleted file mode 100644 index af092c0..0000000 --- a/Firmware/ESP32/main/Reports.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef _REPORTS_H_ -#define _REPORTS_H_ - -#include -// #include -#include -// #include "freertos/FreeRTOS.h" -// #include "freertos/semphr.h" - -enum class ReportID : uint8_t { UNKNOWN = 0, SET_PAD, GET_PAD }; - -#pragma pack(push, 1) -struct ReportIn -{ - uint8_t report_len; - uint8_t report_id; - uint8_t index; - uint8_t dpad; - uint16_t buttons; - uint8_t trigger_l; - uint8_t trigger_r; - int16_t joystick_lx; - int16_t joystick_ly; - int16_t joystick_rx; - int16_t joystick_ry; - - ReportIn() - { - std::memset(this, 0, sizeof(ReportIn)); - report_len = sizeof(ReportIn); - report_id = static_cast(ReportID::SET_PAD); - } -}; -static_assert(sizeof(ReportIn) == 16, "ReportIn is misaligned"); - -struct ReportOut -{ - uint8_t report_len; - uint8_t report_id; - uint8_t index; - uint8_t rumble_l; - uint8_t rumble_r; - - ReportOut() - { - std::memset(this, 0, sizeof(ReportOut)); - report_len = sizeof(ReportOut); - report_id = static_cast(ReportID::GET_PAD); - } -}; -static_assert(sizeof(ReportOut) == 5, "ReportOut is misaligned"); -#pragma pack(pop) - -// class ReportQueue -// { -// public: -// ReportQueue() -// { -// report_in_mutex_ = xSemaphoreCreateMutex(); -// report_out_mutex_ = xSemaphoreCreateMutex(); -// } - -// ~ReportQueue() -// { -// vSemaphoreDelete(report_in_mutex_); -// vSemaphoreDelete(report_out_mutex_); -// } - -// void set_report_in(const ReportIn* report) -// { -// if (xSemaphoreTake(report_in_mutex_, portMAX_DELAY)) -// { -// std::memcpy(&report_in_, report, sizeof(ReportIn)); -// new_report_in_ = true; -// xSemaphoreGive(report_in_mutex_); -// } -// } - -// void set_report_out(const ReportOut* report) -// { -// if (xSemaphoreTake(report_out_mutex_, portMAX_DELAY)) -// { -// std::memcpy(&report_out_, report, sizeof(ReportOut)); -// new_report_out_ = true; -// xSemaphoreGive(report_out_mutex_); -// } -// } - -// //Return false if no new data -// bool get_report_in(ReportIn* report) -// { -// if (xSemaphoreTake(report_in_mutex_, portMAX_DELAY)) -// { -// if (new_report_in_) -// { -// std::memcpy(report, &report_in_, sizeof(ReportIn)); -// new_report_in_ = false; -// xSemaphoreGive(report_in_mutex_); -// return true; -// } -// xSemaphoreGive(report_in_mutex_); -// } -// return false; -// } - -// //Return false if no new data -// bool get_report_out(ReportOut* report) -// { -// if (xSemaphoreTake(report_out_mutex_, portMAX_DELAY)) -// { -// if (new_report_out_) -// { -// std::memcpy(report, &report_out_, sizeof(ReportOut)); -// new_report_out_ = false; -// xSemaphoreGive(report_out_mutex_); -// return true; -// } -// xSemaphoreGive(report_out_mutex_); -// } -// return false; -// } - -// private: -// SemaphoreHandle_t report_in_mutex_; -// SemaphoreHandle_t report_out_mutex_; - -// ReportIn report_in_; -// ReportOut report_out_; - -// bool new_report_in_{false}; -// bool new_report_out_{false}; -// }; - -#endif // _REPORTS_H_ \ No newline at end of file diff --git a/Firmware/ESP32/main/RingBuffer.h b/Firmware/ESP32/main/RingBuffer.h new file mode 100644 index 0000000..61cde39 --- /dev/null +++ b/Firmware/ESP32/main/RingBuffer.h @@ -0,0 +1,57 @@ +#ifndef _RING_BUFFER_H_ +#define _RING_BUFFER_H_ + +#include +#include +#include + +template +class RingBuffer +{ +public: + RingBuffer() : head_(0), tail_(0) {} + + RingBuffer(const RingBuffer&) = delete; + RingBuffer& operator=(const RingBuffer&) = delete; + + RingBuffer(RingBuffer&&) = default; + RingBuffer& operator=(RingBuffer&&) = default; + + bool push(const Type& item) + { + size_t head = head_.load(std::memory_order_relaxed); + size_t next_head = (head + 1) % SIZE; + + if (next_head == tail_.load(std::memory_order_acquire)) + { + tail_.store((tail_.load(std::memory_order_relaxed) + 1) % SIZE, std::memory_order_release); + } + + buffer_[head] = item; + head_.store(next_head, std::memory_order_release); + return true; + } + + bool pop(Type& item) + { + size_t tail = tail_.load(std::memory_order_relaxed); + + if (tail == head_.load(std::memory_order_acquire)) + { + return false; + } + + item = buffer_[tail]; + tail_.store((tail + 1) % SIZE, std::memory_order_release); + return true; + } + +private: + const size_t SIZE = Size; + + std::array buffer_; + std::atomic head_; + std::atomic tail_; +}; + +#endif // _RING_BUFFER_H_ \ No newline at end of file diff --git a/Firmware/ESP32/main/c_wrapper.cpp b/Firmware/ESP32/main/c_wrapper.cpp index 55eb5a2..8ea03df 100644 --- a/Firmware/ESP32/main/c_wrapper.cpp +++ b/Firmware/ESP32/main/c_wrapper.cpp @@ -1,14 +1,24 @@ +#include +#include +#include + #include "c_wrapper.h" -#include "I2CDriver/I2CDriver.h" +#include "sdkconfig.h" #include "Bluepad32/Bluepad32.h" -void run_bluepad32() +void bp32_run_task(void* parameter) { - bluepad32::run_task(); + BP32::run_task(); } -void run_i2c() +void cpp_main() { - I2CDriver i2c_driver; - i2c_driver.run_task(); + xTaskCreatePinnedToCore( + bp32_run_task, + "bp32", + 2048 * 4, + NULL, + configMAX_PRIORITIES-4, + NULL, + 0 ); } \ No newline at end of file diff --git a/Firmware/ESP32/main/c_wrapper.h b/Firmware/ESP32/main/c_wrapper.h index 2356b5a..a972233 100644 --- a/Firmware/ESP32/main/c_wrapper.h +++ b/Firmware/ESP32/main/c_wrapper.h @@ -7,8 +7,7 @@ extern "C" { #endif -void run_bluepad32(); -void run_i2c(); +void cpp_main(); #ifdef __cplusplus } diff --git a/Firmware/ESP32/main/main.c b/Firmware/ESP32/main/main.c index 5c776bc..09f9591 100644 --- a/Firmware/ESP32/main/main.c +++ b/Firmware/ESP32/main/main.c @@ -1,31 +1,9 @@ #include #include -#include -#include -#include "sdkconfig.h" #include "c_wrapper.h" -#define STACK_MULTIPLIER (2048 * CONFIG_BLUEPAD32_MAX_DEVICES) - void app_main(void) { - // run_bluepad32(); - xTaskCreatePinnedToCore( - run_bluepad32, - "bp32", - STACK_MULTIPLIER * 4, - NULL, - configMAX_PRIORITIES-6, - NULL, - 0 ); - - xTaskCreatePinnedToCore( - run_i2c, - "i2c", - STACK_MULTIPLIER * 2, - NULL, - configMAX_PRIORITIES-8, - NULL, - 1 ); + cpp_main(); } \ No newline at end of file diff --git a/Firmware/ESP32/sdkconfig b/Firmware/ESP32/sdkconfig index b3d81ff..1363948 100644 --- a/Firmware/ESP32/sdkconfig +++ b/Firmware/ESP32/sdkconfig @@ -1,6 +1,6 @@ # # Automatically generated file. DO NOT EDIT. -# Espressif IoT Development Framework (ESP-IDF) 5.1.5 Project Configuration +# Espressif IoT Development Framework (ESP-IDF) Project Configuration # CONFIG_SOC_BROWNOUT_RESET_SUPPORTED="Not determined" CONFIG_SOC_TWAI_BRP_DIV_SUPPORTED="Not determined" @@ -362,11 +362,11 @@ CONFIG_ESP_CUSTOM_BOARD=y # CONFIG_COMPILER_OPTIMIZATION_SIZE is not set CONFIG_COMPILER_OPTIMIZATION_PERF=y # CONFIG_COMPILER_OPTIMIZATION_NONE is not set -CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE is not set # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set -# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y -CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=0 # CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set CONFIG_COMPILER_HIDE_PATHS_MACROS=y # CONFIG_COMPILER_CXX_EXCEPTIONS is not set @@ -1358,9 +1358,7 @@ CONFIG_FREERTOS_DEBUG_OCDAWARE=y # CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y # CONFIG_HAL_ASSERTION_DISABLE is not set -# CONFIG_HAL_ASSERTION_SILENT is not set -# CONFIG_HAL_ASSERTION_ENABLE is not set -CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=0 CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM=y CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM=y # CONFIG_HAL_ECDSA_GEN_SIG_CM is not set @@ -1546,7 +1544,6 @@ CONFIG_LWIP_DNS_MAX_SERVERS=3 # end of DNS CONFIG_LWIP_BRIDGEIF_MAX_PORTS=7 -CONFIG_LWIP_ESP_LWIP_ASSERT=y # # Hooks @@ -1981,11 +1978,11 @@ CONFIG_BLUEPAD32_PLATFORM_CUSTOM=y # CONFIG_BLUEPAD32_PLATFORM_MAKEFILE is not set CONFIG_BLUEPAD32_MAX_DEVICES=1 CONFIG_BLUEPAD32_GAP_SECURITY=y -# CONFIG_BLUEPAD32_LOG_LEVEL_NONE is not set -CONFIG_BLUEPAD32_LOG_LEVEL_ERROR=y +CONFIG_BLUEPAD32_LOG_LEVEL_NONE=y +# CONFIG_BLUEPAD32_LOG_LEVEL_ERROR is not set # CONFIG_BLUEPAD32_LOG_LEVEL_INFO is not set # CONFIG_BLUEPAD32_LOG_LEVEL_DEBUG is not set -CONFIG_BLUEPAD32_LOG_LEVEL=1 +CONFIG_BLUEPAD32_LOG_LEVEL=0 # CONFIG_BLUEPAD32_USB_CONSOLE_ENABLE is not set CONFIG_BLUEPAD32_ENABLE_BLE_BY_DEFAULT=y CONFIG_BLUEPAD32_MAX_ALLOWLIST=4 @@ -2025,10 +2022,10 @@ CONFIG_MONITOR_BAUD=115200 # CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set # CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set # CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set -CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED is not set # CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set -# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set -CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED=y +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=0 # CONFIG_CXX_EXCEPTIONS is not set CONFIG_STACK_CHECK_NONE=y # CONFIG_STACK_CHECK_NORM is not set @@ -2372,7 +2369,6 @@ CONFIG_TIMER_TASK_PRIORITY=1 CONFIG_TIMER_TASK_STACK_DEPTH=4096 CONFIG_TIMER_QUEUE_LENGTH=10 # CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set -# CONFIG_HAL_ASSERTION_SILIENT is not set # CONFIG_L2_TO_L3_COPY is not set CONFIG_ESP_GRATUITOUS_ARP=y CONFIG_GARP_TMR_INTERVAL=60 diff --git a/Firmware/RP2040/.vscode/settings.json b/Firmware/RP2040/.vscode/settings.json index 67c86c2..da0fd3d 100644 --- a/Firmware/RP2040/.vscode/settings.json +++ b/Firmware/RP2040/.vscode/settings.json @@ -1,15 +1,23 @@ { "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", + "cmake.buildEnvironment": { + "PICO_SDK_PATH": "C:/Programming/pico-sdk" + }, + "cmake.environment": { + "PICO_SDK_PATH": "C:/Programming/pico-sdk" + }, + "cmake.configureArgs": [ + "-DOGXM_BOARD=PI_PICO", + "-DMAX_GAMEPADS=1" + ], "files.associations": { "array": "cpp", - "any": "cpp", "atomic": "cpp", - "barrier": "cpp", + "any": "cpp", "bit": "cpp", "*.tcc": "cpp", "bitset": "cpp", "cctype": "cpp", - "cfenv": "cpp", "charconv": "cpp", "chrono": "cpp", "cinttypes": "cpp", @@ -17,11 +25,7 @@ "cmath": "cpp", "codecvt": "cpp", "compare": "cpp", - "complex": "cpp", "concepts": "cpp", - "condition_variable": "cpp", - "coroutine": "cpp", - "csetjmp": "cpp", "csignal": "cpp", "cstdarg": "cpp", "cstddef": "cpp", @@ -40,91 +44,44 @@ "set": "cpp", "string": "cpp", "unordered_map": "cpp", - "unordered_set": "cpp", "vector": "cpp", "exception": "cpp", - "expected": "cpp", "algorithm": "cpp", "functional": "cpp", "iterator": "cpp", "memory": "cpp", "memory_resource": "cpp", - "netfwd": "cpp", "numeric": "cpp", "optional": "cpp", "random": "cpp", "ratio": "cpp", "regex": "cpp", - "source_location": "cpp", "string_view": "cpp", "system_error": "cpp", "tuple": "cpp", "type_traits": "cpp", "utility": "cpp", - "rope": "cpp", - "slist": "cpp", "format": "cpp", "fstream": "cpp", - "future": "cpp", "initializer_list": "cpp", "iomanip": "cpp", "iosfwd": "cpp", "iostream": "cpp", "istream": "cpp", - "latch": "cpp", "limits": "cpp", - "mutex": "cpp", "new": "cpp", "numbers": "cpp", "ostream": "cpp", "ranges": "cpp", - "scoped_allocator": "cpp", "semaphore": "cpp", - "shared_mutex": "cpp", "span": "cpp", - "spanstream": "cpp", "sstream": "cpp", - "stacktrace": "cpp", "stdexcept": "cpp", - "stdfloat": "cpp", "stop_token": "cpp", "streambuf": "cpp", - "syncstream": "cpp", "thread": "cpp", - "typeindex": "cpp", "typeinfo": "cpp", "valarray": "cpp", - "variant": "cpp", - "xlocmon": "cpp", - "xtr1common": "cpp", - "xutility": "cpp", - "ios": "cpp", - "locale": "cpp", - "queue": "cpp", - "xfacet": "cpp", - "xhash": "cpp", - "xiosbase": "cpp", - "xlocale": "cpp", - "xlocbuf": "cpp", - "xlocinfo": "cpp", - "xlocmes": "cpp", - "xlocnum": "cpp", - "xloctime": "cpp", - "xmemory": "cpp", - "xstring": "cpp", - "filesystem": "cpp", - "flash.h": "c", - "uart_bridge.h": "c", - "usbh.h": "c" - }, - "cmake.buildEnvironment": { - "PICO_SDK_PATH": "C:/Programming/pico-sdk" - }, - "cmake.environment": { - "PICO_SDK_PATH": "C:/Programming/pico-sdk" - }, - "cmake.configureArgs": [ - "-DOGXM_BOARD=EXTERNAL_4CH", - "-DMAX_GAMEPADS=4" - ] + "variant": "cpp" + } } \ No newline at end of file diff --git a/Firmware/RP2040/CMakeLists.txt b/Firmware/RP2040/CMakeLists.txt index f923a36..6ab9fde 100644 --- a/Firmware/RP2040/CMakeLists.txt +++ b/Firmware/RP2040/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.13) set(FW_NAME "OGX-Mini") -set(FW_VERSION "v1.0.0-alpha") +set(FW_VERSION "v1.0.0a") set(CMAKE_C_COMPILER arm-none-eabi-gcc) set(CMAKE_CXX_COMPILER arm-none-eabi-g++) @@ -19,14 +19,6 @@ include(${CMAKE_CURRENT_LIST_DIR}/cmake/get_pico_sdk.cmake) apply_lib_patches(${EXTERNAL_DIR}) get_pico_sdk(${EXTERNAL_DIR}) -include(${PICO_SDK_PATH}/pico_sdk_init.cmake) -message("PICO_SDK_VERSION_STRING: ${PICO_SDK_VERSION_STRING}") -if (PICO_SDK_VERSION_STRING VERSION_LESS "2.1.0") - message(FATAL_ERROR "Raspberry Pi Pico SDK version 2.1.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}") -endif() - -project(${FW_NAME} C CXX ASM) - set(PICO_PIO_USB_PATH ${EXTERNAL_DIR}/Pico-PIO-USB) set(PICO_TINYUSB_PATH ${EXTERNAL_DIR}/tinyusb) set(BLUEPAD32_ROOT ${EXTERNAL_DIR}/bluepad32) @@ -37,7 +29,7 @@ set(SOURCES_BOARD ${SRC}/main.cpp ${SRC}/OGXMini/OGXMini_Standard.cpp - ${SRC}/OGXMini/OGXMini_4Ch.cpp + ${SRC}/OGXMini/OGXMini_4Channel.cpp ${SRC}/OGXMini/OGXMini_PicoW.cpp ${SRC}/OGXMini/OGXMini_ESP32.cpp @@ -81,6 +73,7 @@ set(INC_DIRS_BOARD ) # Config options + # Max gamepads set(MAX_GAMEPADS 1 CACHE STRING "Set number of gamepads, 1 to 4") if (MAX_GAMEPADS GREATER 4 OR MAX_GAMEPADS LESS 1) @@ -97,6 +90,11 @@ set(PICO_BOARD none) if (OGXM_BOARD STREQUAL "PI_PICO") set(EN_USB_HOST TRUE) +elseif (OGXM_BOARD STREQUAL "PI_PICO2") + set(EN_USB_HOST TRUE) + set(PICO_PLATFORM rp2350) + set(FLASH_SIZE_MB 4) + elseif(OGXM_BOARD STREQUAL "ADA_FEATHER") set(EN_USB_HOST TRUE) set(EN_RGB TRUE) @@ -135,28 +133,29 @@ if(EN_USB_HOST) add_compile_definitions(CONFIG_EN_USB_HOST=1) list(APPEND SOURCES_BOARD ${SRC}/USBHost/tuh_callbacks.cpp - - # ${SRC}/USBHost/HostDriver/DInput/DInput.cpp - # ${SRC}/USBHost/HostDriver/PSClassic/PSClassic.cpp - # ${SRC}/USBHost/HostDriver/SwitchWired/SwitchWired.cpp - # ${SRC}/USBHost/HostDriver/SwitchPro/SwitchPro.cpp - # ${SRC}/USBHost/HostDriver/PS5/PS5.cpp - # ${SRC}/USBHost/HostDriver/PS4/PS4.cpp - # ${SRC}/USBHost/HostDriver/PS3/PS3.cpp - # ${SRC}/USBHost/HostDriver/N64/N64.cpp - # ${SRC}/USBHost/HostDriver/HIDGeneric/HIDGeneric.cpp - - ${SRC}/USBHost/HostDriver/XInput/XboxOG.cpp - ${SRC}/USBHost/HostDriver/XInput/XboxOne.cpp - ${SRC}/USBHost/HostDriver/XInput/Xbox360.cpp - ${SRC}/USBHost/HostDriver/XInput/Xbox360W.cpp - ${SRC}/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.cpp + # HID + ${SRC}/USBHost/HostDriver/DInput/DInput.cpp + ${SRC}/USBHost/HostDriver/PSClassic/PSClassic.cpp + ${SRC}/USBHost/HostDriver/SwitchWired/SwitchWired.cpp + ${SRC}/USBHost/HostDriver/SwitchPro/SwitchPro.cpp + ${SRC}/USBHost/HostDriver/PS5/PS5.cpp + ${SRC}/USBHost/HostDriver/PS4/PS4.cpp + ${SRC}/USBHost/HostDriver/PS3/PS3.cpp + ${SRC}/USBHost/HostDriver/N64/N64.cpp + ${SRC}/USBHost/HostDriver/HIDGeneric/HIDGeneric.cpp ${SRC}/USBHost/HIDParser/HIDJoystick.cpp ${SRC}/USBHost/HIDParser/HIDReportDescriptor.cpp ${SRC}/USBHost/HIDParser/HIDReportDescriptorElements.cpp ${SRC}/USBHost/HIDParser/HIDReportDescriptorUsages.cpp ${SRC}/USBHost/HIDParser/HIDUtils.cpp + + # XInput + ${SRC}/USBHost/HostDriver/XInput/XboxOG.cpp + ${SRC}/USBHost/HostDriver/XInput/XboxOne.cpp + ${SRC}/USBHost/HostDriver/XInput/Xbox360.cpp + ${SRC}/USBHost/HostDriver/XInput/Xbox360W.cpp + ${SRC}/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.cpp ) list(APPEND LIBS_BOARD tinyusb_host @@ -211,7 +210,7 @@ if(EN_ESP32) add_compile_definitions(CONFIG_EN_ESP32=1) message(STATUS "ESP32 enabled.") list(APPEND SOURCES_BOARD - ${SRC}/I2CDriver/i2c_driver_esp32.cpp + ${SRC}/I2CDriver/ESP32/I2CDriver.cpp ) list(APPEND LIBS_BOARD hardware_i2c @@ -238,31 +237,45 @@ if(EXISTS ${SRC}/USBDevice/DeviceDriver/XboxOG/tud_xid/tud_xid_xremote_rom.h) endif() if(NOT EN_BLUETOOTH) - # add_compile_definitions(PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H=1 PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64) add_compile_definitions(PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64) endif() +include(${PICO_SDK_PATH}/pico_sdk_init.cmake) + +message("PICO_SDK_VERSION_STRING: ${PICO_SDK_VERSION_STRING}") +if(PICO_SDK_VERSION_STRING VERSION_LESS "2.1.0") + message(FATAL_ERROR "Raspberry Pi Pico SDK version 2.1.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}") +endif() + +project(${FW_NAME} C CXX ASM) + pico_sdk_init() -# pico_enable_stdio_usb(${FW_NAME} 0) add_executable(${FW_NAME} ${SOURCES_BOARD}) -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - pico_enable_stdio_uart(${FW_NAME} 1) - add_compile_definitions(CFG_TUSB_DEBUG=2) - add_compile_definitions(LOG=2) - # target_compile_options(${FW_NAME} PRIVATE - # -Wall # Enable most warnings - # -Wextra # Enable extra warnings - # -Wconversion # Warn on type conversion issues - # -Wsign-conversion # Warn on sign conversion issues - # # -Werror # Treat warnings as errors - # ) +set(BUILD_STR "") - add_link_options( - -Wl,--gc-sections +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(BUILD_STR "-Debug") + pico_enable_stdio_uart(${FW_NAME} 1) + target_compile_definitions(${FW_NAME} PRIVATE + PICO_DEFAULT_UART=1 + PICO_DEFAULT_UART_TX_PIN=4 + PICO_DEFAULT_UART_RX_PIN=5 + ) + add_compile_definitions(LOG=1) + add_compile_definitions(CFG_TUSB_DEBUG=1) + add_compile_definitions(OGXM_DEBUG=1) + target_compile_options(${FW_NAME} PRIVATE + -Wall # Enable most warnings + -Wextra # Enable extra warnings + -Wconversion # Warn on type conversion issues + -Wsign-conversion # Warn on sign conversion issues + -Wno-unused-parameter # Disable warnings for unused parameters + # -Werror # Treat warnings as errors ) elseif(CMAKE_BUILD_TYPE STREQUAL "Release") + pico_enable_stdio_uart(${FW_NAME} 0) add_compile_definitions(CFG_TUSB_DEBUG=0) add_compile_options( -O3 # Optimize for speed @@ -301,7 +314,7 @@ endif() target_link_libraries(${FW_NAME} PRIVATE ${LIBS_BOARD}) -set(EXE_FILENAME "${FW_NAME}-${FW_VERSION}-${OGXM_BOARD}") +set(EXE_FILENAME "${FW_NAME}-${FW_VERSION}-${OGXM_BOARD}${BUILD_STR}") set_target_properties(${FW_NAME} PROPERTIES OUTPUT_NAME ${EXE_FILENAME}) pico_add_extra_outputs(${FW_NAME}) \ No newline at end of file diff --git a/Firmware/RP2040/src/Bluepad32/Bluepad32.cpp b/Firmware/RP2040/src/Bluepad32/Bluepad32.cpp index c0b0ea4..8beba8e 100644 --- a/Firmware/RP2040/src/Bluepad32/Bluepad32.cpp +++ b/Firmware/RP2040/src/Bluepad32/Bluepad32.cpp @@ -29,8 +29,10 @@ struct BTDevice }; BTDevice bt_devices_[MAX_GAMEPADS]; +btstack_timer_source_t feedback_timer_; btstack_timer_source_t led_timer_; bool led_timer_set_{false}; +bool feedback_timer_set_{false}; //This solves a function pointer/crash issue with bluepad32 void set_rumble(uni_hid_device_t* bp_device, uint16_t length, uint8_t rumble_l, uint8_t rumble_r) @@ -117,11 +119,7 @@ static void init_complete_cb(void) { uni_bt_enable_new_connections_unsafe(true); - // Based on runtime condition, you can delete or list the stored BT keys. - if (1) - uni_bt_del_keys_unsafe(); - else - uni_bt_list_keys_unsafe(); + // uni_bt_del_keys_unsafe(); uni_property_dump_all(); } @@ -155,6 +153,11 @@ static void device_disconnected_cb(uni_hid_device_t* device) btstack_run_loop_set_timer(&led_timer_, LED_CHECK_TIME_MS); btstack_run_loop_add_timer(&led_timer_); } + if (feedback_timer_set_ && !any_connected()) + { + feedback_timer_set_ = false; + btstack_run_loop_remove_timer(&feedback_timer_); + } } static uni_error_t device_ready_cb(uni_hid_device_t* device) @@ -172,6 +175,14 @@ static uni_error_t device_ready_cb(uni_hid_device_t* device) btstack_run_loop_remove_timer(&led_timer_); board_api::set_led(true); } + if (!feedback_timer_set_) + { + feedback_timer_set_ = true; + feedback_timer_.process = send_feedback_cb; + feedback_timer_.context = nullptr; + btstack_run_loop_set_timer(&feedback_timer_, FEEDBACK_TIME_MS); + btstack_run_loop_add_timer(&feedback_timer_); + } return UNI_ERROR_SUCCESS; } @@ -283,12 +294,6 @@ void run_task(Gamepad (&gamepads)[MAX_GAMEPADS]) uni_platform_set_custom(get_driver()); uni_init(0, nullptr); - btstack_timer_source_t feedback_timer; - feedback_timer.process = send_feedback_cb; - feedback_timer.context = nullptr; - btstack_run_loop_set_timer(&feedback_timer, FEEDBACK_TIME_MS); - btstack_run_loop_add_timer(&feedback_timer); - led_timer_set_ = true; led_timer_.process = check_led_cb; led_timer_.context = nullptr; @@ -298,16 +303,6 @@ void run_task(Gamepad (&gamepads)[MAX_GAMEPADS]) btstack_run_loop_execute(); } -std::array get_connected_map() -{ - std::array mounted_map; - for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) - { - mounted_map[i] = bt_devices_[i].connected; - } - return mounted_map; -} - bool any_connected() { for (auto& device : bt_devices_) diff --git a/Firmware/RP2040/src/Bluepad32/Bluepad32.h b/Firmware/RP2040/src/Bluepad32/Bluepad32.h index 2579b50..2d7e76a 100644 --- a/Firmware/RP2040/src/Bluepad32/Bluepad32.h +++ b/Firmware/RP2040/src/Bluepad32/Bluepad32.h @@ -14,7 +14,6 @@ namespace bluepad32 { void run_task(Gamepad (&gamepads)[MAX_GAMEPADS]); - // std::array get_connected_map(); bool any_connected(); } //namespace bluepad32 diff --git a/Firmware/RP2040/src/Board/Pico_WS2812/WS2812.cpp b/Firmware/RP2040/src/Board/Pico_WS2812/WS2812.cpp index f852e64..e3998db 100644 --- a/Firmware/RP2040/src/Board/Pico_WS2812/WS2812.cpp +++ b/Firmware/RP2040/src/Board/Pico_WS2812/WS2812.cpp @@ -1,12 +1,11 @@ +/* + Copyright ForsakenNGS 2021 + https://github.com/ForsakenNGS/Pico_WS2812 +*/ + #include "Board/Pico_WS2812/WS2812.hpp" #include "WS2812.pio.h" -//#define DEBUG - -#ifdef DEBUG -#include -#endif - WS2812::WS2812(uint pin, uint length, PIO pio, uint sm) { initialize(pin, length, pio, sm, NONE, GREEN, RED, BLUE); } @@ -42,16 +41,14 @@ void WS2812::initialize(uint pin, uint length, PIO pio, uint sm, DataByte b1, Da this->length = length; this->pio = pio; this->sm = sm; - this->data.fill(0); + this->data = new uint32_t[length]; this->bytes[0] = b1; this->bytes[1] = b2; this->bytes[2] = b3; this->bytes[3] = b4; uint offset = pio_add_program(pio, &ws2812_program); uint bits = (b1 == NONE ? 24 : 32); - #ifdef DEBUG - printf("WS2812 / Initializing SM %u with offset %X at pin %u and %u data bits...\n", sm, offset, pin, bits); - #endif + ws2812_program_init(pio, sm, offset, pin, 800000, bits); } @@ -111,11 +108,6 @@ void WS2812::fill(uint32_t color, uint first, uint count) { } void WS2812::show() { - #ifdef DEBUG - for (uint i = 0; i < length; i++) { - printf("WS2812 / Put data: %08X\n", data[i]); - } - #endif for (uint i = 0; i < length; i++) { pio_sm_put_blocking(pio, sm, data[i]); } diff --git a/Firmware/RP2040/src/Board/Pico_WS2812/WS2812.hpp b/Firmware/RP2040/src/Board/Pico_WS2812/WS2812.hpp index bb3a165..0420eac 100644 --- a/Firmware/RP2040/src/Board/Pico_WS2812/WS2812.hpp +++ b/Firmware/RP2040/src/Board/Pico_WS2812/WS2812.hpp @@ -1,3 +1,8 @@ +/* + Copyright ForsakenNGS 2021 + https://github.com/ForsakenNGS/Pico_WS2812 +*/ + #ifndef WS2812_H #define WS2812_H @@ -48,7 +53,7 @@ class WS2812 { PIO pio; uint sm; DataByte bytes[4]; - std::array data; + uint32_t *data; void initialize(uint pin, uint length, PIO pio, uint sm, DataByte b1, DataByte b2, DataByte b3, DataByte b4); uint32_t convertData(uint32_t rgbw); diff --git a/Firmware/RP2040/src/Board/board_api.cpp b/Firmware/RP2040/src/Board/board_api.cpp index 178bb63..2850ee8 100644 --- a/Firmware/RP2040/src/Board/board_api.cpp +++ b/Firmware/RP2040/src/Board/board_api.cpp @@ -1,11 +1,11 @@ -/* This is too messy I'll clean it up at some point */ - #include #include +#include #include #include #include "Board/board_api.h" +#include "OGXMini/Debug.h" #include "board_config.h" #if defined(CONFIG_EN_BLUETOOTH) @@ -22,45 +22,35 @@ namespace board_api { bool inited_ = false; mutex_t gpio_mutex_; -#if defined(CONFIG_EN_RGB) -WS2812 ws2812_ = WS2812(RGB_PXL_PIN, 1, pio1, 0, WS2812::FORMAT_GRB); -#endif // defined(CONFIG_EN_RGB) - -void init_gpio() -{ - if (inited_) - { - return; - } - if (!mutex_is_initialized(&gpio_mutex_)) - { - mutex_init(&gpio_mutex_); - } - mutex_enter_blocking(&gpio_mutex_); - -#ifdef VCC_EN_PIN +void init_vcc_en_pin_unsafe() +{ +#if defined(VCC_EN_PIN) gpio_init(VCC_EN_PIN); gpio_set_dir(VCC_EN_PIN, GPIO_OUT); gpio_put(VCC_EN_PIN, 1); #endif +} -#if defined(CONFIG_EN_RGB) - #ifdef RGB_PWR_PIN +void init_rgb_unsafe() +{ +#if defined(CONFIG_EN_RGB) && defined(RGB_PWR_PIN) gpio_init(RGB_PWR_PIN); gpio_set_dir(RGB_PWR_PIN, GPIO_OUT); gpio_put(RGB_PWR_PIN, 1); - #endif +#endif // defined(CONFIG_EN_RGB) && defined(RGB_PWR_PIN) +} -#elif defined(CONFIG_EN_BLUETOOTH) - // - -#elif defined(LED_INDICATOR_PIN) +void init_led_indicator_unsafe() +{ +#if defined(LED_INDICATOR_PIN) && !defined(CONFIG_EN_BLUETOOTH) gpio_init(LED_INDICATOR_PIN); gpio_set_dir(LED_INDICATOR_PIN, GPIO_OUT); gpio_put(LED_INDICATOR_PIN, 0); +#endif // defined(LED_INDICATOR_PIN) +} -#endif - +void init_esp32_io_unsafe() +{ #if defined(CONFIG_EN_ESP32) gpio_init(ESP_PROG_PIN); gpio_set_dir(ESP_PROG_PIN, GPIO_OUT); @@ -71,31 +61,46 @@ void init_gpio() gpio_put(ESP_RST_PIN, 1); #endif //defined(CONFIG_EN_ESP32) +} +void init_uart_bridge_io_unsafe() +{ #if defined(CONFIG_EN_UART_BRIDGE) gpio_init(MODE_SEL_PIN); gpio_set_dir(MODE_SEL_PIN, GPIO_IN); gpio_pull_up(MODE_SEL_PIN); #endif // defined(CONFIG_EN_UART_BRIDGE) +} - inited_ = true; - mutex_exit(&gpio_mutex_); +void init_uart_debug_unsafe() +{ +#if defined(OGXM_DEBUG) + uart_init(DEBUG_UART_PORT, PICO_DEFAULT_UART_BAUD_RATE); + gpio_set_function(PICO_DEFAULT_UART_TX_PIN, GPIO_FUNC_UART); + gpio_set_function(PICO_DEFAULT_UART_RX_PIN, GPIO_FUNC_UART); +#endif // defined(OGXM_DEBUG) } void set_led(bool state) { - if (!inited_) - { - return; - } mutex_enter_blocking(&gpio_mutex_); -#if defined(CONFIG_EN_RGB) - ws2812_.setPixelColor(0, state ? WS2812::RGB(0x00, 0xFF, 0x00) : WS2812::RGB(0xFF, 0, 0)); - ws2812_.show(); + if (!inited_) + { + mutex_exit(&gpio_mutex_); + return; + } -#elif defined(CONFIG_EN_BLUETOOTH) +#if defined(CONFIG_EN_RGB) + static WS2812 ws2812 = WS2812(RGB_PXL_PIN, 1, pio1, 0, WS2812::FORMAT_GRB); + + ws2812.setPixelColor(0, state ? WS2812::RGB(0x00, 0xFF, 0x00) : WS2812::RGB(0xFF, 0, 0)); + ws2812.show(); + +#endif // defined(CONFIG_EN_RGB) + +#if defined(CONFIG_EN_BLUETOOTH) cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, state ? 1 : 0); #elif defined(LED_INDICATOR_PIN) @@ -177,13 +182,43 @@ void reboot() AIRCR_REG = AIRCR_VECTKEY | AIRCR_SYSRESETREQ; while(1); +} - // watchdog_enable(500, true); // 10-second timeout - // while (true) - // { - // // Your main loop logic - // watchdog_update(); // Reset the watchdog timer - // } +void init_board() +{ + if (inited_) + { + return; + } + + if (!set_sys_clock_khz(SYSCLOCK_KHZ, true) && !set_sys_clock_khz(120000, true)) + { + panic("Failed to set sys clock"); + } + + stdio_init_all(); + + if (!mutex_is_initialized(&gpio_mutex_)) + { + mutex_init(&gpio_mutex_); + } + + mutex_enter_blocking(&gpio_mutex_); + + init_uart_debug_unsafe(); + init_vcc_en_pin_unsafe(); + init_rgb_unsafe(); + init_led_indicator_unsafe(); + init_esp32_io_unsafe(); + init_uart_bridge_io_unsafe(); + + inited_ = true; + + mutex_exit(&gpio_mutex_); + + set_led(false); + + OGXM_LOG("Board initialized\n"); } } // namespace board_api \ No newline at end of file diff --git a/Firmware/RP2040/src/Board/board_api.h b/Firmware/RP2040/src/Board/board_api.h index 23527c2..0eab62d 100644 --- a/Firmware/RP2040/src/Board/board_api.h +++ b/Firmware/RP2040/src/Board/board_api.h @@ -1,11 +1,12 @@ -#ifndef _BOARD_API_H_ -#define _BOARD_API_H_ +#ifndef _OGXM_BOARD_API_H_ +#define _OGXM_BOARD_API_H_ #include +#include namespace board_api { - void init_gpio(); + void init_board(); void set_led(bool state); void reboot(); @@ -14,4 +15,4 @@ namespace board_api void enter_esp32_prog_mode(); } -#endif // _BOARD_API_H_ \ No newline at end of file +#endif // _OGXM_BOARD_API_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/Descriptors/CDCDev.h b/Firmware/RP2040/src/Descriptors/CDCDev.h index 439888d..ed981bb 100644 --- a/Firmware/RP2040/src/Descriptors/CDCDev.h +++ b/Firmware/RP2040/src/Descriptors/CDCDev.h @@ -9,73 +9,58 @@ namespace CDCDesc { #define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) - #define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) - // #define USB_VID 0xCafe - // #define USB_BCD 0x0200 + static const uint16_t VID = 0xCafe; + static const uint16_t PID = (0x4000 | _PID_MAP(CDC, 0)); + static const uint16_t USB_VER = 0x0200; - static const tusb_desc_device_t DEVICE_DESCRIPTORS = + const tusb_desc_device_t DESC_DEVICE = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - + .bcdUSB = USB_VER, .bDeviceClass = TUSB_CLASS_MISC, .bDeviceSubClass = MISC_SUBCLASS_COMMON, .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - - .idVendor = 0xCafe, - .idProduct = USB_PID, + .idVendor = VID, + .idProduct = PID, .bcdDevice = 0x0100, - .iManufacturer = 0x01, .iProduct = 0x02, .iSerialNumber = 0x03, - .bNumConfigurations = 0x01 }; enum Itf { - NUM_CDC = 0, - NUM_CDC_DATA, - NUM_TOTAL + CDC_0 = 0, + CDC_0_DATA, + ITF_TOTAL }; - #define EPNUM_CDC_NOTIF 0x81 - #define EPNUM_CDC_OUT 0x02 - #define EPNUM_CDC_IN 0x82 + static const int CONFIG_LEN = (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN); - static constexpr int CONFIG_LEN = (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN); - - static const uint8_t CONFIGURATION_DESCRIPTORS[] = + static const uint8_t DESC_CONFIG[] = { - TUD_CONFIG_DESCRIPTOR(1, Itf::NUM_TOTAL, 0, CONFIG_LEN, 0x00, 500), - TUD_CDC_DESCRIPTOR(Itf::NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), + TUD_CONFIG_DESCRIPTOR(1, Itf::ITF_TOTAL, 0, CONFIG_LEN, 0x00, 500), + TUD_CDC_DESCRIPTOR(Itf::CDC_0, 4, 0x80 | (Itf::CDC_0 + 1), 8, (Itf::CDC_0 + 2), 0x80 | (Itf::CDC_0 + 2), 64), }; - enum + static const uint8_t STRING_DESC_LANGUAGE[] = { 0x09, 0x04 }; + static const uint8_t STRING_MANUFACTURER[] = "Wired Opposite"; + static const uint8_t STRING_PRODUCT[] = "OGX-Mini"; + static const uint8_t STRING_INTERFACE[] = "OGX-Mini CDC"; + + static const uint8_t *DESC_STRING[] = { - STRID_LANGID = 0, - STRID_MANUFACTURER, - STRID_PRODUCT, - STRID_SERIAL, + STRING_DESC_LANGUAGE, + STRING_MANUFACTURER, + STRING_PRODUCT, + nullptr, //Serial + STRING_INTERFACE }; - static const char *STRING_DESCRIPTORS[] = - { - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - NULL, // 3: Serials will use unique ID if possible - "TinyUSB CDC", // 4: CDC Interface - }; - - static uint16_t _desc_str[32 + 1]; - }; // namespace CDCDesc #endif // _CDC_DEV_DESCRIPTORS_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/Descriptors/DInput.h b/Firmware/RP2040/src/Descriptors/DInput.h index 20dc4e0..e15c7ac 100644 --- a/Firmware/RP2040/src/Descriptors/DInput.h +++ b/Firmware/RP2040/src/Descriptors/DInput.h @@ -75,6 +75,11 @@ namespace DInput uint8_t r1_axis; uint8_t l2_axis; uint8_t r2_axis; + + InReport() + { + std::memset(this, 0, sizeof(InReport)); + } }; #pragma pack(pop) static_assert(sizeof(InReport) == 19, "DInput::InReport is misaligned"); diff --git a/Firmware/RP2040/src/Descriptors/PS3.h b/Firmware/RP2040/src/Descriptors/PS3.h index 129bbe6..e7fce0b 100644 --- a/Firmware/RP2040/src/Descriptors/PS3.h +++ b/Firmware/RP2040/src/Descriptors/PS3.h @@ -10,7 +10,7 @@ namespace PS3 { static constexpr uint8_t MAGIC_BYTES[8] = { 0x21, 0x26, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; - static constexpr uint8_t JOYSTICK_MID = 0x80; + static constexpr uint8_t JOYSTICK_MID = 0x7F; static constexpr uint16_t SIXAXIS_MID = 0xFF01; namespace ReportID @@ -94,22 +94,19 @@ namespace PS3 struct InReport { uint8_t report_id; - uint8_t reserved0; + uint8_t unk0; uint8_t buttons[3]; - - uint8_t reserved1; + uint8_t unk1; uint8_t joystick_lx; uint8_t joystick_ly; uint8_t joystick_rx; uint8_t joystick_ry; - uint8_t reserved2[2]; - + uint8_t unk2[2]; uint8_t move_power_status; - - uint8_t reserved3; + uint8_t unk3; uint8_t up_axis; uint8_t right_axis; @@ -126,7 +123,7 @@ namespace PS3 uint8_t cross_axis; uint8_t square_axis; - uint8_t reserved4[3]; + uint8_t unk4[3]; uint8_t plugged; uint8_t power_status; @@ -137,8 +134,7 @@ namespace PS3 uint16_t acceler_x; uint16_t acceler_y; uint16_t acceler_z; - - uint16_t velocity_z; + uint16_t gyro_z; InReport() { @@ -151,44 +147,50 @@ namespace PS3 plugged = PlugState::PLUGGED; power_status = PowerState::FULL; rumble_status = RumbleState::WIRED_RUMBLE; - acceler_x = acceler_y = acceler_z = velocity_z = SIXAXIS_MID; + acceler_x = acceler_y = acceler_z = gyro_z = SIXAXIS_MID; } }; static_assert(sizeof(InReport) == 49, "PS3::InReport size mismatch"); - struct LEDs { - uint8_t time_enabled; /* the total time the led is active (0xff means forever) */ - uint8_t duty_length; /* how long a cycle is in deciseconds (0 means "really fast") */ - uint8_t enabled; - uint8_t duty_off; /* % of duty_length the led is off (0xff means 100%) */ - uint8_t duty_on; /* % of duty_length the led is on (0xff mean 100%) */ - }; - static_assert(sizeof(LEDs) == 5, "PS3::LEDs size mismatch"); - - struct Rumble { - uint8_t reserved; - uint8_t right_duration; /* Right motor duration (0xff means forever) */ - uint8_t right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */ - uint8_t left_duration; /* Left motor duration (0xff means forever) */ - uint8_t left_motor_force; /* left (large) motor, supports force values from 0 to 255 */ - }; - static_assert(sizeof(Rumble) == 5, "PS3::Rumble size mismatch"); - struct OutReport { - struct Rumble rumble; - uint8_t padding[4]; - uint8_t leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */ - struct LEDs led[4]; /* LEDx at (4 - x) */ - struct LEDs reserved; /* LED5, not actually soldered */ + //uint8_t report_id; + uint8_t reserved0; + struct Rumble + { + uint8_t right_duration; /* Right motor duration (0xff means forever) */ + uint8_t right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */ + uint8_t left_duration; /* Left motor duration (0xff means forever) */ + uint8_t left_motor_force; /* left (large) motor, supports force values from 0 to 255 */ + } rumble; + uint8_t reserved1[4]; + uint8_t leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */ + struct LEDs + { + uint8_t time_enabled; /* the total time the led is active (0xff means forever) */ + uint8_t duty_length; /* how long a cycle is in deciseconds (0 means "really fast") */ + uint8_t enabled; + uint8_t duty_off; /* % of duty_length the led is off (0xff means 100%) */ + uint8_t duty_on; /* % of duty_length the led is on (0xff mean 100%) */ + } leds[4]; /* LEDx at (4 - x) */ + struct LEDs unused; /* LED5, not actually soldered */ + uint8_t reserved2[13]; OutReport() { - std::memcpy(this, DEFAULT_OUT_REPORT, sizeof(OutReport)); + std::memset(this, 0, sizeof(OutReport)); + std::memcpy(this, DEFAULT_OUT_REPORT, sizeof(DEFAULT_OUT_REPORT)); } }; - static_assert(sizeof(OutReport) == 35, "PS3::OutReport size mismatch"); - static_assert(sizeof(OutReport) == sizeof(DEFAULT_OUT_REPORT)); + static_assert(sizeof(OutReport) == 48, "PS3::OutReport size mismatch"); + static_assert(sizeof(OutReport) >= sizeof(DEFAULT_OUT_REPORT)); + + static constexpr uint8_t DEFAULT_BT_INFO_HEADER[] = + { + 0xFF, 0xFF, + 0x00, 0x20, 0x40, 0xCE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; struct BTInfo { @@ -200,20 +202,19 @@ namespace PS3 BTInfo() { std::memset(this, 0, sizeof(BTInfo)); - std::memset(reserved0, 0xFF, sizeof(reserved0)); - uint8_t addr[] = { 0x00, 0x20, 0x40, 0xCE, 0x00, 0x00, 0x00 }; - std::memcpy(device_address, addr, sizeof(addr)); + std::memcpy(device_address, DEFAULT_BT_INFO_HEADER, sizeof(DEFAULT_BT_INFO_HEADER)); for (uint8_t addr = 0; addr < 3; addr++) { - device_address[4 + addr] = static_cast(get_rand_32() % 0xFF); + device_address[4 + addr] = static_cast(get_rand_32() % 0xff); } for (uint8_t addr = 0; addr < 6; addr++) { - host_address[1 + addr] = static_cast(get_rand_32() % 0xFF); + host_address[1 + addr] = static_cast(get_rand_32() % 0xff); } } }; static_assert(sizeof(BTInfo) == 17, "PS3::BTInfo size mismatch"); + static_assert(sizeof(BTInfo) >= sizeof(DEFAULT_BT_INFO_HEADER)); #pragma pack(pop) static const uint8_t STRING_LANGUAGE[] = { 0x09, 0x04 }; @@ -327,128 +328,10 @@ namespace PS3 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xC0, // End Collection 0xC0, // End Collection - // 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) - // 0x09, 0x04, // Usage (Joystick) - // 0xA1, 0x01, // Collection (Application) - // 0xA1, 0x02, // Collection (Logical) - // 0x85, 0x01, // Report ID (1) - // 0x75, 0x08, // Report Size (8) - // 0x95, 0x01, // Report Count (1) - // 0x15, 0x00, // Logical Minimum (0) - // 0x26, 0xFF, 0x00, // Logical Maximum (255) - // 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) - // 0x75, 0x01, // Report Size (1) - // 0x95, 0x13, // Report Count (19) - // 0x15, 0x00, // Logical Minimum (0) - // 0x25, 0x01, // Logical Maximum (1) - // 0x35, 0x00, // Physical Minimum (0) - // 0x45, 0x01, // Physical Maximum (1) - // 0x05, 0x09, // Usage Page (Button) - // 0x19, 0x01, // Usage Minimum (0x01) - // 0x29, 0x13, // Usage Maximum (0x13) - // 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) - // 0x75, 0x01, // Report Size (1) - // 0x95, 0x0D, // Report Count (13) - // 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) - // 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) - // 0x15, 0x00, // Logical Minimum (0) - // 0x26, 0xFF, 0x00, // Logical Maximum (255) - // 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) - // 0x09, 0x01, // Usage (Pointer) - // 0xA1, 0x00, // Collection (Physical) - // 0x75, 0x08, // Report Size (8) - // 0x95, 0x04, // Report Count (4) - // 0x35, 0x00, // Physical Minimum (0) - // 0x46, 0xFF, 0x00, // Physical Maximum (255) - // 0x09, 0x30, // Usage (X) - // 0x09, 0x31, // Usage (Y) - // 0x09, 0x32, // Usage (Z) - // 0x09, 0x35, // Usage (Rz) - // 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) - // 0xC0, // End Collection - // 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) - // 0x75, 0x08, // Report Size (8) - // 0x95, 0x27, // Report Count (39) - // 0x09, 0x01, // Usage (Pointer) - // 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) - // 0x75, 0x08, // Report Size (8) - // 0x95, 0x30, // Report Count (48) - // 0x09, 0x01, // Usage (Pointer) - // 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - // 0x75, 0x08, // Report Size (8) - // 0x95, 0x30, // Report Count (48) - // 0x09, 0x01, // Usage (Pointer) - // 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - // 0xC0, // End Collection - // 0xA1, 0x02, // Collection (Logical) - // 0x85, 0x02, // Report ID (2) - // 0x75, 0x08, // Report Size (8) - // 0x95, 0x30, // Report Count (48) - // 0x09, 0x01, // Usage (Pointer) - // 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - // 0xC0, // End Collection - // 0xA1, 0x02, // Collection (Logical) - // 0x85, 0xEE, // Report ID (-18) - // 0x75, 0x08, // Report Size (8) - // 0x95, 0x30, // Report Count (48) - // 0x09, 0x01, // Usage (Pointer) - // 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - // 0xC0, // End Collection - // 0xA1, 0x02, // Collection (Logical) - // 0x85, 0xEF, // Report ID (-17) - // 0x75, 0x08, // Report Size (8) - // 0x95, 0x30, // Report Count (48) - // 0x09, 0x01, // Usage (Pointer) - // 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - // 0xC0, // End Collection - // 0xC0, // End Collection }; - // #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN) - static const uint8_t CONFIGURATION_DESCRIPTORS[] = { - // 0x09, // bLength - // 0x02, // bDescriptorType (Configuration) - // 0x29, 0x00, // wTotalLength 41 - // 0x01, // bNumInterfaces 1 - // 0x01, // bConfigurationValue - // 0x00, // iConfiguration (String Index) - // 0x80, // bmAttributes - // 0xFA, // bMaxPower 500mA - - // 0x09, // bLength - // 0x04, // bDescriptorType (Interface) - // 0x00, // bInterfaceNumber 0 - // 0x00, // bAlternateSetting - // 0x02, // bNumEndpoints 2 - // 0x03, // bInterfaceClass - // 0x00, // bInterfaceSubClass - // 0x00, // bInterfaceProtocol - // 0x00, // iInterface (String Index) - - // 0x09, // bLength - // 0x21, // bDescriptorType (HID) - // 0x11, 0x01, // bcdHID 1.11 - // 0x00, // bCountryCode - // 0x01, // bNumDescriptors - // 0x22, // bDescriptorType[0] (HID) - // 0x94, 0x00, // wDescriptorLength[0] 148 - - // 0x07, // bLength - // 0x05, // bDescriptorType (Endpoint) - // 0x02, // bEndpointAddress (OUT/H2D) - // 0x03, // bmAttributes (Interrupt) - // 0x40, 0x00, // wMaxPacketSize 64 - // 0x0A, // bInterval 10 (unit depends on device speed) - - // 0x07, // bLength - // 0x05, // bDescriptorType (Endpoint) - // 0x81, // bEndpointAddress (IN/D2H) - // 0x03, // bmAttributes (Interrupt) - // 0x40, 0x00, // wMaxPacketSize 64 - // 0x0A, // bInterval 10 (unit depends on device speed) - 0x09, // bLength 0x02, // bDescriptorType (Configuration) 0x29, 0x00, // wTotalLength 41 @@ -490,6 +373,68 @@ namespace PS3 0x40, 0x00, // wMaxPacketSize 64 0x01, // bInterval 1 (unit depends on device speed) }; + + static constexpr uint8_t OUTPUT_0x01[] = + { + 0x01, 0x04, 0x00, 0x0b, 0x0c, 0x01, 0x02, 0x18, + 0x18, 0x18, 0x18, 0x09, 0x0a, 0x10, 0x11, 0x12, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, + 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x04, 0x04, + 0x04, 0x04, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, + 0x07, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + // calibration data + static constexpr uint8_t OUTPUT_0xEF[] = + { + 0xef, 0x04, 0x00, 0x0b, 0x03, 0x01, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, + 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + }; + + // unknown + static constexpr uint8_t OUTPUT_0xF5[] = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // host address - must match 0xf2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + // unknown + static constexpr uint8_t OUTPUT_0xF7[] = + { + 0x02, 0x01, 0xf8, 0x02, 0xe2, 0x01, 0x05, 0xff, + 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + // unknown + static constexpr uint8_t OUTPUT_0xF8[] = + { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; } // namespace PS3 #endif // _PS3_DESCRIPTORS_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/Descriptors/PS5.h b/Firmware/RP2040/src/Descriptors/PS5.h index 0c3d039..a70bee3 100644 --- a/Firmware/RP2040/src/Descriptors/PS5.h +++ b/Firmware/RP2040/src/Descriptors/PS5.h @@ -7,9 +7,13 @@ namespace PS5 { static constexpr uint8_t DPAD_MASK = 0x0F; - static constexpr size_t IN_REPORT_CMP_SIZE = 12; static constexpr uint8_t JOYSTICK_MID = 0x80; - static constexpr uint8_t OUT_REPORT_ID = 5; + + namespace OutReportID + { + static constexpr uint8_t CONTROL = 0x02; + static constexpr uint8_t RUMBLE = 0x05; + }; namespace Buttons0 { @@ -68,30 +72,34 @@ namespace PS5 uint16_t gyro[3]; // Gyroscope data for x, y, z axes uint16_t accel[3]; // Accelerometer data for x, y, z axes uint32_t sensor_timestamp; // Timestamp for sensor data - uint8_t reserved2; + uint8_t reserved0; - // Touchpad - struct dualsense_touch_point { - uint8_t counter : 7; // Incremented every time a finger touches the touchpad - uint8_t touching : 1; // Indicates if a finger is currently touching the touchpad - uint16_t x : 12; // X coordinate of the touchpoint - uint16_t y : 12; // Y coordinate of the touchpoint + struct Touchpad + { + uint32_t counter : 7; // Incremented every time a finger touches the touchpad + uint32_t touching : 1; // Indicates if a finger is currently touching the touchpad + uint32_t x : 12; // X coordinate of the touchpoint + uint32_t y : 12; // Y coordinate of the touchpoint } points[2]; // Array of touchpoints (up to 2) + // uint32_t touchpad[2]; - uint8_t reserved3[12]; + uint8_t reserved1[12]; uint8_t status; // ? - uint8_t reserved4[10]; + uint8_t reserved2[10]; + + InReport() + { + std::memset(this, 0, sizeof(InReport)); + } }; - // static_assert(sizeof(InReport) == 52, "PS5::InReport is not correct size"); + static_assert(sizeof(InReport) == 60, "PS5::InReport is not correct size"); struct OutReport { uint8_t report_id; - - uint8_t valid_flag0; - uint8_t valid_flag1; + uint8_t control_flag[2]; /* For DualShock 4 compatibility mode. */ uint8_t motor_right; @@ -120,14 +128,19 @@ namespace PS5 uint8_t audio_flags2; /* 3 first bits: speaker pre-gain */ /* LEDs and lightbar */ - uint8_t valid_flag2; + uint8_t led_control_flag; uint8_t reserved3[2]; - uint8_t lightbar_setup; + uint8_t pulse_option; uint8_t led_brightness; - uint8_t player_leds; + uint8_t player_number; uint8_t lightbar_red; uint8_t lightbar_green; uint8_t lightbar_blue; + + OutReport() + { + std::memset(this, 0, sizeof(OutReport)); + } }; static_assert(sizeof(OutReport) == 48); #pragma pack(pop) diff --git a/Firmware/RP2040/src/Descriptors/XInput.h b/Firmware/RP2040/src/Descriptors/XInput.h index ecc911f..a9fa589 100644 --- a/Firmware/RP2040/src/Descriptors/XInput.h +++ b/Firmware/RP2040/src/Descriptors/XInput.h @@ -1,7 +1,7 @@ #ifndef _XINPUT_DESCRIPTORS_H_ #define _XINPUT_DESCRIPTORS_H_ -#include +#include #include namespace XInput @@ -133,6 +133,11 @@ namespace XInput uint8_t reserved[6]; uint8_t chatpad_status; uint8_t chatpad[3]; + + InReportWireless() + { + std::memset(this, 0, sizeof(InReportWireless)); + } }; static_assert(sizeof(InReportWireless) == 28, "XInput::InReportWireless is not the correct size"); diff --git a/Firmware/RP2040/src/Descriptors/XboxOG.h b/Firmware/RP2040/src/Descriptors/XboxOG.h index f45d428..1ca26be 100644 --- a/Firmware/RP2040/src/Descriptors/XboxOG.h +++ b/Firmware/RP2040/src/Descriptors/XboxOG.h @@ -99,15 +99,12 @@ namespace XboxOG .bDeviceSubClass = 0x00, .bDeviceProtocol = 0x00, .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0x045E, .idProduct = 0x0289, .bcdDevice = 0x0121, - .iManufacturer = 0x00, .iProduct = 0x00, .iSerialNumber = 0x00, - .bNumConfigurations = 0x01 }; @@ -184,8 +181,6 @@ namespace XboxOG { static constexpr uint16_t AIMING_MID = 32768; static constexpr uint16_t BUTTONS2_TOGGLE_MID = 0xFFFC; - static constexpr int16_t DEFAULT_DEADZONE = 7500; - static constexpr uint16_t DEFAULT_SENSE = 400; namespace Buttons0 { diff --git a/Firmware/RP2040/src/Gamepad.h b/Firmware/RP2040/src/Gamepad.h index fb134f4..0c6ecf0 100644 --- a/Firmware/RP2040/src/Gamepad.h +++ b/Firmware/RP2040/src/Gamepad.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "Scale.h" @@ -38,16 +39,16 @@ public: static constexpr uint16_t BUTTON_SYS = 0x0400; static constexpr uint16_t BUTTON_MISC = 0x0800; - static constexpr uint8_t ANALOG_OFF_UP = 1; - static constexpr uint8_t ANALOG_OFF_DOWN = 2; - static constexpr uint8_t ANALOG_OFF_LEFT = 3; - static constexpr uint8_t ANALOG_OFF_RIGHT = 4; - static constexpr uint8_t ANALOG_OFF_A = 5; - static constexpr uint8_t ANALOG_OFF_B = 6; - static constexpr uint8_t ANALOG_OFF_X = 7; - static constexpr uint8_t ANALOG_OFF_Y = 8; - static constexpr uint8_t ANALOG_OFF_LB = 9; - static constexpr uint8_t ANALOG_OFF_RB = 10; + static constexpr uint8_t ANALOG_OFF_UP = 0; + static constexpr uint8_t ANALOG_OFF_DOWN = 1; + static constexpr uint8_t ANALOG_OFF_LEFT = 2; + static constexpr uint8_t ANALOG_OFF_RIGHT = 3; + static constexpr uint8_t ANALOG_OFF_A = 4; + static constexpr uint8_t ANALOG_OFF_B = 5; + static constexpr uint8_t ANALOG_OFF_X = 6; + static constexpr uint8_t ANALOG_OFF_Y = 7; + static constexpr uint8_t ANALOG_OFF_LB = 8; + static constexpr uint8_t ANALOG_OFF_RB = 9; //Mappings used by host to set buttons @@ -97,7 +98,7 @@ public: int16_t joystick_ly; int16_t joystick_rx; int16_t joystick_ry; - uint8_t chatpad[3]; + // uint8_t chatpad[3]; uint8_t analog[10]; PadIn() @@ -116,15 +117,20 @@ public: std::memset(this, 0, sizeof(PadOut)); } }; + + using ChatpadIn = std::array; + #pragma pack(pop) Gamepad() { mutex_init(&pad_in_mutex_); mutex_init(&pad_out_mutex_); + mutex_init(&chatpad_in_mutex_); reset_pad_in(); reset_pad_out(); - setup_deadzones(profile_); + reset_chatpad_in(); + setup_deadzones(); }; ~Gamepad() = default; @@ -132,42 +138,70 @@ public: //Get inline bool new_pad_in() const { return new_pad_in_.load(); } inline bool new_pad_out() const { return new_pad_out_.load(); } + + //True if both host and device have enabled analog inline bool analog_enabled() const { return analog_enabled_.load(std::memory_order_relaxed); } inline PadIn get_pad_in() { PadIn pad_in; - { - mutex_enter_blocking(&pad_in_mutex_); - pad_in = pad_in_; - new_pad_in_.store(false); - mutex_exit(&pad_in_mutex_); - } + + mutex_enter_blocking(&pad_in_mutex_); + pad_in = pad_in_; + new_pad_in_.store(false); + mutex_exit(&pad_in_mutex_); + return pad_in; } inline PadOut get_pad_out() { PadOut pad_out; + mutex_enter_blocking(&pad_out_mutex_); pad_out = pad_out_; new_pad_out_.store(false); mutex_exit(&pad_out_mutex_); + return pad_out; } + inline ChatpadIn get_chatpad_in() + { + ChatpadIn chatpad_in; + + mutex_enter_blocking(&chatpad_in_mutex_); + chatpad_in = chatpad_in_; + mutex_exit(&chatpad_in_mutex_); + + return chatpad_in; + } + //Set - void set_analog_enabled(bool value) + void set_analog_device(bool value) { - analog_enabled_.store(value); + analog_device_.store(value); + if (analog_host_.load() && analog_device_.load() && profile_.analog_enabled) + { + analog_enabled_.store(true); + } + } + + void set_analog_host(bool value) + { + analog_host_.store(value); + if (analog_host_.load() && analog_device_.load() && profile_.analog_enabled) + { + analog_enabled_.store(true); + } } void set_profile(const UserProfile& user_profile) { profile_ = user_profile; - setup_mappings(profile_); - setup_deadzones(profile_); + setup_mappings(); + setup_deadzones(); } inline void set_pad_in(PadIn pad_in) @@ -180,26 +214,32 @@ public: pad_in.joystick_ry = (pad_in.joystick_ry < dz_.joystick_r_neg || pad_in.joystick_ry > dz_.joystick_r_pos) ? pad_in.joystick_ry : INT_16::MID; pad_in.joystick_ly = profile_.invert_ly ? Scale::invert_joy(pad_in.joystick_ly) : pad_in.joystick_ly; pad_in.joystick_ry = profile_.invert_ry ? Scale::invert_joy(pad_in.joystick_ry) : pad_in.joystick_ry; - { - mutex_enter_blocking(&pad_in_mutex_); - pad_in_ = pad_in; - mutex_exit(&pad_in_mutex_); - } + + mutex_enter_blocking(&pad_in_mutex_); + pad_in_ = pad_in; new_pad_in_.store(true); + mutex_exit(&pad_in_mutex_); } - inline void set_pad_out(PadOut pad_out) + inline void set_pad_out(const PadOut& pad_out) { mutex_enter_blocking(&pad_out_mutex_); pad_out_ = pad_out; - mutex_exit(&pad_out_mutex_); new_pad_out_.store(true); + mutex_exit(&pad_out_mutex_); + } + + inline void set_chatpad_in(const ChatpadIn& chatpad_in) + { + mutex_enter_blocking(&chatpad_in_mutex_); + chatpad_in_ = chatpad_in; + mutex_exit(&chatpad_in_mutex_); } inline void reset_pad_in() { mutex_enter_blocking(&pad_in_mutex_); - std::memset(&pad_in_, 0, sizeof(pad_in_)); + std::memset(reinterpret_cast(&pad_in_), 0, sizeof(pad_in_)); mutex_exit(&pad_in_mutex_); new_pad_in_.store(true); } @@ -207,21 +247,33 @@ public: inline void reset_pad_out() { mutex_enter_blocking(&pad_out_mutex_); - std::memset(&pad_out_, 0, sizeof(pad_out_)); - mutex_exit(&pad_out_mutex_); + std::memset(reinterpret_cast(&pad_out_), 0, sizeof(pad_out_)); new_pad_out_.store(true); + mutex_exit(&pad_out_mutex_); + } + + inline void reset_chatpad_in() + { + mutex_enter_blocking(&chatpad_in_mutex_); + chatpad_in_.fill(0); + mutex_exit(&chatpad_in_mutex_); } private: mutex_t pad_in_mutex_; mutex_t pad_out_mutex_; + mutex_t chatpad_in_mutex_; PadOut pad_out_; PadIn pad_in_; + ChatpadIn chatpad_in_; std::atomic new_pad_in_{false}; std::atomic new_pad_out_{false}; + std::atomic analog_enabled_{false}; + std::atomic analog_host_{false}; + std::atomic analog_device_{false}; UserProfile profile_; @@ -235,44 +287,44 @@ private: int16_t joystick_r_pos{0}; } dz_; - void setup_mappings(const UserProfile& profile) + void setup_mappings() { - MAP_DPAD_UP = profile.dpad_up; - MAP_DPAD_DOWN = profile.dpad_down; - MAP_DPAD_LEFT = profile.dpad_left; - MAP_DPAD_RIGHT = profile.dpad_right; - MAP_DPAD_UP_LEFT = profile.dpad_up | profile.dpad_left; - MAP_DPAD_UP_RIGHT = profile.dpad_up | profile.dpad_right; - MAP_DPAD_DOWN_LEFT = profile.dpad_down | profile.dpad_left; - MAP_DPAD_DOWN_RIGHT = profile.dpad_down | profile.dpad_right; + MAP_DPAD_UP = profile_.dpad_up; + MAP_DPAD_DOWN = profile_.dpad_down; + MAP_DPAD_LEFT = profile_.dpad_left; + MAP_DPAD_RIGHT = profile_.dpad_right; + MAP_DPAD_UP_LEFT = profile_.dpad_up | profile_.dpad_left; + MAP_DPAD_UP_RIGHT = profile_.dpad_up | profile_.dpad_right; + MAP_DPAD_DOWN_LEFT = profile_.dpad_down | profile_.dpad_left; + MAP_DPAD_DOWN_RIGHT = profile_.dpad_down | profile_.dpad_right; MAP_DPAD_NONE = 0; - MAP_BUTTON_A = profile.button_a; - MAP_BUTTON_B = profile.button_b; - MAP_BUTTON_X = profile.button_x; - MAP_BUTTON_Y = profile.button_y; - MAP_BUTTON_L3 = profile.button_l3; - MAP_BUTTON_R3 = profile.button_r3; - MAP_BUTTON_BACK = profile.button_back; - MAP_BUTTON_START = profile.button_start; - MAP_BUTTON_LB = profile.button_lb; - MAP_BUTTON_RB = profile.button_rb; - MAP_BUTTON_SYS = profile.button_sys; - MAP_BUTTON_MISC = profile.button_misc; + MAP_BUTTON_A = profile_.button_a; + MAP_BUTTON_B = profile_.button_b; + MAP_BUTTON_X = profile_.button_x; + MAP_BUTTON_Y = profile_.button_y; + MAP_BUTTON_L3 = profile_.button_l3; + MAP_BUTTON_R3 = profile_.button_r3; + MAP_BUTTON_BACK = profile_.button_back; + MAP_BUTTON_START = profile_.button_start; + MAP_BUTTON_LB = profile_.button_lb; + MAP_BUTTON_RB = profile_.button_rb; + MAP_BUTTON_SYS = profile_.button_sys; + MAP_BUTTON_MISC = profile_.button_misc; - MAP_ANALOG_OFF_UP = profile.analog_off_up; - MAP_ANALOG_OFF_DOWN = profile.analog_off_down; - MAP_ANALOG_OFF_LEFT = profile.analog_off_left; - MAP_ANALOG_OFF_RIGHT = profile.analog_off_right; - MAP_ANALOG_OFF_A = profile.analog_off_a; - MAP_ANALOG_OFF_B = profile.analog_off_b; - MAP_ANALOG_OFF_X = profile.analog_off_x; - MAP_ANALOG_OFF_Y = profile.analog_off_y; - MAP_ANALOG_OFF_LB = profile.analog_off_lb; - MAP_ANALOG_OFF_RB = profile.analog_off_rb; + MAP_ANALOG_OFF_UP = profile_.analog_off_up; + MAP_ANALOG_OFF_DOWN = profile_.analog_off_down; + MAP_ANALOG_OFF_LEFT = profile_.analog_off_left; + MAP_ANALOG_OFF_RIGHT = profile_.analog_off_right; + MAP_ANALOG_OFF_A = profile_.analog_off_a; + MAP_ANALOG_OFF_B = profile_.analog_off_b; + MAP_ANALOG_OFF_X = profile_.analog_off_x; + MAP_ANALOG_OFF_Y = profile_.analog_off_y; + MAP_ANALOG_OFF_LB = profile_.analog_off_lb; + MAP_ANALOG_OFF_RB = profile_.analog_off_rb; } - void setup_deadzones(const UserProfile& profile) //Deadzones in the profile are 0-255 (0-100%) + void setup_deadzones() //Deadzones in the profile are 0-255 (0-100%) { dz_.trigger_l = profile_.dz_trigger_l; dz_.trigger_r = profile_.dz_trigger_r; diff --git a/Firmware/RP2040/src/I2CDriver/4Channel/I2CDriver.h b/Firmware/RP2040/src/I2CDriver/4Channel/I2CDriver.h index c37ccbd..51669db 100644 --- a/Firmware/RP2040/src/I2CDriver/4Channel/I2CDriver.h +++ b/Firmware/RP2040/src/I2CDriver/4Channel/I2CDriver.h @@ -12,16 +12,16 @@ class I2CDriver { public: - virtual ~I2CDriver() = default; + virtual ~I2CDriver() {}; virtual void initialize(uint8_t address) = 0; virtual void process(Gamepad (&gamepads)[MAX_GAMEPADS]) = 0; virtual void notify_tuh_mounted(HostDriver::Type host_type = HostDriver::Type::UNKNOWN) = 0; virtual void notify_tuh_unmounted(HostDriver::Type host_type = HostDriver::Type::UNKNOWN) = 0; - virtual void notify_xbox360w_connected(uint8_t idx) = 0; - virtual void notify_xbox360w_disconnected(uint8_t idx) = 0; + virtual void notify_xbox360w_connected(uint8_t idx) {}; + virtual void notify_xbox360w_disconnected(uint8_t idx) {}; protected: - enum class PacketID : uint8_t { UNKNOWN = 0, PAD, STATUS, ENABLE, DISABLE }; + enum class PacketID : uint8_t { UNKNOWN = 0, PAD, STATUS, ENABLE, DISABLE, REBOOT }; enum class SlaveStatus : uint8_t { NC = 0, NOT_READY, READY, RESP_OK }; #pragma pack(push, 1) @@ -38,7 +38,7 @@ protected: packet_id = static_cast(PacketID::PAD); } }; -static_assert(sizeof(PacketIn) == 28, "I2CDriver::PacketIn is misaligned"); + static_assert(sizeof(PacketIn) == 28, "I2CDriver::PacketIn is misaligned"); struct PacketOut { @@ -53,7 +53,7 @@ static_assert(sizeof(PacketIn) == 28, "I2CDriver::PacketIn is misaligned"); packet_id = static_cast(PacketID::PAD); } }; -static_assert(sizeof(PacketOut) == 4, "I2CDriver::PacketOut is misaligned"); + static_assert(sizeof(PacketOut) == 4, "I2CDriver::PacketOut is misaligned"); struct PacketStatus { @@ -68,7 +68,7 @@ static_assert(sizeof(PacketOut) == 4, "I2CDriver::PacketOut is misaligned"); status = static_cast(SlaveStatus::NC); } }; -static_assert(sizeof(PacketStatus) == 3, "I2CDriver::PacketStatus is misaligned"); + static_assert(sizeof(PacketStatus) == 3, "I2CDriver::PacketStatus is misaligned"); #pragma pack(pop) static constexpr size_t MAX_PACKET_SIZE = std::max(sizeof(PacketStatus), std::max(sizeof(PacketIn), sizeof(PacketOut))); diff --git a/Firmware/RP2040/src/I2CDriver/4Channel/I2CManager.h b/Firmware/RP2040/src/I2CDriver/4Channel/I2CManager.h index fb9adcf..76244f3 100644 --- a/Firmware/RP2040/src/I2CDriver/4Channel/I2CManager.h +++ b/Firmware/RP2040/src/I2CDriver/4Channel/I2CManager.h @@ -23,7 +23,7 @@ public: return instance; } - bool initialize_driver() //Gamepad idx 0 for slave to update on interrupt + bool initialize_driver() { uint8_t i2c_address = get_i2c_address(); if (i2c_address == 0xFF) diff --git a/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.cpp b/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.cpp index 9f48bf8..9f11d0d 100644 --- a/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.cpp +++ b/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.cpp @@ -1,8 +1,14 @@ #include #include "TaskQueue/TaskQueue.h" +#include "OGXMini/OGXMini.h" #include "I2CDriver/4Channel/I2CMaster.h" +I2CMaster::~I2CMaster() +{ + TaskQueue::Core0::cancel_delayed_task(tid_update_slave_); +} + void I2CMaster::initialize(uint8_t address) { i2c_init(I2C_PORT, I2C_BAUDRATE); @@ -21,11 +27,12 @@ void I2CMaster::initialize(uint8_t address) } tid_update_slave_ = TaskQueue::Core0::get_new_task_id(); - TaskQueue::Core0::queue_delayed_task(tid_update_slave_, 1000, true, [this] + + TaskQueue::Core0::queue_delayed_task(tid_update_slave_, 2000, true, [this] { for (auto& slave : slaves_) { - update_slave_status(slave); + check_slave_status(slave); sleep_us(10); } }); @@ -33,26 +40,17 @@ void I2CMaster::initialize(uint8_t address) void I2CMaster::process(Gamepad (&gamepads)[MAX_GAMEPADS]) { - if (notify_deinit_.load()) - { - notify_tud_deinit(); - return; - } for (uint8_t i = 0; i < NUM_SLAVES; ++i) { Slave& slave = slaves_[i]; - if (!slave.enabled.load() || !slave_detected(slave.address)) + if (slave.status != SlaveStatus::READY || !slave_detected(slave.address)) { continue; } - - if (slave.status == SlaveStatus::READY) + if (send_packet_in(slave, gamepads[i + 1])) { - if (send_packet_in(slave, gamepads[i + 1])) - { - get_packet_out(slave, gamepads[i + 1]); - } + get_packet_out(slave, gamepads[i + 1]); } sleep_us(100); @@ -69,8 +67,18 @@ void I2CMaster::notify_tuh_mounted(HostDriver::Type host_type) void I2CMaster::notify_tuh_unmounted(HostDriver::Type host_type) { - i2c_enabled_.store(false); - notify_deinit_.store(true); + if (host_type == HostDriver::Type::XBOX360W) + { + i2c_enabled_.store(false); + + TaskQueue::Core0::queue_task([this]() + { + for (auto& slave : slaves_) + { + notify_disable(slave); + } + }); + } } void I2CMaster::notify_xbox360w_connected(uint8_t idx) @@ -80,6 +88,11 @@ void I2CMaster::notify_xbox360w_connected(uint8_t idx) return; } slaves_[idx - 1].enabled.store(true); + + TaskQueue::Core0::queue_task([this, idx]() + { + notify_enable(slaves_[idx - 1].address); + }); } void I2CMaster::notify_xbox360w_disconnected(uint8_t idx) @@ -89,6 +102,11 @@ void I2CMaster::notify_xbox360w_disconnected(uint8_t idx) return; } slaves_[idx - 1].enabled.store(false); + + TaskQueue::Core0::queue_task([this, idx]() + { + notify_disable(slaves_[idx - 1]); + }); } bool I2CMaster::slave_detected(uint8_t address) @@ -98,53 +116,70 @@ bool I2CMaster::slave_detected(uint8_t address) return (result >= 0); } -void I2CMaster::update_slave_status(Slave& slave) +void I2CMaster::check_slave_status(Slave& slave) { - bool slave_enabled = slave.enabled.load(); if (!slave_detected(slave.address)) { slave.status = SlaveStatus::NC; return; } - if (!update_slave_enabled(slave.address, slave_enabled)) + if (slave.enabled.load()) { - slave.status = SlaveStatus::NOT_READY; - return; - } - if (slave_enabled) - { - PacketStatus status_packet = PacketStatus(); - int count = 0; - - status_packet.packet_id = static_cast(PacketID::STATUS); - count = i2c_write_blocking(I2C_PORT, slave.address, reinterpret_cast(&status_packet), sizeof(PacketStatus), false); - if (count == sizeof(PacketStatus)) - { - count = i2c_read_blocking(I2C_PORT, slave.address, reinterpret_cast(&status_packet), sizeof(PacketStatus), false); - slave.status = (count > 0) ? static_cast(status_packet.status) : SlaveStatus::NOT_READY; - } - else - { - slave.status = SlaveStatus::NOT_READY; - } - } - else - { - slave.status = SlaveStatus::NOT_READY; + slave.status = get_slave_status(slave.address); } + slave.status = SlaveStatus::NOT_READY; } -//Tell slave if it's enabled or not -bool I2CMaster::update_slave_enabled(uint8_t address, bool enabled) +I2CMaster::SlaveStatus I2CMaster::get_slave_status(uint8_t address) { PacketStatus status_packet; - status_packet.packet_id = enabled ? static_cast(PacketID::ENABLE) : static_cast(PacketID::DISABLE); + status_packet.packet_id = static_cast(PacketID::STATUS); int count = i2c_write_blocking(I2C_PORT, address, reinterpret_cast(&status_packet), sizeof(PacketStatus), false); if (count == sizeof(PacketStatus)) { count = i2c_read_blocking(I2C_PORT, address, reinterpret_cast(&status_packet), sizeof(PacketStatus), false); - return (static_cast(status_packet.status) == SlaveStatus::RESP_OK); + return static_cast(status_packet.status); + } + return SlaveStatus::NC; +} + +I2CMaster::SlaveStatus I2CMaster::notify_enable(uint8_t address) +{ + PacketStatus status_packet; + status_packet.packet_id = static_cast(PacketID::ENABLE); + + int count = i2c_write_blocking(I2C_PORT, address, reinterpret_cast(&status_packet), sizeof(PacketStatus), false); + if (count == sizeof(PacketStatus)) + { + count = i2c_read_blocking(I2C_PORT, address, reinterpret_cast(&status_packet), sizeof(PacketStatus), false); + return static_cast(status_packet.status); + } + return SlaveStatus::NC; +} + +bool I2CMaster::notify_disable(Slave& slave) +{ + if (slave_detected(slave.address) && slave.enabled.load()) + { + int retries = 6; + bool success = false; + + while (!success && retries--) + { + PacketStatus status_packet; + status_packet.packet_id = static_cast(PacketID::DISABLE); + + int count = i2c_write_blocking(I2C_PORT, slave.address, reinterpret_cast(&status_packet), sizeof(PacketStatus), false); + if (count == sizeof(PacketStatus)) + { + count = i2c_read_blocking(I2C_PORT, slave.address, reinterpret_cast(&status_packet), sizeof(PacketStatus), false); + success = (static_cast(status_packet.status) == SlaveStatus::RESP_OK); + } + + sleep_ms(1); + } + return success; } return false; } @@ -153,11 +188,10 @@ bool I2CMaster::send_packet_in(Slave& slave, Gamepad& gamepad) { static PacketIn packet_in = PacketIn(); - Gamepad::PadIn pad_in = gamepad.get_pad_in(); - packet_in.pad_in = pad_in; + Gamepad::PadIn pad_in = gamepad.get_pad_in(); + packet_in.pad_in = pad_in; int count = i2c_write_blocking(I2C_PORT, slave.address, reinterpret_cast(&packet_in), sizeof(packet_in), false); - // int count = i2c_write_timeout_us(I2C_PORT, slave.address, reinterpret_cast(&packet_in), sizeof(packet_in), false, 2000); return (count == sizeof(PacketIn)); } @@ -173,20 +207,4 @@ bool I2CMaster::get_packet_out(Slave& slave, Gamepad& gamepad) gamepad.set_pad_out(packet_out.pad_out); return true; -} - -void I2CMaster::notify_tud_deinit() -{ - for (auto& slave : slaves_) - { - if (slave.status != SlaveStatus::NC && slave_detected(slave.address) && slave.enabled.load()) - { - int retries = 0; - while (!update_slave_enabled(slave.address, false) && retries < 6) - { - sleep_ms(1); - ++retries; - } - } - } } \ No newline at end of file diff --git a/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.h b/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.h index 465b302..6331fd6 100644 --- a/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.h +++ b/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.h @@ -5,7 +5,6 @@ #include #include -#include #include #include @@ -17,7 +16,6 @@ class I2CMaster : public I2CDriver { public: ~I2CMaster() override; - void initialize(uint8_t address) override; void process(Gamepad (&gamepads)[MAX_GAMEPADS]) override; void notify_tuh_mounted(HostDriver::Type host_type) override; @@ -36,22 +34,23 @@ private: static constexpr size_t NUM_SLAVES = MAX_GAMEPADS - 1; static_assert(NUM_SLAVES > 0, "I2CMaster::NUM_SLAVES must be greater than 0 to use I2C"); - // repeating_timer_t update_slave_timer_; uint32_t tid_update_slave_; bool update_slave_status_{false}; std::atomic i2c_enabled_{false}; - std::atomic notify_deinit_{false}; + // std::atomic notify_deinit_{false}; std::array slaves_; static bool slave_detected(uint8_t address); - static void update_slave_status(Slave& slave); - static bool update_slave_enabled(uint8_t address, bool enabled); - static bool update_slave_timer_cb(repeating_timer_t* rt); + + void check_slave_status(Slave& slave); + bool notify_disable(Slave& slave); + SlaveStatus notify_enable(uint8_t address); + // bool send_packet_status(uint8_t address, PacketID packet_id); + SlaveStatus get_slave_status(uint8_t address); bool send_packet_in(Slave& slave, Gamepad& gamepad); bool get_packet_out(Slave& slave, Gamepad& gamepad); - void notify_tud_deinit(); }; #endif // I2C_MASTER_4CH_H \ No newline at end of file diff --git a/Firmware/RP2040/src/I2CDriver/4Channel/I2CSlave.cpp b/Firmware/RP2040/src/I2CDriver/4Channel/I2CSlave.cpp index 24579e3..ea7f40c 100644 --- a/Firmware/RP2040/src/I2CDriver/4Channel/I2CSlave.cpp +++ b/Firmware/RP2040/src/I2CDriver/4Channel/I2CSlave.cpp @@ -1,7 +1,7 @@ #include #include -#include "Board/board_api.h" +#include "USBHost/HostManager.h" #include "OGXMini/OGXMini.h" #include "I2CDriver/4Channel/I2CSlave.h" @@ -40,10 +40,15 @@ void I2CSlave::process(Gamepad (&gamepads)[MAX_GAMEPADS]) { return; } + //Don't want to hang up the i2c bus by doing this in the slave handler if (packet_in_.packet_id == static_cast(PacketID::PAD)) { - gamepads[0].set_pad_in(packet_in_.pad_in); - + if (new_packet_in_) + { + new_packet_in_ = false; + gamepads[0].set_pad_in(packet_in_.pad_in); + } + if (gamepads[0].new_pad_out()) { packet_out_.pad_out = gamepads[0].get_pad_out(); @@ -114,34 +119,38 @@ void I2CSlave::slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) { case PacketID::PAD: this_instance_->packet_in_ = *reinterpret_cast(buffer_in.data()); + this_instance_->new_packet_in_ = true; *reinterpret_cast(buffer_out.data()) = this_instance_->packet_out_; break; + case PacketID::STATUS: buffer_out.data()[0] = sizeof(PacketStatus); buffer_out.data()[1] = static_cast(PacketID::STATUS); - // if something is mounted by tuh, signal to not send gamepad data - buffer_out.data()[2] = this_instance_->i2c_disabled_.load() ? static_cast(SlaveStatus::NOT_READY) : static_cast(SlaveStatus::READY); + // if something is mounted by tuh, signal that we're not talking to the master + buffer_out.data()[2] = + this_instance_->i2c_disabled_.load() ? + static_cast(SlaveStatus::NOT_READY) : + static_cast(SlaveStatus::READY); break; + case PacketID::ENABLE: buffer_out.data()[0] = sizeof(PacketStatus); buffer_out.data()[1] = static_cast(PacketID::STATUS); buffer_out.data()[2] = static_cast(SlaveStatus::RESP_OK); - if (!this_instance_->i2c_disabled_.load()) - { - // If no TUH devices are mounted, signal to connect usb - OGXMini::update_tuh_status(true); - } + + OGXMini::update_tud_status(true); break; + case PacketID::DISABLE: buffer_out.data()[0] = sizeof(PacketStatus); buffer_out.data()[1] = static_cast(PacketID::STATUS); buffer_out.data()[2] = static_cast(SlaveStatus::RESP_OK); if (!this_instance_->i2c_disabled_.load()) { - // If no TUH devices are mounted, signal to disconnect usb reset the pico - OGXMini::update_tuh_status(false); + OGXMini::update_tud_status(false); } break; + default: break; } @@ -155,6 +164,5 @@ void I2CSlave::slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) default: break; - } } \ No newline at end of file diff --git a/Firmware/RP2040/src/I2CDriver/4Channel/I2CSlave.h b/Firmware/RP2040/src/I2CDriver/4Channel/I2CSlave.h index 984e8ea..78c5ddd 100644 --- a/Firmware/RP2040/src/I2CDriver/4Channel/I2CSlave.h +++ b/Firmware/RP2040/src/I2CDriver/4Channel/I2CSlave.h @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -16,18 +15,19 @@ class I2CSlave : public I2CDriver { public: + ~I2CSlave() = default; void initialize(uint8_t address) override; void process(Gamepad (&gamepads)[MAX_GAMEPADS]) override; void notify_tuh_mounted(HostDriver::Type host_type) override; void notify_tuh_unmounted(HostDriver::Type host_type) override; - void notify_xbox360w_connected(uint8_t idx) override {}; - void notify_xbox360w_disconnected(uint8_t idx) override {}; private: static I2CSlave* this_instance_; + PacketIn packet_in_; PacketOut packet_out_; - std::atomic i2c_disabled_; + bool new_packet_in_{false}; + std::atomic i2c_disabled_{false}; static PacketID get_packet_id(uint8_t* buffer_in); static void slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event); diff --git a/Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.cpp b/Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.cpp new file mode 100644 index 0000000..a7dd33c --- /dev/null +++ b/Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.cpp @@ -0,0 +1,187 @@ +#include +#include +#include +#include +#include + +#include "Gamepad.h" +#include "board_config.h" +#include "Board/board_api.h" +#include "I2CDriver/ESP32/I2CDriver.h" +#include "TaskQueue/TaskQueue.h" + +namespace I2CDriver { + +//May expand commands in the future +enum class PacketID : uint8_t { UNKNOWN = 0, SET_PAD, GET_PAD }; + +#pragma pack(push, 1) +struct PacketIn +{ + uint8_t packet_len; + uint8_t packet_id; + uint8_t index; + uint8_t gp_data[sizeof(Gamepad::PadIn) - sizeof(Gamepad::PadIn::analog) - sizeof(Gamepad::PadIn::chatpad)]; + + PacketIn() + { + std::memset(this, 0, sizeof(PacketIn)); + packet_len = sizeof(PacketIn); + packet_id = static_cast(PacketID::SET_PAD); + } +}; +static_assert(sizeof(PacketIn) == 16, "i2c_driver_esp::PacketIn size mismatch"); + +struct PacketOut +{ + uint8_t packet_len; + uint8_t packet_id; + uint8_t index; + Gamepad::PadOut pad_out; + uint8_t reserved[3]; + + PacketOut() + { + std::memset(this, 0, sizeof(PacketOut)); + packet_len = sizeof(PacketOut); + packet_id = static_cast(PacketID::GET_PAD); + } +}; +static_assert(sizeof(PacketOut) == 8, "i2c_driver_esp::PacketOut size mismatch"); +#pragma pack(pop) + +static constexpr size_t MAX_BUFFER_SIZE = std::max(sizeof(PacketOut), sizeof(PacketIn)); +static constexpr uint8_t I2C_ADDR = 0x01; + +Gamepad* gamepads_[MAX_GAMEPADS]; + +inline void process_in_packet(PacketIn* packet_in) +{ + Gamepad::PadIn gp_in; + std::memcpy(&gp_in, packet_in->gp_data, sizeof(packet_in->gp_data)); + + //This is a bandaid since the ESP32 doesn't have access to user profiles atm + //Will update this once I write a BLE server for interfacing with the webapp + + Gamepad* gamepad = gamepads_[packet_in->index]; + Gamepad::PadIn mapped_gp_in; + + if (gp_in.dpad & Gamepad::DPAD_UP) mapped_gp_in.dpad |= gamepad->MAP_DPAD_UP; + if (gp_in.dpad & Gamepad::DPAD_DOWN) mapped_gp_in.dpad |= gamepad->MAP_DPAD_DOWN; + if (gp_in.dpad & Gamepad::DPAD_LEFT) mapped_gp_in.dpad |= gamepad->MAP_DPAD_LEFT; + if (gp_in.dpad & Gamepad::DPAD_RIGHT) mapped_gp_in.dpad |= gamepad->MAP_DPAD_RIGHT; + + if (gp_in.buttons & Gamepad::BUTTON_START) mapped_gp_in.buttons |= gamepad->MAP_BUTTON_START; + if (gp_in.buttons & Gamepad::BUTTON_BACK) mapped_gp_in.buttons |= gamepad->MAP_BUTTON_BACK; + if (gp_in.buttons & Gamepad::BUTTON_L3) mapped_gp_in.buttons |= gamepad->MAP_BUTTON_L3; + if (gp_in.buttons & Gamepad::BUTTON_R3) mapped_gp_in.buttons |= gamepad->MAP_BUTTON_R3; + if (gp_in.buttons & Gamepad::BUTTON_LB) mapped_gp_in.buttons |= gamepad->MAP_BUTTON_LB; + if (gp_in.buttons & Gamepad::BUTTON_RB) mapped_gp_in.buttons |= gamepad->MAP_BUTTON_RB; + if (gp_in.buttons & Gamepad::BUTTON_SYS) mapped_gp_in.buttons |= gamepad->MAP_BUTTON_SYS; + if (gp_in.buttons & Gamepad::BUTTON_A) mapped_gp_in.buttons |= gamepad->MAP_BUTTON_A; + if (gp_in.buttons & Gamepad::BUTTON_B) mapped_gp_in.buttons |= gamepad->MAP_BUTTON_B; + if (gp_in.buttons & Gamepad::BUTTON_X) mapped_gp_in.buttons |= gamepad->MAP_BUTTON_X; + if (gp_in.buttons & Gamepad::BUTTON_Y) mapped_gp_in.buttons |= gamepad->MAP_BUTTON_Y; + + mapped_gp_in.trigger_l = gp_in.trigger_l; + mapped_gp_in.trigger_r = gp_in.trigger_r; + mapped_gp_in.joystick_lx = gp_in.joystick_lx; + mapped_gp_in.joystick_ly = gp_in.joystick_ly; + mapped_gp_in.joystick_rx = gp_in.joystick_rx; + mapped_gp_in.joystick_ry = gp_in.joystick_ry; + + gamepad->set_pad_in(mapped_gp_in); +} + +inline void fill_out_report(uint8_t index, PacketOut* report_out) +{ + if (index >= MAX_GAMEPADS) + { + return; + } + + report_out->packet_len = sizeof(PacketOut); + report_out->packet_id = static_cast(PacketID::GET_PAD); + report_out->index = index; + report_out->pad_out = gamepads_[index]->get_pad_out(); +} + +PacketID get_packet_id(uint8_t* buffer_in) +{ + switch (static_cast(buffer_in[1])) + { + case PacketID::SET_PAD: + if (buffer_in[0] == sizeof(PacketIn)) + { + return PacketID::SET_PAD; + } + break; + //Unused ATM + // case PacketID::GET_PAD: + // if (buffer_in[0] == sizeof(PacketOut)) + // { + // return PacketID::GET_PAD; + // } + // break; + default: + break; + } + return PacketID::UNKNOWN; +} + +static inline void slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) +{ + static int count = 0; + static std::array buffer_in{0}; + static std::array buffer_out{0}; + + switch (event) + { + case I2C_SLAVE_RECEIVE: // master has written + if (count < sizeof(PacketIn)) + { + buffer_in.data()[count] = i2c_read_byte_raw(i2c); + ++count; + } + break; + + case I2C_SLAVE_FINISH: // master signalled Stop / Restart + if (get_packet_id(buffer_in.data()) == PacketID::SET_PAD) + { + process_in_packet(reinterpret_cast(buffer_in.data())); + } + count = 0; + break; + + case I2C_SLAVE_REQUEST: // master requesting data + fill_out_report(reinterpret_cast(buffer_in.data())->index, reinterpret_cast(buffer_out.data())); + i2c_write_raw_blocking(i2c, buffer_out.data(), buffer_out.data()[0]); + buffer_in.fill(0); + break; + + default: + break; + } +} + +void initialize(Gamepad (&gamepads)[MAX_GAMEPADS]) +{ + for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) + { + gamepads_[i] = &gamepads[i]; + } + + i2c_init(I2C_PORT, I2C_BAUDRATE); + + gpio_init(I2C_SDA_PIN); + gpio_set_function(I2C_SDA_PIN, GPIO_FUNC_I2C); + gpio_pull_up(I2C_SDA_PIN); + + gpio_init(I2C_SCL_PIN); + gpio_set_function(I2C_SCL_PIN, GPIO_FUNC_I2C); + gpio_pull_up(I2C_SCL_PIN); + + i2c_slave_init(I2C_PORT, I2C_ADDR, &slave_handler); +} + +} // namespace i2c_driver_esp32 \ No newline at end of file diff --git a/Firmware/RP2040/src/I2CDriver/i2c_driver_esp32.h b/Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.h similarity index 51% rename from Firmware/RP2040/src/I2CDriver/i2c_driver_esp32.h rename to Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.h index ea9e3b7..61191fa 100644 --- a/Firmware/RP2040/src/I2CDriver/i2c_driver_esp32.h +++ b/Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.h @@ -5,10 +5,9 @@ #include "Gamepad.h" -namespace i2c_driver_esp32 +namespace I2CDriver { - void initialize(std::array& gamepad); - // bool pad_connected(); + void initialize(Gamepad (&gamepads)[MAX_GAMEPADS]); } #endif // _I2CDRIVER_ESP_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/I2CDriver/i2c_4ch_master.cpp b/Firmware/RP2040/src/I2CDriver/i2c_4ch_master.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/Firmware/RP2040/src/I2CDriver/i2c_driver_4ch.cpp b/Firmware/RP2040/src/I2CDriver/i2c_driver_4ch.cpp deleted file mode 100644 index 427aa1f..0000000 --- a/Firmware/RP2040/src/I2CDriver/i2c_driver_4ch.cpp +++ /dev/null @@ -1,627 +0,0 @@ -// #include -// #include -// #include -// #include - -// #include -// #include -// #include -// #include - -// #include "board_config.h" -// #include "OGXMini/OGXMini.h" -// #include "I2CDriver/i2c_driver_4ch.h" - -// namespace i2c { - -// enum class Mode { MASTER = 0, SLAVE }; -// enum class ReportID : uint8_t { UNKNOWN = 0, PAD, STATUS, CONNECT, DISCONNECT }; -// enum class SlaveStatus : uint8_t { NC = 0, NOT_READY, READY, RESP_OK }; - -// #pragma pack(push, 1) -// struct ReportIn -// { -// uint8_t report_len; -// uint8_t report_id; -// uint8_t pad_in[sizeof(Gamepad::PadIn) - sizeof(Gamepad::PadIn::analog)]; - -// ReportIn() -// { -// std::memset(this, 0, sizeof(ReportIn)); -// report_len = sizeof(ReportIn); -// report_id = static_cast(ReportID::PAD); -// } -// }; -// static_assert(sizeof(ReportIn) == 18, "I2CDriver::ReportIn size mismatch"); - -// struct ReportOut -// { -// uint8_t report_len; -// uint8_t report_id; -// uint8_t pad_out[sizeof(Gamepad::PadOut)]; - -// ReportOut() -// { -// std::memset(this, 0, sizeof(ReportOut)); -// report_len = sizeof(ReportOut); -// report_id = static_cast(ReportID::PAD); -// } -// }; -// static_assert(sizeof(ReportOut) == 4, "I2CDriver::ReportOut size mismatch"); - -// struct ReportStatus -// { -// uint8_t report_len; -// uint8_t report_id; -// uint8_t status; - -// ReportStatus() -// { -// report_len = sizeof(ReportStatus); -// report_id = static_cast(ReportID::STATUS); -// status = static_cast(SlaveStatus::NC); -// } -// }; -// static_assert(sizeof(ReportStatus) == 3, "I2CDriver::ReportStatus size mismatch"); -// #pragma pack(pop) - -// static constexpr size_t MAX_BUFFER_SIZE = std::max(sizeof(ReportStatus), std::max(sizeof(ReportIn), sizeof(ReportOut))); - -// driver driver_; - -// namespace i2c_master -// { -// struct Master -// { -// std::atomic enabled{false}; - -// struct Slave -// { -// uint8_t address{0xFF}; -// Gamepad* gamepad{nullptr}; - -// SlaveStatus status{SlaveStatus::NC}; -// std::atomic enabled{false}; -// uint32_t last_update{0}; -// }; - -// std::array slaves; -// }; - -// Master master_; - -// bool slave_detected(uint8_t address); -// bool send_in_report(Master::Slave& slave); -// bool get_out_report(Master::Slave& slave); -// bool update_slave_enabled(uint8_t address, bool connected); -// void notify_tud_deinit(); -// void update_slave_status(Master::Slave& slave); - -// void notify_tuh_mounted(HostDriver::Type host_type); -// void notify_tuh_unmounted(HostDriver::Type host_type); -// void notify_xbox360w_connected(uint8_t idx); -// void notify_xbox360w_disconnected(uint8_t idx); -// bool is_active(); -// void process(); -// void init(Gamepad (&gamepads)[MAX_GAMEPADS]); -// } - -// namespace i2c_slave -// { -// struct Slave -// { -// uint8_t address{0xFF}; -// Gamepad* gamepad{nullptr}; -// std::atomic i2c_enabled{false}; -// std::atomic tuh_enabled{false}; -// }; - -// Slave slave_; - -// void process_in_report(ReportIn* report_in); -// void fill_out_report(ReportOut* report_out); -// ReportID get_report_id(uint8_t* buffer_in); -// void slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event); - -// bool is_active(); -// void notify_tuh_mounted(); -// void notify_tuh_unmounted(); -// bool is_active(); -// void process() {} -// void init(uint8_t address, Gamepad& gamepad); -// } - -// namespace i2c_master { - -// bool is_active() -// { -// return master_.enabled.load(); -// } - -// bool slave_detected(uint8_t address) -// { -// uint8_t dummy_data = 0; -// int result = i2c_write_timeout_us(I2C_PORT, address, &dummy_data, 0, false, 1000); -// return (result >= 0); -// } - -// void notify_tuh_mounted(HostDriver::Type host_type) -// { -// if (host_type == HostDriver::Type::XBOX360W) -// { -// master_.enabled.store(true); -// } -// } - -// void notify_tuh_unmounted(HostDriver::Type host_type) -// { -// master_.enabled.store(false); -// } - -// void notify_xbox360w_connected(uint8_t idx) -// { -// if (idx < 1 || idx >= MAX_GAMEPADS) -// { -// return; -// } -// master_.slaves[idx - 1].enabled.store(true); -// } - -// void notify_xbox360w_disconnected(uint8_t idx) -// { -// if (idx < 1 || idx >= MAX_GAMEPADS) -// { -// return; -// } -// master_.slaves[idx - 1].enabled.store(false); -// // bool any_connected = false; -// // for (auto& slave : master_.slaves) -// // { -// // if (slave.enabled.load()) -// // { -// // any_connected = true; -// // break; -// // } -// // } -// // if (!any_connected) -// // { -// // master_.enabled.store(false); -// // } -// } - -// bool send_in_report(Master::Slave& slave) -// { -// static ReportIn report_in = ReportIn(); -// Gamepad::PadIn pad_in = slave.gamepad->get_pad_in(); - -// std::memcpy(report_in.pad_in, &pad_in, sizeof(ReportIn::pad_in)); - -// int count = i2c_write_blocking(I2C_PORT, slave.address, reinterpret_cast(&report_in), sizeof(report_in), false); -// return (count == sizeof(ReportIn)); -// } - -// bool get_out_report(Master::Slave& slave) -// { -// static ReportOut report_out = ReportOut(); - -// int count = i2c_read_blocking(I2C_PORT, slave.address, reinterpret_cast(&report_out), sizeof(ReportOut), false); -// if (count != sizeof(ReportOut)) -// { -// return false; -// } - -// Gamepad::PadOut pad_out; -// std::memcpy(&pad_out, report_out.pad_out, sizeof(ReportOut::pad_out)); - -// return true; -// } - -// bool update_slave_enabled(uint8_t address, bool connected) -// { -// ReportStatus report; -// report.report_id = connected ? static_cast(ReportID::CONNECT) : static_cast(ReportID::DISCONNECT); -// int count = i2c_write_blocking(I2C_PORT, address, reinterpret_cast(&report), sizeof(ReportStatus), false); -// if (count == sizeof(ReportStatus)) -// { -// count = i2c_read_blocking(I2C_PORT, address, reinterpret_cast(&report), sizeof(ReportStatus), false); -// return (static_cast(report.status) == SlaveStatus::RESP_OK); -// } -// return false; -// } - -// void notify_tud_deinit() -// { -// for (auto& slave : master_.slaves) -// { -// if (slave.status != SlaveStatus::NC) -// { -// int retries = 0; -// while (!update_slave_enabled(slave.address, false) && retries < 6) -// { -// sleep_ms(1); -// ++retries; -// } -// } -// } -// } - -// void update_slave_status(Master::Slave& slave) -// { -// bool slave_enabled = slave.enabled.load(); - -// if (!slave_detected(slave.address)) -// { -// slave.status = SlaveStatus::NC; -// return; -// } -// if (!update_slave_enabled(slave.address, slave_enabled)) -// { -// slave.status = SlaveStatus::NOT_READY; -// return; -// } -// if (slave_enabled) -// { -// ReportStatus report = ReportStatus(); -// int count = 0; - -// report.report_id = static_cast(ReportID::STATUS); -// count = i2c_write_blocking(I2C_PORT, slave.address, reinterpret_cast(&report), sizeof(ReportStatus), false); -// if (count == sizeof(ReportStatus)) -// { -// count = i2c_read_blocking(I2C_PORT, slave.address, reinterpret_cast(&report), sizeof(ReportStatus), false); -// slave.status = (count == sizeof(ReportStatus)) ? static_cast(report.status) : SlaveStatus::NC; -// } -// else -// { -// slave.status = SlaveStatus::NOT_READY; -// } -// } -// else -// { -// slave.status = SlaveStatus::NOT_READY; -// } -// } - -// void process() -// { -// for (auto& slave : master_.slaves) -// { -// if ((time_us_32() / 1000) - slave.last_update > 1000) -// { -// update_slave_status(slave); -// slave.last_update = time_us_32() / 1000; -// } -// sleep_us(100); -// } -// if (!master_.enabled.load()) -// { -// return; -// } -// for (auto& slave : master_.slaves) -// { -// if (slave.status == SlaveStatus::READY) -// { -// if (send_in_report(slave)) -// { -// get_out_report(slave); -// } -// sleep_us(100); -// } -// } -// } - -// void init(Gamepad (&gamepads)[MAX_GAMEPADS]) -// { -// for (uint8_t i = 0; i < master_.slaves.size(); ++i) -// { -// master_.slaves[i].address = i + 1; -// master_.slaves[i].gamepad = &gamepads[i + 1]; -// } -// } - -// } // namespace i2c_master - -// namespace i2c_slave { - -// bool is_active() -// { -// return slave_.i2c_enabled.load(); -// } - -// void notify_tuh_mounted() -// { -// slave_.tuh_enabled.store(true); -// } - -// void notify_tuh_unmounted() -// { -// slave_.tuh_enabled.store(false); -// } - -// void process_in_report(ReportIn* report_in) -// { -// Gamepad& gamepad = *slave_.gamepad; -// Gamepad::PadIn pad_in; - -// std::memcpy(&pad_in, report_in->pad_in, sizeof(ReportIn::pad_in)); - -// gamepad.set_pad_in(pad_in); -// } - -// void fill_out_report(ReportOut* report_out) -// { -// Gamepad& gamepad = *slave_.gamepad; -// Gamepad::PadOut pad_out = gamepad.get_pad_out(); - -// report_out->report_len = sizeof(ReportOut); -// report_out->report_id = static_cast(ReportID::PAD); -// std::memcpy(report_out->pad_out, &pad_out, sizeof(ReportOut::pad_out)); -// } - -// ReportID get_report_id(uint8_t* buffer_in) -// { -// switch (static_cast(buffer_in[1])) -// { -// case ReportID::PAD: -// if (buffer_in[0] == sizeof(ReportIn)) -// { -// return ReportID::PAD; -// } -// break; -// case ReportID::DISCONNECT: -// if (buffer_in[0] == sizeof(ReportStatus)) -// { -// return ReportID::DISCONNECT; -// } -// break; -// case ReportID::CONNECT: -// if (buffer_in[0] == sizeof(ReportStatus)) -// { -// return ReportID::CONNECT; -// } -// break; -// case ReportID::STATUS: -// if (buffer_in[0] == sizeof(ReportStatus)) -// { -// return ReportID::STATUS; -// } -// break; -// default: -// break; -// } -// return ReportID::UNKNOWN; -// } - -// void slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) -// { -// static int count = 0; -// static std::array buffer_in{0}; -// static std::array buffer_out{0}; - -// switch (event) -// { -// case I2C_SLAVE_RECEIVE: // master has written -// if (count < MAX_BUFFER_SIZE) -// { -// buffer_in.data()[count] = i2c_read_byte_raw(i2c); -// ++count; -// } -// break; - -// case I2C_SLAVE_FINISH: // master signalled Stop / Restart -// // Each master write has an ID indicating the type of data to send back on the next request -// // Every write has an associated read -// switch (get_report_id(buffer_in.data())) -// { -// case ReportID::PAD: -// process_in_report(reinterpret_cast(buffer_in.data())); -// fill_out_report(reinterpret_cast(buffer_out.data())); -// break; -// case ReportID::STATUS: -// buffer_out.data()[0] = sizeof(ReportStatus); -// buffer_out.data()[1] = static_cast(ReportID::STATUS); -// // if something is mounted by tuh, signal to not send gamepad data -// buffer_out.data()[2] = slave_.tuh_enabled.load() ? static_cast(SlaveStatus::NOT_READY) : static_cast(SlaveStatus::READY); -// break; -// case ReportID::CONNECT: -// slave_.i2c_enabled.store(true); -// buffer_out.data()[0] = sizeof(ReportStatus); -// buffer_out.data()[1] = static_cast(ReportID::STATUS); -// buffer_out.data()[2] = static_cast(SlaveStatus::RESP_OK); -// break; -// case ReportID::DISCONNECT: -// slave_.i2c_enabled.store(false); -// buffer_out.data()[0] = sizeof(ReportStatus); -// buffer_out.data()[1] = static_cast(ReportID::STATUS); -// buffer_out.data()[2] = static_cast(SlaveStatus::RESP_OK); -// break; -// default: -// break; -// } -// count = 0; -// break; - -// case I2C_SLAVE_REQUEST: // master requesting data -// i2c_write_raw_blocking(i2c, buffer_out.data(), buffer_out.data()[0]); -// buffer_in.fill(0); -// break; - -// default: -// break; - -// } -// } - -// void init(uint8_t address, Gamepad& gamepad) -// { -// slave_.address = address; -// slave_.gamepad = &gamepad; -// i2c_slave_init(I2C_PORT, slave_.address, &slave_handler); -// } - -// } // namespace i2c_slave - -// Mode mode_{Mode::MASTER}; - -// uint8_t get_address() -// { -// gpio_init(SLAVE_ADDR_PIN_1); -// gpio_init(SLAVE_ADDR_PIN_2); -// gpio_pull_up(SLAVE_ADDR_PIN_1); -// gpio_pull_up(SLAVE_ADDR_PIN_2); - -// if (gpio_get(SLAVE_ADDR_PIN_1) == 1 && gpio_get(SLAVE_ADDR_PIN_2) == 1) -// { -// return 0x00; //Master -// } -// else if (gpio_get(SLAVE_ADDR_PIN_1) == 1 && gpio_get(SLAVE_ADDR_PIN_2) == 0) -// { -// return 0x01; -// } -// else if (gpio_get(SLAVE_ADDR_PIN_1) == 0 && gpio_get(SLAVE_ADDR_PIN_2) == 1) -// { -// return 0x02; -// } -// else if (gpio_get(SLAVE_ADDR_PIN_1) == 0 && gpio_get(SLAVE_ADDR_PIN_2) == 0) -// { -// return 0x03; -// } - -// return 0xFF; -// } - -// //Public methods - -// //Call before core1 starts -// void initialize(Gamepad (&gamepads)[MAX_GAMEPADS]) -// { -// uint8_t address = get_address(); -// if (address == 0xFF) -// { -// return; -// } - -// i2c_init(I2C_PORT, I2C_BAUDRATE); - -// gpio_init(I2C_SDA_PIN); -// gpio_set_function(I2C_SDA_PIN, GPIO_FUNC_I2C); -// gpio_pull_up(I2C_SDA_PIN); - -// gpio_init(I2C_SCL_PIN); -// gpio_set_function(I2C_SCL_PIN, GPIO_FUNC_I2C); -// gpio_pull_up(I2C_SCL_PIN); - -// if (address < 1) -// { -// mode_ = Mode::MASTER; -// driver_.process = i2c_master::process; -// driver_.is_active = i2c_master::is_active; -// driver_.notify_tud_deinit = i2c_master::notify_tud_deinit; -// driver_.notify_tuh_mounted = i2c_master::notify_tuh_mounted; -// driver_.notify_tuh_unmounted = i2c_master::notify_tuh_unmounted; -// driver_.notify_xbox360w_connected = i2c_master::notify_xbox360w_connected; -// driver_.notify_xbox360w_disconnected = i2c_master::notify_xbox360w_disconnected; -// i2c_master::init(gamepads); -// } -// else -// { -// mode_ = Mode::SLAVE; - -// driver_.process = i2c_slave::is_active; -// driver_.is_active = i2c_slave::is_active; -// driver_.notify_tud_deinit = i2c_slave::notify_tuh_unmounted; -// driver_.notify_tuh_mounted = i2c_slave::notify_tuh_mounted; -// driver_.notify_tuh_unmounted = i2c_slave::notify_tuh_unmounted; -// driver_.notify_xbox360w_connected = nullptr; -// i2c_slave::init(address, gamepads[0]); -// } -// } - -// void process() -// { -// switch (mode_) -// { -// case Mode::MASTER: -// i2c_master::process(); -// break; -// case Mode::SLAVE: -// return; -// } -// } - -// bool is_active() -// { -// switch (mode_) -// { -// case Mode::MASTER: -// return i2c_master::is_active(); -// case Mode::SLAVE: -// return i2c_slave::is_active(); -// } -// return false; -// } - -// //Called from core1 -// void notify_tuh_mounted(HostDriver::Type host_type) -// { -// switch (mode_) -// { -// case Mode::MASTER: -// i2c_master::notify_tuh_mounted(host_type); -// break; -// case Mode::SLAVE: -// i2c_slave::notify_tuh_mounted(); -// break; -// } -// } -// //Called from core1 -// void notify_tuh_unmounted(HostDriver::Type host_type) -// { -// switch (mode_) -// { -// case Mode::MASTER: -// i2c_master::notify_tuh_unmounted(host_type); -// break; -// case Mode::SLAVE: -// i2c_slave::notify_tuh_unmounted(); -// break; -// } -// } -// //Called from core1 -// void notify_xbox360w_connected(uint8_t idx) -// { -// switch (mode_) -// { -// case Mode::MASTER: -// i2c_master::notify_xbox360w_connected(idx); -// break; -// case Mode::SLAVE: -// return; -// } -// } -// //Called from core1 -// void notify_xbox360w_disconnected(uint8_t idx) -// { -// switch (mode_) -// { -// case Mode::MASTER: -// i2c_master::notify_xbox360w_disconnected(idx); -// break; -// case Mode::SLAVE: -// return; -// } -// } - -// void notify_tud_deinit() -// { -// switch (mode_) -// { -// case Mode::MASTER: -// i2c_master::notify_tud_deinit(); -// break; -// case Mode::SLAVE: -// return; -// } -// } - -// } // namespace I2CDriver \ No newline at end of file diff --git a/Firmware/RP2040/src/I2CDriver/i2c_driver_4ch.h b/Firmware/RP2040/src/I2CDriver/i2c_driver_4ch.h deleted file mode 100644 index aa66257..0000000 --- a/Firmware/RP2040/src/I2CDriver/i2c_driver_4ch.h +++ /dev/null @@ -1,145 +0,0 @@ -// #ifndef _I2C_DRIVER_H_ -// #define _I2C_DRIVER_H_ - -// #include - -// #include "Gamepad.h" -// #include "USBHost/HostManager.h" - -// // /* Master will only write/read slave if an Xbox360 wireless controller is connected for its corresponding slave. -// // Slaves will read/write from the bus only if they don't have a device mounted by tusb host. -// // Could be made to work so that a USB hub could be connected to port 1 and host 4 controllers, maybe later. -// // This is run on core0 with the device stack, but some values are checked and modified by core1 (atomic types). */ -// // namespace i2c -// // { -// // void initialize(Gamepad (&gamepads)[MAX_GAMEPADS]); - -// // struct driver -// // { -// // void (*process)(){nullptr}; -// // bool (*is_active)(){nullptr}; -// // void (*notify_tud_deinit)(){nullptr}; -// // void (*notify_tuh_mounted)(HostDriver::Type host_type){nullptr}; -// // void (*notify_tuh_unmounted)(HostDriver::Type host_type){nullptr}; -// // void (*notify_xbox360w_connected)(uint8_t idx){nullptr}; -// // void (*notify_xbox360w_disconnected)(uint8_t idx){nullptr}; -// // }; - -// // driver* get_driver(); - -// // // void process(); -// // // bool is_active(); - -// // // void notify_tud_deinit(); - -// // // void notify_tuh_mounted(HostDriver::Type host_type = HostDriver::Type::UNKNOWN); -// // // void notify_tuh_unmounted(HostDriver::Type host_type = HostDriver::Type::UNKNOWN); - -// // // void notify_xbox360w_connected(uint8_t idx); -// // // void notify_xbox360w_disconnected(uint8_t idx); -// // } -// class I2CDriver4Ch -// { -// public: -// I2CDriver4Ch& get_instance() -// { -// static I2CDriver4Ch instance; -// return instance; -// } - -// I2CDriver4Ch(const I2CDriver4Ch&) = delete; -// I2CDriver4Ch& operator=(const I2CDriver4Ch&) = delete; - -// void initialize(Gamepad (&gamepads)[MAX_GAMEPADS]); - -// private: -// I2CDriver4Ch() = default; -// ~I2CDriver4Ch() = default; - -// I2CDriver4Ch(const I2CDriver4Ch&) = delete; -// I2CDriver4Ch& operator=(const I2CDriver4Ch&) = delete; - -// enum class Mode { MASTER = 0, SLAVE }; -// enum class ReportID : uint8_t { UNKNOWN = 0, PAD, STATUS, CONNECT, DISCONNECT }; -// enum class SlaveStatus : uint8_t { NC = 0, NOT_READY, READY, RESP_OK }; - -// #pragma pack(push, 1) -// struct ReportIn -// { -// uint8_t report_len; -// uint8_t report_id; -// uint8_t pad_in[sizeof(Gamepad::PadIn) - sizeof(Gamepad::PadIn::analog)]; - -// ReportIn() -// { -// std::memset(this, 0, sizeof(ReportIn)); -// report_len = sizeof(ReportIn); -// report_id = static_cast(ReportID::PAD); -// } -// }; -// static_assert(sizeof(ReportIn) == 18, "I2CDriver::ReportIn size mismatch"); - -// struct ReportOut -// { -// uint8_t report_len; -// uint8_t report_id; -// uint8_t pad_out[sizeof(Gamepad::PadOut)]; - -// ReportOut() -// { -// std::memset(this, 0, sizeof(ReportOut)); -// report_len = sizeof(ReportOut); -// report_id = static_cast(ReportID::PAD); -// } -// }; -// static_assert(sizeof(ReportOut) == 4, "I2CDriver::ReportOut size mismatch"); - -// struct ReportStatus -// { -// uint8_t report_len; -// uint8_t report_id; -// uint8_t status; - -// ReportStatus() -// { -// report_len = sizeof(ReportStatus); -// report_id = static_cast(ReportID::STATUS); -// status = static_cast(SlaveStatus::NC); -// } -// }; -// static_assert(sizeof(ReportStatus) == 3, "I2CDriver::ReportStatus size mismatch"); -// #pragma pack(pop) - -// static constexpr size_t MAX_BUFFER_SIZE = std::max(sizeof(ReportStatus), std::max(sizeof(ReportIn), sizeof(ReportOut))); - -// struct Master -// { -// std::atomic enabled{false}; - -// struct Slave -// { -// uint8_t address{0xFF}; -// Gamepad* gamepad{nullptr}; - -// SlaveStatus status{SlaveStatus::NC}; -// std::atomic enabled{false}; -// uint32_t last_update{0}; -// }; - -// std::array slaves; -// }; - -// struct Slave -// { -// uint8_t address{0xFF}; -// Gamepad* gamepad{nullptr}; -// std::atomic i2c_enabled{false}; -// std::atomic tuh_enabled{false}; -// }; - -// Slave slave_; - -// static Gamepad* gamepads_[MAX_GAMEPADS]; -// }; - -// #endif // _I2C_DRIVER_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/I2CDriver/i2c_driver_esp32.cpp b/Firmware/RP2040/src/I2CDriver/i2c_driver_esp32.cpp deleted file mode 100644 index 5bae2a9..0000000 --- a/Firmware/RP2040/src/I2CDriver/i2c_driver_esp32.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include -#include -#include -#include -#include - -#include "Gamepad.h" -#include "board_config.h" -#include "Board/board_api.h" -#include "I2CDriver/i2c_driver_esp32.h" - -namespace i2c_driver_esp32 { - -//May expand commands in the future -enum class ReportID : uint8_t { UNKNOWN = 0, SET_PAD, GET_PAD }; - -#pragma pack(push, 1) -struct ReportIn -{ - uint8_t report_len; - uint8_t report_id; - uint8_t index; - uint8_t dpad; - uint16_t buttons; - uint8_t trigger_l; - uint8_t trigger_r; - int16_t joystick_lx; - int16_t joystick_ly; - int16_t joystick_rx; - int16_t joystick_ry; - - ReportIn() - { - std::memset(this, 0, sizeof(ReportIn)); - report_len = sizeof(ReportIn); - report_id = static_cast(ReportID::SET_PAD); - } -}; -static_assert(sizeof(ReportIn) == 16, "i2c_driver_esp::ReportIn size mismatch"); - -struct ReportOut -{ - uint8_t report_len; - uint8_t report_id; - uint8_t index; - uint8_t rumble_l; - uint8_t rumble_r; - - ReportOut() - { - std::memset(this, 0, sizeof(ReportOut)); - report_len = sizeof(ReportOut); - report_id = static_cast(ReportID::GET_PAD); - } -}; -static_assert(sizeof(ReportOut) == 5, "i2c_driver_esp::ReportOut size mismatch"); -#pragma pack(pop) - -static constexpr size_t MAX_BUFFER_SIZE = std::max(sizeof(ReportOut), sizeof(ReportIn)); -static constexpr uint8_t I2C_ADDR = 0x01; - -std::array gamepads_{nullptr}; - -inline void process_in_report(ReportIn* report_in) -{ - if (report_in->index >= MAX_GAMEPADS) - { - return; - } - - Gamepad* gamepad = gamepads_[report_in->index]; - - gamepad->set_buttons(report_in->buttons); - gamepad->set_dpad(report_in->dpad); - gamepad->set_trigger_l(report_in->trigger_l); - gamepad->set_trigger_r(report_in->trigger_r); - gamepad->set_joystick_lx_int10(static_cast(report_in->joystick_lx)); - gamepad->set_joystick_ly_int10(static_cast(report_in->joystick_ly)); - gamepad->set_joystick_rx_int10(static_cast(report_in->joystick_rx)); - gamepad->set_joystick_ry_int10(static_cast(report_in->joystick_ry)); - gamepad->set_new_report(true); -} - -inline void fill_out_report(uint8_t index, ReportOut* report_out) -{ - if (index >= MAX_GAMEPADS) - { - return; - } - - Gamepad* gamepad = gamepads_[index]; - - report_out->report_len = sizeof(ReportOut); - report_out->report_id = static_cast(ReportID::GET_PAD); - report_out->rumble_l = gamepad->get_rumble_l().uint8(); - report_out->rumble_r = gamepad->get_rumble_r().uint8(); -} - -ReportID get_report_id(uint8_t* buffer_in) -{ - switch (static_cast(buffer_in[1])) - { - case ReportID::SET_PAD: - if (buffer_in[0] == sizeof(ReportIn)) - { - return ReportID::SET_PAD; - } - break; - //Unused ATM - // case ReportID::GET_PAD: - // if (buffer_in[0] == sizeof(ReportOut)) - // { - // return ReportID::GET_PAD; - // } - // break; - default: - break; - } - return ReportID::UNKNOWN; -} - -static inline void slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) -{ - static int count = 0; - static std::array buffer_in{0}; - static std::array buffer_out{0}; - - switch (event) - { - case I2C_SLAVE_RECEIVE: // master has written - if (count < MAX_BUFFER_SIZE) - { - buffer_in.data()[count] = i2c_read_byte_raw(i2c); - ++count; - } - break; - - case I2C_SLAVE_FINISH: // master signalled Stop / Restart - if (get_report_id(buffer_in.data()) == ReportID::SET_PAD) - { - process_in_report(reinterpret_cast(buffer_in.data())); - } - count = 0; - break; - - case I2C_SLAVE_REQUEST: // master requesting data - fill_out_report(reinterpret_cast(buffer_in.data())->index, reinterpret_cast(buffer_out.data())); - i2c_write_raw_blocking(i2c, buffer_out.data(), buffer_out.data()[0]); - buffer_in.fill(0); - break; - - default: - break; - } -} - -void initialize(std::array& gamepad) -{ - for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) - { - gamepads_[i] = &gamepad[i]; - } - - i2c_init(I2C_PORT, I2C_BAUDRATE); - - gpio_init(I2C_SDA_PIN); - gpio_set_function(I2C_SDA_PIN, GPIO_FUNC_I2C); - gpio_pull_up(I2C_SDA_PIN); - - gpio_init(I2C_SCL_PIN); - gpio_set_function(I2C_SCL_PIN, GPIO_FUNC_I2C); - gpio_pull_up(I2C_SCL_PIN); - - i2c_slave_init(I2C_PORT, I2C_ADDR, &slave_handler); -} - -} // namespace i2c_driver_esp32 \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/Debug.h b/Firmware/RP2040/src/OGXMini/Debug.h new file mode 100644 index 0000000..7f9c2b4 --- /dev/null +++ b/Firmware/RP2040/src/OGXMini/Debug.h @@ -0,0 +1,55 @@ +#ifndef _OGXM_DEBUG_H_ +#define _OGXM_DEBUG_H_ + +#include "board_config.h" +#if defined(OGXM_DEBUG) + +#include +#include +#include +#include +#include +#include + +namespace OGXMini { + + //Don't use this directly, use the OGXM_LOG macro + static inline void log(const std::string& message) + { + static mutex_t log_mutex; + + if (!mutex_is_initialized(&log_mutex)) + { + mutex_init(&log_mutex); + } + + mutex_enter_blocking(&log_mutex); + uart_puts(DEBUG_UART_PORT, message.c_str()); + mutex_exit(&log_mutex); + } + + //Don't use this directly, use the OGXM_LOG macro + static inline void log_hex(const uint8_t* data, size_t size) + { + std::ostringstream hex_stream; + hex_stream << std::hex << std::setfill('0'); + for (uint16_t i = 0; i < size; ++i) + { + hex_stream << std::setw(2) << static_cast(data[i]) << " "; + } + log(hex_stream.str()); + } + +} // namespace OGXMini + +#endif // defined(OGXM_DEBUG) + +#if defined(OGXM_DEBUG) + #define OGXM_LOG OGXMini::log + #define OGXM_LOG_HEX OGXMini::log_hex +#else + #define OGXM_LOG(...) + #define OGXM_LOG_HEX(...) +#endif // OGXM_DEBUG + +#endif // _OGXM_DEBUG_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/OGXMini.h b/Firmware/RP2040/src/OGXMini/OGXMini.h index b5ab986..24a6f43 100644 --- a/Firmware/RP2040/src/OGXMini/OGXMini.h +++ b/Firmware/RP2040/src/OGXMini/OGXMini.h @@ -7,8 +7,6 @@ namespace OGXMini { - enum class TUDStatus { INIT, DEINIT, NOCHANGE }; - static constexpr int32_t FEEDBACK_DELAY_MS = 150; static constexpr int32_t TUD_CHECK_DELAY_MS = 500; diff --git a/Firmware/RP2040/src/OGXMini/OGXMini_4Ch.cpp b/Firmware/RP2040/src/OGXMini/OGXMini_4Channel.cpp similarity index 76% rename from Firmware/RP2040/src/OGXMini/OGXMini_4Ch.cpp rename to Firmware/RP2040/src/OGXMini/OGXMini_4Channel.cpp index 9621958..6512839 100644 --- a/Firmware/RP2040/src/OGXMini/OGXMini_4Ch.cpp +++ b/Firmware/RP2040/src/OGXMini/OGXMini_4Channel.cpp @@ -18,28 +18,7 @@ namespace OGXMini { Gamepad gamepads_[MAX_GAMEPADS]; - -//Called by tusb host or i2c driver so we know to connect or disconnect usb -void update_tud_status(bool host_mounted) -{ - board_api::set_led(host_mounted); - - if (!host_mounted) - { - TaskQueue::Core0::queue_task([]() - { - tud_disconnect(); - sleep_ms(300); - multicore_reset_core1(); - sleep_ms(300); - board_api::reboot(); - }); - } - else if (!tud_inited()) - { - tud_init(BOARD_TUD_RHPORT); - } -} +std::atomic tud_inited_{false}; void core1_task() { @@ -64,31 +43,34 @@ void core1_task() } } -void run_program() +//Called by tusb host or i2c driver so we know to connect or disconnect usb +void update_tud_status(bool host_mounted) { - UserSettings user_settings; - user_settings.initialize_flash(); + board_api::set_led(host_mounted); - board_init(); - board_api::init_gpio(); - board_api::set_led(false); - - for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) + if (!host_mounted && tud_inited_.load()) { - gamepads_[i].set_profile(user_settings.get_profile_by_index(i)); + TaskQueue::Core0::queue_task([]() + { + tud_disconnect(); + sleep_ms(300); + multicore_reset_core1(); + sleep_ms(300); + board_api::reboot(); + }); } + else if (!tud_inited_.load()) + { + TaskQueue::Core0::queue_task([]() + { + tud_init(BOARD_TUD_RHPORT); + }); + } +} - DeviceManager& device_manager = DeviceManager::get_instance(); - device_manager.initialize_driver(user_settings.get_current_driver()); - - I2CManager& i2c_manager = I2CManager::get_instance(); - i2c_manager.initialize_driver(); - - multicore_reset_core1(); - multicore_launch_core1(core1_task); - - uint32_t tid_gp_check = TaskQueue::Core0::get_new_task_id(); - TaskQueue::Core0::queue_delayed_task(tid_gp_check, UserSettings::GP_CHECK_DELAY_MS, true, [&user_settings] +void set_gp_check_timer(uint32_t task_id, UserSettings& user_settings) +{ + TaskQueue::Core0::queue_delayed_task(task_id, UserSettings::GP_CHECK_DELAY_MS, true, [&user_settings] { //Check gamepad inputs for button combo to change usb device driver if (user_settings.check_for_driver_change(gamepads_[0])) @@ -97,9 +79,31 @@ void run_program() user_settings.store_driver_type_safe(user_settings.get_current_driver()); } }); +} - DeviceDriver* device_driver = device_manager.get_driver(); - I2CDriver* i2c_driver = i2c_manager.get_driver(); +void run_program() +{ + UserSettings user_settings; + user_settings.initialize_flash(); + + board_api::init_board(); + + for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) + { + gamepads_[i].set_profile(user_settings.get_profile_by_index(i)); + } + + DeviceManager::get_instance().initialize_driver(user_settings.get_current_driver(), gamepads_); + I2CManager::get_instance().initialize_driver(); + + multicore_reset_core1(); + multicore_launch_core1(core1_task); + + uint32_t tid_gp_check = TaskQueue::Core0::get_new_task_id(); + set_gp_check_timer(tid_gp_check, user_settings); + + DeviceDriver* device_driver = DeviceManager::get_instance().get_driver(); + I2CDriver* i2c_driver = I2CManager::get_instance().get_driver(); //Wait for something to call tud_init while (!tud_inited()) @@ -108,11 +112,15 @@ void run_program() sleep_ms(10); } + tud_inited_.store(true); + while (true) { TaskQueue::Core0::process_tasks(); + i2c_driver->process(gamepads_); device_driver->process(0, gamepads_[0]); + tud_task(); sleep_us(100); } diff --git a/Firmware/RP2040/src/OGXMini/OGXMini_ESP32.cpp b/Firmware/RP2040/src/OGXMini/OGXMini_ESP32.cpp index 6c67881..db8efa2 100644 --- a/Firmware/RP2040/src/OGXMini/OGXMini_ESP32.cpp +++ b/Firmware/RP2040/src/OGXMini/OGXMini_ESP32.cpp @@ -1,11 +1,7 @@ #include "board_config.h" #if OGXM_BOARD == W_ESP32 -#include -#include #include -#include -#include #include "tusb.h" #include "bsp/board_api.h" @@ -13,36 +9,48 @@ #include "USBDevice/DeviceManager.h" #include "Board/board_api.h" #include "OGXMini/OGXMini.h" -#include "I2CDriver/i2c_driver_esp32.h" +#include "I2CDriver/ESP32/I2CDriver.h" #include "Gamepad.h" +#include "TaskQueue/TaskQueue.h" namespace OGXMini { -std::array gamepads_; +static Gamepad gamepads_[MAX_GAMEPADS]; + +//Not using this for ESP32 currently +void update_tud_status(bool host_mounted) { } + +void core1_task() +{ + I2CDriver::initialize(gamepads_); + + while (true) + { + tight_loop_contents(); + } +} void run_esp32_uart_bridge() { DeviceManager& device_manager = DeviceManager::get_instance(); - device_manager.initialize_driver(DeviceDriver::Type::UART_BRIDGE); + device_manager.initialize_driver(DeviceDriver::Type::UART_BRIDGE, gamepads_); + board_api::enter_esp32_prog_mode(); - device_manager.get_driver()->process(0, gamepads_.front()); //Runs UART Bridge task + + device_manager.get_driver()->process(0, gamepads_[0]); //Runs UART Bridge task, doesn't return } -void core1_task() +void set_gp_check_timer(uint32_t task_id, UserSettings& user_settings) { - i2c_driver_esp32::initialize(gamepads_); - - while (true) + TaskQueue::Core0::queue_delayed_task(task_id, UserSettings::GP_CHECK_DELAY_MS, true, [&user_settings] { - __wfi(); - } -} - -bool gp_check_cb(repeating_timer_t* rt) -{ - GPCheckContext* gp_check_ctx = static_cast(rt->user_data); - gp_check_ctx->driver_changed = gp_check_ctx->user_settings.check_for_driver_change(gamepads_.front()); - return true; + //Check gamepad inputs for button combo to change usb device driver + if (user_settings.check_for_driver_change(gamepads_[0])) + { + //This will store the new mode and reboot the pico + user_settings.store_driver_type_safe(user_settings.get_current_driver()); + } + }); } void run_program() @@ -50,56 +58,44 @@ void run_program() UserSettings user_settings; user_settings.initialize_flash(); - board_api::init_gpio(); + board_api::init_board(); if (board_api::uart_bridge_mode()) { run_esp32_uart_bridge(); return; } - // else if (!user_settings.verify_firmware_version()) - // { - // user_settings.write_firmware_version(); - // } - board_init(); - - for (uint8_t i = 0; i < gamepads_.size(); ++i) + for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) { gamepads_[i].set_profile(user_settings.get_profile_by_index(i)); } - DeviceManager& device_manager = DeviceManager::get_instance(); - device_manager.initialize_driver(user_settings.get_current_driver()); + DeviceManager::get_instance().initialize_driver(user_settings.get_current_driver(), gamepads_); multicore_reset_core1(); multicore_launch_core1(core1_task); board_api::reset_esp32(); - GPCheckContext gp_check_ctx = { false, user_settings }; - repeating_timer_t gp_check_timer; - add_repeating_timer_ms(UserSettings::GP_CHECK_DELAY_MS, gp_check_cb, &gp_check_ctx, &gp_check_timer); + uint32_t tid_gp_check = TaskQueue::Core0::get_new_task_id(); + set_gp_check_timer(tid_gp_check, user_settings); - DeviceDriver* device_driver = device_manager.get_driver(); + DeviceDriver* device_driver = DeviceManager::get_instance().get_driver(); tud_init(BOARD_TUD_RHPORT); while (true) { - for (uint8_t i = 0; i < gamepads_.size(); ++i) + TaskQueue::Core0::process_tasks(); + + for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) { device_driver->process(i, gamepads_[i]); tud_task(); } sleep_us(100); - - if (gp_check_ctx.driver_changed) - { - cancel_repeating_timer(&gp_check_timer); - user_settings.store_driver_type_safe(user_settings.get_current_driver()); - } } } diff --git a/Firmware/RP2040/src/OGXMini/OGXMini_PicoW.cpp b/Firmware/RP2040/src/OGXMini/OGXMini_PicoW.cpp index 0775f27..e60f8e4 100644 --- a/Firmware/RP2040/src/OGXMini/OGXMini_PicoW.cpp +++ b/Firmware/RP2040/src/OGXMini/OGXMini_PicoW.cpp @@ -1,11 +1,7 @@ #include "board_config.h" #if (OGXM_BOARD == PI_PICOW) -#include -#include #include -#include -#include #include #include "tusb.h" @@ -15,57 +11,63 @@ #include "Board/board_api.h" #include "Bluepad32/Bluepad32.h" #include "OGXMini/OGXMini.h" +#include "Gamepad.h" +#include "TaskQueue/TaskQueue.h" namespace OGXMini { Gamepad gamepads_[MAX_GAMEPADS]; +//Not using this for Pico W currently +void update_tud_status(bool host_mounted) { } + void core1_task() { if (cyw43_arch_init() != 0) - { + { return; } + //Doesn't return, don't do anything with core1 unless it's executing within the BTStack loop bluepad32::run_task(gamepads_); } -bool gp_check_cb(repeating_timer_t* rt) -{ - GPCheckContext* gp_check_ctx = static_cast(rt->user_data); - gp_check_ctx->driver_changed = gp_check_ctx->user_settings.check_for_driver_change(gamepads_[0]); - return true; -} - void run_program() { UserSettings user_settings; user_settings.initialize_flash(); - board_init(); - board_api::init_gpio(); + board_api::init_board(); for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) { gamepads_[i].set_profile(user_settings.get_profile_by_index(i)); } - DeviceManager& device_manager = DeviceManager::get_instance(); - device_manager.initialize_driver(user_settings.get_current_driver()); + DeviceManager::get_instance().initialize_driver(user_settings.get_current_driver(), gamepads_); multicore_reset_core1(); multicore_launch_core1(core1_task); - GPCheckContext gp_check_ctx = { false, user_settings }; - repeating_timer_t gp_check_timer; - add_repeating_timer_ms(UserSettings::GP_CHECK_DELAY_MS, gp_check_cb, &gp_check_ctx, &gp_check_timer); + uint32_t tid_gp_check = TaskQueue::Core0::get_new_task_id(); + TaskQueue::Core0::queue_delayed_task(tid_gp_check, UserSettings::GP_CHECK_DELAY_MS, true, [&user_settings] + { + //Check gamepad inputs for button combo to change usb device driver + if (user_settings.check_for_driver_change(gamepads_[0])) + { + //This will store the new mode and reboot the pico + user_settings.store_driver_type_safe(user_settings.get_current_driver()); + } + }); - DeviceDriver* device_driver = device_manager.get_driver(); + DeviceDriver* device_driver = DeviceManager::get_instance().get_driver(); tud_init(BOARD_TUD_RHPORT); while (true) { + TaskQueue::Core0::process_tasks(); + for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) { device_driver->process(i, gamepads_[i]); @@ -73,12 +75,6 @@ void run_program() } sleep_us(100); - - if (gp_check_ctx.driver_changed) - { - cancel_repeating_timer(&gp_check_timer); - user_settings.store_driver_type_safe(user_settings.get_current_driver()); - } } } diff --git a/Firmware/RP2040/src/OGXMini/OGXMini_Standard.cpp b/Firmware/RP2040/src/OGXMini/OGXMini_Standard.cpp index 1dc2942..60a6cef 100644 --- a/Firmware/RP2040/src/OGXMini/OGXMini_Standard.cpp +++ b/Firmware/RP2040/src/OGXMini/OGXMini_Standard.cpp @@ -1,11 +1,7 @@ #include "board_config.h" -#if (OGXM_BOARD == ADA_FEATHER) || (OGXM_BOARD == RP_ZERO) || (OGXM_BOARD == PI_PICO) +#if (OGXM_BOARD == ADA_FEATHER) || (OGXM_BOARD == RP_ZERO) || (OGXM_BOARD == PI_PICO) || (OGXM_BOARD == PI_PICO2) -#include -#include #include -#include -#include #include "tusb.h" #include "bsp/board_api.h" @@ -13,26 +9,15 @@ #include "USBHost/HostManager.h" #include "USBDevice/DeviceManager.h" -#include "Board/board_api.h" #include "OGXMini/OGXMini.h" +#include "TaskQueue/TaskQueue.h" #include "Gamepad.h" +#include "Board/board_api.h" namespace OGXMini { -std::atomic tud_status_ = TUDStatus::NOCHANGE; Gamepad gamepads_[MAX_GAMEPADS]; - -void update_tuh_status(bool mounted) -{ - tud_status_.store(mounted ? TUDStatus::INIT : TUDStatus::DEINIT); - board_api::set_led(mounted); -} - -bool feedback_cb(repeating_timer_t* rt) -{ - static_cast(rt->user_data)->send_feedback(); - return true; -} +std::atomic tud_inited_{false}; void core1_task() { @@ -44,49 +29,63 @@ void core1_task() tuh_init(BOARD_TUH_RHPORT); - repeating_timer_t feedback_timer; - add_repeating_timer_ms(FEEDBACK_DELAY_MS, feedback_cb, &host_manager, &feedback_timer); - - while (true) + uint32_t tid_feedback = TaskQueue::Core1::get_new_task_id(); + TaskQueue::Core1::queue_delayed_task(tid_feedback, FEEDBACK_DELAY_MS, true, [&host_manager] { + host_manager.send_feedback(); + }); + + while (true) + { + TaskQueue::Core1::process_tasks(); tuh_task(); - sleep_us(100); } } -// bool gp_check_cb(repeating_timer_t* rt) -// { -// GPCheckContext* gp_check_ctx = static_cast(rt->user_data); -// // gp_check_ctx->driver_changed = gp_check_ctx->user_settings.check_for_driver_change(gamepads_[0]); -// if (gp_check_ctx->user_settings.check_for_driver_change(gamepads_[0])) -// { -// gp_check_ctx->user_settings.store_driver_type_safe(gp_check_ctx->user_settings.get_current_driver()); -// return false; -// } -// return true; -// } -bool gp_check_cb(repeating_timer_t* rt) +//Called by tusb host or i2c driver so we know to connect or disconnect usb +void update_tud_status(bool host_mounted) { - UserSettings* user_settings = static_cast(rt->user_data); - if (user_settings->check_for_driver_change(gamepads_[0])) + board_api::set_led(host_mounted); + + if (!host_mounted && tud_inited_.load()) { - user_settings->store_driver_type_safe(user_settings->get_current_driver()); - return false; + TaskQueue::Core0::queue_task([]() + { + tud_disconnect(); + sleep_ms(300); + multicore_reset_core1(); + sleep_ms(300); + board_api::reboot(); + }); } - return true; + else if (!tud_inited_.load()) + { + TaskQueue::Core0::queue_task([]() + { + tud_init(BOARD_TUD_RHPORT); + }); + } +} + +void set_gp_check_timer(uint32_t task_id, UserSettings& user_settings) +{ + TaskQueue::Core0::queue_delayed_task(task_id, UserSettings::GP_CHECK_DELAY_MS, true, [&user_settings] + { + //Check gamepad inputs for button combo to change usb device driver + if (user_settings.check_for_driver_change(gamepads_[0])) + { + //This will store the new mode and reboot the pico + user_settings.store_driver_type_safe(user_settings.get_current_driver()); + } + }); } void run_program() { - set_sys_clock_khz(250000, true); - UserSettings user_settings; user_settings.initialize_flash(); - board_init(); - - board_api::init_gpio(); - board_api::set_led(false); + board_api::init_board(); for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) { @@ -94,52 +93,39 @@ void run_program() } DeviceManager& device_manager = DeviceManager::get_instance(); - device_manager.initialize_driver(user_settings.get_current_driver()); + device_manager.initialize_driver(user_settings.get_current_driver(), gamepads_); multicore_reset_core1(); multicore_launch_core1(core1_task); - // GPCheckContext gp_check_ctx = { false, user_settings }; - // repeating_timer_t gp_check_timer; - // add_repeating_timer_ms(UserSettings::GP_CHECK_DELAY_MS, gp_check_cb, &gp_check_ctx, &gp_check_timer); - - repeating_timer_t gp_check_timer; - add_repeating_timer_ms(UserSettings::GP_CHECK_DELAY_MS, gp_check_cb, &user_settings, &gp_check_timer); + uint32_t tid_gp_check = TaskQueue::Core0::get_new_task_id(); + set_gp_check_timer(tid_gp_check, user_settings); DeviceDriver* device_driver = device_manager.get_driver(); - while (tud_status_.load() != TUDStatus::INIT) + // Wait for something to call update_tud_status() + while (!tud_inited()) { - sleep_ms(1); + TaskQueue::Core0::process_tasks(); + sleep_ms(100); } - tud_init(BOARD_TUD_RHPORT); + tud_inited_.store(true); while (true) { - switch(tud_status_.load()) - { - case TUDStatus::DEINIT: - tud_disconnect(); - sleep_ms(300); - multicore_reset_core1(); - sleep_ms(300); - board_api::reboot(); - break; - default: - break; - } + TaskQueue::Core0::process_tasks(); for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) { device_driver->process(i, gamepads_[i]); - tud_task(); } + tud_task(); sleep_us(100); } } } // namespace OGXMini -#endif // (OGXM_BOARD == ADA_FEATHER) || (OGXM_BOARD == RP_ZERO) || (OGXM_BOARD == PI_PICO) \ No newline at end of file +#endif // (OGXM_BOARD == ADA_FEATHER) || (OGXM_BOARD == RP_ZERO) || (OGXM_BOARD == PI_PICO) || (OGXM_BOARD == PI_PICO2) \ No newline at end of file diff --git a/Firmware/RP2040/src/TaskQueue/TaskQueue.cpp b/Firmware/RP2040/src/TaskQueue/TaskQueue.cpp index 1ee7244..374e935 100644 --- a/Firmware/RP2040/src/TaskQueue/TaskQueue.cpp +++ b/Firmware/RP2040/src/TaskQueue/TaskQueue.cpp @@ -1,73 +1,254 @@ #include #include +#include #include #include #include #include #include "Board/board_api.h" +#include "board_config.h" #include "TaskQueue/TaskQueue.h" namespace TaskQueue { -struct Task +class CoreQueue { - std::function function = nullptr; -}; +public: + enum class CoreNum : uint8_t + { + Core0 = 0, + Core1, + }; -struct DelayedTask -{ - uint32_t task_id = 0; - uint32_t interval_ms = 0; - uint64_t target_time = 0; - std::function function = nullptr; -}; + CoreQueue(CoreNum core_num) + : core_num_(core_num) + { + uint32_t idx = (core_num_ == CoreNum::Core0) ? 0 : 1; +#if (OGXM_BOARD != PI_PICOW) + alarm_num_ = idx; +#else + alarm_num_ = idx + 1; //BTStack uses alarm 0 +#endif + instances_[idx] = this; -static constexpr uint8_t MAX_TASKS = 8; -static constexpr uint8_t MAX_DELAYED_TASKS = MAX_TASKS * 2; + hw_set_bits(&timer_hw->inte, 1u << alarm_num_); -static inline uint32_t TIMER_IRQ(int alarm_num) -{ - return timer_hardware_alarm_get_irq_num(timer_hw, alarm_num); -} + irq_set_exclusive_handler( + TIMER_IRQ(alarm_num_), + (core_num_ == CoreNum::Core0) ? timer_irq_wrapper_c0 : timer_irq_wrapper_c1); -static uint64_t get_time_64_us() -{ - static spin_lock_t* spinlock_64_us = spin_lock_instance(4); - uint32_t irq_state = spin_lock_blocking(spinlock_64_us); - uint32_t lo = timer_hw->timelr; - uint32_t hi = timer_hw->timehr; - spin_unlock(spinlock_64_us, irq_state); - return ((uint64_t) hi << 32u) | lo;; -} + irq_set_enabled(TIMER_IRQ(alarm_num_), true); + } -namespace Core1 { - - static constexpr uint32_t CORE = 1; - static constexpr uint32_t ALARM_NUM = CORE; - - static std::array tasks_; - static std::array delayed_tasks_; - - static bool delay_irq_set_ = false; - static uint32_t new_task_id_ = 1; - - static spin_lock_t* spinlock_ = spin_lock_instance(CORE); - static spin_lock_t* spinlock_delayed_ = spin_lock_instance(CORE + 2); + ~CoreQueue() = default; uint32_t get_new_task_id() { return new_task_id_++; } - static void timer_irq_handler() + bool queue_delayed_task(uint32_t task_id, uint32_t delay_ms, bool repeating, const std::function& function) { - hw_clear_bits(&timer_hw->intr, 1u << ALARM_NUM); + uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); + for (const auto& task : task_queue_delayed_) + { + if (task.task_id == task_id) + { + spin_unlock(spinlock_delayed_, irq_state); + return false; + } + } + + hw_set_bits(&timer_hw->inte, 1u << alarm_num_); + + //Might come back to this, there is overflow potential + uint64_t target_time = timer_hw->timerawl + static_cast(delay_ms) * 1000; + + for (auto& task : task_queue_delayed_) + { + if (!task.function) + { + task.target_time = target_time; + task.interval_ms = repeating ? delay_ms : 0; + task.function = function; + task.task_id = task_id; + + auto it = std::min_element(task_queue_delayed_.begin(), task_queue_delayed_.end(), [](const DelayedTask& a, const DelayedTask& b) + { + return a.function && (!b.function || a.target_time < b.target_time); + }); + + if (it != task_queue_delayed_.end() && it->function) + { + timer_hw->alarm[alarm_num_] = static_cast(it->target_time); + } + + spin_unlock(spinlock_delayed_, irq_state); + return true; + } + } + + spin_unlock(spinlock_delayed_, irq_state); + return false; + } + + void cancel_delayed_task(uint32_t task_id) + { + uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); + bool found = false; + + for (auto& task : task_queue_delayed_) + { + if (task.task_id == task_id) + { + task.function = nullptr; + task.task_id = 0; + task.interval_ms = 0; + found = true; + } + } + + if (!found) + { + spin_unlock(spinlock_delayed_, irq_state); + return; + } + + hw_set_bits(&timer_hw->inte, 1u << alarm_num_); + + int64_t next_target_time = get_next_target_time_unsafe(task_queue_delayed_); + if (next_target_time >= 0) + { + timer_hw->alarm[alarm_num_] = static_cast(next_target_time); + } + + spin_unlock(spinlock_delayed_, irq_state); + } + + bool queue_task(const std::function& function) + { + uint32_t irq_state = spin_lock_blocking(spinlock_queue_); + for (auto& task : task_queue_) + { + if (!task.function) + { + task.function = function; + spin_unlock(spinlock_queue_, irq_state); + return true; + } + } + spin_unlock(spinlock_queue_, irq_state); + return false; + } + + void process_tasks() + { + uint32_t irq_state = spin_lock_blocking(spinlock_queue_); + for (auto& task : task_queue_) + { + if (task.function) + { + auto function = task.function; + task.function = nullptr; + spin_unlock(spinlock_queue_, irq_state); + + function(); + + irq_state = spin_lock_blocking(spinlock_queue_); + } + else + { + break; //No more tasks + } + } + spin_unlock(spinlock_queue_, irq_state); + } + +private: + CoreQueue& operator=(const CoreQueue&) = delete; + CoreQueue(CoreQueue&&) = delete; + CoreQueue& operator=(CoreQueue&&) = delete; + + static CoreQueue* instances_[static_cast(CoreNum::Core1) + 1]; + + struct Task + { + // uint32_t task_id = 0; + std::function function = nullptr; + }; + + struct DelayedTask + { + uint32_t task_id = 0; + uint32_t interval_ms = 0; + uint64_t target_time = 0; + std::function function = nullptr; + }; + + static constexpr uint8_t MAX_TASKS = 8; + static constexpr uint8_t MAX_DELAYED_TASKS = MAX_TASKS * 2; + + CoreNum core_num_; + uint32_t alarm_num_; + uint32_t new_task_id_ = 1; + + int spinlock_queue_num_ = spin_lock_claim_unused(true); + int spinlock_delayed_num_ = spin_lock_claim_unused(true); + spin_lock_t* spinlock_queue_ = spin_lock_instance(static_cast(spinlock_queue_num_)); + spin_lock_t* spinlock_delayed_ = spin_lock_instance(static_cast(spinlock_delayed_num_)); + + std::array task_queue_; + std::array task_queue_delayed_; + + static void timer_irq_wrapper_c0() + { + instances_[static_cast(CoreNum::Core0)]->timer_irq_handler(); + } + + static void timer_irq_wrapper_c1() + { + instances_[static_cast(CoreNum::Core1)]->timer_irq_handler(); + } + + static inline uint32_t TIMER_IRQ(uint32_t alarm_num) + { + // switch (alarm_num) + // { + // case 1: + // return TIMER_IRQ_1; + // case 2: + // return TIMER_IRQ_2; + // default: + // return TIMER_IRQ_0; + // } + + return timer_hardware_alarm_get_irq_num(timer_hw, alarm_num); + } + + static inline uint64_t get_time_64_us() + { + static spin_lock_t* spinlock_time_ = nullptr; + if (!spinlock_time_) + { + int spinlock_time_num = spin_lock_claim_unused(true); + spinlock_time_ = spin_lock_instance(static_cast(spinlock_time_num)); + } + uint32_t irq_state = spin_lock_blocking(spinlock_time_); + uint32_t lo = timer_hw->timelr; + uint32_t hi = timer_hw->timehr; + spin_unlock(spinlock_time_, irq_state); + return ((uint64_t) hi << 32u) | lo;; + } + + void timer_irq_handler() + { + hw_clear_bits(&timer_hw->intr, 1u << alarm_num_); uint64_t now = get_time_64_us(); uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); - for (auto& task : delayed_tasks_) + for (auto& task : task_queue_delayed_) { if (task.function && task.target_time <= now) { @@ -88,339 +269,531 @@ namespace Core1 { } } - auto it = std::min_element(delayed_tasks_.begin(), delayed_tasks_.end(), [](const DelayedTask& a, const DelayedTask& b) + int64_t next_target_time = get_next_target_time_unsafe(task_queue_delayed_); + if (next_target_time >= 0) { + timer_hw->alarm[alarm_num_] = static_cast(next_target_time); + } + + spin_unlock(spinlock_delayed_, irq_state); + } + + static inline int64_t get_next_target_time_unsafe(std::array& task_queue_delayed) + { + auto it = std::min_element(task_queue_delayed.begin(), task_queue_delayed.end(), [](const DelayedTask& a, const DelayedTask& b) + { + //Get task with the earliest target time return a.function && (!b.function || a.target_time < b.target_time); }); - if (it != delayed_tasks_.end() && it->function) + if (it != task_queue_delayed.end() && it->function) { - timer_hw->alarm[ALARM_NUM] = static_cast(it->target_time); + return static_cast(it->target_time); } - - spin_unlock(spinlock_delayed_, irq_state); + return -1; } +}; - bool queue_delayed_task(uint32_t task_id, uint32_t delay_ms, bool repeating, const std::function& function) +CoreQueue* CoreQueue::instances_[static_cast(CoreQueue::CoreNum::Core1) + 1]{nullptr}; + +namespace Core0 +{ + static inline CoreQueue& get_core_0() { - uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); - for (const auto& task : delayed_tasks_) - { - if (task.task_id == task_id) - { - spin_unlock(spinlock_delayed_, irq_state); - return false; - } - } - spin_unlock(spinlock_delayed_, irq_state); - - hw_set_bits(&timer_hw->inte, 1u << ALARM_NUM); - - if (!delay_irq_set_) - { - delay_irq_set_ = true; - irq_set_exclusive_handler(TIMER_IRQ(ALARM_NUM), timer_irq_handler); - irq_set_enabled(TIMER_IRQ(ALARM_NUM), true); - } - - irq_state = spin_lock_blocking(spinlock_delayed_); - - uint64_t target_time = timer_hw->timerawl + static_cast(delay_ms) * 1000; - - for (auto& task : delayed_tasks_) - { - if (!task.function) - { - task.target_time = target_time; - task.interval_ms = repeating ? delay_ms : 0; - task.function = function; - task.task_id = task_id; - - auto it = std::min_element(delayed_tasks_.begin(), delayed_tasks_.end(), [](const DelayedTask& a, const DelayedTask& b) - { - return a.function && (!b.function || a.target_time < b.target_time); - }); - - if (it != delayed_tasks_.end() && it->function) - { - timer_hw->alarm[ALARM_NUM] = static_cast(it->target_time); - } - - spin_unlock(spinlock_delayed_, irq_state); - return true; - } - } - - spin_unlock(spinlock_delayed_, irq_state); - return false; + static CoreQueue core(CoreQueue::CoreNum::Core0); + return core; } - - void cancel_delayed_task(uint32_t task_id) - { - uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); - bool found = false; - - for (auto& task : delayed_tasks_) - { - if (task.task_id == task_id) - { - task.function = nullptr; - task.task_id = 0; - found = true; - } - } - - if (!found || !delay_irq_set_) - { - spin_unlock(spinlock_delayed_, irq_state); - return; - } - - hw_set_bits(&timer_hw->inte, 1u << ALARM_NUM); - - auto it = std::min_element(delayed_tasks_.begin(), delayed_tasks_.end(), [](const DelayedTask& a, const DelayedTask& b) - { - return a.function && (!b.function || a.target_time < b.target_time); - }); - - if (it != delayed_tasks_.end() && it->function) - { - timer_hw->alarm[ALARM_NUM] = static_cast(it->target_time); - } - - spin_unlock(spinlock_delayed_, irq_state); - } - - bool queue_task(const std::function& function) - { - uint32_t irq_state = spin_lock_blocking(spinlock_); - for (auto& task : tasks_) - { - if (!task.function) - { - task.function = function; - spin_unlock(spinlock_, irq_state); - return true; - } - } - spin_unlock(spinlock_, irq_state); - return false; - } - - void process_tasks() - { - uint32_t irq_state = spin_lock_blocking(spinlock_); - for (auto& task : tasks_) - { - if (task.function) - { - auto function = task.function; - task.function = nullptr; - spin_unlock(spinlock_, irq_state); - - function(); - - irq_state = spin_lock_blocking(spinlock_); - } - else - { - break; //No more tasks - } - } - spin_unlock(spinlock_, irq_state); - } - -} // namespace Core1 - -namespace Core0 { - - static constexpr uint32_t CORE = 0; - static constexpr uint32_t ALARM_NUM = CORE; - - static std::array tasks_; - static std::array delayed_tasks_; - - static bool delay_irq_set_ = false; - static uint32_t new_task_id_ = 1; - - static spin_lock_t* spinlock_ = spin_lock_instance(CORE); - static spin_lock_t* spinlock_delayed_ = spin_lock_instance(CORE + 2); - uint32_t get_new_task_id() { - return new_task_id_++; + return get_core_0().get_new_task_id(); } - - static void timer_irq_handler() - { - hw_clear_bits(&timer_hw->intr, 1u << ALARM_NUM); - - uint64_t now = get_time_64_us(); - uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); - - for (auto& task : delayed_tasks_) - { - if (task.function && task.target_time <= now) - { - auto function = task.function; - if (task.interval_ms) - { - task.target_time += (task.interval_ms * 1000); - } - else - { - task.function = nullptr; - task.task_id = 0; - } - - spin_unlock(spinlock_delayed_, irq_state); - queue_task(function); - irq_state = spin_lock_blocking(spinlock_delayed_); - } - } - - auto it = std::min_element(delayed_tasks_.begin(), delayed_tasks_.end(), [](const DelayedTask& a, const DelayedTask& b) - { - return a.function && (!b.function || a.target_time < b.target_time); - }); - - if (it != delayed_tasks_.end() && it->function) - { - timer_hw->alarm[ALARM_NUM] = static_cast(it->target_time); - } - - spin_unlock(spinlock_delayed_, irq_state); - } - - bool queue_delayed_task(uint32_t task_id, uint32_t delay_ms, bool repeating, const std::function& function) - { - uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); - for (const auto& task : delayed_tasks_) - { - if (task.task_id == task_id) - { - spin_unlock(spinlock_delayed_, irq_state); - return false; - } - } - spin_unlock(spinlock_delayed_, irq_state); - - hw_set_bits(&timer_hw->inte, 1u << ALARM_NUM); - - if (!delay_irq_set_) - { - delay_irq_set_ = true; - irq_set_exclusive_handler(TIMER_IRQ(ALARM_NUM), timer_irq_handler); - irq_set_enabled(TIMER_IRQ(ALARM_NUM), true); - } - - irq_state = spin_lock_blocking(spinlock_delayed_); - - uint64_t target_time = timer_hw->timerawl + static_cast(delay_ms) * 1000; - - for (auto& task : delayed_tasks_) - { - if (!task.function) - { - task.target_time = target_time; - task.interval_ms = repeating ? delay_ms : 0; - task.function = function; - task.task_id = task_id; - - auto it = std::min_element(delayed_tasks_.begin(), delayed_tasks_.end(), [](const DelayedTask& a, const DelayedTask& b) - { - return a.function && (!b.function || a.target_time < b.target_time); - }); - - if (it != delayed_tasks_.end() && it->function) - { - timer_hw->alarm[ALARM_NUM] = static_cast(it->target_time); - } - - spin_unlock(spinlock_delayed_, irq_state); - return true; - } - } - - spin_unlock(spinlock_delayed_, irq_state); - return false; - } - void cancel_delayed_task(uint32_t task_id) { - uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); - bool found = false; - - for (auto& task : delayed_tasks_) - { - if (task.task_id == task_id) - { - task.function = nullptr; - task.task_id = 0; - found = true; - } - } - - if (!found || !delay_irq_set_) - { - spin_unlock(spinlock_delayed_, irq_state); - return; - } - - hw_set_bits(&timer_hw->inte, 1u << ALARM_NUM); - - auto it = std::min_element(delayed_tasks_.begin(), delayed_tasks_.end(), [](const DelayedTask& a, const DelayedTask& b) - { - return a.function && (!b.function || a.target_time < b.target_time); - }); - - if (it != delayed_tasks_.end() && it->function) - { - timer_hw->alarm[ALARM_NUM] = static_cast(it->target_time); - } - - spin_unlock(spinlock_delayed_, irq_state); + get_core_0().cancel_delayed_task(task_id); + } + bool queue_delayed_task(uint32_t task_id, uint32_t delay_ms, bool repeating, const std::function& function) + { + return get_core_0().queue_delayed_task(task_id, delay_ms, repeating, function); } - bool queue_task(const std::function& function) { - uint32_t irq_state = spin_lock_blocking(spinlock_); - for (auto& task : tasks_) - { - if (!task.function) - { - task.function = function; - spin_unlock(spinlock_, irq_state); - return true; - } - } - spin_unlock(spinlock_, irq_state); - return false; + return get_core_0().queue_task(function); } - void process_tasks() { - uint32_t irq_state = spin_lock_blocking(spinlock_); - for (auto& task : tasks_) - { - if (task.function) - { - auto function = task.function; - task.function = nullptr; - spin_unlock(spinlock_, irq_state); - - function(); - - irq_state = spin_lock_blocking(spinlock_); - } - else - { - break; //No more tasks - } - } - spin_unlock(spinlock_, irq_state); + get_core_0().process_tasks(); } +} -} // namespace Core0 +#if OGXM_BOARD != PI_PICOW -} // namespace TaskQueue \ No newline at end of file +namespace Core1 +{ + static inline CoreQueue& get_core_1() + { + static CoreQueue core(CoreQueue::CoreNum::Core1); + return core; + } + uint32_t get_new_task_id() + { + return get_core_1().get_new_task_id(); + } + void cancel_delayed_task(uint32_t task_id) + { + get_core_1().cancel_delayed_task(task_id); + } + bool queue_delayed_task(uint32_t task_id, uint32_t delay_ms, bool repeating, const std::function& function) + { + return get_core_1().queue_delayed_task(task_id, delay_ms, repeating, function); + } + bool queue_task(const std::function& function) + { + return get_core_1().queue_task(function); + } + void process_tasks() + { + get_core_1().process_tasks(); + } +} + +#endif // OGXM_BOARD != PI_PICOW + +} // namespace TaskQueue + +// #include +// #include +// #include +// #include +// #include +// #include + +// #include "Board/board_api.h" +// #include "TaskQueue/TaskQueue.h" + +// namespace TaskQueue { + +// struct Task +// { +// // uint32_t task_id = 0; +// std::function function = nullptr; +// }; + +// struct DelayedTask +// { +// uint32_t task_id = 0; +// uint32_t interval_ms = 0; +// uint64_t target_time = 0; +// std::function function = nullptr; +// }; + +// static constexpr uint8_t MAX_TASKS = 8; +// static constexpr uint8_t MAX_DELAYED_TASKS = MAX_TASKS * 2; + +// static inline uint32_t TIMER_IRQ(int alarm_num) +// { +// return timer_hardware_alarm_get_irq_num(timer_hw, alarm_num); +// } + +// static uint64_t get_time_64_us() +// { +// static spin_lock_t* spinlock_64_us = spin_lock_instance(4); +// uint32_t irq_state = spin_lock_blocking(spinlock_64_us); +// uint32_t lo = timer_hw->timelr; +// uint32_t hi = timer_hw->timehr; +// spin_unlock(spinlock_64_us, irq_state); +// return ((uint64_t) hi << 32u) | lo;; +// } + +// #if OGXM_BOARD != PI_PICOW + +// namespace Core1 { + +// static constexpr uint32_t ALARM_NUM = 1; + +// static std::array tasks_; +// static std::array delayed_tasks_; + +// static bool delay_irq_set_ = false; +// static uint32_t new_task_id_ = 1; + +// static spin_lock_t* spinlock_ = spin_lock_instance(1); +// static spin_lock_t* spinlock_delayed_ = spin_lock_instance(2); + +// bool queue_task(const std::function& function); + +// uint32_t get_new_task_id() +// { +// return new_task_id_++; +// } + +// static void timer_irq_handler() +// { +// hw_clear_bits(&timer_hw->intr, 1u << ALARM_NUM); + +// uint64_t now = get_time_64_us(); +// uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); + +// for (auto& task : delayed_tasks_) +// { +// if (task.function && task.target_time <= now) +// { +// auto function = task.function; +// if (task.interval_ms) +// { +// task.target_time += (task.interval_ms * 1000); +// } +// else +// { +// task.function = nullptr; +// task.task_id = 0; +// } + +// spin_unlock(spinlock_delayed_, irq_state); +// queue_task(function); +// irq_state = spin_lock_blocking(spinlock_delayed_); +// } +// } + +// auto it = std::min_element(delayed_tasks_.begin(), delayed_tasks_.end(), [](const DelayedTask& a, const DelayedTask& b) +// { +// //Get task with the earliest target time +// return a.function && (!b.function || a.target_time < b.target_time); +// }); + +// if (it != delayed_tasks_.end() && it->function) +// { +// timer_hw->alarm[ALARM_NUM] = static_cast(it->target_time); +// } + +// spin_unlock(spinlock_delayed_, irq_state); +// } + +// bool queue_delayed_task(uint32_t task_id, uint32_t delay_ms, bool repeating, const std::function& function) +// { +// uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); +// for (const auto& task : delayed_tasks_) +// { +// if (task.task_id == task_id) +// { +// spin_unlock(spinlock_delayed_, irq_state); +// return false; +// } +// } +// spin_unlock(spinlock_delayed_, irq_state); + +// hw_set_bits(&timer_hw->inte, 1u << ALARM_NUM); + +// if (!delay_irq_set_) +// { +// delay_irq_set_ = true; +// irq_set_exclusive_handler(TIMER_IRQ(ALARM_NUM), timer_irq_handler); +// irq_set_enabled(TIMER_IRQ(ALARM_NUM), true); +// } + +// irq_state = spin_lock_blocking(spinlock_delayed_); + +// //Might come back to this, there is overflow potential +// uint64_t target_time = timer_hw->timerawl + static_cast(delay_ms) * 1000; + +// for (auto& task : delayed_tasks_) +// { +// if (!task.function) +// { +// task.target_time = target_time; +// task.interval_ms = repeating ? delay_ms : 0; +// task.function = function; +// task.task_id = task_id; + +// auto it = std::min_element(delayed_tasks_.begin(), delayed_tasks_.end(), [](const DelayedTask& a, const DelayedTask& b) +// { +// return a.function && (!b.function || a.target_time < b.target_time); +// }); + +// if (it != delayed_tasks_.end() && it->function) +// { +// timer_hw->alarm[ALARM_NUM] = static_cast(it->target_time); +// } + +// spin_unlock(spinlock_delayed_, irq_state); +// return true; +// } +// } + +// spin_unlock(spinlock_delayed_, irq_state); +// return false; +// } + +// void cancel_delayed_task(uint32_t task_id) +// { +// uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); +// bool found = false; + +// for (auto& task : delayed_tasks_) +// { +// if (task.task_id == task_id) +// { +// task.function = nullptr; +// task.task_id = 0; +// found = true; +// } +// } + +// if (!found || !delay_irq_set_) +// { +// spin_unlock(spinlock_delayed_, irq_state); +// return; +// } + +// hw_set_bits(&timer_hw->inte, 1u << ALARM_NUM); + +// auto it = std::min_element(delayed_tasks_.begin(), delayed_tasks_.end(), [](const DelayedTask& a, const DelayedTask& b) +// { +// return a.function && (!b.function || a.target_time < b.target_time); +// }); + +// if (it != delayed_tasks_.end() && it->function) +// { +// timer_hw->alarm[ALARM_NUM] = static_cast(it->target_time); +// } + +// spin_unlock(spinlock_delayed_, irq_state); +// } + +// bool queue_task(const std::function& function) +// { +// uint32_t irq_state = spin_lock_blocking(spinlock_); +// for (auto& task : tasks_) +// { +// if (!task.function) +// { +// task.function = function; +// spin_unlock(spinlock_, irq_state); +// return true; +// } +// } +// spin_unlock(spinlock_, irq_state); +// return false; +// } + +// void process_tasks() +// { +// uint32_t irq_state = spin_lock_blocking(spinlock_); +// for (auto& task : tasks_) +// { +// if (task.function) +// { +// auto function = task.function; +// task.function = nullptr; +// spin_unlock(spinlock_, irq_state); + +// function(); + +// irq_state = spin_lock_blocking(spinlock_); +// } +// else +// { +// break; //No more tasks +// } +// } +// spin_unlock(spinlock_, irq_state); +// } + +// } // namespace Core1 + +// #endif // OGXM_BOARD != PI_PICOW + +// namespace Core0 { + +// #if OGXM_BOARD == PI_PICOW +// static constexpr uint32_t ALARM_NUM = 1; +// #else +// static constexpr uint32_t ALARM_NUM = 0; +// #endif + +// static std::array tasks_; +// static std::array delayed_tasks_; + +// static bool delay_irq_set_ = false; +// static uint32_t new_task_id_ = 1; + +// static spin_lock_t* spinlock_ = spin_lock_instance(3); +// static spin_lock_t* spinlock_delayed_ = spin_lock_instance(4); + +// uint32_t get_new_task_id() +// { +// return new_task_id_++; +// } + +// static void timer_irq_handler() +// { +// hw_clear_bits(&timer_hw->intr, 1u << ALARM_NUM); + +// uint64_t now = get_time_64_us(); +// uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); + +// for (auto& task : delayed_tasks_) +// { +// if (task.function && task.target_time <= now) +// { +// auto function = task.function; +// if (task.interval_ms) +// { +// task.target_time += (task.interval_ms * 1000); +// } +// else +// { +// task.function = nullptr; +// task.task_id = 0; +// } + +// spin_unlock(spinlock_delayed_, irq_state); +// queue_task(function); +// irq_state = spin_lock_blocking(spinlock_delayed_); +// } +// } + +// auto it = std::min_element(delayed_tasks_.begin(), delayed_tasks_.end(), [](const DelayedTask& a, const DelayedTask& b) +// { +// return a.function && (!b.function || a.target_time < b.target_time); +// }); + +// if (it != delayed_tasks_.end() && it->function) +// { +// timer_hw->alarm[ALARM_NUM] = static_cast(it->target_time); +// } + +// spin_unlock(spinlock_delayed_, irq_state); +// } + +// bool queue_delayed_task(uint32_t task_id, uint32_t delay_ms, bool repeating, const std::function& function) +// { +// uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); +// for (const auto& task : delayed_tasks_) +// { +// if (task.task_id == task_id) +// { +// spin_unlock(spinlock_delayed_, irq_state); +// return false; +// } +// } +// spin_unlock(spinlock_delayed_, irq_state); + +// hw_set_bits(&timer_hw->inte, 1u << ALARM_NUM); + +// if (!delay_irq_set_) +// { +// delay_irq_set_ = true; +// irq_set_exclusive_handler(TIMER_IRQ(ALARM_NUM), timer_irq_handler); +// irq_set_enabled(TIMER_IRQ(ALARM_NUM), true); +// } + +// irq_state = spin_lock_blocking(spinlock_delayed_); + +// uint64_t target_time = timer_hw->timerawl + static_cast(delay_ms) * 1000; + +// for (auto& task : delayed_tasks_) +// { +// if (!task.function) +// { +// task.target_time = target_time; +// task.interval_ms = repeating ? delay_ms : 0; +// task.function = function; +// task.task_id = task_id; + +// auto it = std::min_element(delayed_tasks_.begin(), delayed_tasks_.end(), [](const DelayedTask& a, const DelayedTask& b) +// { +// return a.function && (!b.function || a.target_time < b.target_time); +// }); + +// if (it != delayed_tasks_.end() && it->function) +// { +// timer_hw->alarm[ALARM_NUM] = static_cast(it->target_time); +// } + +// spin_unlock(spinlock_delayed_, irq_state); +// return true; +// } +// } + +// spin_unlock(spinlock_delayed_, irq_state); +// return false; +// } + +// void cancel_delayed_task(uint32_t task_id) +// { +// uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); +// bool found = false; + +// for (auto& task : delayed_tasks_) +// { +// if (task.task_id == task_id) +// { +// task.function = nullptr; +// task.task_id = 0; +// found = true; +// } +// } + +// if (!found || !delay_irq_set_) +// { +// spin_unlock(spinlock_delayed_, irq_state); +// return; +// } + +// hw_set_bits(&timer_hw->inte, 1u << ALARM_NUM); + +// auto it = std::min_element(delayed_tasks_.begin(), delayed_tasks_.end(), [](const DelayedTask& a, const DelayedTask& b) +// { +// return a.function && (!b.function || a.target_time < b.target_time); +// }); + +// if (it != delayed_tasks_.end() && it->function) +// { +// timer_hw->alarm[ALARM_NUM] = static_cast(it->target_time); +// } + +// spin_unlock(spinlock_delayed_, irq_state); +// } + +// bool queue_task(const std::function& function) +// { +// uint32_t irq_state = spin_lock_blocking(spinlock_); +// for (auto& task : tasks_) +// { +// if (!task.function) +// { +// task.function = function; +// spin_unlock(spinlock_, irq_state); +// return true; +// } +// } +// spin_unlock(spinlock_, irq_state); +// return false; +// } + +// void process_tasks() +// { +// uint32_t irq_state = spin_lock_blocking(spinlock_); +// for (auto& task : tasks_) +// { +// if (task.function) +// { +// auto function = task.function; +// task.function = nullptr; +// spin_unlock(spinlock_, irq_state); + +// function(); + +// irq_state = spin_lock_blocking(spinlock_); +// } +// else +// { +// break; //No more tasks +// } +// } +// spin_unlock(spinlock_, irq_state); +// } + +// } // namespace Core0 + +// } // namespace TaskQueue \ No newline at end of file diff --git a/Firmware/RP2040/src/TaskQueue/TaskQueue.h b/Firmware/RP2040/src/TaskQueue/TaskQueue.h index 6d416a1..15b2b10 100644 --- a/Firmware/RP2040/src/TaskQueue/TaskQueue.h +++ b/Firmware/RP2040/src/TaskQueue/TaskQueue.h @@ -4,7 +4,10 @@ #include #include -/* Queue tasks to be executed with process_tasks() */ +#include "board_config.h" + +/* Queue tasks to be executed with process_tasks() in the main loop on either core. + Don't use this on the core running BTStack, that is not safe. */ namespace TaskQueue { namespace Core0 @@ -16,6 +19,7 @@ namespace TaskQueue void process_tasks(); } +#if OGXM_BOARD != PI_PICOW namespace Core1 { uint32_t get_new_task_id(); @@ -24,6 +28,7 @@ namespace TaskQueue bool queue_task(const std::function& function); void process_tasks(); } +#endif // OGXM_BOARD != PI_PICOW } // namespace TaskQueue diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/DInput/DInput.cpp b/Firmware/RP2040/src/USBDevice/DeviceDriver/DInput/DInput.cpp index c650496..2665cdd 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/DInput/DInput.cpp +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/DInput/DInput.cpp @@ -20,7 +20,7 @@ void DInputDevice::initialize() { for (auto& in_report : in_reports_) { - std::memset(&in_report, 0, sizeof(DInput::InReport)); + std::memset(reinterpret_cast(&in_report), 0, sizeof(DInput::InReport)); in_report.dpad = DInput::DPad::CENTER; in_report.joystick_lx = DInput::AXIS_MID; in_report.joystick_ly = DInput::AXIS_MID; @@ -29,10 +29,9 @@ void DInputDevice::initialize() } class_driver_ = { - #if CFG_TUSB_DEBUG >= 2 - .name = "HID", - #endif + .name = TUD_DRV_NAME("HID"), .init = hidd_init, + .deinit = hidd_deinit, .reset = hidd_reset, .open = hidd_open, .control_xfer_cb = DInputDevice::control_xfer_cb, @@ -43,84 +42,84 @@ void DInputDevice::initialize() void DInputDevice::process(const uint8_t idx, Gamepad& gamepad) { - if (!gamepad.new_pad_in()) - { - return; - } - Gamepad::PadIn gp_in = gamepad.get_pad_in(); DInput::InReport& in_report = in_reports_[idx]; - switch (gp_in.dpad) + if (gamepad.new_pad_in()) { - case Gamepad::DPAD_UP: - in_report.dpad = DInput::DPad::UP; - break; - case Gamepad::DPAD_DOWN: - in_report.dpad = DInput::DPad::DOWN; - break; - case Gamepad::DPAD_LEFT: - in_report.dpad = DInput::DPad::LEFT; - break; - case Gamepad::DPAD_RIGHT: - in_report.dpad = DInput::DPad::RIGHT; - break; - case Gamepad::DPAD_UP_LEFT: - in_report.dpad = DInput::DPad::UP_LEFT; - break; - case Gamepad::DPAD_UP_RIGHT: - in_report.dpad = DInput::DPad::UP_RIGHT; - break; - case Gamepad::DPAD_DOWN_LEFT: - in_report.dpad = DInput::DPad::DOWN_LEFT; - break; - case Gamepad::DPAD_DOWN_RIGHT: - in_report.dpad = DInput::DPad::DOWN_RIGHT; - break; - default: - in_report.dpad = DInput::DPad::CENTER; - break; + Gamepad::PadIn gp_in = gamepad.get_pad_in(); + + switch (gp_in.dpad) + { + case Gamepad::DPAD_UP: + in_report.dpad = DInput::DPad::UP; + break; + case Gamepad::DPAD_DOWN: + in_report.dpad = DInput::DPad::DOWN; + break; + case Gamepad::DPAD_LEFT: + in_report.dpad = DInput::DPad::LEFT; + break; + case Gamepad::DPAD_RIGHT: + in_report.dpad = DInput::DPad::RIGHT; + break; + case Gamepad::DPAD_UP_LEFT: + in_report.dpad = DInput::DPad::UP_LEFT; + break; + case Gamepad::DPAD_UP_RIGHT: + in_report.dpad = DInput::DPad::UP_RIGHT; + break; + case Gamepad::DPAD_DOWN_LEFT: + in_report.dpad = DInput::DPad::DOWN_LEFT; + break; + case Gamepad::DPAD_DOWN_RIGHT: + in_report.dpad = DInput::DPad::DOWN_RIGHT; + break; + default: + in_report.dpad = DInput::DPad::CENTER; + break; + } + + std::memset(in_report.buttons, 0, sizeof(in_report.buttons)); + + if (gp_in.buttons & Gamepad::BUTTON_A) in_report.buttons[0] |= DInput::Buttons0::CROSS; + if (gp_in.buttons & Gamepad::BUTTON_B) in_report.buttons[0] |= DInput::Buttons0::CIRCLE; + if (gp_in.buttons & Gamepad::BUTTON_X) in_report.buttons[0] |= DInput::Buttons0::SQUARE; + if (gp_in.buttons & Gamepad::BUTTON_Y) in_report.buttons[0] |= DInput::Buttons0::TRIANGLE; + if (gp_in.buttons & Gamepad::BUTTON_LB) in_report.buttons[0] |= DInput::Buttons0::L1; + if (gp_in.buttons & Gamepad::BUTTON_RB) in_report.buttons[0] |= DInput::Buttons0::R1; + + if (gp_in.buttons & Gamepad::BUTTON_L3) in_report.buttons[1] |= DInput::Buttons1::L3; + if (gp_in.buttons & Gamepad::BUTTON_R3) in_report.buttons[1] |= DInput::Buttons1::R3; + if (gp_in.buttons & Gamepad::BUTTON_BACK) in_report.buttons[1] |= DInput::Buttons1::SELECT; + if (gp_in.buttons & Gamepad::BUTTON_START) in_report.buttons[1] |= DInput::Buttons1::START; + if (gp_in.buttons & Gamepad::BUTTON_SYS) in_report.buttons[1] |= DInput::Buttons1::PS; + if (gp_in.buttons & Gamepad::BUTTON_MISC) in_report.buttons[1] |= DInput::Buttons1::TP; + + if (gamepad.analog_enabled()) + { + in_report.up_axis = gp_in.analog[Gamepad::ANALOG_OFF_UP]; + in_report.down_axis = gp_in.analog[Gamepad::ANALOG_OFF_DOWN]; + in_report.right_axis = gp_in.analog[Gamepad::ANALOG_OFF_RIGHT]; + in_report.left_axis = gp_in.analog[Gamepad::ANALOG_OFF_LEFT]; + + in_report.triangle_axis = gp_in.analog[Gamepad::ANALOG_OFF_Y]; + in_report.circle_axis = gp_in.analog[Gamepad::ANALOG_OFF_X]; + in_report.cross_axis = gp_in.analog[Gamepad::ANALOG_OFF_B]; + in_report.square_axis = gp_in.analog[Gamepad::ANALOG_OFF_A]; + + in_report.r1_axis = gp_in.analog[Gamepad::ANALOG_OFF_RB]; + in_report.l1_axis = gp_in.analog[Gamepad::ANALOG_OFF_LB]; + } + + in_report.joystick_lx = Scale::int16_to_uint8(gp_in.joystick_lx); + in_report.joystick_ly = Scale::int16_to_uint8(gp_in.joystick_ly); + in_report.joystick_rx = Scale::int16_to_uint8(gp_in.joystick_rx); + in_report.joystick_ry = Scale::int16_to_uint8(gp_in.joystick_ry); + + in_report.l2_axis = gp_in.trigger_l; + in_report.r2_axis = gp_in.trigger_r; } - std::memset(in_report.buttons, 0, sizeof(in_report.buttons)); - - if (gp_in.buttons & Gamepad::BUTTON_A) in_report.buttons[0] |= DInput::Buttons0::CROSS; - if (gp_in.buttons & Gamepad::BUTTON_B) in_report.buttons[0] |= DInput::Buttons0::CIRCLE; - if (gp_in.buttons & Gamepad::BUTTON_X) in_report.buttons[0] |= DInput::Buttons0::SQUARE; - if (gp_in.buttons & Gamepad::BUTTON_Y) in_report.buttons[0] |= DInput::Buttons0::TRIANGLE; - if (gp_in.buttons & Gamepad::BUTTON_LB) in_report.buttons[0] |= DInput::Buttons0::L1; - if (gp_in.buttons & Gamepad::BUTTON_RB) in_report.buttons[0] |= DInput::Buttons0::R1; - - if (gp_in.buttons & Gamepad::BUTTON_L3) in_report.buttons[1] |= DInput::Buttons1::L3; - if (gp_in.buttons & Gamepad::BUTTON_R3) in_report.buttons[1] |= DInput::Buttons1::R3; - if (gp_in.buttons & Gamepad::BUTTON_BACK) in_report.buttons[1] |= DInput::Buttons1::SELECT; - if (gp_in.buttons & Gamepad::BUTTON_START) in_report.buttons[1] |= DInput::Buttons1::START; - if (gp_in.buttons & Gamepad::BUTTON_SYS) in_report.buttons[1] |= DInput::Buttons1::PS; - if (gp_in.buttons & Gamepad::BUTTON_MISC) in_report.buttons[1] |= DInput::Buttons1::TP; - - if (gamepad.analog_enabled()) - { - in_report.up_axis = gp_in.analog[Gamepad::ANALOG_OFF_UP]; - in_report.down_axis = gp_in.analog[Gamepad::ANALOG_OFF_DOWN]; - in_report.right_axis = gp_in.analog[Gamepad::ANALOG_OFF_RIGHT]; - in_report.left_axis = gp_in.analog[Gamepad::ANALOG_OFF_LEFT]; - - in_report.triangle_axis = gp_in.analog[Gamepad::ANALOG_OFF_Y]; - in_report.circle_axis = gp_in.analog[Gamepad::ANALOG_OFF_X]; - in_report.cross_axis = gp_in.analog[Gamepad::ANALOG_OFF_B]; - in_report.square_axis = gp_in.analog[Gamepad::ANALOG_OFF_A]; - - in_report.r1_axis = gp_in.analog[Gamepad::ANALOG_OFF_RB]; - in_report.l1_axis = gp_in.analog[Gamepad::ANALOG_OFF_LB]; - } - - in_report.joystick_lx = Scale::int16_to_uint8(gp_in.joystick_lx); - in_report.joystick_ly = Scale::int16_to_uint8(gp_in.joystick_ly); - in_report.joystick_rx = Scale::int16_to_uint8(gp_in.joystick_rx); - in_report.joystick_ry = Scale::int16_to_uint8(gp_in.joystick_ry); - - in_report.l2_axis = gp_in.trigger_l; - in_report.r2_axis = gp_in.trigger_r; - if (tud_suspended()) { tud_remote_wakeup(); diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/DeviceDriver.cpp b/Firmware/RP2040/src/USBDevice/DeviceDriver/DeviceDriver.cpp index ab796a2..3312af3 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/DeviceDriver.cpp +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/DeviceDriver.cpp @@ -1,3 +1,5 @@ +#include "class/cdc/cdc_device.h" +#include "bsp/board_api.h" #include "USBDevice/DeviceDriver/DeviceDriver.h" uint16_t* DeviceDriver::get_string_descriptor(const char* value, uint8_t index) diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/DeviceDriver.h b/Firmware/RP2040/src/USBDevice/DeviceDriver/DeviceDriver.h index 493ff8a..654d66a 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/DeviceDriver.h +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/DeviceDriver.h @@ -9,6 +9,12 @@ #include "Gamepad.h" +#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL + #define TUD_DRV_NAME(name) name +#else + #define TUD_DRV_NAME(name) NULL +#endif + class DeviceDriver { public: @@ -28,7 +34,7 @@ public: }; virtual void initialize() = 0; - virtual void process(const uint8_t idx, Gamepad& gamepad) = 0; + virtual void process(const uint8_t idx, Gamepad& gamepad) = 0; virtual uint16_t get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t req_len) = 0; virtual void set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t buffer_size) = 0; virtual bool vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) = 0; diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/PS3/PS3.cpp b/Firmware/RP2040/src/USBDevice/DeviceDriver/PS3/PS3.cpp index ca2f57d..bbf6e4c 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/PS3/PS3.cpp +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/PS3/PS3.cpp @@ -1,4 +1,5 @@ #include +#include #include "USBDevice/DeviceDriver/PS3/PS3.h" @@ -6,9 +7,7 @@ void PS3Device::initialize() { class_driver_ = { - #if CFG_TUSB_DEBUG >= 2 - .name = "PS3", - #endif + .name = TUD_DRV_NAME("PS3"), .init = hidd_init, .deinit = hidd_deinit, .reset = hidd_reset, @@ -17,25 +16,6 @@ void PS3Device::initialize() .xfer_cb = hidd_xfer_cb, .sof = NULL }; - - in_report_ = PS3::InReport(); - - // bt_info_ = - // { - // .reserved0 = {0xFF,0xFF}, - // .device_address = { 0x00, 0x20, 0x40, 0xCE, 0x00, 0x00, 0x00 }, - // .host_address = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - // }; - - // for (uint8_t addr = 0; addr < 3; addr++) - // { - // bt_info_.device_address[4 + addr] = static_cast(get_rand_32() % 0xFF); - // } - - // for (uint8_t addr = 0; addr < 6; addr++) - // { - // bt_info_.host_address[1 + addr] = static_cast(get_rand_32() % 0xFF); - // } } void PS3Device::process(const uint8_t idx, Gamepad& gamepad) @@ -43,180 +23,117 @@ void PS3Device::process(const uint8_t idx, Gamepad& gamepad) if (gamepad.new_pad_in()) { Gamepad::PadIn gp_in = gamepad.get_pad_in(); - std::memset(in_report_.buttons, 0, sizeof(in_report_.buttons)); + report_in_ = PS3::InReport(); switch (gp_in.dpad) { case Gamepad::DPAD_UP: - in_report_.buttons[0] = PS3::Buttons0::DPAD_UP; + report_in_.buttons[0] = PS3::Buttons0::DPAD_UP; break; case Gamepad::DPAD_DOWN: - in_report_.buttons[0] = PS3::Buttons0::DPAD_DOWN; + report_in_.buttons[0] = PS3::Buttons0::DPAD_DOWN; break; case Gamepad::DPAD_LEFT: - in_report_.buttons[0] = PS3::Buttons0::DPAD_LEFT; + report_in_.buttons[0] = PS3::Buttons0::DPAD_LEFT; break; case Gamepad::DPAD_RIGHT: - in_report_.buttons[0] = PS3::Buttons0::DPAD_RIGHT; + report_in_.buttons[0] = PS3::Buttons0::DPAD_RIGHT; break; case Gamepad::DPAD_UP_LEFT: - in_report_.buttons[0] = PS3::Buttons0::DPAD_UP | PS3::Buttons0::DPAD_LEFT; + report_in_.buttons[0] = PS3::Buttons0::DPAD_UP | PS3::Buttons0::DPAD_LEFT; break; case Gamepad::DPAD_UP_RIGHT: - in_report_.buttons[0] = PS3::Buttons0::DPAD_UP | PS3::Buttons0::DPAD_RIGHT; + report_in_.buttons[0] = PS3::Buttons0::DPAD_UP | PS3::Buttons0::DPAD_RIGHT; break; case Gamepad::DPAD_DOWN_LEFT: - in_report_.buttons[0] = PS3::Buttons0::DPAD_DOWN | PS3::Buttons0::DPAD_LEFT; + report_in_.buttons[0] = PS3::Buttons0::DPAD_DOWN | PS3::Buttons0::DPAD_LEFT; break; case Gamepad::DPAD_DOWN_RIGHT: - in_report_.buttons[0] = PS3::Buttons0::DPAD_DOWN | PS3::Buttons0::DPAD_RIGHT; + report_in_.buttons[0] = PS3::Buttons0::DPAD_DOWN | PS3::Buttons0::DPAD_RIGHT; break; default: break; } - if (gp_in.buttons & Gamepad::BUTTON_X) in_report_.buttons[1] |= PS3::Buttons1::SQUARE; - if (gp_in.buttons & Gamepad::BUTTON_A) in_report_.buttons[1] |= PS3::Buttons1::CROSS; - if (gp_in.buttons & Gamepad::BUTTON_Y) in_report_.buttons[1] |= PS3::Buttons1::TRIANGLE; - if (gp_in.buttons & Gamepad::BUTTON_B) in_report_.buttons[1] |= PS3::Buttons1::CIRCLE; - if (gp_in.buttons & Gamepad::BUTTON_LB) in_report_.buttons[1] |= PS3::Buttons1::L1; - if (gp_in.buttons & Gamepad::BUTTON_RB) in_report_.buttons[1] |= PS3::Buttons1::R1; - if (gp_in.buttons & Gamepad::BUTTON_BACK) in_report_.buttons[0] |= PS3::Buttons0::SELECT; - if (gp_in.buttons & Gamepad::BUTTON_START) in_report_.buttons[0] |= PS3::Buttons0::START; - if (gp_in.buttons & Gamepad::BUTTON_L3) in_report_.buttons[0] |= PS3::Buttons0::L3; - if (gp_in.buttons & Gamepad::BUTTON_R3) in_report_.buttons[0] |= PS3::Buttons0::R3; - if (gp_in.buttons & Gamepad::BUTTON_SYS) in_report_.buttons[2] |= PS3::Buttons2::PS; - if (gp_in.buttons & Gamepad::BUTTON_MISC) in_report_.buttons[2] |= PS3::Buttons2::TP; + if (gp_in.buttons & Gamepad::BUTTON_X) report_in_.buttons[1] |= PS3::Buttons1::SQUARE; + if (gp_in.buttons & Gamepad::BUTTON_A) report_in_.buttons[1] |= PS3::Buttons1::CROSS; + if (gp_in.buttons & Gamepad::BUTTON_Y) report_in_.buttons[1] |= PS3::Buttons1::TRIANGLE; + if (gp_in.buttons & Gamepad::BUTTON_B) report_in_.buttons[1] |= PS3::Buttons1::CIRCLE; + if (gp_in.buttons & Gamepad::BUTTON_LB) report_in_.buttons[1] |= PS3::Buttons1::L1; + if (gp_in.buttons & Gamepad::BUTTON_RB) report_in_.buttons[1] |= PS3::Buttons1::R1; + if (gp_in.buttons & Gamepad::BUTTON_BACK) report_in_.buttons[0] |= PS3::Buttons0::SELECT; + if (gp_in.buttons & Gamepad::BUTTON_START) report_in_.buttons[0] |= PS3::Buttons0::START; + if (gp_in.buttons & Gamepad::BUTTON_L3) report_in_.buttons[0] |= PS3::Buttons0::L3; + if (gp_in.buttons & Gamepad::BUTTON_R3) report_in_.buttons[0] |= PS3::Buttons0::R3; + if (gp_in.buttons & Gamepad::BUTTON_SYS) report_in_.buttons[2] |= PS3::Buttons2::PS; + if (gp_in.buttons & Gamepad::BUTTON_MISC) report_in_.buttons[2] |= PS3::Buttons2::TP; - if (gp_in.trigger_l) in_report_.buttons[1] |= PS3::Buttons1::L2; - if (gp_in.trigger_r) in_report_.buttons[1] |= PS3::Buttons1::R2; + if (gp_in.trigger_l) report_in_.buttons[1] |= PS3::Buttons1::L2; + if (gp_in.trigger_r) report_in_.buttons[1] |= PS3::Buttons1::R2; - in_report_.joystick_lx = Scale::int16_to_uint8(gp_in.joystick_lx); - in_report_.joystick_ly = Scale::int16_to_uint8(gp_in.joystick_ly); - in_report_.joystick_rx = Scale::int16_to_uint8(gp_in.joystick_rx); - in_report_.joystick_ry = Scale::int16_to_uint8(gp_in.joystick_ry); + report_in_.joystick_lx = Scale::int16_to_uint8(gp_in.joystick_lx); + report_in_.joystick_ly = Scale::int16_to_uint8(gp_in.joystick_ly); + report_in_.joystick_rx = Scale::int16_to_uint8(gp_in.joystick_rx); + report_in_.joystick_ry = Scale::int16_to_uint8(gp_in.joystick_ry); if (gamepad.analog_enabled()) { - in_report_.up_axis = gp_in.analog[Gamepad::ANALOG_OFF_UP]; - in_report_.down_axis = gp_in.analog[Gamepad::ANALOG_OFF_DOWN]; - in_report_.right_axis = gp_in.analog[Gamepad::ANALOG_OFF_RIGHT]; - in_report_.left_axis = gp_in.analog[Gamepad::ANALOG_OFF_LEFT]; + report_in_.up_axis = gp_in.analog[Gamepad::ANALOG_OFF_UP]; + report_in_.down_axis = gp_in.analog[Gamepad::ANALOG_OFF_DOWN]; + report_in_.right_axis = gp_in.analog[Gamepad::ANALOG_OFF_RIGHT]; + report_in_.left_axis = gp_in.analog[Gamepad::ANALOG_OFF_LEFT]; - in_report_.triangle_axis = gp_in.analog[Gamepad::ANALOG_OFF_Y]; - in_report_.circle_axis = gp_in.analog[Gamepad::ANALOG_OFF_B]; - in_report_.cross_axis = gp_in.analog[Gamepad::ANALOG_OFF_A]; - in_report_.square_axis = gp_in.analog[Gamepad::ANALOG_OFF_X]; + report_in_.triangle_axis = gp_in.analog[Gamepad::ANALOG_OFF_Y]; + report_in_.circle_axis = gp_in.analog[Gamepad::ANALOG_OFF_B]; + report_in_.cross_axis = gp_in.analog[Gamepad::ANALOG_OFF_A]; + report_in_.square_axis = gp_in.analog[Gamepad::ANALOG_OFF_X]; - in_report_.r1_axis = gp_in.analog[Gamepad::ANALOG_OFF_RB]; - in_report_.l1_axis = gp_in.analog[Gamepad::ANALOG_OFF_LB]; + report_in_.r1_axis = gp_in.analog[Gamepad::ANALOG_OFF_RB]; + report_in_.l1_axis = gp_in.analog[Gamepad::ANALOG_OFF_LB]; } else { - in_report_.up_axis = (gp_in.dpad & Gamepad::DPAD_UP) ? 0xFF : 0; - in_report_.down_axis = (gp_in.dpad & Gamepad::DPAD_DOWN) ? 0xFF : 0; - in_report_.right_axis = (gp_in.dpad & Gamepad::DPAD_RIGHT) ? 0xFF : 0; - in_report_.left_axis = (gp_in.dpad & Gamepad::DPAD_LEFT) ? 0xFF : 0; + report_in_.up_axis = (gp_in.dpad & Gamepad::DPAD_UP) ? 0xFF : 0; + report_in_.down_axis = (gp_in.dpad & Gamepad::DPAD_DOWN) ? 0xFF : 0; + report_in_.right_axis = (gp_in.dpad & Gamepad::DPAD_RIGHT) ? 0xFF : 0; + report_in_.left_axis = (gp_in.dpad & Gamepad::DPAD_LEFT) ? 0xFF : 0; - in_report_.triangle_axis = (gp_in.buttons & Gamepad::BUTTON_Y) ? 0xFF : 0; - in_report_.circle_axis = (gp_in.buttons & Gamepad::BUTTON_X) ? 0xFF : 0; - in_report_.cross_axis = (gp_in.buttons & Gamepad::BUTTON_B) ? 0xFF : 0; - in_report_.square_axis = (gp_in.buttons & Gamepad::BUTTON_A) ? 0xFF : 0; + report_in_.triangle_axis = (gp_in.buttons & Gamepad::BUTTON_Y) ? 0xFF : 0; + report_in_.circle_axis = (gp_in.buttons & Gamepad::BUTTON_X) ? 0xFF : 0; + report_in_.cross_axis = (gp_in.buttons & Gamepad::BUTTON_B) ? 0xFF : 0; + report_in_.square_axis = (gp_in.buttons & Gamepad::BUTTON_A) ? 0xFF : 0; - in_report_.r1_axis = (gp_in.buttons & Gamepad::BUTTON_RB) ? 0xFF : 0; - in_report_.l1_axis = (gp_in.buttons & Gamepad::BUTTON_LB) ? 0xFF : 0; - } - - if (tud_suspended()) - { - tud_remote_wakeup(); - } - - if (tud_hid_ready()) - { - tud_hid_report(0, reinterpret_cast(&in_report_), sizeof(PS3::InReport)); + report_in_.r1_axis = (gp_in.buttons & Gamepad::BUTTON_RB) ? 0xFF : 0; + report_in_.l1_axis = (gp_in.buttons & Gamepad::BUTTON_LB) ? 0xFF : 0; } } - if (new_out_report_) + if (tud_suspended()) + { + tud_remote_wakeup(); + } + + if (tud_hid_ready()) + { + //PS3 seems to start using stale data if a report isn't sent every frame + tud_hid_report(0, reinterpret_cast(&report_in_), sizeof(PS3::InReport)); + } + + if (new_report_out_) { Gamepad::PadOut gp_out; - gp_out.rumble_l = out_report_.rumble.left_motor_force; - gp_out.rumble_r = out_report_.rumble.right_motor_on ? 0xFF : 0; + gp_out.rumble_l = report_out_.rumble.left_motor_force; + gp_out.rumble_r = report_out_.rumble.right_motor_on ? UINT_8::MAX : 0; gamepad.set_pad_out(gp_out); - new_out_report_ = false; + new_report_out_ = false; } } -static constexpr uint8_t output_ps3_0x01[] = -{ - 0x01, 0x04, 0x00, 0x0b, 0x0c, 0x01, 0x02, 0x18, - 0x18, 0x18, 0x18, 0x09, 0x0a, 0x10, 0x11, 0x12, - 0x13, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x04, 0x04, - 0x04, 0x04, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, - 0x07, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -// calibration data -static constexpr uint8_t output_ps3_0xef[] = -{ - 0xef, 0x04, 0x00, 0x0b, 0x03, 0x01, 0xa0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, - 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, -}; - -// unknown -static constexpr uint8_t output_ps3_0xf5[] = -{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // host address - must match 0xf2 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -// unknown -static constexpr uint8_t output_ps3_0xf7[] = -{ - 0x02, 0x01, 0xf8, 0x02, 0xe2, 0x01, 0x05, 0xff, - 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -// unknown -static constexpr uint8_t output_ps3_0xf8[] = -{ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* Based on: https://github.com/OpenStickCommunity/GP2040-CE/blob/main/src/drivers/ps3/PS3Driver.cpp */ - uint16_t PS3Device::get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen) { if (report_type == HID_REPORT_TYPE_INPUT) { - std::memcpy(buffer, &in_report_, sizeof(PS3::InReport)); + std::memcpy(buffer, &report_in_, sizeof(PS3::InReport)); return sizeof(PS3::InReport); } else if (report_type == HID_REPORT_TYPE_FEATURE) @@ -228,43 +145,37 @@ uint16_t PS3Device::get_report_cb(uint8_t itf, uint8_t report_id, hid_report_typ { case PS3::ReportID::FEATURE_01: resp_len = reqlen; - std::memcpy(buffer, output_ps3_0x01, resp_len); + std::memcpy(buffer, PS3::OUTPUT_0x01, resp_len); return resp_len; - case PS3::ReportID::FEATURE_EF: resp_len = reqlen; - std::memcpy(buffer, output_ps3_0xef, resp_len); + std::memcpy(buffer, PS3::OUTPUT_0xEF, resp_len); buffer[6] = ef_byte_; return resp_len; - case PS3::ReportID::GET_PAIRING_INFO: resp_len = reqlen; std::memcpy(buffer, &bt_info_, resp_len); return resp_len; - case PS3::ReportID::FEATURE_F5: resp_len = reqlen; - std::memcpy(buffer, output_ps3_0xf5, resp_len); - + std::memcpy(buffer, PS3::OUTPUT_0xF5, resp_len); for (ctr = 0; ctr < 6; ctr++) { - buffer[1 + ctr] = bt_info_.host_address[ctr]; + buffer[1+ctr] = bt_info_.host_address[ctr]; } return resp_len; - case PS3::ReportID::FEATURE_F7: resp_len = reqlen; - std::memcpy(buffer, output_ps3_0xf7, resp_len); + std::memcpy(buffer, PS3::OUTPUT_0xF7, resp_len); return resp_len; - case PS3::ReportID::FEATURE_F8: resp_len = reqlen; - std::memcpy(buffer, output_ps3_0xf8, resp_len); + std::memcpy(buffer, PS3::OUTPUT_0xF8, resp_len); buffer[6] = ef_byte_; return resp_len; } } - return -1; + return 0; } void PS3Device::set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) @@ -278,7 +189,7 @@ void PS3Device::set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t break; } } - else if (report_type == HID_REPORT_TYPE_OUTPUT ) + else if (report_type == HID_REPORT_TYPE_OUTPUT) { // DS3 command uint8_t const *buf = buffer; @@ -288,12 +199,11 @@ void PS3Device::set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t bufsize = bufsize - 1; buf = &buffer[1]; } - switch(report_id) { case PS3::ReportID::FEATURE_01: - std::memcpy(&out_report_, buf, std::min(bufsize, static_cast(sizeof(PS3::OutReport)))); - new_out_report_ = true; + new_report_out_ = true; + std::memcpy(&report_out_, buf, std::min(bufsize, static_cast(sizeof(PS3::OutReport)))); break; } } diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/PS3/PS3.h b/Firmware/RP2040/src/USBDevice/DeviceDriver/PS3/PS3.h index 95d2bc1..97f511a 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/PS3/PS3.h +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/PS3/PS3.h @@ -22,11 +22,11 @@ public: const uint8_t* get_descriptor_device_qualifier_cb() override; private: - PS3::InReport in_report_; - PS3::OutReport out_report_; + PS3::InReport report_in_; + PS3::OutReport report_out_; PS3::BTInfo bt_info_; uint8_t ef_byte_; - bool new_out_report_{false}; + bool new_report_out_{false}; }; #endif // _PS3_DEVICE_H_ diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/PSClassic/PSClassic.cpp b/Firmware/RP2040/src/USBDevice/DeviceDriver/PSClassic/PSClassic.cpp index 2e4a84e..db5fdd5 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/PSClassic/PSClassic.cpp +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/PSClassic/PSClassic.cpp @@ -6,10 +6,9 @@ void PSClassicDevice::initialize() { class_driver_ = { - #if CFG_TUSB_DEBUG >= 2 - .name = "PSClassic", - #endif + .name = TUD_DRV_NAME("PSClassic"), .init = hidd_init, + .deinit = hidd_deinit, .reset = hidd_reset, .open = hidd_open, .control_xfer_cb = hidd_control_xfer_cb, @@ -20,98 +19,96 @@ void PSClassicDevice::initialize() void PSClassicDevice::process(const uint8_t idx, Gamepad& gamepad) { - if (!gamepad.new_pad_in()) + if (gamepad.new_pad_in()) { - return; - } + Gamepad::PadIn gp_in = gamepad.get_pad_in(); + switch (gp_in.dpad) + { + case Gamepad::DPAD_UP: + in_report_.buttons = PSClassic::Buttons::UP; + break; + case Gamepad::DPAD_DOWN: + in_report_.buttons = PSClassic::Buttons::DOWN; + break; + case Gamepad::DPAD_LEFT: + in_report_.buttons = PSClassic::Buttons::LEFT; + break; + case Gamepad::DPAD_RIGHT: + in_report_.buttons = PSClassic::Buttons::RIGHT; + break; + case Gamepad::DPAD_UP_LEFT: + in_report_.buttons = PSClassic::Buttons::UP_LEFT; + break; + case Gamepad::DPAD_UP_RIGHT: + in_report_.buttons = PSClassic::Buttons::UP_RIGHT; + break; + case Gamepad::DPAD_DOWN_LEFT: + in_report_.buttons = PSClassic::Buttons::DOWN_LEFT; + break; + case Gamepad::DPAD_DOWN_RIGHT: + in_report_.buttons = PSClassic::Buttons::DOWN_RIGHT; + break; + default: + in_report_.buttons = PSClassic::Buttons::CENTER; + break; + } - Gamepad::PadIn gp_in = gamepad.get_pad_in(); - switch (gp_in.dpad) - { - case Gamepad::DPAD_UP: - in_report_.buttons = PSClassic::Buttons::UP; - break; - case Gamepad::DPAD_DOWN: + int16_t joy_lx = gp_in.joystick_lx; + int16_t joy_ly = Scale::invert_joy(gp_in.joystick_ly); + int16_t joy_rx = gp_in.joystick_rx; + int16_t joy_ry = Scale::invert_joy(gp_in.joystick_ry); + + if (meets_pos_threshold(joy_lx, joy_rx)) + { + if (meets_neg_45_threshold(joy_ly, joy_ry)) + { + in_report_.buttons = PSClassic::Buttons::DOWN_RIGHT; + } + else if (meets_pos_45_threshold(joy_ly, joy_ry)) + { + in_report_.buttons = PSClassic::Buttons::UP_RIGHT; + } + else + { + in_report_.buttons = PSClassic::Buttons::RIGHT; + } + } + else if (meets_neg_threshold(joy_lx, joy_rx)) + { + if (meets_neg_45_threshold(joy_ly, joy_ry)) + { + in_report_.buttons = PSClassic::Buttons::DOWN_LEFT; + } + else if (meets_pos_45_threshold(joy_ly, joy_ry)) + { + in_report_.buttons = PSClassic::Buttons::UP_LEFT; + } + else + { + in_report_.buttons = PSClassic::Buttons::LEFT; + } + } + else if (meets_neg_threshold(joy_ly, joy_ry)) + { in_report_.buttons = PSClassic::Buttons::DOWN; - break; - case Gamepad::DPAD_LEFT: - in_report_.buttons = PSClassic::Buttons::LEFT; - break; - case Gamepad::DPAD_RIGHT: - in_report_.buttons = PSClassic::Buttons::RIGHT; - break; - case Gamepad::DPAD_UP_LEFT: - in_report_.buttons = PSClassic::Buttons::UP_LEFT; - break; - case Gamepad::DPAD_UP_RIGHT: - in_report_.buttons = PSClassic::Buttons::UP_RIGHT; - break; - case Gamepad::DPAD_DOWN_LEFT: - in_report_.buttons = PSClassic::Buttons::DOWN_LEFT; - break; - case Gamepad::DPAD_DOWN_RIGHT: - in_report_.buttons = PSClassic::Buttons::DOWN_RIGHT; - break; - default: - in_report_.buttons = PSClassic::Buttons::CENTER; - break; - } + } + else if (meets_pos_threshold(joy_ly, joy_ry)) + { + in_report_.buttons = PSClassic::Buttons::UP; + } - int16_t joy_lx = gp_in.joystick_lx; - int16_t joy_ly = Scale::invert_joy(gp_in.joystick_ly); - int16_t joy_rx = gp_in.joystick_rx; - int16_t joy_ry = Scale::invert_joy(gp_in.joystick_ry); - - if (meets_pos_threshold(joy_lx, joy_rx)) - { - if (meets_neg_45_threshold(joy_ly, joy_ry)) - { - in_report_.buttons = PSClassic::Buttons::DOWN_RIGHT; - } - else if (meets_pos_45_threshold(joy_ly, joy_ry)) - { - in_report_.buttons = PSClassic::Buttons::UP_RIGHT; - } - else - { - in_report_.buttons = PSClassic::Buttons::RIGHT; - } + if (gp_in.buttons & Gamepad::BUTTON_A) in_report_.buttons |= PSClassic::Buttons::CROSS; + if (gp_in.buttons & Gamepad::BUTTON_B) in_report_.buttons |= PSClassic::Buttons::CIRCLE; + if (gp_in.buttons & Gamepad::BUTTON_X) in_report_.buttons |= PSClassic::Buttons::SQUARE; + if (gp_in.buttons & Gamepad::BUTTON_Y) in_report_.buttons |= PSClassic::Buttons::TRIANGLE; + if (gp_in.buttons & Gamepad::BUTTON_LB) in_report_.buttons |= PSClassic::Buttons::L1; + if (gp_in.buttons & Gamepad::BUTTON_RB) in_report_.buttons |= PSClassic::Buttons::R1; + if (gp_in.buttons & Gamepad::BUTTON_BACK) in_report_.buttons |= PSClassic::Buttons::SELECT; + if (gp_in.buttons & Gamepad::BUTTON_START) in_report_.buttons |= PSClassic::Buttons::START; + + if (gp_in.trigger_l) in_report_.buttons |= PSClassic::Buttons::L2; + if (gp_in.trigger_r) in_report_.buttons |= PSClassic::Buttons::R2; } - else if (meets_neg_threshold(joy_lx, joy_rx)) - { - if (meets_neg_45_threshold(joy_ly, joy_ry)) - { - in_report_.buttons = PSClassic::Buttons::DOWN_LEFT; - } - else if (meets_pos_45_threshold(joy_ly, joy_ry)) - { - in_report_.buttons = PSClassic::Buttons::UP_LEFT; - } - else - { - in_report_.buttons = PSClassic::Buttons::LEFT; - } - } - else if (meets_neg_threshold(joy_ly, joy_ry)) - { - in_report_.buttons = PSClassic::Buttons::DOWN; - } - else if (meets_pos_threshold(joy_ly, joy_ry)) - { - in_report_.buttons = PSClassic::Buttons::UP; - } - - if (gp_in.buttons & Gamepad::BUTTON_A) in_report_.buttons |= PSClassic::Buttons::CROSS; - if (gp_in.buttons & Gamepad::BUTTON_B) in_report_.buttons |= PSClassic::Buttons::CIRCLE; - if (gp_in.buttons & Gamepad::BUTTON_X) in_report_.buttons |= PSClassic::Buttons::SQUARE; - if (gp_in.buttons & Gamepad::BUTTON_Y) in_report_.buttons |= PSClassic::Buttons::TRIANGLE; - if (gp_in.buttons & Gamepad::BUTTON_LB) in_report_.buttons |= PSClassic::Buttons::L1; - if (gp_in.buttons & Gamepad::BUTTON_RB) in_report_.buttons |= PSClassic::Buttons::R1; - if (gp_in.buttons & Gamepad::BUTTON_BACK) in_report_.buttons |= PSClassic::Buttons::SELECT; - if (gp_in.buttons & Gamepad::BUTTON_START) in_report_.buttons |= PSClassic::Buttons::START; - - if (gp_in.trigger_l) in_report_.buttons |= PSClassic::Buttons::L2; - if (gp_in.trigger_r) in_report_.buttons |= PSClassic::Buttons::R2; if (tud_suspended()) { diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/Switch/Switch.cpp b/Firmware/RP2040/src/USBDevice/DeviceDriver/Switch/Switch.cpp index f0c9cfe..df1dddd 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/Switch/Switch.cpp +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/Switch/Switch.cpp @@ -6,10 +6,9 @@ void SwitchDevice::initialize() { class_driver_ = { - #if CFG_TUSB_DEBUG >= 2 - .name = "SWITCH", - #endif + .name = TUD_DRV_NAME("SWITCH"), .init = hidd_init, + .deinit = hidd_deinit, .reset = hidd_reset, .open = hidd_open, .control_xfer_cb = hidd_control_xfer_cb, @@ -22,68 +21,67 @@ void SwitchDevice::initialize() void SwitchDevice::process(const uint8_t idx, Gamepad& gamepad) { - if (!gamepad.new_pad_in()) - { - return; - } - - Gamepad::PadIn gp_in = gamepad.get_pad_in(); SwitchWired::InReport& in_report = in_report_[idx]; - switch (gp_in.dpad) + if (gamepad.new_pad_in()) { - case Gamepad::DPAD_UP: - in_report.dpad = SwitchWired::DPad::UP; - break; - case Gamepad::DPAD_DOWN: - in_report.dpad = SwitchWired::DPad::DOWN; - break; - case Gamepad::DPAD_LEFT: - in_report.dpad = SwitchWired::DPad::LEFT; - break; - case Gamepad::DPAD_RIGHT: - in_report.dpad = SwitchWired::DPad::RIGHT; - break; - case Gamepad::DPAD_UP_LEFT: - in_report.dpad = SwitchWired::DPad::UP_LEFT; - break; - case Gamepad::DPAD_UP_RIGHT: - in_report.dpad = SwitchWired::DPad::UP_RIGHT; - break; - case Gamepad::DPAD_DOWN_LEFT: - in_report.dpad = SwitchWired::DPad::DOWN_LEFT; - break; - case Gamepad::DPAD_DOWN_RIGHT: - in_report.dpad = SwitchWired::DPad::DOWN_RIGHT; - break; - default: - in_report.dpad = SwitchWired::DPad::CENTER; - break; + Gamepad::PadIn gp_in = gamepad.get_pad_in(); + + switch (gp_in.dpad) + { + case Gamepad::DPAD_UP: + in_report.dpad = SwitchWired::DPad::UP; + break; + case Gamepad::DPAD_DOWN: + in_report.dpad = SwitchWired::DPad::DOWN; + break; + case Gamepad::DPAD_LEFT: + in_report.dpad = SwitchWired::DPad::LEFT; + break; + case Gamepad::DPAD_RIGHT: + in_report.dpad = SwitchWired::DPad::RIGHT; + break; + case Gamepad::DPAD_UP_LEFT: + in_report.dpad = SwitchWired::DPad::UP_LEFT; + break; + case Gamepad::DPAD_UP_RIGHT: + in_report.dpad = SwitchWired::DPad::UP_RIGHT; + break; + case Gamepad::DPAD_DOWN_LEFT: + in_report.dpad = SwitchWired::DPad::DOWN_LEFT; + break; + case Gamepad::DPAD_DOWN_RIGHT: + in_report.dpad = SwitchWired::DPad::DOWN_RIGHT; + break; + default: + in_report.dpad = SwitchWired::DPad::CENTER; + break; + } + + in_report.buttons = 0; + + if (gp_in.buttons & Gamepad::BUTTON_X) in_report.buttons |= SwitchWired::Buttons::Y; + if (gp_in.buttons & Gamepad::BUTTON_A) in_report.buttons |= SwitchWired::Buttons::B; + if (gp_in.buttons & Gamepad::BUTTON_Y) in_report.buttons |= SwitchWired::Buttons::X; + if (gp_in.buttons & Gamepad::BUTTON_B) in_report.buttons |= SwitchWired::Buttons::A; + if (gp_in.buttons & Gamepad::BUTTON_LB) in_report.buttons |= SwitchWired::Buttons::L; + if (gp_in.buttons & Gamepad::BUTTON_RB) in_report.buttons |= SwitchWired::Buttons::R; + if (gp_in.buttons & Gamepad::BUTTON_BACK) in_report.buttons |= SwitchWired::Buttons::MINUS; + if (gp_in.buttons & Gamepad::BUTTON_START) in_report.buttons |= SwitchWired::Buttons::PLUS; + if (gp_in.buttons & Gamepad::BUTTON_L3) in_report.buttons |= SwitchWired::Buttons::L3; + if (gp_in.buttons & Gamepad::BUTTON_R3) in_report.buttons |= SwitchWired::Buttons::R3; + if (gp_in.buttons & Gamepad::BUTTON_SYS) in_report.buttons |= SwitchWired::Buttons::HOME; + if (gp_in.buttons & Gamepad::BUTTON_MISC) in_report.buttons |= SwitchWired::Buttons::CAPTURE; + + if (gp_in.trigger_l) in_report.buttons |= SwitchWired::Buttons::ZL; + if (gp_in.trigger_r) in_report.buttons |= SwitchWired::Buttons::ZR; + + in_report.joystick_lx = Scale::int16_to_uint8(gp_in.joystick_lx); + in_report.joystick_ly = Scale::int16_to_uint8(gp_in.joystick_ly); + in_report.joystick_rx = Scale::int16_to_uint8(gp_in.joystick_rx); + in_report.joystick_ry = Scale::int16_to_uint8(gp_in.joystick_ry); } - in_report.buttons = 0; - - if (gp_in.buttons & Gamepad::BUTTON_X) in_report.buttons |= SwitchWired::Buttons::Y; - if (gp_in.buttons & Gamepad::BUTTON_A) in_report.buttons |= SwitchWired::Buttons::B; - if (gp_in.buttons & Gamepad::BUTTON_Y) in_report.buttons |= SwitchWired::Buttons::X; - if (gp_in.buttons & Gamepad::BUTTON_B) in_report.buttons |= SwitchWired::Buttons::A; - if (gp_in.buttons & Gamepad::BUTTON_LB) in_report.buttons |= SwitchWired::Buttons::L; - if (gp_in.buttons & Gamepad::BUTTON_RB) in_report.buttons |= SwitchWired::Buttons::R; - if (gp_in.buttons & Gamepad::BUTTON_BACK) in_report.buttons |= SwitchWired::Buttons::MINUS; - if (gp_in.buttons & Gamepad::BUTTON_START) in_report.buttons |= SwitchWired::Buttons::PLUS; - if (gp_in.buttons & Gamepad::BUTTON_L3) in_report.buttons |= SwitchWired::Buttons::L3; - if (gp_in.buttons & Gamepad::BUTTON_R3) in_report.buttons |= SwitchWired::Buttons::R3; - if (gp_in.buttons & Gamepad::BUTTON_SYS) in_report.buttons |= SwitchWired::Buttons::HOME; - if (gp_in.buttons & Gamepad::BUTTON_MISC) in_report.buttons |= SwitchWired::Buttons::CAPTURE; - - if (gp_in.trigger_l) in_report.buttons |= SwitchWired::Buttons::ZL; - if (gp_in.trigger_r) in_report.buttons |= SwitchWired::Buttons::ZR; - - in_report.joystick_lx = Scale::int16_to_uint8(gp_in.joystick_lx); - in_report.joystick_ly = Scale::int16_to_uint8(gp_in.joystick_ly); - in_report.joystick_rx = Scale::int16_to_uint8(gp_in.joystick_rx); - in_report.joystick_ry = Scale::int16_to_uint8(gp_in.joystick_ry); - if (tud_suspended()) { tud_remote_wakeup(); diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/UARTBridge.cpp b/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/UARTBridge.cpp index 17bca2e..9d15a37 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/UARTBridge.cpp +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/UARTBridge.cpp @@ -1,33 +1,37 @@ +#include "class/cdc/cdc_device.h" +#include "bsp/board_api.h" + +#include "Descriptors/CDCDev.h" #include "USBDevice/DeviceDriver/UARTBridge/UARTBridge.h" #include "USBDevice/DeviceDriver/UARTBridge/uart_bridge/uart_bridge.h" void UARTBridgeDevice::initialize() { - class_driver_ = { - #if CFG_TUSB_DEBUG >= 2 - .name = "UART", - #endif - .init = cdcd_init, - .reset = cdcd_reset, - .open = cdcd_open, - .control_xfer_cb = cdcd_control_xfer_cb, - .xfer_cb = cdcd_xfer_cb, - .sof = NULL - }; + class_driver_ = + { + .name = TUD_DRV_NAME("UART_BRIDGE"), + .init = cdcd_init, + .deinit = cdcd_deinit, + .reset = cdcd_reset, + .open = cdcd_open, + .control_xfer_cb = cdcd_control_xfer_cb, + .xfer_cb = cdcd_xfer_cb, + .sof = NULL + }; } void UARTBridgeDevice::process(const uint8_t idx, Gamepad& gamepad) { - if (!uart_initialized_) + if (!task_running_) { - uart_initialized_ = true; + task_running_ = true; uart_bridge_run(); } } uint16_t UARTBridgeDevice::get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen) { - return sizeof(buffer); + return reqlen; } void UARTBridgeDevice::set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) @@ -42,12 +46,47 @@ bool UARTBridgeDevice::vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tus const uint16_t * UARTBridgeDevice::get_descriptor_string_cb(uint8_t index, uint16_t langid) { - return uart_bridge_descriptor_string_cb(index, langid); + static uint16_t desc_str[32 + 1]; + size_t char_count = 0; + + switch(index) + { + case 0: + std::memcpy(&desc_str[1], CDCDesc::DESC_STRING[0], 2); + char_count = 1; + break; + + case 3: + char_count = board_usb_get_serial(&desc_str[1], 32); + break; + + default: + if (index >= sizeof(CDCDesc::DESC_STRING) / sizeof(CDCDesc::DESC_STRING[0])) + { + return nullptr; + } + const char *str = reinterpret_cast(CDCDesc::DESC_STRING[index]); + char_count = std::strlen(str); + const size_t max_count = sizeof(desc_str) / sizeof(desc_str[0]) - 1; + if (char_count > max_count) + { + char_count = max_count; + } + + for (size_t i = 0; i < char_count; i++) + { + desc_str[1 + i] = str[i]; + } + break; + } + + desc_str[0] = static_cast((TUSB_DESC_STRING << 8) | (2 * char_count + 2)); + return desc_str; } const uint8_t * UARTBridgeDevice::get_descriptor_device_cb() { - return uart_bridge_descriptor_device_cb(); + return reinterpret_cast(&CDCDesc::DESC_DEVICE); } const uint8_t * UARTBridgeDevice::get_hid_descriptor_report_cb(uint8_t itf) @@ -57,7 +96,7 @@ const uint8_t * UARTBridgeDevice::get_hid_descriptor_report_cb(uint8_t itf) const uint8_t * UARTBridgeDevice::get_descriptor_configuration_cb(uint8_t index) { - return uart_bridge_descriptor_configuration_cb(index); + return CDCDesc::DESC_CONFIG; } const uint8_t * UARTBridgeDevice::get_descriptor_device_qualifier_cb() diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/UARTBridge.h b/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/UARTBridge.h index c3cdac3..c089ecc 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/UARTBridge.h +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/UARTBridge.h @@ -20,7 +20,7 @@ public: const uint8_t* get_descriptor_device_qualifier_cb() override; private: - bool uart_initialized_ = false; + bool task_running_ = false; }; #endif // _UART_BRIDGE_DEVICE_H_ diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/uart_bridge/uart_bridge.c b/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/uart_bridge/uart_bridge.c index 6cd2d66..004d534 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/uart_bridge/uart_bridge.c +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/uart_bridge/uart_bridge.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -302,13 +303,10 @@ void core1_entry(void) } } -void usbd_serial_init(void); - int uart_bridge_run(void) { set_sys_clock_khz(125000, false); - usbd_serial_init(); tud_init(BOARD_TUD_RHPORT); multicore_reset_core1(); @@ -328,129 +326,4 @@ int uart_bridge_run(void) } return 0; -} - -#define DESC_STR_MAX 20 - -#define USBD_VID 0x2E8A /* Raspberry Pi */ -#define USBD_PID 0x000A /* Raspberry Pi Pico SDK CDC */ - -#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + (TUD_CDC_DESC_LEN * CFG_TUD_CDC)) -#define USBD_MAX_POWER_MA 500 - -enum -{ - USBD_ITF_CDC_0_1 = 0, - USBD_ITF_CDC_0_2, -#if CFG_TUD_CDC > 1 - USBD_ITF_CDC_1_1, - USBD_ITF_CDC_1_2, -#endif - USBD_ITF_MAX, -}; - -#define USBD_CDC_0_EP_CMD 0x81 -#define USBD_CDC_1_EP_CMD 0x83 - -#define USBD_CDC_0_EP_OUT 0x01 -#define USBD_CDC_1_EP_OUT 0x03 - -#define USBD_CDC_0_EP_IN 0x82 -#define USBD_CDC_1_EP_IN 0x84 - -#define USBD_CDC_CMD_MAX_SIZE 8 -#define USBD_CDC_IN_OUT_MAX_SIZE 64 - -#define USBD_STR_0 0x00 -#define USBD_STR_MANUF 0x01 -#define USBD_STR_PRODUCT 0x02 -#define USBD_STR_SERIAL 0x03 -#define USBD_STR_SERIAL_LEN 17 -#define USBD_STR_CDC 0x04 - -static const tusb_desc_device_t usbd_desc_device = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = USBD_VID, - .idProduct = USBD_PID, - .bcdDevice = 0x0100, - .iManufacturer = USBD_STR_MANUF, - .iProduct = USBD_STR_PRODUCT, - .iSerialNumber = USBD_STR_SERIAL, - .bNumConfigurations = 1, -}; - -static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = { - TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN, - TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA), - - TUD_CDC_DESCRIPTOR(USBD_ITF_CDC_0_1, USBD_STR_CDC, USBD_CDC_0_EP_CMD, - USBD_CDC_CMD_MAX_SIZE, USBD_CDC_0_EP_OUT, USBD_CDC_0_EP_IN, - USBD_CDC_IN_OUT_MAX_SIZE), - -#if CFG_TUD_CDC > 1 - TUD_CDC_DESCRIPTOR(USBD_ITF_CDC_1_1, USBD_STR_CDC, USBD_CDC_1_EP_CMD, - USBD_CDC_CMD_MAX_SIZE, USBD_CDC_1_EP_OUT, USBD_CDC_1_EP_IN, - USBD_CDC_IN_OUT_MAX_SIZE), -#endif -}; - -static char usbd_serial[USBD_STR_SERIAL_LEN] = "000000000000"; - -static const char *const usbd_desc_str[] = { - [USBD_STR_MANUF] = "Raspberry Pi", - [USBD_STR_PRODUCT] = "Pico", - [USBD_STR_SERIAL] = usbd_serial, - [USBD_STR_CDC] = "Board CDC", -}; - -const uint8_t *uart_bridge_descriptor_device_cb(void) -{ - return (const uint8_t *) &usbd_desc_device; -} - -const uint8_t *uart_bridge_descriptor_configuration_cb(uint8_t index) -{ - return usbd_desc_cfg; -} - -const uint16_t *uart_bridge_descriptor_string_cb(uint8_t index, uint16_t langid) -{ - static uint16_t desc_str[DESC_STR_MAX]; - uint8_t len; - - if (index == 0) { - desc_str[1] = 0x0409; - len = 1; - } else { - const char *str; - char serial[USBD_STR_SERIAL_LEN]; - - if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) - return NULL; - - str = usbd_desc_str[index]; - for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) - desc_str[1 + len] = str[len]; - } - - desc_str[0] = (TUSB_DESC_STRING << 8) | (2 * len + 2); - - return desc_str; -} - -void usbd_serial_init(void) -{ - uint8_t id[8]; - - flash_get_unique_id(id); - - snprintf(usbd_serial, USBD_STR_SERIAL_LEN, "%02X%02X%02X%02X%02X%02X%02X%02X", - id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]); } \ No newline at end of file diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/uart_bridge/uart_bridge.h b/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/uart_bridge/uart_bridge.h index b5ad90e..6a31d49 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/uart_bridge/uart_bridge.h +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/UARTBridge/uart_bridge/uart_bridge.h @@ -6,9 +6,9 @@ extern "C" { #endif int uart_bridge_run(void); -const uint8_t *uart_bridge_descriptor_device_cb(void); -const uint8_t *uart_bridge_descriptor_configuration_cb(uint8_t index); -const uint16_t *uart_bridge_descriptor_string_cb(uint8_t index, uint16_t langid); +// const uint8_t *uart_bridge_descriptor_device_cb(void); +// const uint8_t *uart_bridge_descriptor_configuration_cb(uint8_t index); +// const uint16_t *uart_bridge_descriptor_string_cb(uint8_t index, uint16_t langid); #ifdef __cplusplus } diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/WebApp/WebApp.cpp b/Firmware/RP2040/src/USBDevice/DeviceDriver/WebApp/WebApp.cpp index e38624e..526d6b3 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/WebApp/WebApp.cpp +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/WebApp/WebApp.cpp @@ -8,10 +8,9 @@ void WebAppDevice::initialize() { class_driver_ = { - #if CFG_TUSB_DEBUG >= 2 - .name = "WEBAPP", - #endif + .name = TUD_DRV_NAME("WEBAPP"), .init = cdcd_init, + .deinit = cdcd_deinit, .reset = cdcd_reset, .open = cdcd_open, .control_xfer_cb = cdcd_control_xfer_cb, @@ -36,7 +35,7 @@ void WebAppDevice::process(const uint8_t idx, Gamepad& gamepad) switch (in_report_.report_id) { case ReportID::INIT_READ: - in_report_.input_mode = static_cast(driver_type_); + in_report_.input_mode = static_cast(user_settings_.get_current_driver()); in_report_.player_idx = 0; in_report_.report_id = ReportID::RESP_OK; in_report_.max_gamepads = MAX_GAMEPADS; @@ -49,7 +48,7 @@ void WebAppDevice::process(const uint8_t idx, Gamepad& gamepad) break; case ReportID::READ_PROFILE: - in_report_.input_mode = static_cast(driver_type_); + in_report_.input_mode = static_cast(user_settings_.get_current_driver()); in_report_.profile = user_settings_.get_profile_by_id(in_report_.profile.id); in_report_.report_id = ReportID::RESP_OK; @@ -58,7 +57,7 @@ void WebAppDevice::process(const uint8_t idx, Gamepad& gamepad) break; case ReportID::WRITE_PROFILE: - if (in_report_.input_mode != static_cast(driver_type_) && in_report_.input_mode != 0) + if (user_settings_.valid_mode(static_cast(in_report_.input_mode))) { success = user_settings_.store_profile_and_driver_type_safe(static_cast(in_report_.input_mode), in_report_.player_idx, in_report_.profile); } @@ -93,50 +92,47 @@ bool WebAppDevice::vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_co const uint16_t * WebAppDevice::get_descriptor_string_cb(uint8_t index, uint16_t langid) { - size_t chr_count; + static uint16_t desc_str[32 + 1]; + size_t char_count = 0; - switch ( index ) - { - case CDCDesc::STRID_LANGID: - std::memcpy(&CDCDesc::_desc_str[1], CDCDesc::STRING_DESCRIPTORS[0], 2); - chr_count = 1; - break; + switch(index) + { + case 0: + std::memcpy(&desc_str[1], CDCDesc::DESC_STRING[0], 2); + char_count = 1; + break; - case CDCDesc::STRID_SERIAL: - chr_count = board_usb_get_serial(CDCDesc::_desc_str + 1, 32); - break; + case 3: + char_count = board_usb_get_serial(&desc_str[1], 32); + break; - default: - if ( !(index < sizeof(CDCDesc::STRING_DESCRIPTORS) / sizeof(CDCDesc::STRING_DESCRIPTORS[0])) ) + default: + if (index >= sizeof(CDCDesc::DESC_STRING) / sizeof(CDCDesc::DESC_STRING[0])) { - return NULL; + return nullptr; + } + const char *str = reinterpret_cast(CDCDesc::DESC_STRING[index]); + char_count = std::strlen(str); + const size_t max_count = sizeof(desc_str) / sizeof(desc_str[0]) - 1; + if (char_count > max_count) + { + char_count = max_count; } - const char *str = CDCDesc::STRING_DESCRIPTORS[index]; - - chr_count = strlen(str); - size_t const max_count = sizeof(CDCDesc::_desc_str) / sizeof(CDCDesc::_desc_str[0]) - 1; - - if ( chr_count > max_count ) + for (size_t i = 0; i < char_count; i++) { - chr_count = max_count; + desc_str[1 + i] = str[i]; } + break; + } - for ( size_t i = 0; i < chr_count; i++ ) - { - CDCDesc::_desc_str[1 + i] = str[i]; - } - break; - } - - CDCDesc::_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); - - return CDCDesc::_desc_str; + desc_str[0] = static_cast((TUSB_DESC_STRING << 8) | (2 * char_count + 2)); + return desc_str; } const uint8_t * WebAppDevice::get_descriptor_device_cb() { - return reinterpret_cast(&CDCDesc::DEVICE_DESCRIPTORS); + return reinterpret_cast(&CDCDesc::DESC_DEVICE); } const uint8_t * WebAppDevice::get_hid_descriptor_report_cb(uint8_t itf) @@ -146,7 +142,7 @@ const uint8_t * WebAppDevice::get_hid_descriptor_report_cb(uint8_t itf) const uint8_t * WebAppDevice::get_descriptor_configuration_cb(uint8_t index) { - return CDCDesc::CONFIGURATION_DESCRIPTORS; + return CDCDesc::DESC_CONFIG; } const uint8_t * WebAppDevice::get_descriptor_device_qualifier_cb() diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/XInput/XInput.h b/Firmware/RP2040/src/USBDevice/DeviceDriver/XInput/XInput.h index cc8c708..2e97d89 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/XInput/XInput.h +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/XInput/XInput.h @@ -1,8 +1,6 @@ #ifndef _XINPUT_DEVICE_H_ #define _XINPUT_DEVICE_H_ -#include - #include "USBDevice/DeviceDriver/DeviceDriver.h" #include "Descriptors/XInput.h" @@ -23,8 +21,6 @@ public: private: XInput::InReport in_report_; XInput::OutReport out_report_; - XInput::InReport prev_in_report_; - XInput::OutReport prev_out_report_; }; #endif // _XINPUT_DEVICE_H_ diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/XInput/tud_xinput/tud_xinput.cpp b/Firmware/RP2040/src/USBDevice/DeviceDriver/XInput/tud_xinput/tud_xinput.cpp index 6d4250e..81e0455 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/XInput/tud_xinput/tud_xinput.cpp +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/XInput/tud_xinput/tud_xinput.cpp @@ -29,6 +29,12 @@ static void init(void) std::memset(out_buffer_, 0, ENDPOINT_SIZE); } +static bool deinit(void) +{ + init(); + return true; +} + static void reset(uint8_t rhport) { init(); @@ -84,10 +90,13 @@ const usbd_class_driver_t* class_driver() { static const usbd_class_driver_t tud_class_driver_ = { - #if CFG_TUSB_DEBUG >= 2 + #if CFG_TUSB_DEBUG >= 2 .name = "XINPUT", - #endif + #else + .name = NULL, + #endif .init = init, + .deinit = deinit, .reset = reset, .open = open, .control_xfer_cb = control_xfer_cb, diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/XboxOG/XboxOG_SB.cpp b/Firmware/RP2040/src/USBDevice/DeviceDriver/XboxOG/XboxOG_SB.cpp index efa59a6..f9b85e0 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/XboxOG/XboxOG_SB.cpp +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/XboxOG/XboxOG_SB.cpp @@ -1,10 +1,10 @@ #include -#include -#include "pico/time.h" +#include #include "Descriptors/XInput.h" #include "USBDevice/DeviceDriver/XboxOG/tud_xid/tud_xid.h" #include "USBDevice/DeviceDriver/XboxOG/XboxOG_SB.h" +#include "OGXMini/Debug.h" static constexpr std::array GP_MAP = {{ @@ -82,118 +82,55 @@ void XboxOGSBDevice::initialize() in_report_.bLength = sizeof(XboxOG::SB::InReport); in_report_.gearLever = XboxOG::SB::Gear::N; - std::memcpy(&prev_in_report_, &in_report_, sizeof(XboxOG::SB::InReport)); + prev_in_report_ = in_report_; } void XboxOGSBDevice::process(const uint8_t idx, Gamepad& gamepad) { - if (gamepad.new_pad_in()) + Gamepad::PadIn gp_in = gamepad.get_pad_in(); + Gamepad::ChatpadIn gp_in_chatpad = gamepad.get_chatpad_in(); + + in_report_.dButtons[0] = 0; + in_report_.dButtons[1] = 0; + in_report_.dButtons[2] &= XboxOG::SB::BUTTONS2_TOGGLE_MID; + + for (const auto& map : GP_MAP) { - Gamepad::PadIn gp_in = gamepad.get_pad_in(); - - in_report_.dButtons[0] = 0; - in_report_.dButtons[1] = 0; - in_report_.dButtons[2] &= XboxOG::SB::BUTTONS2_TOGGLE_MID; - - // uint16_t gp_buttons = gamepad.get_buttons(); - - for (const auto& map : GP_MAP) + if (gp_in.buttons & map.gp_mask) { - if (gp_in.buttons & map.gp_mask) + in_report_.dButtons[map.button_offset] |= map.sb_mask; + } + } + + for (const auto& map : CHATPAD_MAP) + { + if (chatpad_pressed(gp_in_chatpad, map.gp_mask)) + { + in_report_.dButtons[map.button_offset] |= map.sb_mask; + } + } + + static std::array toggle_pressed{false}; + + for (uint8_t i = 0; i < CHATPAD_TOGGLE_MAP.size(); i++) + { + if (chatpad_pressed(gp_in_chatpad, CHATPAD_TOGGLE_MAP[i].gp_mask)) + { + if (!toggle_pressed[i]) { - in_report_.dButtons[map.button_offset] |= map.sb_mask; + in_report_.dButtons[CHATPAD_TOGGLE_MAP[i].button_offset] ^= CHATPAD_TOGGLE_MAP[i].sb_mask; + toggle_pressed[i] = true; } } - - // Gamepad::Chatpad gp_chatpad = gamepad.get_chatpad(); - - for (const auto& map : CHATPAD_MAP) + else { - if (chatpad_pressed(gp_in.chatpad, map.gp_mask)) - { - in_report_.dButtons[map.button_offset] |= map.sb_mask; - } + toggle_pressed[i] = false; } + } - for (const auto& map : CHATPAD_TOGGLE_MAP) - { - if (chatpad_pressed(gp_in.chatpad, map.gp_mask)) - { - in_report_.dButtons[map.button_offset] |= map.sb_mask; - } - } - - if (gp_in.buttons & Gamepad::BUTTON_X) - { - if (out_report_.Chaff_Extinguisher & 0x0F) - { - in_report_.dButtons[1] |= XboxOG::SB::Buttons1::EXTINGUISHER; - } - if (out_report_.Comm1_MagazineChange & 0x0F) - { - in_report_.dButtons[1] |= XboxOG::SB::Buttons1::WEAPONCONMAGAZINE; - } - if (out_report_.Washing_LineColorChange & 0xF0) - { - in_report_.dButtons[1] |= XboxOG::SB::Buttons1::WASHING; - } - } - - if (chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_MESSENGER) || gp_in.buttons & Gamepad::BUTTON_BACK) - { - for (const auto& map : CHATPAD_MAP_ALT1) - { - if (chatpad_pressed(gp_in.chatpad, map.gp_mask)) - { - in_report_.dButtons[map.button_offset] |= map.sb_mask; - } - } - // for (uint8_t i = 0; i < sizeof(CHATPAD_MAP_ALT1) / sizeof(CHATPAD_MAP_ALT1[0]); i++) - // { - // if (chatpad_pressed(gp_in.chatpad, CHATPAD_MAP_ALT1[i].gp_mask)) - // { - // in_report_.dButtons[CHATPAD_MAP_ALT1[i].button_offset] |= CHATPAD_MAP_ALT1[i].sb_mask; - // } - // } - if (gp_in.dpad & Gamepad::DPAD_UP || gp_in.dpad & Gamepad::DPAD_RIGHT) - { - in_report_.tunerDial += (prev_in_report_.tunerDial < 15) ? 1 : -15; - } - if (gp_in.dpad & Gamepad::DPAD_DOWN || gp_in.dpad & Gamepad::DPAD_LEFT) - { - in_report_.tunerDial -= (prev_in_report_.tunerDial > 0) ? 1 : -15; - } - } - else if (chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_ORANGE)) - { - for (const auto& map : CHATPAD_MAP_ALT2) - { - if (chatpad_pressed(gp_in.chatpad, map.gp_mask)) - { - in_report_.dButtons[map.button_offset] |= map.sb_mask; - } - } - // for (uint8_t i = 0; i < sizeof(CHATPAD_MAP_ALT2) / sizeof(CHATPAD_MAP_ALT2[0]); i++) - // { - // if (chatpad_pressed(gp_in.chatpad, CHATPAD_MAP_ALT2[i].gp_mask)) - // { - // in_report_.dButtons[CHATPAD_MAP_ALT2[i].button_offset] |= CHATPAD_MAP_ALT2[i].sb_mask; - // } - // } - if (!(gp_in.dpad & Gamepad::DPAD_LEFT) && !(gp_in.dpad & Gamepad::DPAD_RIGHT)) - { - if (gp_in.dpad & Gamepad::DPAD_UP) - { - in_report_.gearLever += (prev_in_report_.gearLever < XboxOG::SB::Gear::G5) ? 1 : 0; - } - if (gp_in.dpad & Gamepad::DPAD_DOWN) - { - in_report_.gearLever -= (prev_in_report_.gearLever > XboxOG::SB::Gear::R) ? 1 : 0; - } - } - } - - if (chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_SHIFT)) + if (chatpad_pressed(gp_in_chatpad, XInput::Chatpad::CODE_SHIFT)) + { + if (!toggle_pressed.back()) { if (in_report_.dButtons[2] & XboxOG::SB::BUTTONS2_TOGGLE_MID) { @@ -203,108 +140,193 @@ void XboxOGSBDevice::process(const uint8_t idx, Gamepad& gamepad) { in_report_.dButtons[2] |= XboxOG::SB::BUTTONS2_TOGGLE_MID; } + toggle_pressed.back() = true; + } + } + else + { + toggle_pressed.back() = false; + } + + if (gp_in.buttons & Gamepad::BUTTON_X) + { + if (out_report_.Chaff_Extinguisher & 0x0F) + { + in_report_.dButtons[1] |= XboxOG::SB::Buttons1::EXTINGUISHER; + } + if (out_report_.Comm1_MagazineChange & 0x0F) + { + in_report_.dButtons[1] |= XboxOG::SB::Buttons1::WEAPONCONMAGAZINE; + } + if (out_report_.Washing_LineColorChange & 0xF0) + { + in_report_.dButtons[1] |= XboxOG::SB::Buttons1::WASHING; + } + } + + if (chatpad_pressed(gp_in_chatpad, XInput::Chatpad::CODE_MESSENGER) || gp_in.buttons & Gamepad::BUTTON_BACK) + { + for (const auto& map : CHATPAD_MAP_ALT1) + { + if (chatpad_pressed(gp_in_chatpad, map.gp_mask)) + { + in_report_.dButtons[map.button_offset] |= map.sb_mask; + } } - in_report_.leftPedal = Scale::uint8_to_uint16(gp_in.trigger_l); - in_report_.rightPedal = Scale::uint8_to_uint16(gp_in.trigger_r); - in_report_.middlePedal = chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_BACK) ? 0xFF00 : 0x0000; - in_report_.rotationLever = chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_MESSENGER) ? 0 : - (gp_in.buttons & Gamepad::BUTTON_BACK) ? 0 : - (gp_in.dpad & Gamepad::DPAD_LEFT) ? INT16_MIN : - (gp_in.dpad & Gamepad::DPAD_RIGHT) ? INT16_MAX : 0; - - in_report_.sightChangeX = Scale::invert_joy(gp_in.joystick_lx); - in_report_.sightChangeY = gp_in.joystick_ly; - - int32_t axis_value = static_cast(Scale::invert_joy(gp_in.joystick_rx)); - - if (axis_value > XboxOG::SB::DEFAULT_DEADZONE) + if (gp_in.dpad & Gamepad::DPAD_UP && dpad_reset_) { - vmouse_x_ += axis_value / sensitivity_; + in_report_.tunerDial = (in_report_.tunerDial + 1) % 16; + dpad_reset_ = false; + } + else if (gp_in.dpad & Gamepad::DPAD_DOWN && dpad_reset_) + { + in_report_.tunerDial = (in_report_.tunerDial + 15) % 16; + dpad_reset_ = false; + } + else if (!(gp_in.dpad & Gamepad::DPAD_DOWN) && !(gp_in.dpad & Gamepad::DPAD_UP)) + { + dpad_reset_ = true; + } + } + else if (chatpad_pressed(gp_in_chatpad, XInput::Chatpad::CODE_ORANGE)) + { + for (const auto& map : CHATPAD_MAP_ALT2) + { + if (chatpad_pressed(gp_in_chatpad, map.gp_mask)) + { + in_report_.dButtons[map.button_offset] |= map.sb_mask; + } } - axis_value = static_cast(Scale::invert_joy(gp_in.joystick_ry)); + // if (!(gp_in.dpad & Gamepad::DPAD_LEFT) && !(gp_in.dpad & Gamepad::DPAD_RIGHT)) + // { + if (gp_in.dpad & Gamepad::DPAD_UP && dpad_reset_) + { + if (in_report_.gearLever < XboxOG::SB::Gear::G5) + { + in_report_.gearLever++; + } + dpad_reset_ = false; + } + else if (gp_in.dpad & Gamepad::DPAD_DOWN && dpad_reset_) + { + if (in_report_.gearLever > XboxOG::SB::Gear::R) + { + in_report_.gearLever--; + } + dpad_reset_ = false; + } + else if (!(gp_in.dpad & Gamepad::DPAD_DOWN) && !(gp_in.dpad & Gamepad::DPAD_UP)) + { + dpad_reset_ = true; + } + // } + } + else + { + dpad_reset_ = true; + } - if (axis_value > XboxOG::SB::DEFAULT_DEADZONE) + in_report_.leftPedal = Scale::uint8_to_uint16(gp_in.trigger_l); + in_report_.rightPedal = Scale::uint8_to_uint16(gp_in.trigger_r); + in_report_.middlePedal = chatpad_pressed( gp_in_chatpad, XInput::Chatpad::CODE_BACK) ? 0xFF00 : 0x0000; + in_report_.rotationLever= chatpad_pressed( gp_in_chatpad, XInput::Chatpad::CODE_MESSENGER) ? 0 : + (gp_in.buttons & Gamepad::BUTTON_BACK) ? 0 : + (gp_in.dpad & Gamepad::DPAD_LEFT) ? INT_16::MIN : + (gp_in.dpad & Gamepad::DPAD_RIGHT) ? INT_16::MAX : 0; + + in_report_.sightChangeX = gp_in.joystick_lx; + in_report_.sightChangeY = gp_in.joystick_ly; + + int32_t axis_value_x = static_cast(gp_in.joystick_rx); + if (std::abs(axis_value_x) > DEFAULT_DEADZONE) + { + vmouse_x_ += axis_value_x / sensitivity_; + } + + int32_t axis_value_y = static_cast(Scale::invert_joy(gp_in.joystick_ry)); + if (std::abs(axis_value_y) > DEFAULT_DEADZONE) + { + vmouse_y_ -= axis_value_y / sensitivity_; + } + + if (vmouse_x_ < 0) vmouse_x_ = 0; + if (vmouse_x_ > UINT_16::MAX) vmouse_x_ = UINT_16::MAX; + if (vmouse_y_ > UINT_16::MAX) vmouse_y_ = UINT_16::MAX; + if (vmouse_y_ < 0) vmouse_y_ = 0; + + if (gp_in.buttons & Gamepad::BUTTON_L3) + { + if ((time_us_32() / 1000) - aim_reset_timer_ > 500) { - vmouse_y_ -= axis_value / sensitivity_; + vmouse_x_ = XboxOG::SB::AIMING_MID; + vmouse_y_ = XboxOG::SB::AIMING_MID; + } + } + else + { + aim_reset_timer_ = time_us_32() / 1000; + } + + in_report_.aimingX = static_cast(vmouse_x_); + in_report_.aimingY = static_cast(vmouse_y_); + + if (tud_suspended()) + { + tud_remote_wakeup(); + } + if (tud_xid::send_report_ready(0) && + std::memcmp(&prev_in_report_, &in_report_, sizeof(XboxOG::SB::InReport)) && + tud_xid::send_report(0, reinterpret_cast(&in_report_), sizeof(XboxOG::SB::InReport))) + { + std::memcpy(&prev_in_report_, &in_report_, sizeof(XboxOG::SB::InReport)); + } + + if (chatpad_pressed(gp_in_chatpad, XInput::Chatpad::CODE_ORANGE)) + { + uint16_t new_sense = 0; + + if (chatpad_pressed(gp_in_chatpad, XInput::Chatpad::CODE_9)) + { + new_sense = 200; + } + else if (chatpad_pressed(gp_in_chatpad, XInput::Chatpad::CODE_8)) + { + new_sense = 250; + } + else if (chatpad_pressed(gp_in_chatpad, XInput::Chatpad::CODE_7)) + { + new_sense = 300; + } + else if (chatpad_pressed(gp_in_chatpad, XInput::Chatpad::CODE_6)) + { + new_sense = 350; + } + else if (chatpad_pressed(gp_in_chatpad, XInput::Chatpad::CODE_5)) + { + new_sense = 400; + } + else if (chatpad_pressed(gp_in_chatpad, XInput::Chatpad::CODE_4)) + { + new_sense = 650; + } + else if (chatpad_pressed(gp_in_chatpad, XInput::Chatpad::CODE_3)) + { + new_sense = 800; + } + else if (chatpad_pressed(gp_in_chatpad, XInput::Chatpad::CODE_2)) + { + new_sense = 1000; + } + else if (chatpad_pressed(gp_in_chatpad, XInput::Chatpad::CODE_1)) + { + new_sense = 1200; } - if (vmouse_x_ < 0) vmouse_x_ = 0; - if (vmouse_x_ > UINT16_MAX) vmouse_x_ = UINT16_MAX; - if (vmouse_y_ > UINT16_MAX) vmouse_y_ = UINT16_MAX; - if (vmouse_y_ < 0) vmouse_y_ = 0; - - if (gp_in.buttons & Gamepad::BUTTON_L3) + if (new_sense != 0) { - if ((time_us_32() / 1000) - aim_reset_timer_ > 500) - { - vmouse_x_ = XboxOG::SB::AIMING_MID; - vmouse_y_ = XboxOG::SB::AIMING_MID; - } - } - else - { - aim_reset_timer_ = time_us_32() / 1000; - } - - in_report_.aimingX = static_cast(vmouse_x_); - in_report_.aimingY = static_cast(vmouse_y_); - - if (tud_suspended()) - { - tud_remote_wakeup(); - } - if (tud_xid::send_report_ready(0)) - { - tud_xid::send_report(0, reinterpret_cast(&in_report_), sizeof(XboxOG::SB::InReport)); - } - - if (chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_ORANGE)) - { - uint16_t new_sense = 0; - - if (chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_9)) - { - new_sense = 200; - } - else if (chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_8)) - { - new_sense = 250; - } - else if (chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_7)) - { - new_sense = 300; - } - else if (chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_6)) - { - new_sense = 350; - } - else if (chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_5)) - { - new_sense = 400; - } - else if (chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_4)) - { - new_sense = 650; - } - else if (chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_3)) - { - new_sense = 800; - } - else if (chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_2)) - { - new_sense = 1000; - } - else if (chatpad_pressed(gp_in.chatpad, XInput::Chatpad::CODE_1)) - { - new_sense = 1200; - } - - if (new_sense != 0 && new_sense != sensitivity_) - { - sensitivity_ = new_sense; - } + sensitivity_ = new_sense; } } diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/XboxOG/XboxOG_SB.h b/Firmware/RP2040/src/USBDevice/DeviceDriver/XboxOG/XboxOG_SB.h index 1290037..02f99b1 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/XboxOG/XboxOG_SB.h +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/XboxOG/XboxOG_SB.h @@ -30,22 +30,27 @@ public: const uint8_t* get_descriptor_device_qualifier_cb() override; private: + static constexpr int16_t DEFAULT_DEADZONE = 7500; + static constexpr uint16_t DEFAULT_SENSE = 400; + int32_t vmouse_x_ = XboxOG::SB::AIMING_MID; int32_t vmouse_y_ = XboxOG::SB::AIMING_MID; - uint16_t sensitivity_ = XboxOG::SB::DEFAULT_SENSE; + uint16_t sensitivity_ = DEFAULT_SENSE; uint32_t aim_reset_timer_ = 0; + bool dpad_reset_ = true; + XboxOG::SB::InReport in_report_; XboxOG::SB::InReport prev_in_report_; XboxOG::SB::OutReport out_report_; - static inline bool chatpad_pressed(const uint8_t* chatpad_array, const uint16_t keycode) + static inline bool chatpad_pressed(const Gamepad::ChatpadIn& chatpad, const uint16_t keycode) { - if (std::accumulate(chatpad_array, chatpad_array + 3, 0) == 0) + if (std::accumulate(std::begin(chatpad), std::end(chatpad), 0) == 0) { return false; } - else if (keycode < 17 && (chatpad_array[0] & keycode)) + else if (keycode < 17 && (chatpad[0] & keycode)) { return true; } @@ -53,11 +58,11 @@ private: { return false; } - else if (chatpad_array[1] == keycode) + else if (chatpad[1] == keycode) { return true; } - else if (chatpad_array[2] == keycode) + else if (chatpad[2] == keycode) { return true; } diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/XboxOG/tud_xid/tud_xid.cpp b/Firmware/RP2040/src/USBDevice/DeviceDriver/XboxOG/tud_xid/tud_xid.cpp index a5e514c..71709bc 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/XboxOG/tud_xid/tud_xid.cpp +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/XboxOG/tud_xid/tud_xid.cpp @@ -609,6 +609,12 @@ static void xid_init() } } +static bool xid_deinit() +{ + xid_init(); + return true; +} + static void xid_reset(uint8_t rhport) { xid_init(); @@ -834,8 +840,11 @@ static const usbd_class_driver_t tud_xid_class_driver_ = { #if CFG_TUSB_DEBUG >= 2 .name = "XID DRIVER (DUKE,SB OR XREMOTE)", +#else + .name = nullptr, #endif .init = xid_init, + .deinit = xid_deinit, .reset = xid_reset, .open = xid_open, .control_xfer_cb = xid_control_xfer_cb, diff --git a/Firmware/RP2040/src/USBDevice/DeviceManager.cpp b/Firmware/RP2040/src/USBDevice/DeviceManager.cpp index 38017ee..0f9fa30 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceManager.cpp +++ b/Firmware/RP2040/src/USBDevice/DeviceManager.cpp @@ -16,45 +16,57 @@ #include "USBDevice/DeviceDriver/UARTBridge/UARTBridge.h" #endif // defined(CONFIG_EN_UART_BRIDGE) -void DeviceManager::initialize_driver(DeviceDriver::Type driver_type) +void DeviceManager::initialize_driver(DeviceDriver::Type driver_type, Gamepad(&gamepads)[MAX_GAMEPADS]) { + bool has_analog = false; //TODO: Put gamepad setup in the drivers themselves switch (driver_type) { case DeviceDriver::Type::DINPUT: - device_driver_ = new DInputDevice(); + has_analog = true; + device_driver_ = std::make_unique(); break; case DeviceDriver::Type::PS3: - device_driver_ = new PS3Device(); + has_analog = true; + device_driver_ = std::make_unique(); break; case DeviceDriver::Type::PSCLASSIC: - device_driver_ = new PSClassicDevice(); + device_driver_ = std::make_unique(); break; case DeviceDriver::Type::SWITCH: - device_driver_ = new SwitchDevice(); + device_driver_ = std::make_unique(); break; case DeviceDriver::Type::XINPUT: - device_driver_ = new XInputDevice(); + device_driver_ = std::make_unique(); break; case DeviceDriver::Type::XBOXOG: - device_driver_ = new XboxOGDevice(); + has_analog = true; + device_driver_ = std::make_unique(); break; case DeviceDriver::Type::XBOXOG_SB: - device_driver_ = new XboxOGSBDevice(); + device_driver_ = std::make_unique(); break; case DeviceDriver::Type::XBOXOG_XR: - device_driver_ = new XboxOGXRDevice(); + device_driver_ = std::make_unique(); break; case DeviceDriver::Type::WEBAPP: - device_driver_ = new WebAppDevice(); + device_driver_ = std::make_unique(); break; #if defined(CONFIG_EN_UART_BRIDGE) case DeviceDriver::Type::UART_BRIDGE: - device_driver_ = new UARTBridgeDevice(); + device_driver_ = std::make_unique(); break; #endif //defined(CONFIG_EN_UART_BRIDGE) default: return; } + if (has_analog) + { + for (size_t i = 0; i < MAX_GAMEPADS; ++i) + { + gamepads[i].set_analog_device(true); + } + } + device_driver_->initialize(); } \ No newline at end of file diff --git a/Firmware/RP2040/src/USBDevice/DeviceManager.h b/Firmware/RP2040/src/USBDevice/DeviceManager.h index 7a96020..227fcf1 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceManager.h +++ b/Firmware/RP2040/src/USBDevice/DeviceManager.h @@ -1,8 +1,10 @@ #ifndef _DEVICE_MANAGER_H_ #define _DEVICE_MANAGER_H_ +#include #include +#include "Gamepad.h" #include "USBDevice/DeviceDriver/DeviceDriver.h" class DeviceManager @@ -18,14 +20,15 @@ public: } //Must be called before any other method - void initialize_driver(DeviceDriver::Type driver_type); + void initialize_driver(DeviceDriver::Type driver_type, Gamepad(&gamepads)[MAX_GAMEPADS]); - DeviceDriver* get_driver() { return device_driver_; } + DeviceDriver* get_driver() { return device_driver_.get(); } private: - DeviceManager() {} - ~DeviceManager() { delete device_driver_; } - DeviceDriver* device_driver_{nullptr}; + DeviceManager() = default; + ~DeviceManager() = default; + + std::unique_ptr device_driver_{nullptr}; }; #endif // _DEVICE_MANAGER_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/USBHost/HIDParser/HIDJoystick.cpp b/Firmware/RP2040/src/USBHost/HIDParser/HIDJoystick.cpp index c369b6e..da379c8 100644 --- a/Firmware/RP2040/src/USBHost/HIDParser/HIDJoystick.cpp +++ b/Firmware/RP2040/src/USBHost/HIDParser/HIDJoystick.cpp @@ -1,3 +1,27 @@ +/* + MIT License + + Copyright (c) 2024 o0zz + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + #include "USBHost/HIDParser/HIDJoystick.h" #include "USBHost/HIDParser/HIDUtils.h" #include diff --git a/Firmware/RP2040/src/USBHost/HIDParser/HIDJoystick.h b/Firmware/RP2040/src/USBHost/HIDParser/HIDJoystick.h index 4d5a83d..d6b7a1a 100644 --- a/Firmware/RP2040/src/USBHost/HIDParser/HIDJoystick.h +++ b/Firmware/RP2040/src/USBHost/HIDParser/HIDJoystick.h @@ -1,3 +1,27 @@ +/* + MIT License + + Copyright (c) 2024 o0zz + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + #include "USBHost/HIDParser/HIDReportDescriptor.h" #include #include diff --git a/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptor.cpp b/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptor.cpp index a46d11b..fdc5e85 100644 --- a/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptor.cpp +++ b/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptor.cpp @@ -1,3 +1,27 @@ +/* + MIT License + + Copyright (c) 2024 o0zz + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + #include "USBHost/HIDParser/HIDReportDescriptor.h" #include "USBHost/HIDParser/HIDReportDescriptorElements.h" #include "USBHost/HIDParser/HIDReportDescriptorUsages.h" diff --git a/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptor.h b/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptor.h index 9239fe9..1415ef6 100644 --- a/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptor.h +++ b/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptor.h @@ -1,3 +1,27 @@ +/* + MIT License + + Copyright (c) 2024 o0zz + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + #pragma once #include diff --git a/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorElements.cpp b/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorElements.cpp index 507797e..381bf9b 100644 --- a/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorElements.cpp +++ b/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorElements.cpp @@ -1,3 +1,27 @@ +/* + MIT License + + Copyright (c) 2024 o0zz + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + #include "USBHost/HIDParser/HIDReportDescriptorElements.h" #include diff --git a/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorElements.h b/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorElements.h index 10c004e..a369991 100644 --- a/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorElements.h +++ b/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorElements.h @@ -1,3 +1,27 @@ +/* + MIT License + + Copyright (c) 2024 o0zz + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + #pragma once #include #include diff --git a/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorUsages.cpp b/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorUsages.cpp index 4cb047b..3319e45 100644 --- a/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorUsages.cpp +++ b/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorUsages.cpp @@ -1,3 +1,27 @@ +/* + MIT License + + Copyright (c) 2024 o0zz + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + #include "USBHost/HIDParser/HIDReportDescriptorUsages.h" #include #include diff --git a/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorUsages.h b/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorUsages.h index a84000b..4eb172f 100644 --- a/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorUsages.h +++ b/Firmware/RP2040/src/USBHost/HIDParser/HIDReportDescriptorUsages.h @@ -1,3 +1,27 @@ +/* + MIT License + + Copyright (c) 2024 o0zz + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + #pragma once #include "USBHost/HIDParser/HIDReportDescriptorElements.h" #include diff --git a/Firmware/RP2040/src/USBHost/HIDParser/HIDUtils.cpp b/Firmware/RP2040/src/USBHost/HIDParser/HIDUtils.cpp index c97dcc8..e926002 100644 --- a/Firmware/RP2040/src/USBHost/HIDParser/HIDUtils.cpp +++ b/Firmware/RP2040/src/USBHost/HIDParser/HIDUtils.cpp @@ -1,3 +1,27 @@ +/* + MIT License + + Copyright (c) 2024 o0zz + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + #include "USBHost/HIDParser/HIDUtils.h" uint32_t HIDUtils::readBitsLE(uint8_t *buffer, uint32_t bitOffset, uint32_t bitLength) { diff --git a/Firmware/RP2040/src/USBHost/HIDParser/HIDUtils.h b/Firmware/RP2040/src/USBHost/HIDParser/HIDUtils.h index 4478676..5ac7cde 100644 --- a/Firmware/RP2040/src/USBHost/HIDParser/HIDUtils.h +++ b/Firmware/RP2040/src/USBHost/HIDParser/HIDUtils.h @@ -1,3 +1,27 @@ +/* + MIT License + + Copyright (c) 2024 o0zz + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + #pragma once #include diff --git a/Firmware/RP2040/src/USBHost/HostDriver/DInput/DInput.cpp b/Firmware/RP2040/src/USBHost/HostDriver/DInput/DInput.cpp index 51220c2..53354fc 100644 --- a/Firmware/RP2040/src/USBHost/HostDriver/DInput/DInput.cpp +++ b/Firmware/RP2040/src/USBHost/HostDriver/DInput/DInput.cpp @@ -7,7 +7,7 @@ void DInputHost::initialize(Gamepad& gamepad, uint8_t address, uint8_t instance, const uint8_t* report_desc, uint16_t desc_len) { - gamepad.set_analog_enabled(true); + gamepad.set_analog_host(true); tuh_hid_receive_report(address, instance); } diff --git a/Firmware/RP2040/src/USBHost/HostDriver/HostDriver.h b/Firmware/RP2040/src/USBHost/HostDriver/HostDriver.h index 50550ad..265b0ae 100644 --- a/Firmware/RP2040/src/USBHost/HostDriver/HostDriver.h +++ b/Firmware/RP2040/src/USBHost/HostDriver/HostDriver.h @@ -39,6 +39,9 @@ public: virtual void process_report(Gamepad& gamepad, uint8_t address, uint8_t instance, const uint8_t* report, uint16_t len) = 0; virtual bool send_feedback(Gamepad& gamepad, uint8_t address, uint8_t instance) = 0; + virtual void connect_cb(Gamepad& gamepad, uint8_t address, uint8_t instance) {}; //Wireless specific + virtual void disconnect_cb(Gamepad& gamepad, uint8_t address, uint8_t instance) {}; //Wireless specific + protected: const uint8_t idx_; diff --git a/Firmware/RP2040/src/USBHost/HostDriver/PS3/PS3.cpp b/Firmware/RP2040/src/USBHost/HostDriver/PS3/PS3.cpp index d415fc5..55a5ff7 100644 --- a/Firmware/RP2040/src/USBHost/HostDriver/PS3/PS3.cpp +++ b/Firmware/RP2040/src/USBHost/HostDriver/PS3/PS3.cpp @@ -16,12 +16,14 @@ const tusb_control_request_t PS3Host::RUMBLE_REQUEST = void PS3Host::initialize(Gamepad& gamepad, uint8_t address, uint8_t instance, const uint8_t* report_desc, uint16_t desc_len) { - gamepad.set_analog_enabled(true); + gamepad.set_analog_host(true); - std::memcpy(&out_report_, PS3::DEFAULT_OUT_REPORT, std::min(sizeof(PS3::OutReport), sizeof(PS3::DEFAULT_OUT_REPORT))); + std::memcpy(reinterpret_cast(&out_report_), + PS3::DEFAULT_OUT_REPORT, + std::min(sizeof(PS3::OutReport), sizeof(PS3::DEFAULT_OUT_REPORT))); out_report_.leds_bitmap = 0x1 << (idx_ + 1); - out_report_.led[idx_].time_enabled = 0xFF; + out_report_.leds[idx_].time_enabled = 0xFF; init_state_.out_report = &out_report_; init_state_.dev_addr = address; @@ -154,12 +156,13 @@ bool PS3Host::send_feedback(Gamepad& gamepad, uint8_t address, uint8_t instance) static uint32_t last_rumble_ms = 0; uint32_t current_ms = time_us_32() / 1000; - Gamepad::PadOut gp_out = gamepad.get_pad_out(); - //Spamming control xfers doesn't work, limit the rate + //Spamming set_report doesn't work, limit the rate if (init_state_.reports_enabled && current_ms - last_rumble_ms >= 300) { + Gamepad::PadOut gp_out = gamepad.get_pad_out(); + out_report_.rumble.right_duration = (gp_out.rumble_r > 0) ? 20 : 0; out_report_.rumble.right_motor_on = (gp_out.rumble_r > 0) ? 1 : 0; diff --git a/Firmware/RP2040/src/USBHost/HostDriver/PS5/PS5.cpp b/Firmware/RP2040/src/USBHost/HostDriver/PS5/PS5.cpp index 95f5bab..510ae3a 100644 --- a/Firmware/RP2040/src/USBHost/HostDriver/PS5/PS5.cpp +++ b/Firmware/RP2040/src/USBHost/HostDriver/PS5/PS5.cpp @@ -7,21 +7,35 @@ void PS5Host::initialize(Gamepad& gamepad, uint8_t address, uint8_t instance, const uint8_t* report_desc, uint16_t desc_len) { - std::memset(&out_report_, 0, sizeof(out_report_)); - out_report_.report_id = PS5::OUT_REPORT_ID; - out_report_.valid_flag0 = 0x02; - out_report_.valid_flag1 = 0x02; - out_report_.valid_flag2 = 0x04; + out_report_.report_id = PS5::OutReportID::CONTROL; + out_report_.control_flag[0] = 2; + out_report_.control_flag[1] = 2; + out_report_.led_control_flag = 0x01 | 0x02; + out_report_.pulse_option = 1; + out_report_.led_brightness = 0xFF; + out_report_.player_number = idx_ + 1; + out_report_.lightbar_blue = 0xFF; + + while (!tuh_hid_send_report(address, instance, 0, &out_report_, sizeof(PS5::OutReport))) + { + tuh_task(); + } + + out_report_ = PS5::OutReport(); + out_report_.report_id = PS5::OutReportID::RUMBLE; + out_report_.control_flag[0] = 2; + out_report_.control_flag[1] = 2; + out_report_.led_control_flag = 0x04; tuh_hid_receive_report(address, instance); } void PS5Host::process_report(Gamepad& gamepad, uint8_t address, uint8_t instance, const uint8_t* report, uint16_t len) { - in_report_ = *reinterpret_cast(report); - in_report_.seq_number = 0; + const PS5::InReport* in_report = reinterpret_cast(report); - if (std::memcmp(&prev_in_report_, &in_report_, PS5::IN_REPORT_CMP_SIZE) == 0) + if (std::memcmp(&prev_in_report_.joystick_lx, &in_report->joystick_lx, sizeof(uint8_t) * 6) == 0 && + std::memcmp(prev_in_report_.buttons, in_report->buttons, sizeof(in_report->buttons)) == 0) { tuh_hid_receive_report(address, instance); return; @@ -29,7 +43,7 @@ void PS5Host::process_report(Gamepad& gamepad, uint8_t address, uint8_t instance Gamepad::PadIn gp_in; - switch (in_report_.buttons[0] & PS5::DPAD_MASK) + switch (in_report->buttons[0] & PS5::DPAD_MASK) { case PS5::Buttons0::DPAD_UP: gp_in.dpad |= gamepad.MAP_DPAD_UP; @@ -59,31 +73,31 @@ void PS5Host::process_report(Gamepad& gamepad, uint8_t address, uint8_t instance break; } - if (in_report_.buttons[0] & PS5::Buttons0::SQUARE) gp_in.buttons |= gamepad.MAP_BUTTON_X; - if (in_report_.buttons[0] & PS5::Buttons0::CROSS) gp_in.buttons |= gamepad.MAP_BUTTON_A; - if (in_report_.buttons[0] & PS5::Buttons0::CIRCLE) gp_in.buttons |= gamepad.MAP_BUTTON_B; - if (in_report_.buttons[0] & PS5::Buttons0::TRIANGLE) gp_in.buttons |= gamepad.MAP_BUTTON_Y; - if (in_report_.buttons[1] & PS5::Buttons1::L1) gp_in.buttons |= gamepad.MAP_BUTTON_LB; - if (in_report_.buttons[1] & PS5::Buttons1::R1) gp_in.buttons |= gamepad.MAP_BUTTON_RB; - if (in_report_.buttons[1] & PS5::Buttons1::L3) gp_in.buttons |= gamepad.MAP_BUTTON_L3; - if (in_report_.buttons[1] & PS5::Buttons1::R3) gp_in.buttons |= gamepad.MAP_BUTTON_R3; - if (in_report_.buttons[1] & PS5::Buttons1::SHARE) gp_in.buttons |= gamepad.MAP_BUTTON_BACK; - if (in_report_.buttons[1] & PS5::Buttons1::OPTIONS) gp_in.buttons |= gamepad.MAP_BUTTON_START; - if (in_report_.buttons[2] & PS5::Buttons2::PS) gp_in.buttons |= gamepad.MAP_BUTTON_SYS; - if (in_report_.buttons[2] & PS5::Buttons2::MUTE) gp_in.buttons |= gamepad.MAP_BUTTON_MISC; + if (in_report->buttons[0] & PS5::Buttons0::SQUARE) gp_in.buttons |= gamepad.MAP_BUTTON_X; + if (in_report->buttons[0] & PS5::Buttons0::CROSS) gp_in.buttons |= gamepad.MAP_BUTTON_A; + if (in_report->buttons[0] & PS5::Buttons0::CIRCLE) gp_in.buttons |= gamepad.MAP_BUTTON_B; + if (in_report->buttons[0] & PS5::Buttons0::TRIANGLE) gp_in.buttons |= gamepad.MAP_BUTTON_Y; + if (in_report->buttons[1] & PS5::Buttons1::L1) gp_in.buttons |= gamepad.MAP_BUTTON_LB; + if (in_report->buttons[1] & PS5::Buttons1::R1) gp_in.buttons |= gamepad.MAP_BUTTON_RB; + if (in_report->buttons[1] & PS5::Buttons1::L3) gp_in.buttons |= gamepad.MAP_BUTTON_L3; + if (in_report->buttons[1] & PS5::Buttons1::R3) gp_in.buttons |= gamepad.MAP_BUTTON_R3; + if (in_report->buttons[1] & PS5::Buttons1::SHARE) gp_in.buttons |= gamepad.MAP_BUTTON_BACK; + if (in_report->buttons[1] & PS5::Buttons1::OPTIONS) gp_in.buttons |= gamepad.MAP_BUTTON_START; + if (in_report->buttons[2] & PS5::Buttons2::PS) gp_in.buttons |= gamepad.MAP_BUTTON_SYS; + if (in_report->buttons[2] & PS5::Buttons2::MUTE) gp_in.buttons |= gamepad.MAP_BUTTON_MISC; - gp_in.trigger_l = in_report_.trigger_l; - gp_in.trigger_r = in_report_.trigger_r; + gp_in.trigger_l = in_report->trigger_l; + gp_in.trigger_r = in_report->trigger_r; - gp_in.joystick_lx = Scale::uint8_to_int16(in_report_.joystick_lx); - gp_in.joystick_ly = Scale::uint8_to_int16(in_report_.joystick_ly); - gp_in.joystick_rx = Scale::uint8_to_int16(in_report_.joystick_rx); - gp_in.joystick_ry = Scale::uint8_to_int16(in_report_.joystick_ry); + gp_in.joystick_lx = Scale::uint8_to_int16(in_report->joystick_lx); + gp_in.joystick_ly = Scale::uint8_to_int16(in_report->joystick_ly); + gp_in.joystick_rx = Scale::uint8_to_int16(in_report->joystick_rx); + gp_in.joystick_ry = Scale::uint8_to_int16(in_report->joystick_ry); gamepad.set_pad_in(gp_in); tuh_hid_receive_report(address, instance); - std::memcpy(&prev_in_report_, &in_report_, PS5::IN_REPORT_CMP_SIZE); + std::memcpy(&prev_in_report_, in_report, sizeof(PS5::InReport)); } bool PS5Host::send_feedback(Gamepad& gamepad, uint8_t address, uint8_t instance) diff --git a/Firmware/RP2040/src/USBHost/HostDriver/PS5/PS5.h b/Firmware/RP2040/src/USBHost/HostDriver/PS5/PS5.h index a7b6fbc..fef2687 100644 --- a/Firmware/RP2040/src/USBHost/HostDriver/PS5/PS5.h +++ b/Firmware/RP2040/src/USBHost/HostDriver/PS5/PS5.h @@ -17,7 +17,6 @@ public: bool send_feedback(Gamepad& gamepad, uint8_t address, uint8_t instance) override; private: - PS5::InReport in_report_{}; PS5::InReport prev_in_report_{}; PS5::OutReport out_report_{}; }; diff --git a/Firmware/RP2040/src/USBHost/HostDriver/XInput/Xbox360W.cpp b/Firmware/RP2040/src/USBHost/HostDriver/XInput/Xbox360W.cpp index 87b8462..4d4e500 100644 --- a/Firmware/RP2040/src/USBHost/HostDriver/XInput/Xbox360W.cpp +++ b/Firmware/RP2040/src/USBHost/HostDriver/XInput/Xbox360W.cpp @@ -5,36 +5,48 @@ #include "host/usbh.h" +#include "TaskQueue/TaskQueue.h" #include "USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.h" #include "USBHost/HostDriver/XInput/Xbox360W.h" +#include "OGXMini/Debug.h" Xbox360WHost::~Xbox360WHost() { - TaskQueue::Core1::cancel_delayed_task(timer_info_.task_id); + TaskQueue::Core1::cancel_delayed_task(tid_chatpad_keepalive_); } void Xbox360WHost::initialize(Gamepad& gamepad, uint8_t address, uint8_t instance, const uint8_t* report_desc, uint16_t desc_len) { - std::memset(&prev_in_report_, 0, sizeof(XInput::InReportWireless)); - - timer_info_.address = address; - timer_info_.instance = instance; - timer_info_.led_quadrant = idx_ + 1; - timer_info_.task_id = TaskQueue::Core1::get_new_task_id(); - - //Repeatedly set the LED incase of disconnect, may rework the XInput driver to handle this - TaskQueue::Core1::queue_delayed_task(timer_info_.task_id, 1000, true, [this] - { - tuh_xinput::set_led(timer_info_.address, timer_info_.instance, timer_info_.led_quadrant, false); - }); - tuh_xinput::receive_report(address, instance); } void Xbox360WHost::process_report(Gamepad& gamepad, uint8_t address, uint8_t instance, const uint8_t* report, uint16_t len) { const XInput::InReportWireless* in_report = reinterpret_cast(report); - if (std::memcmp(&prev_in_report_, in_report, std::min(static_cast(len), sizeof(XInput::InReportWireless))) == 0) + + if (in_report->command[1] & 2) + { + if (in_report->chatpad_status == 0x00) + { + Gamepad::ChatpadIn gp_in_chatpad; + gp_in_chatpad[0] = in_report->chatpad[0]; + gp_in_chatpad[1] = in_report->chatpad[1]; + gp_in_chatpad[2] = in_report->chatpad[2]; + + gamepad.set_chatpad_in(gp_in_chatpad); + } + else if (in_report->chatpad_status == 0xF0 && in_report->chatpad[0] == 0x03) + { + tuh_xinput::xbox360_chatpad_init(address, instance); + } + + tuh_xinput::receive_report(address, instance); + return; + } + + if (!(in_report->command[1] & 1) || + !(in_report->report_size == 0x13) || + std::memcmp(&prev_in_report_, in_report, std::min(static_cast(len), sizeof(XInput::InReportWireless))) == 0) { tuh_xinput::receive_report(address, instance); return; @@ -67,21 +79,39 @@ void Xbox360WHost::process_report(Gamepad& gamepad, uint8_t address, uint8_t ins gp_in.joystick_rx = in_report->joystick_rx; gp_in.joystick_ry = Scale::invert_joy(in_report->joystick_ry); - if ((in_report->command[1] & 2) && (in_report->chatpad_status == 0x00)) - { - gp_in.chatpad[0] = in_report->chatpad[0]; - gp_in.chatpad[1] = in_report->chatpad[1]; - gp_in.chatpad[2] = in_report->chatpad[2]; - } - gamepad.set_pad_in(gp_in); tuh_xinput::receive_report(address, instance); - std::memcpy(&prev_in_report_, in_report, sizeof(XInput::InReportWireless)); + prev_in_report_ = *in_report; } bool Xbox360WHost::send_feedback(Gamepad& gamepad, uint8_t address, uint8_t instance) { Gamepad::PadOut gp_out = gamepad.get_pad_out(); return tuh_xinput::set_rumble(address, instance, gp_out.rumble_l, gp_out.rumble_r, false); +} + +void Xbox360WHost::connect_cb(Gamepad& gamepad, uint8_t address, uint8_t instance) +{ + tid_chatpad_keepalive_ = TaskQueue::Core1::get_new_task_id(); + + //Might not be ready for leds yet, needs delay + TaskQueue::Core1::queue_delayed_task(TaskQueue::Core1::get_new_task_id(), 1000, false, + [address, instance, this] + { + tuh_xinput::set_led(address, instance, idx_ + 1, false); + tuh_xinput::xbox360_chatpad_init(address, instance); + + TaskQueue::Core1::queue_delayed_task(tid_chatpad_keepalive_, tuh_xinput::KEEPALIVE_MS, true, + [address, instance] + { + OGXM_LOG("XInput Chatpad Keepalive\r\n"); + tuh_xinput::xbox360_chatpad_keepalive(address, instance); + }); + }); +} + +void Xbox360WHost::disconnect_cb(Gamepad& gamepad, uint8_t address, uint8_t instance) +{ + TaskQueue::Core1::cancel_delayed_task(tid_chatpad_keepalive_); } \ No newline at end of file diff --git a/Firmware/RP2040/src/USBHost/HostDriver/XInput/Xbox360W.h b/Firmware/RP2040/src/USBHost/HostDriver/XInput/Xbox360W.h index f832113..e048f2d 100644 --- a/Firmware/RP2040/src/USBHost/HostDriver/XInput/Xbox360W.h +++ b/Firmware/RP2040/src/USBHost/HostDriver/XInput/Xbox360W.h @@ -3,7 +3,6 @@ #include -#include "TaskQueue/TaskQueue.h" #include "Descriptors/XInput.h" #include "USBHost/HostDriver/HostDriver.h" @@ -19,19 +18,12 @@ public: void process_report(Gamepad& gamepad, uint8_t address, uint8_t instance, const uint8_t* report, uint16_t len) override; bool send_feedback(Gamepad& gamepad, uint8_t address, uint8_t instance) override; + void connect_cb(Gamepad& gamepad, uint8_t address, uint8_t instance) override; + void disconnect_cb(Gamepad& gamepad, uint8_t address, uint8_t instance) override; + private: - struct TimerInfo - { - uint8_t address; - uint8_t instance; - uint8_t led_quadrant; - uint32_t task_id; - }; - - TimerInfo timer_info_; + uint32_t tid_chatpad_keepalive_{0}; XInput::InReportWireless prev_in_report_; - - static bool timer_cb(struct repeating_timer *t); }; #endif // _XBOX360_WIRELESS_HOST_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/USBHost/HostDriver/XInput/XboxOG.cpp b/Firmware/RP2040/src/USBHost/HostDriver/XInput/XboxOG.cpp index cd6bbe1..37085d2 100644 --- a/Firmware/RP2040/src/USBHost/HostDriver/XInput/XboxOG.cpp +++ b/Firmware/RP2040/src/USBHost/HostDriver/XInput/XboxOG.cpp @@ -7,7 +7,7 @@ void XboxOGHost::initialize(Gamepad& gamepad, uint8_t address, uint8_t instance, const uint8_t* report_desc, uint16_t desc_len) { - gamepad.set_analog_enabled(true); + gamepad.set_analog_host(true); std::memset(&prev_in_report_, 0, sizeof(XboxOG::GP::InReport)); tuh_xinput::receive_report(address, instance); } diff --git a/Firmware/RP2040/src/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.cpp b/Firmware/RP2040/src/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.cpp index 04a53a1..afc5f70 100644 --- a/Firmware/RP2040/src/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.cpp +++ b/Firmware/RP2040/src/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.cpp @@ -3,6 +3,7 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_XINPUT) #include +#include #include "Board/board_api.h" #include "USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.h" @@ -21,49 +22,65 @@ struct Device std::array devices_; -// TU_ATTR_ALWAYS_INLINE static inline Device* get_device_by_addr(uint8_t dev_addr) -// { -// TU_VERIFY((dev_addr <= devices_.size() && dev_addr > 0), nullptr); -// return &devices_[dev_addr - 1]; -// } - -// TU_ATTR_ALWAYS_INLINE static inline Interface* get_itf_by_instance(uint8_t dev_addr, uint8_t instance) -// { -// Device* device = get_device_by_addr(dev_addr); -// TU_VERIFY(device != nullptr, nullptr); -// TU_VERIFY(instance < device->interfaces.size(), nullptr); -// return &device->interfaces[instance]; -// } - -// TU_ATTR_ALWAYS_INLINE static inline Interface* get_free_interface(uint8_t dev_addr) -// { -// Device* device = get_device_by_addr(dev_addr); -// TU_VERIFY(device != nullptr, nullptr); - -// for (auto& interface : device->interfaces) -// { -// if (interface.itf_num == 0xFF) -// { -// return &interface; -// } -// } -// return nullptr; -// } - -TU_ATTR_ALWAYS_INLINE static inline uint8_t get_device_idx_by_addr(uint8_t dev_addr) +TU_ATTR_ALWAYS_INLINE static inline Device* get_device_by_addr(uint8_t dev_addr) { - TU_VERIFY((dev_addr <= devices_.size() && dev_addr > 0), INVALID_IDX); - return dev_addr - 1; + TU_VERIFY((dev_addr <= devices_.size() && dev_addr > 0), nullptr); + return &devices_[dev_addr - 1]; +} + +TU_ATTR_ALWAYS_INLINE static inline Interface* get_itf_by_itf_num(uint8_t dev_addr, uint8_t itf_num) +{ + Device* device = get_device_by_addr(dev_addr); + TU_VERIFY(device != nullptr, nullptr); + + for (auto& interface : device->interfaces) + { + if (interface.itf_num == itf_num) + { + return &interface; + } + } + return nullptr; +} + +TU_ATTR_ALWAYS_INLINE static inline Interface* get_itf_by_ep(uint8_t dev_addr, uint8_t ep_addr) +{ + Device* device = get_device_by_addr(dev_addr); + TU_VERIFY(device != nullptr, nullptr); + + for (auto& interface : device->interfaces) + { + if (interface.ep_in == ep_addr || interface.ep_out == ep_addr) + { + return &interface; + } + } + return nullptr; +} + +TU_ATTR_ALWAYS_INLINE static inline Interface* get_free_itf(uint8_t dev_addr) +{ + Device* device = get_device_by_addr(dev_addr); + TU_VERIFY(device != nullptr, nullptr); + + for (auto& interface : device->interfaces) + { + if (interface.itf_num == INVALID_IDX) + { + return &interface; + } + } + return nullptr; } TU_ATTR_ALWAYS_INLINE static inline uint8_t get_instance_by_itf_num(uint8_t dev_addr, uint8_t itf_num) { - uint8_t dev_idx = get_device_idx_by_addr(dev_addr); - TU_VERIFY(dev_idx != INVALID_IDX, INVALID_IDX); + Device* device = get_device_by_addr(dev_addr); + TU_VERIFY(device != nullptr, INVALID_IDX); - for (uint8_t i = 0; i < devices_[dev_idx].interfaces.size(); ++i) + for (uint8_t i = 0; i < device->interfaces.size(); ++i) { - if (devices_[dev_idx].interfaces[i].itf_num == itf_num) + if (device->interfaces[i].itf_num == itf_num) { return i; } @@ -71,34 +88,22 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t get_instance_by_itf_num(uint8_t dev_ return INVALID_IDX; } -TU_ATTR_ALWAYS_INLINE static inline uint8_t get_instance_by_ep(uint8_t dev_addr, uint8_t ep_addr) +TU_ATTR_ALWAYS_INLINE static inline Interface* get_itf_by_instance(uint8_t dev_addr, uint8_t instance) { - uint8_t dev_idx = get_device_idx_by_addr(dev_addr); - TU_VERIFY(dev_idx != INVALID_IDX, INVALID_IDX); - - for (uint8_t i = 0; i < devices_[dev_idx].interfaces.size(); ++i) - { - if (devices_[dev_idx].interfaces[i].ep_in == ep_addr || devices_[dev_idx].interfaces[i].ep_out == ep_addr) - { - return i; - } - } - return INVALID_IDX; + Device* device = get_device_by_addr(dev_addr); + TU_VERIFY(device != nullptr, nullptr); + TU_VERIFY(instance < device->interfaces.size(), nullptr); + return &device->interfaces[instance]; } -TU_ATTR_ALWAYS_INLINE static inline uint8_t get_free_itf_idx(uint8_t dev_addr) +static void std_sleep_ms(uint32_t ms) { - uint8_t dev_idx = get_device_idx_by_addr(dev_addr); - TU_VERIFY(dev_idx != INVALID_IDX, INVALID_IDX); - - for (uint8_t i = 0; i < devices_[dev_idx].interfaces.size(); ++i) + auto start = std::chrono::high_resolution_clock::now(); + while ( std::chrono::duration_cast( + std::chrono::high_resolution_clock::now() - start).count() < ms) { - if (devices_[dev_idx].interfaces[i].itf_num == INVALID_IDX) - { - return i; - } + tuh_task(); } - return INVALID_IDX; } static void wait_for_tx_complete(uint8_t dev_addr, uint8_t ep_addr) @@ -123,69 +128,6 @@ bool send_ctrl_xfer(uint8_t dev_addr, const tusb_control_request_t* request, uin return tuh_control_xfer(&transfer); } -static void xbox360w_chatpad_init(Interface *interface, uint8_t address, uint8_t instance) -{ - send_report(address, instance, Xbox360W::INQUIRE_PRESENT, sizeof(Xbox360W::INQUIRE_PRESENT)); - wait_for_tx_complete(address, interface->ep_out); - send_report(address, instance, Xbox360W::CONTROLLER_INFO, sizeof(Xbox360W::CONTROLLER_INFO)); - wait_for_tx_complete(address, interface->ep_out); - send_report(address, instance, Xbox360W::Chatpad::INIT, sizeof(Xbox360W::Chatpad::INIT)); - wait_for_tx_complete(address, interface->ep_out); - - uint8_t led_ctrl[4]; - std::memcpy(led_ctrl, Xbox360W::Chatpad::LED_CTRL, sizeof(Xbox360W::Chatpad::LED_CTRL)); - led_ctrl[2] = Xbox360W::Chatpad::LED_ON[0]; - - send_report(address, instance, led_ctrl, sizeof(led_ctrl)); - wait_for_tx_complete(address, interface->ep_out); - - interface->chatpad_inited = true; - interface->chatpad_stage = ChatpadStage::KEEPALIVE_1; -} - -bool xbox360_chatpad_keepalive(uint8_t address, uint8_t instance) -{ - uint8_t dev_idx = get_device_idx_by_addr(address); - uint8_t itf_idx = get_instance_by_itf_num(address, instance); - TU_VERIFY(dev_idx != INVALID_IDX && itf_idx != INVALID_IDX, false); - - Interface& interface = devices_[dev_idx].interfaces[itf_idx]; - TU_VERIFY(interface.connected, false); - - switch (interface.chatpad_stage) - { - case ChatpadStage::KEEPALIVE_1: - switch (interface.dev_type) - { - case DevType::XBOX360: - send_ctrl_xfer(interface.dev_addr, &Xbox360::Chatpad::KEEPALIVE_1, nullptr, nullptr, 0); - break; - case DevType::XBOX360W: - send_report(interface.dev_addr, instance, Xbox360W::Chatpad::KEEPALIVE_1, sizeof(Xbox360W::Chatpad::KEEPALIVE_1)); - break; - default: - break; - } - interface.chatpad_stage = ChatpadStage::KEEPALIVE_2; - break; - case ChatpadStage::KEEPALIVE_2: - switch (interface.dev_type) - { - case DevType::XBOX360: - send_ctrl_xfer(interface.dev_addr, &Xbox360::Chatpad::KEEPALIVE_2, nullptr, nullptr, 0); - break; - case DevType::XBOX360W: - send_report(interface.dev_addr, instance, Xbox360W::Chatpad::KEEPALIVE_2, sizeof(Xbox360W::Chatpad::KEEPALIVE_2)); - break; - default: - break; - } - interface.chatpad_stage = ChatpadStage::KEEPALIVE_1; - break; - } - return true; -} - static void xboxone_init(Interface *interface, uint8_t dev_addr, uint8_t instance) { uint16_t PID, VID; @@ -216,14 +158,14 @@ static void xboxone_init(Interface *interface, uint8_t dev_addr, uint8_t instanc static bool init() { - TU_LOG2("XInput Init\r\n"); + TU_LOG1("XInput Init\r\n"); devices_.fill(Device()); return true; } static bool open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { - TU_LOG2("XInput Open\r\n"); + TU_LOG1("XInput Open\r\n"); TU_VERIFY(desc_itf->bNumEndpoints > 0); DevType dev_type = DevType::UNKNOWN; @@ -250,13 +192,10 @@ static bool open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * dev_type = DevType::XBOXOG; } - TU_VERIFY(dev_type != DevType::UNKNOWN); + TU_VERIFY(dev_type != DevType::UNKNOWN && itf_type != ItfType::UNKNOWN); - uint8_t dev_idx = get_device_idx_by_addr(dev_addr); - uint8_t itf_idx = get_free_itf_idx(dev_addr); - TU_VERIFY(itf_idx != INVALID_IDX && dev_idx != INVALID_IDX); - - Interface& interface = devices_[dev_idx].interfaces[itf_idx]; + Interface* interface = get_free_itf(dev_addr); + TU_VERIFY(interface != nullptr); const uint8_t *p_desc = reinterpret_cast(desc_itf); int endpoint = 0; @@ -275,20 +214,20 @@ static bool open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); - interface.itf_num = desc_itf->bInterfaceNumber; - interface.itf_type = itf_type; - interface.dev_type = dev_type; - interface.dev_addr = dev_addr; + interface->itf_num = desc_itf->bInterfaceNumber; + interface->itf_type = itf_type; + interface->dev_type = dev_type; + interface->dev_addr = dev_addr; if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_OUT) { - interface.ep_out = desc_ep->bEndpointAddress; - interface.ep_out_size = tu_edpt_packet_size(desc_ep); + interface->ep_out = desc_ep->bEndpointAddress; + interface->ep_out_size = tu_edpt_packet_size(desc_ep); } else { - interface.ep_in = desc_ep->bEndpointAddress; - interface.ep_in_size = tu_edpt_packet_size(desc_ep); + interface->ep_in = desc_ep->bEndpointAddress; + interface->ep_in_size = tu_edpt_packet_size(desc_ep); } endpoint++; @@ -301,22 +240,23 @@ static bool open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * static bool set_config(uint8_t dev_addr, uint8_t itf_num) { + TU_LOG1("XInput Set Config\r\n"); + + Interface* interface = get_itf_by_itf_num(dev_addr, itf_num); uint8_t instance = get_instance_by_itf_num(dev_addr, itf_num); - uint8_t dev_idx = get_device_idx_by_addr(dev_addr); - TU_VERIFY(instance != INVALID_IDX && dev_idx != INVALID_IDX); - Interface& interface = devices_[dev_idx].interfaces[instance]; + TU_VERIFY(instance != INVALID_IDX && interface != nullptr); - interface.connected = true; + interface->connected = true; - switch (interface.dev_type) + switch (interface->dev_type) { case DevType::XBOX360W: - interface.connected = false; + interface->connected = false; send_report(dev_addr, instance, Xbox360W::INQUIRE_PRESENT, sizeof(Xbox360W::INQUIRE_PRESENT)); - wait_for_tx_complete(dev_addr, interface.ep_out); + wait_for_tx_complete(dev_addr, interface->ep_out); break; case DevType::XBOXONE: - xboxone_init(&interface, dev_addr, instance); + xboxone_init(interface, dev_addr, instance); break; default: break; @@ -324,40 +264,39 @@ static bool set_config(uint8_t dev_addr, uint8_t itf_num) if (mount_cb) { - mount_cb(dev_addr, instance, &interface); + mount_cb(dev_addr, instance, interface); } - usbh_driver_set_config_complete(dev_addr, interface.itf_num); + usbh_driver_set_config_complete(dev_addr, interface->itf_num); return true; } static bool xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + Interface* interface = get_itf_by_ep(dev_addr, ep_addr); + uint8_t instance = get_instance_by_itf_num(dev_addr, interface->itf_num); + TU_VERIFY(interface != nullptr && instance != INVALID_IDX); + const uint8_t dir = tu_edpt_dir(ep_addr); - uint8_t dev_idx = get_device_idx_by_addr(dev_addr); - uint8_t instance = get_instance_by_ep(dev_addr, ep_addr); - TU_VERIFY(dev_idx != INVALID_IDX && instance != INVALID_IDX); - - Interface& interface = devices_[dev_idx].interfaces[instance]; if (result != XFER_RESULT_SUCCESS) { if (dir == TUSB_DIR_IN) { - report_received_cb(dev_addr, instance, interface.ep_in_buffer.data(), static_cast(interface.ep_in_size)); + report_received_cb(dev_addr, instance, interface->ep_in_buffer.data(), static_cast(interface->ep_in_size)); } else if (report_sent_cb) { - report_sent_cb(dev_addr, instance, interface.ep_out_buffer.data(), static_cast(interface.ep_out_size)); + report_sent_cb(dev_addr, instance, interface->ep_out_buffer.data(), static_cast(interface->ep_out_size)); } } if (dir == TUSB_DIR_IN) { bool new_pad_data = false; - uint8_t* in_buffer = interface.ep_in_buffer.data(); + uint8_t* in_buffer = interface->ep_in_buffer.data(); - switch (interface.dev_type) + switch (interface->dev_type) { case DevType::XBOX360: if (in_buffer[1] == 0x14) @@ -368,20 +307,27 @@ static bool xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uin case DevType::XBOX360W: if (in_buffer[0] & 0x08) { - if (in_buffer[1] != 0x00 && !interface.connected) + if (in_buffer[1] != 0x00 && !interface->connected) { - interface.connected = true; - // xbox360w_chatpad_init(interface, dev_addr, instance); + interface->connected = true; + + TU_LOG1("Xbox 360 wireless controller connected\n"); + + //I think some 3rd party adapters need this: + std_sleep_ms(1000); send_report(dev_addr, instance, Xbox360W::RUMBLE_ENABLE, sizeof(Xbox360W::RUMBLE_ENABLE)); + if (xbox360w_connect_cb) { xbox360w_connect_cb(dev_addr, instance); } } - else if (in_buffer[1] == 0x00 && interface.connected) + else if (in_buffer[1] == 0x00 && interface->connected) { - interface.connected = false; - interface.chatpad_inited = false; + interface->connected = false; + interface->chatpad_inited = false; + + TU_LOG1("Xbox 360 wireless controller disconnected\n"); if (xbox360w_disconnect_cb) { @@ -389,7 +335,7 @@ static bool xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uin } } } - if ((in_buffer[1] & 1) && in_buffer[5] == 0x13) + if ((in_buffer[1] & 1 && in_buffer[5] == 0x13) || (in_buffer[1] & 2)) { new_pad_data = true; } @@ -413,7 +359,7 @@ static bool xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uin } break; case XboxOne::GIP_CMD_ANNOUNCE: - xboxone_init(&interface, dev_addr, instance); + xboxone_init(interface, dev_addr, instance); break; } break; @@ -439,7 +385,7 @@ static bool xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uin { if (report_sent_cb) { - report_sent_cb(dev_addr, instance, interface.ep_out_buffer.data(), static_cast(xferred_bytes)); + report_sent_cb(dev_addr, instance, interface->ep_out_buffer.data(), static_cast(xferred_bytes)); } } return true; @@ -447,30 +393,28 @@ static bool xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uin bool deinit() { - TU_LOG2("XInput deinit\r\n"); + TU_LOG1("XInput deinit\r\n"); return true; } void close(uint8_t dev_addr) { - TU_LOG2("XInput close\r\n"); - uint8_t dev_idx = get_device_idx_by_addr(dev_addr); - TU_VERIFY(dev_idx != INVALID_IDX, ); - TU_LOG2("XInput dev addr verified\r\n"); - Device& device = devices_[dev_idx]; + TU_LOG1("XInput close\r\n"); - for (uint8_t i = 0; i < device.interfaces.size(); ++i) + Device* device = get_device_by_addr(dev_addr); + TU_VERIFY(device != nullptr, ); + + for (uint8_t i = 0; i < device->interfaces.size(); ++i) { - if (device.interfaces[i].itf_num != 0xFF && unmount_cb) + if (device->interfaces[i].itf_num != 0xFF && unmount_cb) { - TU_LOG2("XInput unmounting\r\n"); - unmount_cb(dev_addr, i, &device.interfaces[i]); - TU_LOG2("XInput unmount\r\n"); - device.interfaces[i].itf_num = 0xFF; - device.interfaces[i].connected = false; + TU_LOG1("XInput unmounting\r\n"); + unmount_cb(dev_addr, i, &device->interfaces[i]); + TU_LOG1("XInput unmount\r\n"); + device->interfaces[i].itf_num = 0xFF; + device->interfaces[i].connected = false; } } - // device = Device(); } //Public API @@ -479,6 +423,11 @@ const usbh_class_driver_t* class_driver() { static const usbh_class_driver_t class_driver = { + #if CFG_TUSB_DEBUG >= 2 + .name = "XInput", + #else + .name = nullptr, + #endif .init = init, .deinit = deinit, .open = open, @@ -491,18 +440,15 @@ const usbh_class_driver_t* class_driver() bool send_report(uint8_t dev_addr, uint8_t instance, const uint8_t *buffer, uint16_t len) { - uint8_t dev_idx = get_device_idx_by_addr(dev_addr); - TU_VERIFY(dev_idx != INVALID_IDX && instance < MAX_INTERFACES, false); + Interface* interface = get_itf_by_instance(dev_addr, instance); + TU_VERIFY(interface != nullptr); + TU_VERIFY(usbh_edpt_claim(dev_addr, interface->ep_out)); - Interface& interface = devices_[dev_idx].interfaces[instance]; + std::memcpy(interface->ep_out_buffer.data(), buffer, len); - TU_VERIFY(usbh_edpt_claim(dev_addr, interface.ep_out)); - - std::memcpy(interface.ep_out_buffer.data(), buffer, len); - - if (!usbh_edpt_xfer(dev_addr, interface.ep_out, interface.ep_out_buffer.data(), len)) + if (!usbh_edpt_xfer(dev_addr, interface->ep_out, interface->ep_out_buffer.data(), len)) { - usbh_edpt_release(dev_addr, interface.ep_out); + usbh_edpt_release(dev_addr, interface->ep_out); return false; } return true; @@ -510,14 +456,12 @@ bool send_report(uint8_t dev_addr, uint8_t instance, const uint8_t *buffer, uint bool receive_report(uint8_t dev_addr, uint8_t instance) { - uint8_t dev_idx = get_device_idx_by_addr(dev_addr); - TU_VERIFY(dev_idx != INVALID_IDX && instance < MAX_INTERFACES, false); + Interface* interface = get_itf_by_instance(dev_addr, instance); + TU_VERIFY(interface != nullptr); - Interface& interface = devices_[dev_idx].interfaces[instance]; - - if (!usbh_edpt_xfer(dev_addr, interface.ep_in, interface.ep_in_buffer.data(), interface.ep_in_size)) + if (!usbh_edpt_xfer(dev_addr, interface->ep_in, interface->ep_in_buffer.data(), interface->ep_in_size)) { - usbh_edpt_release(dev_addr, interface.ep_in); + usbh_edpt_release(dev_addr, interface->ep_in); return false; } return true; @@ -525,15 +469,13 @@ bool receive_report(uint8_t dev_addr, uint8_t instance) bool set_led(uint8_t dev_addr, uint8_t instance, uint8_t quadrant, bool block) { - uint8_t dev_idx = get_device_idx_by_addr(dev_addr); - TU_VERIFY(dev_idx != INVALID_IDX && instance < MAX_INTERFACES, false); - - Interface& interface = devices_[dev_idx].interfaces[instance]; + Interface* interface = get_itf_by_instance(dev_addr, instance); + TU_VERIFY(interface != nullptr); uint8_t buffer[32]; uint16_t len; - switch (interface.dev_type) + switch (interface->dev_type) { case DevType::XBOX360W: std::memcpy(buffer, Xbox360W::LED, sizeof(Xbox360W::LED)); @@ -552,22 +494,20 @@ bool set_led(uint8_t dev_addr, uint8_t instance, uint8_t quadrant, bool block) bool ret = send_report(dev_addr, instance, buffer, len); if (block && ret) { - wait_for_tx_complete(dev_addr, interface.ep_out); + wait_for_tx_complete(dev_addr, interface->ep_out); } return ret; } bool set_rumble(uint8_t dev_addr, uint8_t instance, uint8_t rumble_l, uint8_t rumble_r, bool block) { - uint8_t dev_idx = get_device_idx_by_addr(dev_addr); - TU_VERIFY(dev_idx != INVALID_IDX && instance < MAX_INTERFACES, false); - - Interface& interface = devices_[dev_idx].interfaces[instance]; + Interface* interface = get_itf_by_instance(dev_addr, instance); + TU_VERIFY(interface != nullptr); uint8_t buffer[32]; uint16_t len; - switch (interface.dev_type) + switch (interface->dev_type) { case DevType::XBOX360W: std::memcpy(buffer, Xbox360W::RUMBLE, sizeof(Xbox360W::RUMBLE)); @@ -602,718 +542,79 @@ bool set_rumble(uint8_t dev_addr, uint8_t instance, uint8_t rumble_l, uint8_t ru bool ret = send_report(dev_addr, instance, buffer, len); if (block && ret) { - wait_for_tx_complete(dev_addr, interface.ep_out); + wait_for_tx_complete(dev_addr, interface->ep_out); + } + return true; +} + +void xbox360_chatpad_init(uint8_t address, uint8_t instance) +{ + TU_LOG1("XInput Chatpad Init\r\n"); + + Interface* interface = get_itf_by_itf_num(address, instance); + TU_VERIFY(interface != nullptr && interface->connected, ); + TU_VERIFY(interface->dev_type == DevType::XBOX360W, ); //Only supported on Xbox 360 Wireless atm, wired is more complicated + + send_report(address, instance, Xbox360W::CONTROLLER_INFO, sizeof(Xbox360W::CONTROLLER_INFO)); + wait_for_tx_complete(address, interface->ep_out); + send_report(address, instance, Xbox360W::Chatpad::INIT, sizeof(Xbox360W::Chatpad::INIT)); + wait_for_tx_complete(address, interface->ep_out); + send_report(address, instance, Xbox360W::RUMBLE_ENABLE, sizeof(Xbox360W::RUMBLE_ENABLE)); + wait_for_tx_complete(address, interface->ep_out); + + uint8_t led_ctrl[4]; + std::memcpy(led_ctrl, Xbox360W::Chatpad::LED_CTRL, sizeof(Xbox360W::Chatpad::LED_CTRL)); + led_ctrl[2] = Xbox360W::Chatpad::LED_ON[0]; + + send_report(address, instance, led_ctrl, sizeof(led_ctrl)); + wait_for_tx_complete(address, interface->ep_out); + + interface->chatpad_inited = true; + interface->chatpad_stage = ChatpadStage::KEEPALIVE_1; +} + +bool xbox360_chatpad_keepalive(uint8_t address, uint8_t instance) +{ + Interface* interface = get_itf_by_itf_num(address, instance); + TU_VERIFY(interface != nullptr, false); + TU_VERIFY(interface->connected && interface->chatpad_inited, false); + + switch (interface->chatpad_stage) + { + case ChatpadStage::KEEPALIVE_1: + switch (interface->dev_type) + { + case DevType::XBOX360: + send_ctrl_xfer(interface->dev_addr, &Xbox360::Chatpad::KEEPALIVE_1, nullptr, nullptr, 0); + break; + case DevType::XBOX360W: + send_report(interface->dev_addr, instance, Xbox360W::Chatpad::KEEPALIVE_1, sizeof(Xbox360W::Chatpad::KEEPALIVE_1)); + break; + default: + break; + } + interface->chatpad_stage = ChatpadStage::KEEPALIVE_2; + break; + case ChatpadStage::KEEPALIVE_2: + switch (interface->dev_type) + { + case DevType::XBOX360: + send_ctrl_xfer(interface->dev_addr, &Xbox360::Chatpad::KEEPALIVE_2, nullptr, nullptr, 0); + break; + case DevType::XBOX360W: + send_report(interface->dev_addr, instance, Xbox360W::Chatpad::KEEPALIVE_2, sizeof(Xbox360W::Chatpad::KEEPALIVE_2)); + break; + default: + break; + } + interface->chatpad_stage = ChatpadStage::KEEPALIVE_1; + break; + default: + break; } return true; } } // namespace tuh_xinput -// #ifndef CFG_TUH_XINPUT_WIRED_CHATPAD_EN -// #define CFG_TUH_XINPUT_WIRED_CHATPAD_EN 0 -// #endif - -// #include - -// #include "USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.h" -// #include "USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput_cmd.h" - -// namespace tuh_xinput { - -// static constexpr uint8_t INTERFACE_MULT = (CFG_TUH_XINPUT_WIRED_CHATPAD_EN > 0) ? 2 : 1; -// static constexpr uint8_t INTERFACE_MAX = CFG_TUH_XINPUT * INTERFACE_MULT; - -// enum class ChatpadStage -// { -// INIT_1 = 0, -// INIT_2, -// INIT_3, -// INIT_4, -// INIT_5, -// INIT_6, -// INIT_1E, -// INIT_1F, -// LED_REQUEST -// }; - -// struct Device -// { -// uint8_t inst_count{0}; -// std::array interfaces_; -// }; - -// static std::array devices_; - -// TU_ATTR_ALWAYS_INLINE static inline Device* get_device(uint8_t dev_addr) -// { -// return &devices_[dev_addr - 1]; -// } - -// TU_ATTR_ALWAYS_INLINE static inline Interface* get_interface_by_inst(uint8_t dev_addr, uint8_t instance) -// { -// return &get_device(dev_addr)->interfaces_[instance]; -// } - -// TU_ATTR_ALWAYS_INLINE static inline uint8_t get_instance_by_epaddr(uint8_t dev_addr, uint8_t ep_addr) -// { -// for (uint8_t inst = 0; inst < INTERFACE_MAX; inst++) -// { -// Interface *interface = get_interface_by_inst(dev_addr, inst); - -// if ((ep_addr == interface->ep_in) || (ep_addr == interface->ep_out)) -// { -// return inst; -// } -// } -// return 0xff; -// } - -// TU_ATTR_ALWAYS_INLINE static inline uint8_t get_instance_by_itf(uint8_t dev_addr, uint8_t itf_num) -// { -// for (uint8_t inst = 0; inst < INTERFACE_MAX; inst++) -// { -// Interface *interface = get_interface_by_inst(dev_addr, inst); - -// if (itf_num == interface->itf_num) -// { -// return inst; -// } -// } -// return 0xff; -// } - -// static void wait_for_tx_complete(uint8_t dev_addr, uint8_t ep_addr) -// { -// while (usbh_edpt_busy(dev_addr, ep_addr)) -// { -// tuh_task(); -// } -// } - -// void ctrl_xfer_cb(tuh_xfer_t* xfer) { return; } - -// bool send_ctrl_xfer(uint8_t dev_addr, const tusb_control_request_t* setup, uint8_t* buffer, bool block = true) -// { -// tuh_xfer_t xfer = -// { -// .daddr = dev_addr, -// .ep_addr = 0, -// .setup = setup, -// .buffer = buffer, -// .complete_cb = block ? nullptr : ctrl_xfer_cb, -// .user_data = 0 -// }; -// if (tuh_control_xfer(&xfer)) -// { -// return true; -// } -// return false; -// } - -// bool run_tuh_task(uint32_t duration_ms) -// { -// if (!time_in_milliseconds_cb) -// { -// return false; -// } -// uint32_t end_time = time_in_milliseconds_cb() + duration_ms; -// while (end_time > time_in_milliseconds_cb()) -// { -// tuh_task(); -// } -// return true; -// } - -// static void xboxone_init(Interface *xid_itf, uint8_t dev_addr, uint8_t instance) -// { -// uint16_t pid, vid; -// tuh_vid_pid_get(dev_addr, &vid, &pid); - -// send_report(dev_addr, instance, XboxOne::POWER_ON, sizeof(XboxOne::POWER_ON)); -// wait_for_tx_complete(dev_addr, xid_itf->ep_out); -// send_report(dev_addr, instance, XboxOne::S_INIT, sizeof(XboxOne::S_INIT)); -// wait_for_tx_complete(dev_addr, xid_itf->ep_out); - -// if (vid == 0x045e && (pid == 0x0b00)) -// { -// send_report(dev_addr, instance, XboxOne::EXTRA_INPUT_PACKET_INIT, sizeof(XboxOne::EXTRA_INPUT_PACKET_INIT)); -// wait_for_tx_complete(dev_addr, xid_itf->ep_out); -// } - -// //Required for PDP aftermarket controllers -// if (vid == 0x0e6f) -// { -// send_report(dev_addr, instance, XboxOne::PDP_LED_ON, sizeof(XboxOne::PDP_LED_ON)); -// wait_for_tx_complete(dev_addr, xid_itf->ep_out); -// send_report(dev_addr, instance, XboxOne::PDP_AUTH, sizeof(XboxOne::PDP_AUTH)); -// wait_for_tx_complete(dev_addr, xid_itf->ep_out); -// } -// } - -// static void xbox360w_chatpad_init(uint8_t address, uint8_t instance) -// { -// Interface *xid_itf = get_interface_by_inst(address, instance); - -// send_report(address, instance, Xbox360W::INQUIRE_PRESENT, sizeof(Xbox360W::INQUIRE_PRESENT)); -// wait_for_tx_complete(address, xid_itf->ep_out); -// send_report(address, instance, Xbox360W::CONTROLLER_INFO, sizeof(Xbox360W::CONTROLLER_INFO)); -// wait_for_tx_complete(address, xid_itf->ep_out); -// send_report(address, instance, Xbox360W::Chatpad::INIT, sizeof(Xbox360W::Chatpad::INIT)); -// wait_for_tx_complete(address, xid_itf->ep_out); - -// uint8_t led_ctrl[4]; -// std::memcpy(led_ctrl, Xbox360W::Chatpad::LED_CTRL, sizeof(Xbox360W::Chatpad::LED_CTRL)); -// led_ctrl[2] = Xbox360W::Chatpad::LED_ON[0]; - -// send_report(address, instance, led_ctrl, sizeof(led_ctrl)); -// wait_for_tx_complete(address, xid_itf->ep_out); - -// xid_itf->chatpad_initialized = true; -// } - -// #if (CFG_TUH_XINPUT_WIRED_CHATPAD_EN > 0) -// static void xbox360_chatpad_init(uint8_t address, uint8_t instance) -// { -// if (!time_in_milliseconds_cb) -// { -// return; -// } - -// Interface *xid_itf = get_interface_by_inst(address, instance); -// ChatpadStage init_stage = ChatpadStage::INIT_1; - -// tusb_desc_device_t desc_device; -// tuh_descriptor_get_device(address, &desc_device, 18, nullptr, 0); - -// uint8_t buffer[2] = {0x01, 0x02}; - -// // if (desc_device.bcdDevice == 0x0114) -// // { -// buffer[0] = 0x09; -// buffer[1] = 0x00; -// // } - -// while (!xid_itf->chatpad_initialized) -// { -// switch (init_stage) -// { -// case ChatpadStage::INIT_1: -// send_ctrl_xfer(address, &Xbox360::Chatpad::INIT_1, nullptr); -// init_stage = ChatpadStage::INIT_2; -// break; -// case ChatpadStage::INIT_2: -// send_ctrl_xfer(address, &Xbox360::Chatpad::INIT_2, nullptr); -// init_stage = ChatpadStage::INIT_3; -// break; -// case ChatpadStage::INIT_3: -// send_ctrl_xfer(address, &Xbox360::Chatpad::INIT_3, nullptr); -// init_stage = ChatpadStage::INIT_4; -// break; -// case ChatpadStage::INIT_4: -// if (send_ctrl_xfer(address, &Xbox360::Chatpad::INIT_4, buffer)) -// { -// init_stage = ChatpadStage::INIT_5; -// } -// break; -// case ChatpadStage::INIT_5: -// if (send_ctrl_xfer(address, &Xbox360::Chatpad::INIT_5, buffer)) -// { -// init_stage = ChatpadStage::INIT_6; -// } -// break; -// case ChatpadStage::INIT_6: -// if (send_ctrl_xfer(address, &Xbox360::Chatpad::INIT_6, buffer)) -// { -// init_stage = ChatpadStage::INIT_1E; -// } -// break; -// case ChatpadStage::INIT_1E: -// run_tuh_task(1000); -// if (send_ctrl_xfer(address, &Xbox360::Chatpad::KEEPALIVE_2, nullptr)) -// { -// init_stage = ChatpadStage::INIT_1F; -// } -// break; -// case ChatpadStage::INIT_1F: -// run_tuh_task(1000); -// if (send_ctrl_xfer(address, &Xbox360::Chatpad::KEEPALIVE_1, nullptr)) -// { -// init_stage = ChatpadStage::LED_REQUEST; -// } -// break; -// case ChatpadStage::LED_REQUEST: -// if (send_ctrl_xfer(address, &Xbox360::Chatpad::LEDS_1B, nullptr)) -// { -// xid_itf->chatpad_initialized = true; -// } -// break; -// } -// } -// } -// #endif // CFG_TUH_XINPUT_WIRED_CHATPAD_EN - -// //Class driver - -// bool xinputh_init() -// { -// for (auto& device : devices_) -// { -// device.inst_count = 0; -// device.interfaces_.fill(Interface()); -// } -// return true; -// } - -// bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -// { -// TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX); - -// Type type = Type::UNKNOWN; - -// if (desc_itf->bNumEndpoints < 1) -// { -// type = Type::UNKNOWN; -// } -// else if (desc_itf->bInterfaceSubClass == 0x5D && desc_itf->bInterfaceProtocol == 0x81) -// { -// type = Type::XBOX360_WIRELESS; -// } -// else if (desc_itf->bInterfaceSubClass == 0x5D && desc_itf->bInterfaceProtocol == 0x01) -// { -// type = Type::XBOX360_WIRED; -// } -// #if (CFG_TUH_XINPUT_WIRED_CHATPAD_EN > 0) -// else if (desc_itf->bInterfaceNumber == 2 && desc_itf->bInterfaceSubClass == 0x5d && desc_itf->bInterfaceProtocol == 0x02) -// { -// uint16_t vid, pid; -// tuh_vid_pid_get(dev_addr, &vid, &pid); -// if (vid == 0x045e && pid == 0x028e) -// { -// type = Type::XBOX360_WIRED_CHATPAD; -// } -// } -// #endif // CFG_TUH_XINPUT_WIRED_CHATPAD_EN -// else if (desc_itf->bInterfaceSubClass == 0x47 && desc_itf->bInterfaceProtocol == 0xD0) -// { -// type = Type::XBOXONE; -// } -// else if (desc_itf->bInterfaceClass == 0x58 && desc_itf->bInterfaceSubClass == 0x42) -// { -// type = Type::XBOXOG; -// } - -// if (type == Type::UNKNOWN) -// { -// TU_LOG2("XINPUT: Not a valid interface\n"); -// return false; -// } - -// TU_LOG2("XINPUT opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); - -// Device *xinput_dev = get_device(dev_addr); -// bool dual_interface = (type == Type::XBOX360_WIRED_CHATPAD || type == Type::XBOX360_WIRED); -// TU_ASSERT(xinput_dev->inst_count < (dual_interface ? INTERFACE_MAX : CFG_TUH_XINPUT), 0); - -// Interface *xid_itf = get_interface_by_inst(dev_addr, xinput_dev->inst_count); -// xid_itf->itf_num = desc_itf->bInterfaceNumber; -// xid_itf->type = type; - -// //Parse descriptor for all endpoints and open them -// uint8_t const *p_desc = (uint8_t const *)desc_itf; -// int endpoint = 0; -// int pos = 0; - -// while (endpoint < desc_itf->bNumEndpoints && pos < max_len) -// { -// if (tu_desc_type(p_desc) != TUSB_DESC_ENDPOINT) -// { -// pos += tu_desc_len(p_desc); -// p_desc = tu_desc_next(p_desc); -// continue; -// } - -// tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *)p_desc; -// TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); -// TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); - -// if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_OUT) -// { -// xid_itf->ep_out = desc_ep->bEndpointAddress; -// xid_itf->ep_out_size = static_cast(tu_edpt_packet_size(desc_ep)); -// } -// else -// { -// xid_itf->ep_in = desc_ep->bEndpointAddress; -// xid_itf->ep_in_size = static_cast(tu_edpt_packet_size(desc_ep)); -// } - -// endpoint++; -// pos += tu_desc_len(p_desc); -// p_desc = tu_desc_next(p_desc); -// } - -// xinput_dev->inst_count++; -// return true; -// } - -// bool xinputh_set_config(uint8_t dev_addr, uint8_t itf_num) -// { -// uint8_t instance = get_instance_by_itf(dev_addr, itf_num); -// Interface *xid_itf = get_interface_by_inst(dev_addr, instance); -// xid_itf->connected = true; - -// if (xid_itf->type == Type::XBOX360_WIRELESS) -// { -// xid_itf->connected = false; -// send_report(dev_addr, instance, Xbox360W::INQUIRE_PRESENT, sizeof(Xbox360W::INQUIRE_PRESENT)); -// wait_for_tx_complete(dev_addr, xid_itf->ep_out); -// } -// else if (xid_itf->type == Type::XBOX360_WIRED) -// { -// } -// #if (CFG_TUH_XINPUT_WIRED_CHATPAD_EN > 0) -// else if (xid_itf->type == Type::XBOX360_WIRED_CHATPAD) -// { -// xbox360_chatpad_init(dev_addr, instance); -// } -// #endif -// else if (xid_itf->type == Type::XBOXONE) -// { -// xboxone_init(xid_itf, dev_addr, instance); -// } - -// if (mount_cb) -// { -// mount_cb(dev_addr, instance, xid_itf); -// } - -// usbh_driver_set_config_complete(dev_addr, xid_itf->itf_num); -// return true; -// } - -// bool xinputh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -// { -// uint8_t const dir = tu_edpt_dir(ep_addr); -// uint8_t const instance = get_instance_by_epaddr(dev_addr, ep_addr); -// Interface *xid_itf = get_interface_by_inst(dev_addr, instance); -// uint8_t *rdata = xid_itf->ep_in_buffer.data(); -// bool new_pad_data = false; - -// xid_itf->last_xfer_result = result; -// xid_itf->last_xfer_size = xferred_bytes; - -// // On transfer error, bail early but notify the application -// if (result != XFER_RESULT_SUCCESS) -// { -// // if (dir == TUSB_DIR_IN) -// // { -// // report_received_cb(dev_addr, instance, xid_itf->ep_in_buffer.data(), xid_itf->ep_in_buffer.size()); -// // } -// // else if (report_sent_cb) -// // { -// // report_sent_cb(dev_addr, instance, xid_itf->ep_out_buffer.data(), xferred_bytes); -// // } -// return false; -// } - -// if (xid_itf->type == Type::XBOX360_WIRED_CHATPAD) -// { -// TU_LOG1("XINPUT: Chatpad data received (%u bytes)\n", xferred_bytes); -// } - -// if (dir == TUSB_DIR_IN) -// { -// TU_LOG2("Get Report callback (%u, %u, %u bytes)\r\n", dev_addr, instance, xferred_bytes); - -// switch (xid_itf->type) -// { -// case Type::XBOX360_WIRED: -// if (rdata[1] == 0x14) -// { -// std::memcpy(xid_itf->gp_report_buffer.data(), rdata, xferred_bytes); -// xid_itf->gp_report_size = xferred_bytes; -// new_pad_data = true; -// } -// break; -// case Type::XBOX360_WIRELESS: -// if (rdata[0] & 0x08) -// { -// if (rdata[1] != 0x00 && xid_itf->connected == false) -// { -// TU_LOG2("XINPUT: WIRELESS CONTROLLER CONNECTED\n"); -// xid_itf->connected = true; -// xbox360w_chatpad_init(dev_addr, instance); -// } -// else if (rdata[1] == 0x00 && xid_itf->connected == true) -// { -// TU_LOG2("XINPUT: WIRELESS CONTROLLER DISCONNECTED\n"); -// xid_itf->connected = false; -// } -// } -// if ((rdata[1] & 1) && rdata[5] == 0x13) -// { -// std::memcpy(xid_itf->gp_report_buffer.data(), rdata, xferred_bytes); -// xid_itf->gp_report_size = xferred_bytes; -// new_pad_data = true; -// } -// break; -// case Type::XBOXONE: -// if (rdata[0] == XboxOne::GIP_CMD_INPUT) -// { -// std::memcpy(xid_itf->gp_report_buffer.data(), rdata, xferred_bytes); -// xid_itf->gp_report_size = xferred_bytes; -// new_pad_data = true; -// } -// else if (rdata[0] == XboxOne::GIP_CMD_VIRTUAL_KEY) -// { -// if (rdata[4] == 0x01 && !(xid_itf->gp_report_buffer[4] & (1 << 1))) -// { -// xid_itf->gp_report_buffer[4] |= (1 << 1); -// new_pad_data = true; -// } -// else if (rdata[4] == 0x00 && (xid_itf->gp_report_buffer[4] & (1 << 1))) -// { -// xid_itf->gp_report_buffer[4] &= ~(1 << 1); -// new_pad_data = true; -// } -// } -// else if (rdata[0] == XboxOne::GIP_CMD_ANNOUNCE) -// { -// xboxone_init(xid_itf, dev_addr, instance); -// } -// break; -// case Type::XBOXOG: -// if (rdata[1] == 0x14) -// { -// std::memcpy(xid_itf->gp_report_buffer.data(), rdata, xferred_bytes); -// xid_itf->gp_report_size = xferred_bytes; -// new_pad_data = true; -// } -// break; -// #if (CFG_TUH_XINPUT_WIRED_CHATPAD_EN > 0) -// case Type::XBOX360_WIRED_CHATPAD: -// std::memcpy(xid_itf->gp_report_buffer.data(), rdata, xferred_bytes); -// xid_itf->gp_report_size = xferred_bytes; -// new_pad_data = true; -// break; -// #endif // CFG_TUH_XINPUT_WIRED_CHATPAD_EN -// default: -// break; -// } - -// if (new_pad_data) -// { -// report_received_cb(dev_addr, instance, xid_itf->gp_report_buffer.data(), static_cast(xid_itf->gp_report_size)); -// } -// else -// { -// receive_report(dev_addr, instance); -// } -// } -// else -// { -// if (report_sent_cb) -// { -// report_sent_cb(dev_addr, instance, xid_itf->ep_out_buffer.data(), static_cast(xferred_bytes)); -// } -// } - -// return true; -// } - -// void xinputh_close(uint8_t dev_addr) -// { -// TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); -// Device *xinput_dev = get_device(dev_addr); - -// for (uint8_t i = 0; i < xinput_dev->interfaces_.size(); i++) -// { -// if (umount_cb) -// { -// umount_cb(dev_addr, i, &xinput_dev->interfaces_[i]); -// } -// } - -// *xinput_dev = Device(); -// xinput_dev->interfaces_.fill(Interface()); -// } - -// #ifndef DRIVER_NAME -// #if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL -// #define DRIVER_NAME(_name) .name = _name, -// #else -// #define DRIVER_NAME(_name) -// #endif -// #endif - -// const usbh_class_driver_t usbh_xinput_class_driver = -// { -// DRIVER_NAME("XINPUT") -// .init = xinputh_init, -// .open = xinputh_open, -// .set_config = xinputh_set_config, -// .xfer_cb = xinputh_xfer_cb, -// .close = xinputh_close -// }; - -// //Public API - -// const usbh_class_driver_t* class_driver() -// { -// return &usbh_xinput_class_driver; -// } - -// const Interface& get_interface(uint8_t address, uint8_t instance) -// { -// return *get_interface_by_inst(address, instance); -// } - -// bool receive_report(uint8_t dev_addr, uint8_t instance) -// { -// Interface *xid_itf = get_interface_by_inst(dev_addr, instance); -// TU_VERIFY(usbh_edpt_claim(dev_addr, xid_itf->ep_in)); - -// if (!usbh_edpt_xfer(dev_addr, xid_itf->ep_in, xid_itf->ep_in_buffer.data(), xid_itf->ep_in_size)) -// { -// usbh_edpt_release(dev_addr, xid_itf->ep_in); -// return false; -// } -// return true; -// } - -// bool send_report(uint8_t dev_addr, uint8_t instance, const uint8_t *report, uint16_t len) -// { -// Interface *xid_itf = get_interface_by_inst(dev_addr, instance); - -// TU_ASSERT(len <= xid_itf->ep_out_size); -// TU_VERIFY(usbh_edpt_claim(dev_addr, xid_itf->ep_out)); - -// std::memcpy(xid_itf->ep_out_buffer.data(), report, len); - -// if (!usbh_edpt_xfer(dev_addr, xid_itf->ep_out, xid_itf->ep_out_buffer.data(), len)) -// { -// usbh_edpt_release(dev_addr, xid_itf->ep_out); -// return false; -// } -// return true; -// } - -// bool set_led(uint8_t dev_addr, uint8_t instance, uint8_t led_number, bool block) -// { -// Interface *xid_itf = get_interface_by_inst(dev_addr, instance); -// uint8_t buffer[32]; -// uint16_t len; - -// switch (xid_itf->type) -// { -// case Type::XBOX360_WIRELESS: -// std::memcpy(buffer, Xbox360W::LED, sizeof(Xbox360W::LED)); -// buffer[3] = (led_number == 0) ? 0x40 : (0x40 | (led_number + 5)); -// len = sizeof(Xbox360W::LED); -// break; -// case Type::XBOX360_WIRED: -// std::memcpy(buffer, Xbox360::LED, sizeof(Xbox360::LED)); -// buffer[2] = (led_number == 0) ? 0 : (led_number + 5); -// len = sizeof(Xbox360::LED); -// break; -// default: -// return true; -// } -// bool ret = send_report(dev_addr, instance, buffer, len); -// if (block && ret) -// { -// wait_for_tx_complete(dev_addr, xid_itf->ep_out); -// } -// return ret; -// } - -// bool set_rumble(uint8_t dev_addr, uint8_t instance, uint8_t rumble_l, uint8_t rumble_r, bool block) -// { -// Interface *xid_itf = get_interface_by_inst(dev_addr, instance); -// uint8_t buffer[32]; -// uint16_t len; - -// switch (xid_itf->type) -// { -// case Type::XBOX360_WIRELESS: -// std::memcpy(buffer, Xbox360W::RUMBLE, sizeof(Xbox360W::RUMBLE)); -// buffer[5] = rumble_l; -// buffer[6] = rumble_r; -// len = sizeof(Xbox360W::RUMBLE); -// break; -// case Type::XBOX360_WIRED: -// std::memcpy(buffer, Xbox360::RUMBLE, sizeof(Xbox360::RUMBLE)); -// buffer[3] = rumble_l; -// buffer[4] = rumble_r; -// len = sizeof(Xbox360::RUMBLE); -// break; -// case Type::XBOXONE: -// std::memcpy(buffer, XboxOne::RUMBLE, sizeof(XboxOne::RUMBLE)); -// buffer[8] = rumble_l / 2; // 0 - 128 -// buffer[9] = rumble_r / 2; // 0 - 128 -// len = sizeof(XboxOne::RUMBLE); -// break; -// case Type::XBOXOG: -// std::memcpy(buffer, XboxOG::RUMBLE, sizeof(XboxOG::RUMBLE)); -// buffer[2] = rumble_l; -// buffer[3] = rumble_l; -// buffer[4] = rumble_r; -// buffer[5] = rumble_r; -// len = sizeof(XboxOG::RUMBLE); -// break; -// default: -// return true; -// } -// bool ret = send_report(dev_addr, instance, buffer, len); -// if (block && ret) -// { -// wait_for_tx_complete(dev_addr, xid_itf->ep_out); -// } -// return true; -// } - -// //Call every TUHXInput::CHATPAD_KEEPALIVE_MS if using chatpad -// void chatpad_keepalive(uint8_t address, uint8_t instance) -// { -// Interface *xid_itf = get_interface_by_inst(address, instance); -// if ((xid_itf->type != Type::XBOX360_WIRED_CHATPAD && xid_itf->type != Type::XBOX360_WIRELESS) || -// !xid_itf->chatpad_initialized) -// { -// return; -// } -// switch (xid_itf->chatpad_keepalive) -// { -// case KeepaliveStage::KEEPALIVE_1: -// switch (xid_itf->type) -// { -// case Type::XBOX360_WIRED_CHATPAD: -// send_ctrl_xfer(address, &Xbox360::Chatpad::KEEPALIVE_1, nullptr, false); -// break; -// case Type::XBOX360_WIRELESS: -// send_report(address, instance, Xbox360W::Chatpad::KEEPALIVE_1, sizeof(Xbox360W::Chatpad::KEEPALIVE_1)); -// break; -// default: -// break; -// } -// xid_itf->chatpad_keepalive = KeepaliveStage::KEEPALIVE_2; -// break; -// case KeepaliveStage::KEEPALIVE_2: -// switch (xid_itf->type) -// { -// case Type::XBOX360_WIRED_CHATPAD: -// send_ctrl_xfer(address, &Xbox360::Chatpad::KEEPALIVE_2, nullptr, false); -// break; -// case Type::XBOX360_WIRELESS: -// send_report(address, instance, Xbox360W::Chatpad::KEEPALIVE_2, sizeof(Xbox360W::Chatpad::KEEPALIVE_2)); -// break; -// default: -// break; -// } -// xid_itf->chatpad_keepalive = KeepaliveStage::KEEPALIVE_1; -// break; -// } -// } - -// }; // namespace TUHXInput - #endif // (TUSB_OPT_HOST_ENABLED && CFG_TUH_XINPUT) \ No newline at end of file diff --git a/Firmware/RP2040/src/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.h b/Firmware/RP2040/src/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.h index 83c4f5f..76d46bc 100644 --- a/Firmware/RP2040/src/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.h +++ b/Firmware/RP2040/src/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.h @@ -72,8 +72,8 @@ namespace tuh_xinput uint8_t ep_in{0xFF}; uint8_t ep_out{0xFF}; - uint8_t ep_in_size{0xFF}; - uint8_t ep_out_size{0xFF}; + uint16_t ep_in_size{0xFF}; + uint16_t ep_out_size{0xFF}; std::array ep_in_buffer{0}; std::array ep_out_buffer{0}; @@ -82,10 +82,14 @@ namespace tuh_xinput // API const usbh_class_driver_t* class_driver(); + bool send_report(uint8_t address, uint8_t instance, const uint8_t* report, uint16_t len); bool receive_report(uint8_t address, uint8_t instance); bool set_rumble(uint8_t address, uint8_t instance, uint8_t rumble_l, uint8_t rumble_r, bool block); bool set_led(uint8_t address, uint8_t instance, uint8_t led_number, bool block); + + //Wireless only atm + void xbox360_chatpad_init(uint8_t address, uint8_t instance); bool xbox360_chatpad_keepalive(uint8_t address, uint8_t instance); // User implemented callbacks diff --git a/Firmware/RP2040/src/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput_cmd.h b/Firmware/RP2040/src/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput_cmd.h index 7265920..17c2bab 100644 --- a/Firmware/RP2040/src/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput_cmd.h +++ b/Firmware/RP2040/src/USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput_cmd.h @@ -77,10 +77,10 @@ namespace tuh_xinput static constexpr tusb_control_request_t INIT_5 = { .bmRequestType = 0x40, .bRequest = 0xA1, .wValue = 0x0000, .wIndex = 0xE416, .wLength = 2 }; static constexpr tusb_control_request_t INIT_6 = { .bmRequestType = 0xC0, .bRequest = 0xA1, .wValue = 0x0000, .wIndex = 0xE416, .wLength = 2 }; //wValue in xbox360_wired_chatpad_command can be replaced with CHATPAD_CMD constants for different functions - static constexpr tusb_control_request_t CMD = { .bmRequestType = 0x41, .bRequest = 0x00, .wValue = 0x0000, .wIndex = 0x0002, .wLength = 0 }; + static constexpr tusb_control_request_t CMD = { .bmRequestType = 0x41, .bRequest = 0x00, .wValue = 0x0000, .wIndex = 0x0002, .wLength = 0 }; static constexpr tusb_control_request_t KEEPALIVE_1 = { .bmRequestType = 0x41, .bRequest = 0x00, .wValue = 0x001F, .wIndex = 0x0002, .wLength = 0 }; static constexpr tusb_control_request_t KEEPALIVE_2 = { .bmRequestType = 0x41, .bRequest = 0x00, .wValue = 0x001E, .wIndex = 0x0002, .wLength = 0 }; - static constexpr tusb_control_request_t LEDS_1B = { .bmRequestType = 0x41, .bRequest = 0x00, .wValue = 0x001B, .wIndex = 0x0002, .wLength = 0 }; + static constexpr tusb_control_request_t LEDS_1B = { .bmRequestType = 0x41, .bRequest = 0x00, .wValue = 0x001B, .wIndex = 0x0002, .wLength = 0 }; } } diff --git a/Firmware/RP2040/src/USBHost/HostManager.h b/Firmware/RP2040/src/USBHost/HostManager.h index 05e92e5..efa3622 100644 --- a/Firmware/RP2040/src/USBHost/HostManager.h +++ b/Firmware/RP2040/src/USBHost/HostManager.h @@ -1,3 +1,383 @@ +#ifndef _HOST_MANAGER_H_ +#define _HOST_MANAGER_H_ + +#include +#include +#include +#include +#include +#include + +#include "board_config.h" +#include "Gamepad.h" +#include "OGXMini/OGXMini.h" +#include "USBHost/HardwareIDs.h" +#include "USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.h" +#include "USBHost/HostDriver/HostDriver.h" +#include "USBHost/HostDriver/PS5/PS5.h" +#include "USBHost/HostDriver/PS4/PS4.h" +#include "USBHost/HostDriver/PS3/PS3.h" +#include "USBHost/HostDriver/PSClassic/PSClassic.h" +#include "USBHost/HostDriver/DInput/DInput.h" +#include "USBHost/HostDriver/SwitchWired/SwitchWired.h" +#include "USBHost/HostDriver/SwitchPro/SwitchPro.h" +#include "USBHost/HostDriver/XInput/XboxOne.h" +#include "USBHost/HostDriver/XInput/Xbox360.h" +#include "USBHost/HostDriver/XInput/Xbox360W.h" +#include "USBHost/HostDriver/XInput/XboxOG.h" +#include "USBHost/HostDriver/N64/N64.h" +#include "USBHost/HostDriver/HIDGeneric/HIDGeneric.h" + +#define MAX_INTERFACES MAX_GAMEPADS //This may change if support is added for audio or other chatpads beside 360 wireless + +class HostManager +{ +public: + enum class DriverClass { NONE, HID, XINPUT }; + + HostManager(HostManager const&) = delete; + void operator=(HostManager const&) = delete; + + static HostManager& get_instance() + { + static HostManager instance; + return instance; + } + + inline void initialize(Gamepad (&gamepads)[MAX_GAMEPADS]) + { + for (size_t i = 0; i < MAX_GAMEPADS; ++i) + { + gamepads_[i] = &gamepads[i]; + } + } + + //XInput doesn't need report_desc or desc_len + inline bool setup_driver(const HostDriver::Type driver_type, const uint8_t address, const uint8_t instance, uint8_t const* report_desc = nullptr, uint16_t desc_len = 0) + { + uint8_t gp_idx = find_free_gamepad(); + if (gp_idx == INVALID_IDX || instance >= MAX_INTERFACES) + { + return false; + } + + //Check if this device is already mounted + uint8_t dev_idx = get_device_slot(address); + //If not, find a free device slot + if (dev_idx == INVALID_IDX && ((dev_idx = find_free_device_slot()) == INVALID_IDX)) + { + return false; + } + + Device& device_slot = device_slots_[dev_idx]; + Interface& interface = device_slot.interfaces[instance]; + + switch (driver_type) + { + case HostDriver::Type::PS5: + interface.driver = std::make_unique(gp_idx); + break; + case HostDriver::Type::PS4: + interface.driver = std::make_unique(gp_idx); + break; + case HostDriver::Type::PS3: + interface.driver = std::make_unique(gp_idx); + break; + case HostDriver::Type::DINPUT: + interface.driver = std::make_unique(gp_idx); + break; + case HostDriver::Type::SWITCH: + interface.driver = std::make_unique(gp_idx); + break; + case HostDriver::Type::SWITCH_PRO: + interface.driver = std::make_unique(gp_idx); + break; + case HostDriver::Type::N64: + interface.driver = std::make_unique(gp_idx); + break; + case HostDriver::Type::PSCLASSIC: + interface.driver = std::make_unique(gp_idx); + break; + case HostDriver::Type::XBOXOG: + interface.driver = std::make_unique(gp_idx); + break; + case HostDriver::Type::XBOXONE: + interface.driver = std::make_unique(gp_idx); + break; + case HostDriver::Type::XBOX360: + interface.driver = std::make_unique(gp_idx); + break; + case HostDriver::Type::XBOX360W: //Composite device, takes up all 4 gamepads when mounted + interface.driver = std::make_unique(gp_idx); + break; + default: + if (is_hid_gamepad(report_desc, desc_len)) + { + interface.driver = std::make_unique(gp_idx); + } + else + { + return false; + } + break; + } + + device_slot.address = address; + interface.gamepad_idx = gp_idx; + interface.gamepad = gamepads_[gp_idx]; + interface.driver->initialize(*interface.gamepad, device_slot.address, instance, report_desc, desc_len); + + return true; + } + + inline void process_report(DriverClass driver_class, uint8_t address, uint8_t instance, const uint8_t* report, uint16_t len) + { + for (auto& device_slot : device_slots_) + { + if (device_slot.address == address && + device_slot.interfaces[instance].driver && + device_slot.interfaces[instance].gamepad) + { + device_slot.interfaces[instance].driver->process_report(*device_slot.interfaces[instance].gamepad, address, instance, report, len); + } + } + } + + inline void connect_cb(DriverClass driver_class, uint8_t address, uint8_t instance) + { + for (auto& device_slot : device_slots_) + { + if (device_slot.address == address && + device_slot.interfaces[instance].driver && + device_slot.interfaces[instance].gamepad) + { + device_slot.interfaces[instance].driver->connect_cb(*device_slot.interfaces[instance].gamepad, address, instance); + } + } + } + + inline void disconnect_cb(DriverClass driver_class, uint8_t address, uint8_t instance) + { + for (auto& device_slot : device_slots_) + { + if (device_slot.address == address && + device_slot.interfaces[instance].driver && + device_slot.interfaces[instance].gamepad) + { + device_slot.interfaces[instance].driver->disconnect_cb(*device_slot.interfaces[instance].gamepad, address, instance); + } + } + } + + //Call on a timer + inline void send_feedback() + { + for (auto& device_slot : device_slots_) + { + if (device_slot.address == INVALID_IDX) + { + continue; + } + for (uint8_t i = 0; i < MAX_INTERFACES; ++i) + { + if (device_slot.interfaces[i].driver != nullptr && device_slot.interfaces[i].gamepad->new_pad_out()) + { + device_slot.interfaces[i].driver->send_feedback(*device_slot.interfaces[i].gamepad, device_slot.address, i); + tuh_task(); + } + } + } + } + + void deinit_driver(DriverClass driver_class, uint8_t address, uint8_t instance) + { + for (auto& device_slot : device_slots_) + { + if (device_slot.address == address) + { + TU_LOG2("Deinit driver\r\n"); + device_slot.reset(); + TU_LOG2("Driver deinitialized\r\n"); + } + } + } + + static inline HostDriver::Type get_type(const HardwareID& ids) + { + for (const auto& map : HOST_TYPE_MAP) + { + for (size_t i = 0; i < map.num_ids; i++) + { + if (ids.pid == map.ids[i].pid && ids.vid == map.ids[i].vid) + { + return map.type; + } + } + } + return HostDriver::Type::UNKNOWN; + } + + static inline HostDriver::Type get_type(const tuh_xinput::DevType xinput_type) + { + switch (xinput_type) + { + case tuh_xinput::DevType::XBOXONE: + return HostDriver::Type::XBOXONE; + case tuh_xinput::DevType::XBOX360W: + return HostDriver::Type::XBOX360W; + case tuh_xinput::DevType::XBOX360: + return HostDriver::Type::XBOX360; + // case tuh_xinput::DevType::XBOX360_CHATPAD: + // return HostDriver::Type::XBOX360_CHATPAD; + case tuh_xinput::DevType::XBOXOG: + return HostDriver::Type::XBOXOG; + default: + return HostDriver::Type::UNKNOWN; + } + } + + inline uint8_t get_gamepad_idx(DriverClass driver_class, uint8_t address, uint8_t instance) + { + for (auto& device_slot : device_slots_) + { + if (device_slot.address == address && instance < MAX_INTERFACES) + { + return device_slot.interfaces[instance].gamepad_idx; + } + } + return INVALID_IDX; + } + + inline bool any_mounted() + { + for (auto& device_slot : device_slots_) + { + if (device_slot.address != INVALID_IDX) + { + return true; + } + } + return false; + } + +private: + static constexpr uint8_t INVALID_IDX = 0xFF; + + struct Interface + { + std::unique_ptr driver{nullptr}; + Gamepad* gamepad{nullptr}; + uint8_t gamepad_idx{INVALID_IDX}; + }; + struct Device + { + uint8_t address{INVALID_IDX}; + Interface interfaces[MAX_INTERFACES]; + + void reset() + { + address = INVALID_IDX; + for (auto& interface : interfaces) + { + interface.driver.reset(); + interface.gamepad_idx = INVALID_IDX; + interface.gamepad = nullptr; + } + } + }; + + Device device_slots_[MAX_GAMEPADS]; + Gamepad* gamepads_[MAX_GAMEPADS]; + + HostManager() {} + + inline uint8_t find_free_device_slot() + { + for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) + { + if (device_slots_[i].address == INVALID_IDX) + { + return i; + } + } + return INVALID_IDX; + } + + inline uint8_t find_free_gamepad() + { + uint8_t count = 0; + + for (auto& device_slot : device_slots_) + { + for (auto& interface : device_slot.interfaces) + { + if (interface.gamepad_idx != INVALID_IDX) + { + ++count; + } + } + } + return (count < MAX_GAMEPADS) ? count : INVALID_IDX; + } + + inline uint8_t get_device_slot(uint8_t address) + { + if (address > MAX_GAMEPADS) + { + return INVALID_IDX; + } + return address - 1; + } + + // inline DriverClass determine_driver_class(HostDriver::Type host_type) + // { + // switch (host_type) + // { + // case HostDriver::Type::XBOXOG: + // case HostDriver::Type::XBOXONE: + // case HostDriver::Type::XBOX360: + // case HostDriver::Type::XBOX360W: + // return DriverClass::XINPUT; + // default: + // return DriverClass::HID; + // } + // } + + bool is_hid_gamepad(const uint8_t* report_desc, uint16_t desc_len) + { + std::array start_bytes = { 0x05, 0x01, 0x09, 0x05, 0xA1, 0x01 }; + if (desc_len < start_bytes.size()) + { + return false; + } + for (size_t i = 0; i < start_bytes.size(); ++i) + { + if (report_desc[i] != start_bytes[i]) + { + return false; + } + } + return true; + } + + inline HostDriver* get_driver_by_gamepad(uint8_t gamepad_idx) + { + for (const auto& device_slot : device_slots_) + { + for (const auto& interface : device_slot.interfaces) + { + if (interface.gamepad_idx == gamepad_idx) + { + return interface.driver.get(); + } + } + } + return nullptr; + } +}; + +#endif // _HOST_MANAGER_H_ + // #ifndef _HOST_MANAGER_H_ // #define _HOST_MANAGER_H_ @@ -361,368 +741,4 @@ // } // }; -// #endif // _HOST_MANAGER_H_ - -#ifndef _HOST_MANAGER_H_ -#define _HOST_MANAGER_H_ - -#include -#include -#include -#include -#include -#include - -#include "board_config.h" -#include "Gamepad.h" -#include "OGXMini/OGXMini.h" -#include "USBHost/HardwareIDs.h" -#include "USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.h" -#include "USBHost/HostDriver/HostDriver.h" -// #include "USBHost/HostDriver/PS5/PS5.h" -// #include "USBHost/HostDriver/PS4/PS4.h" -// #include "USBHost/HostDriver/PS3/PS3.h" -// #include "USBHost/HostDriver/PSClassic/PSClassic.h" -// #include "USBHost/HostDriver/DInput/DInput.h" -// #include "USBHost/HostDriver/SwitchWired/SwitchWired.h" -// #include "USBHost/HostDriver/SwitchPro/SwitchPro.h" -#include "USBHost/HostDriver/XInput/XboxOne.h" -#include "USBHost/HostDriver/XInput/Xbox360.h" -#include "USBHost/HostDriver/XInput/Xbox360W.h" -#include "USBHost/HostDriver/XInput/XboxOG.h" -// #include "USBHost/HostDriver/N64/N64.h" -// #include "USBHost/HostDriver/HIDGeneric/HIDGeneric.h" - -#define MAX_INTERFACES MAX_GAMEPADS //This may change if support is added for audio or other chatpads beside 360 wireless - -class HostManager -{ -public: - enum class DriverClass { NONE, HID, XINPUT }; - - HostManager(HostManager const&) = delete; - void operator=(HostManager const&) = delete; - - static HostManager& get_instance() - { - static HostManager instance; - return instance; - } - - inline void initialize(Gamepad (&gamepads)[MAX_GAMEPADS]) - { - for (size_t i = 0; i < MAX_GAMEPADS; ++i) - { - gamepads_[i] = &gamepads[i]; - } - } - - inline bool setup_driver(const HostDriver::Type driver_type, const uint8_t address, const uint8_t instance, uint8_t const* report_desc = nullptr, uint16_t desc_len = 0) - { - uint8_t gp_idx = find_free_gamepad(); - if (gp_idx == INVALID_IDX || instance >= MAX_INTERFACES) - { - return false; - } - - // DriverClass driver_class = determine_driver_class(driver_type); - uint8_t dev_idx = get_device_slot(address); - - //This is a new device, else it's another interface on an already mounted device - if (dev_idx == INVALID_IDX && ((dev_idx = find_free_device_slot()) == INVALID_IDX)) - { - return false; - } - - Device& device_slot = device_slots_[dev_idx]; - Interface& interface = device_slot.interfaces[instance]; - - switch (driver_type) - { - // case HostDriver::Type::PS5: - // interface.driver = std::make_unique(gp_idx); - // break; - // case HostDriver::Type::PS4: - // interface.driver = std::make_unique(gp_idx); - // break; - // case HostDriver::Type::PS3: - // interface.driver = std::make_unique(gp_idx); - // break; - // case HostDriver::Type::DINPUT: - // interface.driver = std::make_unique(gp_idx); - // break; - // case HostDriver::Type::SWITCH: - // interface.driver = std::make_unique(gp_idx); - // break; - // case HostDriver::Type::SWITCH_PRO: - // interface.driver = std::make_unique(gp_idx); - // break; - // case HostDriver::Type::N64: - // interface.driver = std::make_unique(gp_idx); - // break; - // case HostDriver::Type::PSCLASSIC: - // interface.driver = std::make_unique(gp_idx); - // break; - case HostDriver::Type::XBOXOG: - interface.driver = std::make_unique(gp_idx); - break; - case HostDriver::Type::XBOXONE: - interface.driver = std::make_unique(gp_idx); - break; - case HostDriver::Type::XBOX360: - interface.driver = std::make_unique(gp_idx); - break; - case HostDriver::Type::XBOX360W: //Composite device, takes up all 4 gamepads when mounted - interface.driver = std::make_unique(gp_idx); - break; - default: - // if (is_hid_gamepad(report_desc, desc_len)) - // { - // interface.driver = std::make_unique(gp_idx); - // } - // else - { - return false; - } - break; - } - - device_slot.address = address; - interface.gamepad_idx = gp_idx; - interface.gamepad = gamepads_[gp_idx]; - interface.driver->initialize(*interface.gamepad, device_slot.address, instance, report_desc, desc_len); - - return true; - } - - inline void process_report(DriverClass driver_class, uint8_t address, uint8_t instance, const uint8_t* report, uint16_t len) - { - for (auto& device_slot : device_slots_) - { - if (device_slot.address == address && - device_slot.interfaces[instance].driver && - device_slot.interfaces[instance].gamepad) - { - device_slot.interfaces[instance].driver->process_report(*device_slot.interfaces[instance].gamepad, address, instance, report, len); - } - } - } - - //Call on a timer - inline void send_feedback() - { - for (auto& device_slot : device_slots_) - { - if (device_slot.address == INVALID_IDX) - { - continue; - } - for (uint8_t i = 0; i < MAX_INTERFACES; ++i) - { - if (device_slot.interfaces[i].driver != nullptr && device_slot.interfaces[i].gamepad->new_pad_out()) - { - device_slot.interfaces[i].driver->send_feedback(*device_slot.interfaces[i].gamepad, device_slot.address, i); - tuh_task(); - } - } - } - } - - void deinit_driver(DriverClass driver_class, uint8_t address, uint8_t instance) - { - for (auto& device_slot : device_slots_) - { - if (device_slot.address == address) - { - TU_LOG2("Deinit driver\r\n"); - device_slot.reset(); - TU_LOG2("Driver deinitialized\r\n"); - } - } - - // OGXMini::update_tuh_status(any_mounted()); - } - - static inline HostDriver::Type get_type(const HardwareID& ids) - { - for (const auto& map : HOST_TYPE_MAP) - { - for (size_t i = 0; i < map.num_ids; i++) - { - if (ids.pid == map.ids[i].pid && ids.vid == map.ids[i].vid) - { - return map.type; - } - } - } - return HostDriver::Type::UNKNOWN; - } - - static inline HostDriver::Type get_type(const tuh_xinput::DevType xinput_type) - { - switch (xinput_type) - { - case tuh_xinput::DevType::XBOXONE: - return HostDriver::Type::XBOXONE; - case tuh_xinput::DevType::XBOX360W: - return HostDriver::Type::XBOX360W; - case tuh_xinput::DevType::XBOX360: - return HostDriver::Type::XBOX360; - // case tuh_xinput::DevType::XBOX360_CHATPAD: - // return HostDriver::Type::XBOX360_CHATPAD; - case tuh_xinput::DevType::XBOXOG: - return HostDriver::Type::XBOXOG; - default: - return HostDriver::Type::UNKNOWN; - } - } - - inline uint8_t get_gamepad_idx(DriverClass driver_class, uint8_t address, uint8_t instance) - { - for (auto& device_slot : device_slots_) - { - if (device_slot.address == address && instance < MAX_INTERFACES) - { - return device_slot.interfaces[instance].gamepad_idx; - } - } - return INVALID_IDX; - } - - inline bool any_mounted() - { - for (auto& device_slot : device_slots_) - { - if (device_slot.address != INVALID_IDX) - { - return true; - } - } - return false; - } - -private: - static constexpr uint8_t INVALID_IDX = 0xFF; - - struct Interface - { - std::unique_ptr driver{nullptr}; - Gamepad* gamepad{nullptr}; - uint8_t gamepad_idx{INVALID_IDX}; - }; - struct Device - { - uint8_t address{INVALID_IDX}; - Interface interfaces[MAX_INTERFACES]; - - void reset() - { - address = INVALID_IDX; - for (auto& interface : interfaces) - { - interface.driver.reset(); - interface.gamepad_idx = INVALID_IDX; - interface.gamepad = nullptr; - } - } - }; - - Device device_slots_[MAX_GAMEPADS]; - Gamepad* gamepads_[MAX_GAMEPADS]; - - HostManager() - { - // irq_set_exclusive_handler(USBCTRL_IRQ, disconnect_irq_handler); - // irq_set_enabled(USBCTRL_IRQ, true); - } - - inline uint8_t find_free_device_slot() - { - for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) - { - if (device_slots_[i].address == INVALID_IDX) - { - return i; - } - } - return INVALID_IDX; - } - - inline uint8_t find_free_gamepad() - { - uint8_t count = 0; - - for (auto& device_slot : device_slots_) - { - for (auto& interface : device_slot.interfaces) - { - if (interface.gamepad_idx != INVALID_IDX) - { - ++count; - } - } - } - return (count < MAX_GAMEPADS) ? count : INVALID_IDX; - } - - inline uint8_t get_device_slot(uint8_t address) - { - if (address > MAX_GAMEPADS) - { - return INVALID_IDX; - } - return address - 1; - } - - // inline DriverClass determine_driver_class(HostDriver::Type host_type) - // { - // switch (host_type) - // { - // case HostDriver::Type::XBOXOG: - // case HostDriver::Type::XBOXONE: - // case HostDriver::Type::XBOX360: - // case HostDriver::Type::XBOX360W: - // return DriverClass::XINPUT; - // default: - // return DriverClass::HID; - // } - // } - - bool is_hid_gamepad(const uint8_t* report_desc, uint16_t desc_len) - { - std::array start_bytes = { 0x05, 0x01, 0x09, 0x05, 0xA1, 0x01 }; - if (desc_len < start_bytes.size()) - { - return false; - } - for (size_t i = 0; i < start_bytes.size(); ++i) - { - if (report_desc[i] != start_bytes[i]) - { - return false; - } - } - return true; - } - - /* This should not be necessary, but Pico-PIO-USB/TinyUSB - cannot detect a disconnect correctly, sad! */ - static void __isr disconnect_irq_handler() - { - // uint32_t portsc = usb_hw->portsc1; - - // // Check for connect status change - // if (portsc & USBHS_PORTSC1_CSC) - // { - // if (!(portsc & USBHS_PORTSC1_CCS)) - // { - // // Device disconnected - // printf("Device disconnected!\n"); - // } - // // Clear the CSC flag - // usb_hw->portsc1 |= USBHS_PORTSC1_CSC; - // } - } -}; - -#endif // _HOST_MANAGER_H_ \ No newline at end of file +// #endif // _HOST_MANAGER_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/USBHost/tuh_callbacks.cpp b/Firmware/RP2040/src/USBHost/tuh_callbacks.cpp index da38fec..2c42ff1 100644 --- a/Firmware/RP2040/src/USBHost/tuh_callbacks.cpp +++ b/Firmware/RP2040/src/USBHost/tuh_callbacks.cpp @@ -9,7 +9,6 @@ #include "USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.h" #include "USBHost/HostManager.h" #include "OGXMini/OGXMini.h" -#include "Board/board_api.h" #if defined(CONFIG_EN_4CH) #include "I2CDriver/4Channel/I2CManager.h" @@ -36,7 +35,7 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re I2CManager::get_instance().get_driver()->notify_tuh_mounted(); #endif //defined(CONFIG_EN_4CH) - OGXMini::update_tuh_status(true); + OGXMini::update_tud_status(true); } } @@ -47,11 +46,11 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) if (!host_manager.any_mounted()) { -// #if defined(CONFIG_EN_4CH) -// I2CManager::get_instance().get_driver()->notify_tuh_unmounted(); -// #endif //defined(CONFIG_EN_4CH) +#if defined(CONFIG_EN_4CH) + I2CManager::get_instance().get_driver()->notify_tuh_unmounted(); +#endif //defined(CONFIG_EN_4CH) - OGXMini::update_tuh_status(false); + OGXMini::update_tud_status(false); } } @@ -69,11 +68,11 @@ void tuh_xinput::mount_cb(uint8_t dev_addr, uint8_t instance, const tuh_xinput:: if (host_manager.setup_driver(host_type, dev_addr, instance)) { -// #if defined(CONFIG_EN_4CH) -// I2CManager::get_instance().get_driver()->notify_tuh_mounted(host_type); -// #endif //defined(CONFIG_EN_4CH) - - OGXMini::update_tuh_status(true); +#if defined(CONFIG_EN_4CH) + I2CManager::get_instance().get_driver()->notify_tuh_mounted(host_type); +#endif //defined(CONFIG_EN_4CH) + + OGXMini::update_tud_status(true); } } @@ -84,11 +83,11 @@ void tuh_xinput::unmount_cb(uint8_t dev_addr, uint8_t instance, const tuh_xinput if (!host_manager.any_mounted()) { -// #if defined(CONFIG_EN_4CH) -// I2CManager::get_instance().get_driver()->notify_tuh_mounted(host_manager.get_type(interface->dev_type)); -// #endif //defined(CONFIG_EN_4CH) +#if defined(CONFIG_EN_4CH) + I2CManager::get_instance().get_driver()->notify_tuh_mounted(host_manager.get_type(interface->dev_type)); +#endif //defined(CONFIG_EN_4CH) - OGXMini::update_tuh_status(false); + OGXMini::update_tud_status(false); } } @@ -99,16 +98,20 @@ void tuh_xinput::report_received_cb(uint8_t dev_addr, uint8_t instance, const ui void tuh_xinput::xbox360w_connect_cb(uint8_t dev_addr, uint8_t instance) { -// #if defined(CONFIG_EN_4CH) -// uint8_t idx = HostManager::get_instance().get_gamepad_idx(HostManager::DriverClass::XINPUT, dev_addr, instance); -// I2CManager::get_instance().get_driver()->notify_xbox360w_connected(idx); -// #endif //defined(CONFIG_EN_4CH) +#if defined(CONFIG_EN_4CH) + uint8_t idx = HostManager::get_instance().get_gamepad_idx(HostManager::DriverClass::XINPUT, dev_addr, instance); + I2CManager::get_instance().get_driver()->notify_xbox360w_connected(idx); +#endif //defined(CONFIG_EN_4CH) + + HostManager::get_instance().connect_cb(HostManager::DriverClass::XINPUT, dev_addr, instance); } void tuh_xinput::xbox360w_disconnect_cb(uint8_t dev_addr, uint8_t instance) { -// #if defined(CONFIG_EN_4CH) -// uint8_t idx = HostManager::get_instance().get_gamepad_idx(HostManager::DriverClass::XINPUT, dev_addr, instance); -// I2CManager::get_instance().get_driver()->notify_xbox360w_disconnected(idx); -// #endif //defined(CONFIG_EN_4CH) +#if defined(CONFIG_EN_4CH) + uint8_t idx = HostManager::get_instance().get_gamepad_idx(HostManager::DriverClass::XINPUT, dev_addr, instance); + I2CManager::get_instance().get_driver()->notify_xbox360w_disconnected(idx); +#endif //defined(CONFIG_EN_4CH) + + HostManager::get_instance().disconnect_cb(HostManager::DriverClass::XINPUT, dev_addr, instance); } \ No newline at end of file diff --git a/Firmware/RP2040/src/UserSettings/UserProfile.cpp b/Firmware/RP2040/src/UserSettings/UserProfile.cpp index 1f77b59..8375735 100644 --- a/Firmware/RP2040/src/UserSettings/UserProfile.cpp +++ b/Firmware/RP2040/src/UserSettings/UserProfile.cpp @@ -35,14 +35,14 @@ UserProfile::UserProfile() analog_enabled = 1; - analog_off_up = 0; - analog_off_down = 1; - analog_off_left = 2; - analog_off_right = 3; - analog_off_a = 4; - analog_off_b = 5; - analog_off_x = 6; - analog_off_y = 7; - analog_off_lb = 8; - analog_off_rb = 9; + analog_off_up = Gamepad::ANALOG_OFF_UP; + analog_off_down = Gamepad::ANALOG_OFF_DOWN; + analog_off_left = Gamepad::ANALOG_OFF_LEFT; + analog_off_right = Gamepad::ANALOG_OFF_RIGHT; + analog_off_a = Gamepad::ANALOG_OFF_A; + analog_off_b = Gamepad::ANALOG_OFF_B; + analog_off_x = Gamepad::ANALOG_OFF_X; + analog_off_y = Gamepad::ANALOG_OFF_Y; + analog_off_lb = Gamepad::ANALOG_OFF_LB; + analog_off_rb = Gamepad::ANALOG_OFF_RB; } \ No newline at end of file diff --git a/Firmware/RP2040/src/UserSettings/UserSettings.cpp b/Firmware/RP2040/src/UserSettings/UserSettings.cpp index b928193..e5caaaf 100644 --- a/Firmware/RP2040/src/UserSettings/UserSettings.cpp +++ b/Firmware/RP2040/src/UserSettings/UserSettings.cpp @@ -33,25 +33,31 @@ static constexpr DeviceDriver::Type VALID_DRIVER_TYPES[] = #if defined(CONFIG_EN_4CH) DeviceDriver::Type::XBOXOG, DeviceDriver::Type::XBOXOG_SB, - DeviceDriver::Type::XBOXOG_XR, + DeviceDriver::Type::XINPUT, DeviceDriver::Type::PS3, + DeviceDriver::Type::PSCLASSIC, DeviceDriver::Type::WEBAPP, - + #if defined(XREMOTE_ROM_AVAILABLE) + DeviceDriver::Type::XBOXOG_XR, + #endif + #elif MAX_GAMEPADS > 1 DeviceDriver::Type::DINPUT, DeviceDriver::Type::SWITCH, DeviceDriver::Type::WEBAPP, -#else +#else // MAX_GAMEPADS == 1 DeviceDriver::Type::XBOXOG, DeviceDriver::Type::XBOXOG_SB, - DeviceDriver::Type::XBOXOG_XR, - // DeviceDriver::Type::DINPUT, + DeviceDriver::Type::DINPUT, DeviceDriver::Type::SWITCH, DeviceDriver::Type::WEBAPP, DeviceDriver::Type::PS3, DeviceDriver::Type::PSCLASSIC, DeviceDriver::Type::XINPUT, + #if defined(XREMOTE_ROM_AVAILABLE) + DeviceDriver::Type::XBOXOG_XR, + #endif #endif }; @@ -59,14 +65,14 @@ static constexpr DeviceDriver::Type VALID_DRIVER_TYPES[] = struct ComboMap { uint32_t combo; DeviceDriver::Type driver; }; static constexpr std::array BUTTON_COMBO_MAP = {{ - { ButtonCombo::XBOXOG, DeviceDriver::Type::XBOXOG }, + { ButtonCombo::XBOXOG, DeviceDriver::Type::XBOXOG }, { ButtonCombo::XBOXOG_SB, DeviceDriver::Type::XBOXOG_SB }, { ButtonCombo::XBOXOG_XR, DeviceDriver::Type::XBOXOG_XR }, - { ButtonCombo::WEBAPP, DeviceDriver::Type::WEBAPP }, - { ButtonCombo::DINPUT, DeviceDriver::Type::DINPUT }, - { ButtonCombo::SWITCH, DeviceDriver::Type::SWITCH }, - { ButtonCombo::XINPUT, DeviceDriver::Type::XINPUT }, - { ButtonCombo::PS3, DeviceDriver::Type::PS3 }, + { ButtonCombo::WEBAPP, DeviceDriver::Type::WEBAPP }, + { ButtonCombo::DINPUT, DeviceDriver::Type::DINPUT }, + { ButtonCombo::SWITCH, DeviceDriver::Type::SWITCH }, + { ButtonCombo::XINPUT, DeviceDriver::Type::XINPUT }, + { ButtonCombo::PS3, DeviceDriver::Type::PS3 }, { ButtonCombo::PSCLASSIC, DeviceDriver::Type::PSCLASSIC } }}; @@ -166,8 +172,6 @@ bool UserSettings::write_firmware_version_safe() DeviceDriver::Type UserSettings::get_current_driver() { - return DeviceDriver::Type::XINPUT; - if (current_driver_ != DeviceDriver::Type::NONE) { return current_driver_; @@ -431,4 +435,16 @@ UserProfile UserSettings::get_profile_by_id(const uint8_t profile_id) DeviceDriver::Type UserSettings::get_default_driver() { return VALID_DRIVER_TYPES[0]; +} + +bool UserSettings::valid_mode(DeviceDriver::Type mode) +{ + for (const auto& driver : VALID_DRIVER_TYPES) + { + if (mode == driver) + { + return true; + } + } + return false; } \ No newline at end of file diff --git a/Firmware/RP2040/src/UserSettings/UserSettings.h b/Firmware/RP2040/src/UserSettings/UserSettings.h index 0a9fa82..f54794a 100644 --- a/Firmware/RP2040/src/UserSettings/UserSettings.h +++ b/Firmware/RP2040/src/UserSettings/UserSettings.h @@ -26,6 +26,8 @@ public: bool verify_firmware_version(); bool write_firmware_version_safe(); + bool valid_mode(DeviceDriver::Type mode); + DeviceDriver::Type get_current_driver(); bool check_for_driver_change(Gamepad& gamepad); diff --git a/Firmware/RP2040/src/board_config.h b/Firmware/RP2040/src/board_config.h index c6d5b8d..d52fd61 100644 --- a/Firmware/RP2040/src/board_config.h +++ b/Firmware/RP2040/src/board_config.h @@ -1,8 +1,9 @@ #ifndef _BOARD_CONFIG_H_ #define _BOARD_CONFIG_H_ -/* OGXM_BOARD and MAX_GAMEPADS are both defined as Cmake configure args, - add args -DOGXM_BOARD=PI_PICO and -DMAX_GAMEPADS=1 (or = whatever option you want). +/* Don't edit this file directly, instead use CMake to configure the board. + Add args -DOGXM_BOARD=PI_PICO and -DMAX_GAMEPADS=1 (or = whatever option you want) + to set the board and the number of gamepads. If you're setting MAX_GAMEPADS > 1 only D-Input, Switch, and WebApp device drivers will work. */ #define ADA_FEATHER 1 @@ -13,7 +14,7 @@ #define EXTERNAL_4CH 6 #define W_ESP32 7 -#define SYSCLOCK_HZ 250000 +#define SYSCLOCK_KHZ 240000 #ifndef MAX_GAMEPADS #define MAX_GAMEPADS 1 @@ -31,7 +32,7 @@ #define LED_INDICATOR_PIN 13 #define VCC_EN_PIN 18 -#elif OGXM_BOARD == PI_PICO +#elif OGXM_BOARD == PI_PICO || OGXM_BOARD == PI_PICO2 #define PIO_USB_DP_PIN 0 // DM = 1 #define LED_INDICATOR_PIN 25 @@ -62,6 +63,7 @@ #elif OGXM_BOARD == W_ESP32 #define I2C_SDA_PIN 18 // SCL = 19 #define UART0_TX_PIN 16 // RX = 17 + #define UART0_RX_PIN (UART0_TX_PIN + 1) #define MODE_SEL_PIN 21 #define ESP_PROG_PIN 20 // ESP32 IO0 #define ESP_RST_PIN 8 // ESP32 EN @@ -73,10 +75,6 @@ #endif // OGXM_BOARD -#if defined(UART0_TX_PIN) - #define UART0_RX_PIN (UART0_TX_PIN + 1) -#endif // defined(UART0_TX_PIN) - #if defined(I2C_SDA_PIN) #define I2C_BAUDRATE 400 * 1000 #define I2C_SCL_PIN (I2C_SDA_PIN + 1) @@ -97,19 +95,23 @@ #if defined(CONFIG_EN_USB_HOST) #define PIO_USB_CONFIG { \ - PIO_USB_DP_PIN, \ - PIO_USB_TX_DEFAULT, \ - PIO_SM_USB_TX_DEFAULT, \ - PIO_USB_DMA_TX_DEFAULT, \ - PIO_USB_RX_DEFAULT, \ - PIO_SM_USB_RX_DEFAULT, \ - PIO_SM_USB_EOP_DEFAULT, \ - NULL, \ - PIO_USB_DEBUG_PIN_NONE, \ - PIO_USB_DEBUG_PIN_NONE, \ - false, \ - PIO_USB_PINOUT_DPDM \ - } + PIO_USB_DP_PIN, \ + PIO_USB_TX_DEFAULT, \ + PIO_SM_USB_TX_DEFAULT, \ + PIO_USB_DMA_TX_DEFAULT, \ + PIO_USB_RX_DEFAULT, \ + PIO_SM_USB_RX_DEFAULT, \ + PIO_SM_USB_EOP_DEFAULT, \ + NULL, \ + PIO_USB_DEBUG_PIN_NONE, \ + PIO_USB_DEBUG_PIN_NONE, \ + false, \ + PIO_USB_PINOUT_DPDM \ + } #endif // PIO_USB_DP_PIN +#if defined(OGXM_DEBUG) + #define DEBUG_UART_PORT __CONCAT(uart,PICO_DEFAULT_UART) +#endif // defined(OGXM_DEBUG) + #endif // _BOARD_CONFIG_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/main.cpp b/Firmware/RP2040/src/main.cpp index 3112b1d..4a87066 100644 --- a/Firmware/RP2040/src/main.cpp +++ b/Firmware/RP2040/src/main.cpp @@ -6,8 +6,5 @@ int main() { - if (set_sys_clock_hz(SYSCLOCK_HZ*1000, true)) - { - OGXMini::run_program(); - } + OGXMini::run_program(); } \ No newline at end of file diff --git a/Firmware/RP2040/src/tusb_config.h b/Firmware/RP2040/src/tusb_config.h index de50ac1..19ee410 100644 --- a/Firmware/RP2040/src/tusb_config.h +++ b/Firmware/RP2040/src/tusb_config.h @@ -130,27 +130,24 @@ // Enable host stack with pio-usb if Pico-PIO-USB library is available #define CFG_TUH_ENABLED 1 #define CFG_TUH_RPI_PIO_USB 1 -// #define PICO_DEFAULT_PIO_USB_DP_PIN PIO_USB_DP_PIN #define TUH_OPT_RHPORT 1 // Size of buffer to hold descriptors and other data used for enumeration #define CFG_TUH_ENUMERATION_BUFSIZE 512 -#define CFG_TUH_HUB 0 +#define CFG_TUH_HUB 1 #define CFG_TUH_CDC 0 #if defined(CONFIG_EN_4CH) -#define CFG_TUH_HID 0 +#define CFG_TUH_HID 1 #else #define CFG_TUH_HID MAX_GAMEPADS #endif #define CFG_TUH_MSC 0 #define CFG_TUH_VENDOR 0 -#define CFG_TUH_XINPUT 4 - -#define CFG_TUH_XINPUT_WIRED_CHATPAD_EN 0 +#define CFG_TUH_XINPUT MAX_GAMEPADS // max device support (excluding hub device) #define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports diff --git a/Firmware/external/Pico-PIO-USB b/Firmware/external/Pico-PIO-USB new file mode 160000 index 0000000..d17f8ef --- /dev/null +++ b/Firmware/external/Pico-PIO-USB @@ -0,0 +1 @@ +Subproject commit d17f8efe9e6ee266d0b818634ca0ac256825579f diff --git a/Firmware/external/patch_libs.cmake b/Firmware/external/patch_libs.cmake index 7b7122e..d991aea 100644 --- a/Firmware/external/patch_libs.cmake +++ b/Firmware/external/patch_libs.cmake @@ -40,25 +40,4 @@ function(apply_lib_patches EXTERNAL_DIR) else () message(FATAL_ERROR "Failed to apply Bluepad32 patch: ${BLUEPAD32_PATCH_ERROR}") endif () - - # set(TUSB_PATCH "${EXTERNAL_DIR}/patches/tinyusb_disable_hidh.diff") - # set(TUSB_PATH "${EXTERNAL_DIR}/tinyusb") - - # message(STATUS "Applying tinyusb patch: ${TUSB_PATCH}") - - # execute_process( - # COMMAND git apply --ignore-whitespace ${TUSB_PATCH} - # WORKING_DIRECTORY ${TUSB_PATH} - # RESULT_VARIABLE TUSB_PATCH_RESULT - # OUTPUT_VARIABLE TUSB_PATCH_OUTPUT - # ERROR_VARIABLE TUSB_PATCH_ERROR - # ) - - # if (TUSB_PATCH_RESULT EQUAL 0) - # message(STATUS "tinyusb patch applied successfully.") - # elseif (TUSB_PATCH_ERROR MATCHES "patch does not apply") - # message(STATUS "tinyusb patch already applied.") - # else () - # message(FATAL_ERROR "Failed to apply tinyusb patch: ${TUSB_PATCH_ERROR}") - # endif () endfunction() \ No newline at end of file diff --git a/Firmware/external/patches/tinyusb_disable_hidh.diff b/Firmware/external/patches/tinyusb_disable_hidh.diff deleted file mode 100644 index 0c04d8a..0000000 --- a/Firmware/external/patches/tinyusb_disable_hidh.diff +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h -index 9681c704b..ad055105e 100644 ---- a/src/class/hid/hid_host.h -+++ b/src/class/hid/hid_host.h -@@ -28,6 +28,7 @@ - #define _TUSB_HID_HOST_H_ - - #include "hid.h" -+#include "host/usbh.h" - - #ifdef __cplusplus - extern "C" { -diff --git a/src/host/usbh.c b/src/host/usbh.c -index a2994cde7..052f17d1c 100644 ---- a/src/host/usbh.c -+++ b/src/host/usbh.c -@@ -176,7 +176,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = { - }, - #endif - -- #if CFG_TUH_HID -+ #if CFG_TUH_HID_NO - { - .name = DRIVER_NAME("HID"), - .init = hidh_init, diff --git a/README.md b/README.md index ce1b2d9..b94777a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # OGX-Mini ![OGX-Mini Boards](images/OGX-Mini-github.jpg "OGX-Mini Boards") -Firmware for the RP2040, capable of emulating gamepads for several game consoles. The firmware comes in 6 flavors, the [Adafruit Feather USB Host board](https://www.adafruit.com/product/5723), Pi Pico, Waveshare RP2040-Zero, Pi Pico W, RP2040/ESP32 hybrid, and 4-Channel RP2040-Zero. +Firmware for the RP2040, capable of emulating gamepads for several game consoles. The firmware comes in many flavors, supported on the [Adafruit Feather USB Host board](https://www.adafruit.com/product/5723), Pi Pico, Waveshare RP2040-Zero, Pi Pico W, RP2040/ESP32 hybrid, and a 4-Channel RP2040-Zero setup. ## Supported platforms - Original Xbox @@ -9,6 +9,7 @@ Firmware for the RP2040, capable of emulating gamepads for several game consoles - Nintendo Switch (docked) - XInput (use [UsbdSecPatch](https://github.com/InvoxiPlayGames/UsbdSecPatch) for Xbox 360, or select the patch in J-Runner while flashing your NAND) - Playstation Classic +- DInput ## Supported devices ### Wired controllers @@ -68,14 +69,15 @@ Start = Plus (Switch) = Options (Dualsense/DS4) After a new mode is stored, the RP2040 will reset itself so you don't need to unplug it. ## Features new to v1.0.0 +- Bluetooth functionality for the Pico W and Pico+ESP32. - Web application for configuring deadzones and buttons mappings, supports up to 8 saved profiles. -- Bluetooth functionality for the Pico W and ESP32 (in combination with an RP2040). -- 4 channel functionality, connect 4 Picos via I2C and use your Xbox 360 wireless adapter. -- Delayed USB mount until a controller is plugged in, useful for internal installation. +- Pi Pico 2 (RP2350) support. +- 4 channel functionality, connect 4 Picos and use one Xbox 360 wireless adapter to control all 4. +- Delayed USB mount until a controller is plugged in, useful for internal installation (non-Bluetooth boards only). - Generic HID controller support. - Dualshock 3 emulation (minus gyros), rumble now works. - Steel Battalion controller emulation with a wireless Xbox 360 chatpad. -- Xbox DVD dongle emulation, you must provide or dump your own firmware, see the Tools directory. +- Xbox DVD dongle emulation. You must provide or dump your own firmware, see the Tools directory. - Analog button support on OG Xbox and PS3. - RGB LED support for RP2040-Zero and Adafruit Feather boards. @@ -85,13 +87,12 @@ After a new mode is stored, the RP2040 will reset itself so you don't need to un - Anti-deadzone settings - More accurate report parser for unknown HID controllers - Hardware design for internal OG Xbox install -- Hardware design for 4 channel adapter +- Hardware design for 4 channel RP2040-Zero adapter - Wired Xbox 360 chatpad support - Wired Xbox One chatpad support - Switch (as input) rumble support -- OG Xbox communicator support (in some form, will probably require custom hardware) +- OG Xbox communicator support (in some form) - Generic bluetooth dongle support -- Removal of some abstraction between TinyUSB class drivers and the rest of the app for decreased memory usage and (possible) speed improvement ## Hardware For Pi Pico, RP2040-Zero, 4 channel, and ESP32 configurations, please see the hardware folder for diagrams. diff --git a/Tools/README.md b/Tools/README.md index d7245ed..9b18136 100644 --- a/Tools/README.md +++ b/Tools/README.md @@ -1,2 +1,2 @@ -#Dumping Xbox DVD dongle firmware -The firmware for the DVD Playback Kit is not included here, but you can dump your own or place a `.BIN` dump in this directory. Whichever you do, you'll have to run `dump-xremote-firmware.py` to have it included with the firmware. \ No newline at end of file +# Dumping Xbox DVD dongle firmware +The firmware for the DVD Playback Kit is not included here, but you can dump your own or place a `.BIN` dump in this directory. Whichever you do, you'll have to run `dump-xremote-firmware.py` to have it included with the firmware when you compile it. \ No newline at end of file diff --git a/WebApp/constants.js b/WebApp/constants.js index b58d15c..dec17a5 100644 --- a/WebApp/constants.js +++ b/WebApp/constants.js @@ -4,10 +4,10 @@ export const DEVICE_MODE_KEY_VALUE = "Xbox OG: Steel Battalion" : 8, "Xbox OG: XRemote" : 9, "XInput" : 6, - "PS3" : 2, + "PS3" : 1, "PS Classic" : 5, "Switch" : 4, - "WebApp" : 99, + "WebApp" : 100, }; export const PROFILE_ID_KEY_VALUE = diff --git a/WebApp/start.bat b/WebApp/start.bat new file mode 100644 index 0000000..f266b01 --- /dev/null +++ b/WebApp/start.bat @@ -0,0 +1 @@ +python -m http.server 8000 \ No newline at end of file diff --git a/hardware/README.md b/hardware/README.md index 33405c3..41ce683 100644 --- a/hardware/README.md +++ b/hardware/README.md @@ -1,3 +1,13 @@ +# Pi Pico +![](../Images/DiagramPiPico.png) + +# Pi Pico 2 +The Pico 2 will likely require 4.7k resistors between the USB data lines and ground to work correctly. +![](../Images/DiagramPiPico2.png) + +# RP2040-Zero +![](../images/DiagramRPZero.png) + Gerber, BOM, and schematic for an RP2040-Zero interposer board you can make yourself. LED1 and R3 are both optional. The RP2040-Zero board can be found on Amazon and AliExpress. diff --git a/hardware/BOM_OGX-Mini_RP2040-Zero_Interposer.csv b/hardware/RP2040-Zero_PCB/BOM_OGX-Mini_RP2040-Zero_Interposer.csv similarity index 100% rename from hardware/BOM_OGX-Mini_RP2040-Zero_Interposer.csv rename to hardware/RP2040-Zero_PCB/BOM_OGX-Mini_RP2040-Zero_Interposer.csv diff --git a/hardware/Gerber_OGX-Mini_RP2040-Zero_Interposer.zip b/hardware/RP2040-Zero_PCB/Gerber_OGX-Mini_RP2040-Zero_Interposer.zip similarity index 100% rename from hardware/Gerber_OGX-Mini_RP2040-Zero_Interposer.zip rename to hardware/RP2040-Zero_PCB/Gerber_OGX-Mini_RP2040-Zero_Interposer.zip diff --git a/hardware/Schematic_OGX-Mini_RP2040-Zero_Interposer.pdf b/hardware/RP2040-Zero_PCB/Schematic_OGX-Mini_RP2040-Zero_Interposer.pdf similarity index 100% rename from hardware/Schematic_OGX-Mini_RP2040-Zero_Interposer.pdf rename to hardware/RP2040-Zero_PCB/Schematic_OGX-Mini_RP2040-Zero_Interposer.pdf diff --git a/images/DiagramPico.png b/images/DiagramPico.png new file mode 100644 index 0000000000000000000000000000000000000000..52c91f51b0dd51d4675d4146d32fe4794690264a GIT binary patch literal 134847 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

0Y&-FBlespZ%d390KGuB6g}4P&LW&L|O% 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

R*rtHYRLV(Mo{9LbPL1Mdmfb0mkbe03(aA#gV` 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�X@(c98aoBglEp4{s+JRS5J@4 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 literal 0 HcmV?d00001 diff --git a/images/DiagramPico2.png b/images/DiagramPico2.png new file mode 100644 index 0000000000000000000000000000000000000000..5d36b889f6fdc95c422f89f5d97dd73310a8c394 GIT binary patch literal 116011 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 z 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

h5Z4t)H$IjD6F6%?EvQM|nMZGtb$Uo-Tav}_J0 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 {CEq!`B0h7oI*9`yJVN_x-!} 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

LL)ivMLs|L6HOFbCzd|s< z5}LAd!3wU6yx3GsKi(X&cVN>)BDeygu-1MRI2A{;|IL<0EjV$j{%`wf0%}Ba;dPAvuBT z^apsDd1!m&KjpW{$(U(%8X9IFwULmdQzBh=O0EqS_mCKo-VyXHLqozBBB{d~`L7nV znSs!0VgJ?-7e`}rvgQkjQtYRQqNSy!WlC)3Q{2}BA}sL?-hcGGogKes{=h7awx$Sh zKrpt>zB?(NXy&pC->@h>T$4a@8M%Rbq1;gX-^yt}Rgk@$-rx7n_k48sC!g}`S-t4` z7V^j)DA$g9w6NAGAa{~(-zVZnwDjrInO&w=Nf5#;#NZ>A2cCzHp!#(dIr;l_9pHO_ zAU0Z*=rnAh*@2H9`TlZWk;VDuSz*N~mS>;=0AQi9+u@@A#8JYkC|kV%kVK^Ee+FBn zGSDF9y5NbIAP{#5@lznO90pt-Dvy~*^$QnlJuNtVXH#H?9XWUJIk@?G%se4189vmU zKNMJICo(gZBJvx#mKqiYo^4MNvi%4#ClksR-}HWxgv46M<}oujVmg^h2!zz_eRCEj{RbXw0syDTPS^X zBX*1{t}Ch|nO83+rjB?YwpmLTEhkoT9T8?i-~B)qCHcb1$M=nU4h(rXbavNI=s~u8 zuOSde#myhfD^ngZ9>&u8I*J}1yAwIIJ!Tz9+1B=%;G7&8jgOH037}euGbRNUb>5mW z4D+c2D1msV%Vl_@uJ5D#U8~$_fi>u~FRl0@4!ri*g*HpAN9v{pp z0_9|3lGcPt6cX5Pp9TV2{Ed*JN8>I&$3v)@;mpij^gHBWhP52l4r^w0lhnDN^dNi< zM9O%gw#rThjY8zo9CGCinc%1HQMI#mWeXoNFxY}=x2*Z8`TiR@629BMk<%G=@RNum zB>PgHfDdp~iq#AKmbFV^Pxm-|pC;fDJsfp*j#{5y#<@<{o0Pj8P_jWT+dOy+hYvF6 z(>i*iFt9BzayQoNJr=LE_@&oKSIwQxmm>lQ3oM3dgA=nO~} z8KM>rKgav(GEl=l6}nOXsUn9P0NAroDV$-nzhK!9G&$W{j-lykr5gP@f4<B|C$rJQ>9oK* zlxIP|la7rq1eVw6uSQ6$9+C@fm+KUmaD35-pX3FI^J}Tl=76!VEILr7CwYfF-!l#L zzY@2y)@Ywlgu!44u!)_Nr8Gsiur2?ZMV}JPEK&qJY?N+{TLjGwHf#g=2$0{jWmP$( zC=0_*RH1@z{@K5h))Xxs5}1GG?5jbQO<~RisBYK=nEh*L(y%a`^YgT~8hKpb9~gOl zzE8NQbE6Y?BSmFu%sfowu;RTg4lrtPs1WnvSGNBX)AlE{a9Y9C0~2-i?J$=gO>mYJ z>7nZv2tXa|8NO%L{86$i0V_j~2Fo+!dw&12$!$tU#|OLxo8iZ$0Gw3p(hp-R0m7wi z!VQfRSzj~mBR+-+JiB9(cFRyG>w60rjS*qu-R1i{E>8#L);*hLOPtA9-9(GMxVyB> z@$Xx7Q>Ht$T{<4LKq>O}3%V>(Ka@BUW-s5-Lb0-B{NDaT+tm#@KBsT-{vu+dHpOu7 z6P3s!L1iGIpN+{Z9>>e*xn7x(@r&a9`K%P>!`{}Elrn2<^`>v7b#4uKY4Ec)7hOzI zsyIO`jS(k^hDXFGF}L`R-p8n$A0H~E2>)iNCc&4lA-YUnrbcfHLX&jwSziyT@Xq=4 zQB)i)*y@@J2+D?`f*qH8fF@yIc&m%+s#%Y&UFgHib-|KfrFJ?)VMvx=rlw^HOweo| zgcM>mOAr3__Cx@Y5g89Ya=alJspCFHNU3yo|8CHaHwc*}2!zP|t=1(I_1Cb_(6Diu zFTtpI1Vu%uO#9O!>x+g>`h0Q_h&SXVGnbOgK=friVWmb#6N!xJ>OSt<+*Jh;h5E_b za=FV|tzm$MYK)=a!LZ?$UpN*bCbiz!Y|8W(+2=qZ2At7PNsMBzxkbJFxO^3~MG(aJ zKA<<_^9C8m1M@(6fLayH-)m4}S%K*LfcB9#;nrrYR`EDR8Ohm>_P5P_)(_M|Q*=fY zti;l~^<>0a>VYN|Sy>)E-iywJ(wtVOd-YFK==WR7KV~}uly4m;+pyIE!AF<9fthTp z0&fj@M#vsc7i=B}MUJ=Ggk%?oaEKC3RTlb_0CH?^g4`z2UBYh`ADl`Yj;&i7v}i4f zFG}HI$W*+z>=+uM3TWaTRRqLD3S30xR6Ef{;`=ukb`!HhqF@wv56IvrLRF-BSpeXO z>NOG6R#90RX-o)RofZ|L_u`rvL!}5LGTBc;p(3^WNf?|QBiNe_Q2lMS@CF6{`azVA zir$ErIj4vk6(k|4E>4TA4UzzFcjtgUo3W=uq3-MjTrxQ5GA81D71ENl)rImtEpS#p zg4B3?q4QOh%s6>@5SH|izo7;aDwTt1fVL~ckGj%(B^HcEH(r}X#v|W@0=hHioBCp1 z;PdX)`kmZ@AB&Z@=uI98&Z8R?yqhJPj`FoIun%)po1&v6@|p5=fcV5)bm_0)$LoPD zkptJy;WyXdqV7&Lk4O@@>a#OHZ61$B z9(!e48%jO`L4rv0U(Tj~zNJ8jK0%INC*60^skba#ZAV6@v+Ym@!KlJU4T4i(DWlVp zNaRiO8nM!fV65+PwBn56o$oNU#o49_h!SR>%@QbH8?=cPnUU79BM&Oe%dFYq6M!Iu zgm#zW9kJe2`Pzi$6*D#q{K308Cpd*v(%Rbj7xs276n2s6J2{N$8`Y($b!TPuQlvP~ zRZ77Il%=W8yBTRE=qRJdi+_cE%zbm-pieFKHawTx*Cryb5rP&HsrF`K?||@U4cY$V#B4PyvSl2_iOT(glgb z@KUgi63}W0STteSMy`^*6@8zTSE|fC1jp2OWPj;rV2I?S^O+#VQ^kK2?wSaS zf*n({%E$#XP&EJbL`Je;<8${m{}!-uw_jWzcBDC9nLwDW0b9sScgv?kN3OEU9lP(j zuw3~x=c2YY5FfNjy+?U;jcXafSE(ZV`;kO@Z1x9XTv!em*>k&kKf#=dDJ7zoV$6dM z4SJ(Ws9wg}K8LaZ*3q$ZWjGA$4vx>m36KIv7@O>1wvYdEb*J5E;RyR0nZ-{7H05*< zNK0oAla!&4bNZ>FZSpfmQCXw$zO{w`O-4rjBT>e00tiT9YFIeIc7{M$=g{iWeW9)l zMx~|rj|YW@OUS+4Q3jG~fDCeT5}qg&FseQ|&LrJ6Yi_M`UmMcN67o9_Sz39;2++1C zU(ke}Ar>WMuKj$^tEqctTM_*2s|Xwf%Mn7MADJbD&-m#bBbb=9{Pbh3}UK33m z43g$07%6j*LoIQRWpfgCw|*EJeL^CLk=Kk)!NH^UQVaeRPY3npSw%&K0`>Y9OZsyd zQ!R3+25G@|6P$4@zS@C%=Rhz$*8@*&%3)bp$wY^vBv^bIEX0#G2JHN5N@(JESSd|p z#|H@XYH~ve;ma3gWVvo19~XXiKfgX0p$xdwKhPPLP%J0g|D9K)=lOX++_kO^h8H6- z(i1+SqB?a_oqlrp+KA(MXNB@nO|0!M6eW;o!Zqy8F94(C0iEN$M>poGn~UVjVZ(XA z-TbQc6Z@KNC-1S7P)wkmll>T3vFD-J<8cdzT3i@^-zqYxjxrNFcQ{EgC*+QYCG#7rgI{}4lSk1KiOQr01`aYMCfZ4k zmQF|kn3eS8FFltOVbTl-y{g4wr6P>suT6_nP%PeuM7Cg2P&@0!n}bZXBY0@|z{pVw z=6%WC0~t+P&YX2ua}#|d>Hb|LM1XcT6{53a z>o6|)EGUw?L?1qTLCFe5+f&OKnrG6n7&7DI0m*<<`^&Q>f55pT`6ViTQMRp1JCZa& zRbp+@{5j%8C*b7uz2#6`Kw(dSc<-l1KKXG)wfNeLk4k8KegY5Rk<*>)&~tt>wgvn26HQo77Qmks=$wA%qUZ_p1i~ z74=V9GB<;hWl^0OTzu~x@xbI{rhHl^U0jvFFpFRGFf(%r#ee00krjh&4&q8|bkat_ z1l;*=WMYf5@48ZTYMGgRJJMu!VQGHTOnwC9vJBxl})? zxAC2>ep^rgfN6aS*ZVB}p>JjHsf48eH>rbAT27cWx8p%V3b^Aa7!#a* z>6x47#A1#w3mh5ya)8-crmuvVO{emnkD5s14N|g}1Y6+Zk0bz~ODBq?aQe3Gc5-t> zbe`NWUgFoTYYEWR6d$R=ev~C?u_B=UJ|L@t-EQ124`a>KY`#+jr~Zn#*E7&baG z)&3*Nr1-&Tt=}G;15O1H+NDN9LsKdvG+0A1qEj%sJ}|bNcj;Uo&bh3%Bh@6K>kp+r z_vBDqu?(sjR$e$BOoD#^a)MpA_7gl*vq+-^<}?&Rn4#(k{nd-Jvrw}_Y0mOKL|p|u zUT25->i~b-ExqY2@>hT%%I%Vcv(<+4;8;?-uxFdSI*V<%^ed1mW@oYhLs;QN27OuN0(sVpWay zn~f{m5&)^LDzam2ShdS2Y+uB}Rv60a5= z?EVH-)OkLF1GW;@SDLk3-M$kU?^tZ`b1WYW-RlqaChAKrEvu1g^hQt?b|qCjGixAf z>T)M=w`G5eQ>u-5ED!Ci*kP%=6yxC~fkVq!m~hiuscxA?9ym0GTj( zZc)gxkiI}<8jniSqHY+P@vEDVVQ6#l&c&hiYMj_S)kjz zsGtx#+t!Ee&LRM4dyj=R=%Oo$ubip#Cta?g=i)|>BG{3w|QI|3YI#cqZ+oOJ1R z)b=k=Wv%3_hk9lAICeaSZO-Lyqv~u)mhKPcl3c<|y6(0JyY3TQHpU>)3#|nuRA-Nm z<#+i@*nga^I=Aoh2{*3Z=GI4VGTvr*JYMWPI@8H{HV>tjv zWZ}Q9RWf1^sKCJdOgrg3XnZVnIgHI7aDEPk*m2MItlx|_x!y*@!xm>12E1L8asZhId%jzL`t0M^L%8qkS&XsWa0>N4{8n8N#=;{) z!WWnS`du`-Rjws4K96)z?6y1USm;_>_gcz!INkqg%d)M}e~-7y=Z5mHe}HpO42IZK zJ53hFD`LXS&W3tJ|Klk3EU%}!Oi>W+vd?WtpV*m;%f$fTPnFYNk7dBiU}zF#Wk8jV ziLsU~-D-Cb*6N3yJV{@fYpe(eGA?epZ8d@}+-hM~o%G*5ua?(^v}ygwtH8BKg3=foAzT1{~n8{^+v1|B|02#O4;4R zJ_9|WTqzX4wlo%Ok*V_H=YarQatuwyWf34i;V&&$3IhVQA#FmYsW>b&g*uBH_e)VR zG-ej0Vs{%HpPX9vA>fQ0U)TXF2aQ@cQ*Gf#ogIWaI6Af`YJ72VR7hur4_UhvfGF}x zVJaV{Yfa{`LZefpUL0 z|KXPhF1UJ@Y`MwXI1@gRG%c~^?l2O-`zst8XJeNQI4?-{w~WW)r!+!1S7;K7973??Y@~vfvJye_*mNTDv-iE~ zpTZfJeapv*YtXD}jU6o!&CGW6;qsOtz~1c!1V)F#1$++~{97|^KMOtmsMX-N`D*Q{ z#*%ow*`BETTP$<(CfeBVB2ySkfsznRn<`y9;439L8qcdx zeQFg>DMKGFaj|TJKtIH7Y1P2>=#VCUlE(-R3|HZJYY;B`fUu|qEz~ioVc0^<;ju6P zZ^7)4ofJunRItn%2nSHPYeVL7Jtz$o|9&GK48;yxeEUt0yR&nBeW&g8dkCdha0?~g zeYjE+yJ743`D-I9DMXOtMrb!_*LeS}VY*=fPHw)=LH;yb+_!SqHe%?1&?%Db(M4*k zyq`uWrF(Tl>0iW(F+P-(pZwK(F<(!ot7Ix~@N{_lewFL%c}jE#S}*O&>#4K7qTOJc_Tqs@=!cnZil(J;;%AhW5+ z65&g=T_#c?(#YU=%rt}~w0t*sXy&NU39j|uS~P3+ud?TuzN!f9nT!@FEf$lgW9;EFp6+R5i6}% zb+E4PT}&j2F|Vvx=g=gc;6M<+Xr3%*1+V{n6 zJ7CVpt8T137~TKCW7o*yzn?cw4~luSKsLyjvb5i7D(x#4Q%Hg9upckY*W-RLp9|-1 z%1=OH@i}&qM{{@yF0y99x5MPC6CjKXZ@NCx6Lk$P`t!Wx6f&SHUxlZlJg0CkH%-=b zQ{Qv~+{nxP+~|3BRIfIv!XqGNbmjfmHu8}-PVMd$ z)1J~?(uT;uX1y#E!iuQyc^DM9WCM>m6=E?lfkG!f5c3Fb0OxDuo%EZ`c*!u**daW| zqMLU_lFi$Ggi^|O`__W#s$wO=CrDJGm8QtQ{isrotK73HfLgX`00a}-$dg{~urwK5 zP+-L`O9K#e+&vxq(!S5R^9jOX&`4;Ccx@)?&wsz%JW6j$;s0@MkGI_@@mf+JMf}3Q z?fnn_A9YBxz5#Y^vy!&@P^agvd#-r$5*gdH&HetXO*JuuX z<%ttfvEP_9I_|A66sqEbsYCM`ogzQQ0pZAbZ{ChQbSgUzTFHXqXyq|u5n{AW{T>(7 z%O&zZL7}W0RNbFu_;?6vAWVruc20r{nu=q1J8_u9?|rmm7<+eN47q2M^tdYJqsmCy zT8f6EL3MV?iJy_7);`(W5&-6$Usjd&gTZnT6J>XcxjH+t&TUUE@j!JMwto>ZJ3Bi` zNr+{l_3?aw<8??^Pfrg*3DdvL;cbDJD_h*Z$3IGVU{(4!9?M~bDUOLj#S8?Xy({m-&x*x5kQ}`kJ^-Q2 zFL;X~A8CYaE(kwCW{+IJEsmCYyz}vKyH_59*em@+0${jEX_0^+L?>OmGy;x#V#NVMmO0A#K~)aRz!g-1$Q9T<(c(GW`i+snNPoeD#WsJ`pV zu)hd2Req`kcgkRtn`xPdh?BjSm)A?+(*R3J6EO*!F9877h+{spVS;eo&77KA%8eN7 zQ6kYd8QIJ*%>ha-@KSvgM4<8Wl1<3wi%6xV6zyJZG`_X7$3t&fYn~}csV$?Lb|XNr z#j8lv#m!C-Ak%Xh2?a@IJ4`#WQaKV+$-J|?<=I)Yoxw+M?v(B~#F(dz`@FGl!MlTMP($AURDOn?P2 z1P~q`jsTX&{WG((8zQz+S>sMo-d4K}3J6gy)om(1keqv`Adox77i5uD0B8DMhl{wQ zgn^_51YNsR#6lJryf@hH>Nj(~Gu?E_a=0Yh!5^Vt^ zb7YH(`m8)Ev1r-GQGeMK05|D!rh9YFgVPUigwwp4~O8FDNelE~BTz^;D_MBXTKJM-;A${)e zqpgt{F=OSC?#*N_V91I9>F8(IE1t0*uZn8k=t$BgTFIwTjG5j<@iv{2Ku{%66--u^ zRZmpHCI>O?9*ta?bH(OZxev-8I9T=7-n#O#FeEMkOa{P}o3r&=he zNd>Yp;tYC`Vj=~$U`!708Q)`S5eO|d-limp^Q0&zrjywurE$P&N;aoU7{K^$c%Bw+ z-(Z|7N@+|3rNJqphpfqOV;Ys;$%y0sHhzbUrlBN{4C>j-QTFJmx1(q}M*+uddCXfD z2Nk)a{fuCx`J|rx{foXfhGAjq%w3A1(Pew>o7mz_SFxXZxHCQYi=|-CE-jC)HpI2J z`wX1zwc^TOFl`&ySA3_Iw()(IzOB0H9H`EU7lw@s5f1L7ki{RAFTp29I?Ak|0-Fx& ziRDYfI*%SKA10mQO&9_cN907I&YOCOl_B;KQue`bhY>6H*` z9|AMJ`M))|DQPKBZ=r9$ZxvqUO87JJqzqE9332uQGmFidj{3Q2HibCVqkQwzA4`8d z#GKH(@Z7O7AbR1}b^cG6adiLFNMS`tAN=PY|MLx^amV!cKNm?%|Ib0QfB)Z?|Nrgf zf4cnd+5he8|26pkHvT(?|918NjNyM9(ElCC|NJWdht0@#U&ITgS06P#w2n_4fcPlL Ls7jYh8VCI^11v!m literal 0 HcmV?d00001 diff --git a/images/DiagramRPZero.png b/images/DiagramRPZero.png new file mode 100644 index 0000000000000000000000000000000000000000..d31bd8d269a8861ec9c2d0d27cc8b3f84913632e GIT binary patch literal 191990 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 z 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