From ea14d683adeea579228109d2f92a4465fb76974d Mon Sep 17 00:00:00 2001 From: wiredopposite Date: Mon, 31 Mar 2025 17:40:46 -0600 Subject: [PATCH] add blueretro support via i2c --- .vscode/c_cpp_properties.json | 20 + .vscode/settings.json | 64 +++ Firmware/ESP32_Blueretro | 2 +- Firmware/RP2040/.vscode/settings.json | 76 +-- Firmware/RP2040/CMakeLists.txt | 66 ++- Firmware/RP2040/src/BLEServer/BLEServer.cpp | 150 ++---- Firmware/RP2040/src/BLEServer/BLEServer.h | 10 +- Firmware/RP2040/src/Bluepad32/Bluepad32.cpp | 57 +-- Firmware/RP2040/src/Bluepad32/Bluepad32.h | 12 +- Firmware/RP2040/src/Board/Config.h | 129 +++++ Firmware/RP2040/src/Board/board_api.cpp | 96 +--- Firmware/RP2040/src/Board/board_api.h | 13 +- .../Board/board_api_private/board_api_bt.cpp | 18 +- .../Board/board_api_private/board_api_led.cpp | 8 +- .../board_api_private/board_api_private.h | 20 +- .../Board/board_api_private/board_api_rgb.cpp | 11 +- .../board_api_private/board_api_usbh.cpp | 28 +- .../board_api_esp32.cpp => esp32_api.cpp} | 16 +- Firmware/RP2040/src/Board/esp32_api.h | 13 + Firmware/RP2040/src/Board/ogxm_log.cpp | 33 +- Firmware/RP2040/src/Board/ogxm_log.h | 20 +- Firmware/RP2040/src/Descriptors/DInput.h | 12 +- Firmware/RP2040/src/Gamepad/Gamepad.h | 17 +- .../RP2040/src/I2CDriver/4Channel/I2CDriver.h | 61 --- .../src/I2CDriver/4Channel/I2CManager.h | 92 ---- .../src/I2CDriver/4Channel/I2CMaster.cpp | 146 ------ .../RP2040/src/I2CDriver/4Channel/I2CMaster.h | 50 -- .../src/I2CDriver/4Channel/I2CSlave.cpp | 152 ------ .../RP2040/src/I2CDriver/4Channel/I2CSlave.h | 34 -- .../RP2040/src/I2CDriver/ESP32/I2CDriver.cpp | 146 ------ .../RP2040/src/I2CDriver/ESP32/I2CDriver.h | 13 - .../src/OGXMini/Board/ESP32_Bluepad32_I2C.cpp | 201 ++++++++ .../src/OGXMini/Board/ESP32_Bluepad32_I2C.h | 8 + .../src/OGXMini/Board/ESP32_Blueretro_I2C.cpp | 200 ++++++++ .../src/OGXMini/Board/ESP32_Blueretro_I2C.h | 8 + .../src/OGXMini/Board/Four_Channel_I2C.cpp | 470 ++++++++++++++++++ .../src/OGXMini/Board/Four_Channel_I2C.h | 13 + .../{OGXMini_PicoW.cpp => Board/PicoW.cpp} | 64 ++- Firmware/RP2040/src/OGXMini/Board/PicoW.h | 8 + .../Standard.cpp} | 135 +++-- Firmware/RP2040/src/OGXMini/Board/Standard.h | 9 + Firmware/RP2040/src/OGXMini/OGXMini.cpp | 103 ++++ Firmware/RP2040/src/OGXMini/OGXMini.h | 21 +- .../RP2040/src/OGXMini/OGXMini_4Channel.cpp | 141 ------ Firmware/RP2040/src/OGXMini/OGXMini_ESP32.cpp | 101 ---- Firmware/RP2040/src/TaskQueue/TaskQueue.cpp | 2 +- Firmware/RP2040/src/TaskQueue/TaskQueue.h | 4 +- .../USBDevice/DeviceDriver/DInput/DInput.h | 2 +- .../RP2040/src/USBDevice/DeviceManager.cpp | 19 +- Firmware/RP2040/src/USBDevice/DeviceManager.h | 6 +- Firmware/RP2040/src/USBHost/HostManager.h | 2 +- Firmware/RP2040/src/USBHost/tuh_callbacks.cpp | 79 +-- Firmware/RP2040/src/UserSettings/NVSTool.h | 4 +- .../RP2040/src/UserSettings/UserSettings.cpp | 18 +- .../RP2040/src/UserSettings/UserSettings.h | 2 +- Firmware/RP2040/src/board_config.h | 127 ----- Firmware/RP2040/src/main.cpp | 9 +- Firmware/RP2040/src/sdkconfig.h | 2 +- Firmware/RP2040/src/tusb_config.h | 5 +- 59 files changed, 1614 insertions(+), 1734 deletions(-) create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/settings.json create mode 100644 Firmware/RP2040/src/Board/Config.h rename Firmware/RP2040/src/Board/{board_api_private/board_api_esp32.cpp => esp32_api.cpp} (77%) create mode 100644 Firmware/RP2040/src/Board/esp32_api.h delete mode 100644 Firmware/RP2040/src/I2CDriver/4Channel/I2CDriver.h delete mode 100644 Firmware/RP2040/src/I2CDriver/4Channel/I2CManager.h delete mode 100644 Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.cpp delete mode 100644 Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.h delete mode 100644 Firmware/RP2040/src/I2CDriver/4Channel/I2CSlave.cpp delete mode 100644 Firmware/RP2040/src/I2CDriver/4Channel/I2CSlave.h delete mode 100644 Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.cpp delete mode 100644 Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.h create mode 100644 Firmware/RP2040/src/OGXMini/Board/ESP32_Bluepad32_I2C.cpp create mode 100644 Firmware/RP2040/src/OGXMini/Board/ESP32_Bluepad32_I2C.h create mode 100644 Firmware/RP2040/src/OGXMini/Board/ESP32_Blueretro_I2C.cpp create mode 100644 Firmware/RP2040/src/OGXMini/Board/ESP32_Blueretro_I2C.h create mode 100644 Firmware/RP2040/src/OGXMini/Board/Four_Channel_I2C.cpp create mode 100644 Firmware/RP2040/src/OGXMini/Board/Four_Channel_I2C.h rename Firmware/RP2040/src/OGXMini/{OGXMini_PicoW.cpp => Board/PicoW.cpp} (55%) create mode 100644 Firmware/RP2040/src/OGXMini/Board/PicoW.h rename Firmware/RP2040/src/OGXMini/{OGXMini_Standard.cpp => Board/Standard.cpp} (52%) create mode 100644 Firmware/RP2040/src/OGXMini/Board/Standard.h create mode 100644 Firmware/RP2040/src/OGXMini/OGXMini.cpp delete mode 100644 Firmware/RP2040/src/OGXMini/OGXMini_4Channel.cpp delete mode 100644 Firmware/RP2040/src/OGXMini/OGXMini_ESP32.cpp delete mode 100644 Firmware/RP2040/src/board_config.h diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..568b593 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,20 @@ +{ + "configurations": [ + { + "name": "Pico", + "includePath": [ + "${workspaceFolder}/Firmware/external/pico-sdk/**" + ], + "forcedInclude": [ + "${workspaceFolder}/Firmware/external/pico-sdk/src/common/pico_base_headers/include/pico.h", + "${workspaceFolder}/Firmware/RP2040/build/generated/pico_base/pico/config_autogen.h" + ], + "defines": [], + "compileCommands": "${workspaceFolder}/Firmware/RP2040/build/compile_commands.json", + "cStandard": "c17", + "cppStandard": "c++14", + "intelliSenseMode": "linux-gcc-arm" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..566db00 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,64 @@ +{ + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", + "cmake.sourceDirectory": "${workspaceFolder}/Firmware/RP2040", + "cmake.buildDirectory": "${workspaceFolder}/Firmware/RP2040/build", + "cmake.configureArgs": [ + "-DOGXM_BOARD=EXTERNAL_4CH_I2C", + "-DMAX_GAMEPADS=4" + ], + "files.associations": { + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp", + "xmemory": "cpp", + "xtr1common": "cpp", + "xutility": "cpp" + }, +} \ No newline at end of file diff --git a/Firmware/ESP32_Blueretro b/Firmware/ESP32_Blueretro index 30f2e83..bb98a87 160000 --- a/Firmware/ESP32_Blueretro +++ b/Firmware/ESP32_Blueretro @@ -1 +1 @@ -Subproject commit 30f2e837e8220d3241d4a668b26c4290f12d352c +Subproject commit bb98a87da76cb74903b3496914414179a5e1ccb4 diff --git a/Firmware/RP2040/.vscode/settings.json b/Firmware/RP2040/.vscode/settings.json index a3decc0..da9731d 100644 --- a/Firmware/RP2040/.vscode/settings.json +++ b/Firmware/RP2040/.vscode/settings.json @@ -2,82 +2,12 @@ "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", "cmake.configureArgs": [ - "-DOGXM_BOARD=ADA_FEATHER", + "-DOGXM_BOARD=ESP32_BLUERETRO_I2C", + // "-DOGXM_RETAIL=TRUE", "-DMAX_GAMEPADS=1" ], "files.associations": { - "array": "cpp", - "atomic": "cpp", - "any": "cpp", - "bit": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "charconv": "cpp", - "chrono": "cpp", - "cinttypes": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "codecvt": "cpp", - "compare": "cpp", - "concepts": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cuchar": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "forward_list": "cpp", - "list": "cpp", - "map": "cpp", - "set": "cpp", - "string": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "format": "cpp", - "fstream": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "new": "cpp", - "numbers": "cpp", - "ostream": "cpp", - "ranges": "cpp", - "semaphore": "cpp", - "span": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "stop_token": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp" + } } \ No newline at end of file diff --git a/Firmware/RP2040/CMakeLists.txt b/Firmware/RP2040/CMakeLists.txt index 946f0bd..260ffbf 100644 --- a/Firmware/RP2040/CMakeLists.txt +++ b/Firmware/RP2040/CMakeLists.txt @@ -35,19 +35,21 @@ apply_lib_patches(${EXTERNAL_DIR}) set(SOURCES_BOARD ${SRC}/main.cpp - ${SRC}/OGXMini/OGXMini_Standard.cpp - ${SRC}/OGXMini/OGXMini_4Channel.cpp - ${SRC}/OGXMini/OGXMini_PicoW.cpp - ${SRC}/OGXMini/OGXMini_ESP32.cpp + ${SRC}/OGXMini/OGXMini.cpp + ${SRC}/OGXMini/Board/Standard.cpp + ${SRC}/OGXMini/Board/PicoW.cpp + ${SRC}/OGXMini/Board/Four_Channel_I2C.cpp + ${SRC}/OGXMini/Board/ESP32_Bluepad32_I2C.cpp + ${SRC}/OGXMini/Board/ESP32_Blueretro_I2C.cpp ${SRC}/TaskQueue/TaskQueue.cpp ${SRC}/Board/ogxm_log.cpp + ${SRC}/Board/esp32_api.cpp ${SRC}/Board/board_api.cpp ${SRC}/Board/board_api_private/board_api_led.cpp ${SRC}/Board/board_api_private/board_api_rgb.cpp ${SRC}/Board/board_api_private/board_api_bt.cpp - ${SRC}/Board/board_api_private/board_api_esp32.cpp ${SRC}/Board/board_api_private/board_api_usbh.cpp ${SRC}/UserSettings/UserSettings.cpp @@ -102,48 +104,67 @@ set(FLASH_SIZE_MB 2) set(PICO_BOARD none) if (OGXM_BOARD STREQUAL "PI_PICO") + add_compile_definitions(CONFIG_OGXM_BOARD_PI_PICO=1) set(EN_USB_HOST TRUE) elseif (OGXM_BOARD STREQUAL "PI_PICO2") + add_compile_definitions(CONFIG_OGXM_BOARD_PI_PICO2=1) set(EN_USB_HOST TRUE) set(PICO_PLATFORM rp2350) set(FLASH_SIZE_MB 4) elseif(OGXM_BOARD STREQUAL "PI_PICOW") + add_compile_definitions(CONFIG_OGXM_BOARD_PI_PICOW=1) set(EN_BLUETOOTH TRUE) set(PICO_BOARD pico_w) elseif(OGXM_BOARD STREQUAL "PI_PICO2W") + add_compile_definitions(CONFIG_OGXM_BOARD_PI_PICO2W=1) set(EN_BLUETOOTH TRUE) set(PICO_BOARD pico2_w) set(PICO_PLATFORM rp2350) set(FLASH_SIZE_MB 4) -elseif(OGXM_BOARD STREQUAL "ADA_FEATHER") +elseif(OGXM_BOARD STREQUAL "ADAFRUIT_FEATHER") + add_compile_definitions(CONFIG_OGXM_BOARD_ADAFRUIT_FEATHER=1) set(EN_USB_HOST TRUE) set(EN_RGB TRUE) set(FLASH_SIZE_MB 8) -elseif(OGXM_BOARD STREQUAL "RP_ZERO") +elseif(OGXM_BOARD STREQUAL "RP2040_ZERO") + add_compile_definitions(CONFIG_OGXM_BOARD_RP2040_ZERO=1) set(EN_USB_HOST TRUE) set(EN_RGB TRUE) -elseif(OGXM_BOARD STREQUAL "INTERNAL_4CH") - set(EN_USB_HOST TRUE) - set(EN_4CH TRUE) +# elseif(OGXM_BOARD STREQUAL "INTERNAL_4CH") +# set(EN_USB_HOST TRUE) +# set(EN_4CH TRUE) -elseif(OGXM_BOARD STREQUAL "EXTERNAL_4CH") +elseif(OGXM_BOARD STREQUAL "EXTERNAL_4CH_I2C") + add_compile_definitions(CONFIG_OGXM_BOARD_EXTERNAL_4CH=1) set(EN_USB_HOST TRUE) set(EN_4CH TRUE) set(EN_RGB TRUE) -elseif(OGXM_BOARD STREQUAL "PICO_ESP32") +elseif(OGXM_BOARD STREQUAL "ESP32_BLUEPAD32_I2C") + add_compile_definitions(CONFIG_OGXM_BOARD_ESP32_BLUEPAD32_I2C=1) set(EN_ESP32 TRUE) set(EN_UART_BRIDGE TRUE) if(OGXM_RETAIL STREQUAL "TRUE") message(STATUS "Retail mode enabled.") - add_definitions(-DOGXM_ESP32_RETAIL) + add_compile_definitions(OGXM_RETAIL=1) + endif() + +elseif(OGXM_BOARD STREQUAL "ESP32_BLUERETRO_I2C") + add_compile_definitions(CONFIG_OGXM_BOARD_ESP32_BLUERETRO_I2C=1) + set(EN_ESP32 TRUE) + set(EN_BLUERETRO_I2C TRUE) + set(EN_UART_BRIDGE TRUE) + + if(OGXM_RETAIL STREQUAL "TRUE") + message(STATUS "Retail mode enabled.") + add_compile_definitions(OGXM_RETAIL=1) endif() else() @@ -225,10 +246,10 @@ endif() if(EN_4CH) add_compile_definitions(CONFIG_EN_4CH=1) message(STATUS "4CH enabled.") - list(APPEND SOURCES_BOARD - ${SRC}/I2CDriver/4Channel/I2CMaster.cpp - ${SRC}/I2CDriver/4Channel/I2CSlave.cpp - ) + # list(APPEND SOURCES_BOARD + # ${SRC}/I2CDriver/4Channel/I2CMaster.cpp + # ${SRC}/I2CDriver/4Channel/I2CSlave.cpp + # ) list(APPEND LIBS_BOARD hardware_i2c pico_i2c_slave @@ -238,12 +259,15 @@ endif() if(EN_ESP32) add_compile_definitions(CONFIG_EN_ESP32=1) message(STATUS "ESP32 enabled.") - list(APPEND SOURCES_BOARD - ${SRC}/I2CDriver/ESP32/I2CDriver.cpp - ) + if (EN_BLUERETRO_I2C) + # Nothing + else() + list(APPEND LIBS_BOARD + pico_i2c_slave + ) + endif() list(APPEND LIBS_BOARD hardware_i2c - pico_i2c_slave ) endif() diff --git a/Firmware/RP2040/src/BLEServer/BLEServer.cpp b/Firmware/RP2040/src/BLEServer/BLEServer.cpp index 881858b..0f09e9f 100644 --- a/Firmware/RP2040/src/BLEServer/BLEServer.cpp +++ b/Firmware/RP2040/src/BLEServer/BLEServer.cpp @@ -14,8 +14,7 @@ namespace BLEServer { static constexpr uint16_t PACKET_LEN_MAX = 20; -namespace Handle -{ +namespace Handle { static constexpr uint16_t FW_VERSION = ATT_CHARACTERISTIC_12345678_1234_1234_1234_123456789020_01_VALUE_HANDLE; static constexpr uint16_t FW_NAME = ATT_CHARACTERISTIC_12345678_1234_1234_1234_123456789021_01_VALUE_HANDLE; @@ -28,22 +27,19 @@ namespace Handle static constexpr uint16_t GAMEPAD = ATT_CHARACTERISTIC_12345678_1234_1234_1234_123456789050_01_VALUE_HANDLE; } -namespace ADV -{ +namespace ADV { // Flags general discoverable, BR/EDR not supported static const uint8_t FLAGS[] = { 0x02, 0x01, 0x06 }; static const uint8_t NAME_TYPE = 0x09; #pragma pack(push, 1) - struct Data - { + struct Data { uint8_t flags[sizeof(FLAGS)]; uint8_t name_len; uint8_t name_type; uint8_t name[sizeof(FIRMWARE_NAME) - 1]; - Data() - { + Data() { std::memcpy(flags, FLAGS, sizeof(flags)); name_len = sizeof(FIRMWARE_NAME); name_type = NAME_TYPE; @@ -56,8 +52,7 @@ namespace ADV } #pragma pack(push, 1) -struct SetupPacket -{ +struct SetupPacket { DeviceDriverType device_type{DeviceDriverType::NONE}; uint8_t max_gamepads{MAX_GAMEPADS}; uint8_t player_idx{0}; @@ -66,43 +61,35 @@ struct SetupPacket static_assert(sizeof(SetupPacket) == 4, "BLEServer::SetupPacket struct size mismatch"); #pragma pack(pop) -class ProfileReader -{ +class ProfileReader { public: ProfileReader() = default; ~ProfileReader() = default; - void set_setup_packet(const SetupPacket& setup_packet) - { + void set_setup_packet(const SetupPacket& setup_packet) { setup_packet_ = setup_packet; current_offset_ = 0; } - const SetupPacket& get_setup_packet() const - { + + const SetupPacket& get_setup_packet() const { return setup_packet_; } - uint16_t get_xfer_len() - { + + uint16_t get_xfer_len() { return static_cast(std::min(static_cast(PACKET_LEN_MAX), sizeof(UserProfile) - current_offset_)); } - uint16_t get_profile_data(uint8_t* buffer, uint16_t buffer_len) - { + + uint16_t get_profile_data(uint8_t* buffer, uint16_t buffer_len) { size_t copy_len = get_xfer_len(); - if (!buffer || buffer_len < copy_len) - { + if (!buffer || buffer_len < copy_len) { return 0; } - - if (current_offset_ == 0 && !set_profile()) - { + if (current_offset_ == 0 && !set_profile()) { return 0; } - std::memcpy(buffer, reinterpret_cast(&profile_) + current_offset_, copy_len); - current_offset_ += copy_len; - if (current_offset_ >= sizeof(UserProfile)) - { + if (current_offset_ >= sizeof(UserProfile)) { current_offset_ = 0; } return copy_len; @@ -113,20 +100,14 @@ private: UserProfile profile_; size_t current_offset_ = 0; - bool set_profile() - { - if (setup_packet_.profile_id == 0xFF) - { - if (setup_packet_.player_idx >= UserSettings::MAX_PROFILES) - { + bool set_profile() { + if (setup_packet_.profile_id == 0xFF) { + if (setup_packet_.player_idx >= UserSettings::MAX_PROFILES) { return false; } profile_ = UserSettings::get_instance().get_profile_by_index(setup_packet_.player_idx); - } - else - { - if (setup_packet_.profile_id > UserSettings::MAX_PROFILES) - { + } else { + if (setup_packet_.profile_id > UserSettings::MAX_PROFILES) { return false; } profile_ = UserSettings::get_instance().get_profile_by_id(setup_packet_.profile_id); @@ -141,24 +122,22 @@ public: ProfileWriter() = default; ~ProfileWriter() = default; - void set_setup_packet(const SetupPacket& setup_packet) - { + void set_setup_packet(const SetupPacket& setup_packet) { setup_packet_ = setup_packet; current_offset_ = 0; } - const SetupPacket& get_setup_packet() const - { + + const SetupPacket& get_setup_packet() const { return setup_packet_; } - uint16_t get_xfer_len() - { + + uint16_t get_xfer_len() { return static_cast(std::min(static_cast(PACKET_LEN_MAX), sizeof(UserProfile) - current_offset_)); } - size_t set_profile_data(const uint8_t* buffer, uint16_t buffer_len) - { + + size_t set_profile_data(const uint8_t* buffer, uint16_t buffer_len) { size_t copy_len = get_xfer_len(); - if (!buffer || buffer_len < copy_len) - { + if (!buffer || buffer_len < copy_len) { return 0; } @@ -167,25 +146,21 @@ public: current_offset_ += copy_len; size_t ret = current_offset_; - if (current_offset_ >= sizeof(UserProfile)) - { + if (current_offset_ >= sizeof(UserProfile)) { current_offset_ = 0; } return ret; } - bool commit_profile() - { + + bool commit_profile() { bool success = false; - if (setup_packet_.device_type != DeviceDriverType::NONE) - { + if (setup_packet_.device_type != DeviceDriverType::NONE) { success = TaskQueue::Core0::queue_delayed_task(TaskQueue::Core0::get_new_task_id(), 1000, false, [driver_type = setup_packet_.device_type, profile = profile_, index = setup_packet_.player_idx] { UserSettings::get_instance().store_profile_and_driver_type(driver_type, index, profile); }); - } - else - { + } else { success = TaskQueue::Core0::queue_delayed_task(TaskQueue::Core0::get_new_task_id(), 1000, false, [index = setup_packet_.player_idx, profile = profile_] { @@ -205,24 +180,20 @@ std::array gamepads_; ProfileReader profile_reader_; ProfileWriter profile_writer_; -static int verify_write(const uint16_t buffer_size, const uint16_t expected_size) -{ - if (buffer_size != expected_size) - { +static int verify_write(const uint16_t buffer_size, const uint16_t expected_size) { + if (buffer_size != expected_size) { return ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH; } return 0; } -static void disconnect_client_cb(btstack_timer_source_t *ts) -{ +static void disconnect_client_cb(btstack_timer_source_t *ts) { hci_con_handle_t connection_handle = *static_cast(ts->context); hci_send_cmd(&hci_disconnect, connection_handle); delete static_cast(ts->context); } -static void queue_disconnect(hci_con_handle_t connection_handle, uint32_t dealy_ms) -{ +static void queue_disconnect(hci_con_handle_t connection_handle, uint32_t dealy_ms) { static btstack_timer_source_t disconnect_timer; hci_con_handle_t* connection_handle_ptr = new hci_con_handle_t(connection_handle); @@ -238,33 +209,28 @@ static uint16_t att_read_callback( hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t *buffer, - uint16_t buffer_size) -{ + uint16_t buffer_size) { std::string fw_version; std::string fw_name; Gamepad::PadIn pad_in; - switch (att_handle) - { + switch (att_handle) { case Handle::FW_VERSION: fw_version = FIRMWARE_VERSION; - if (buffer) - { + if (buffer) { std::memcpy(buffer, reinterpret_cast(fw_version.c_str()), fw_version.size()); } return static_cast(fw_version.size()); case Handle::FW_NAME: fw_name = FIRMWARE_NAME; - if (buffer) - { + if (buffer) { std::memcpy(buffer, reinterpret_cast(fw_name.c_str()), fw_name.size());; } return static_cast(fw_name.size()); case Handle::GET_SETUP: - if (buffer) - { + if (buffer) { buffer[0] = static_cast(UserSettings::get_instance().get_current_driver()); buffer[1] = MAX_GAMEPADS; buffer[2] = 0; @@ -273,15 +239,13 @@ static uint16_t att_read_callback( hci_con_handle_t connection_handle, return static_cast(sizeof(SetupPacket)); case Handle::PROFILE: - if (buffer) - { + if (buffer) { return profile_reader_.get_profile_data(buffer, buffer_size); } return profile_reader_.get_xfer_len(); case Handle::GAMEPAD: - if (buffer) - { + if (buffer) { pad_in = gamepads_.front()->get_pad_in(); std::memcpy(buffer, &pad_in, sizeof(Gamepad::PadIn)); } @@ -298,35 +262,29 @@ static int att_write_callback( hci_con_handle_t connection_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, - uint16_t buffer_size) -{ + uint16_t buffer_size) { int ret = 0; - switch (att_handle) - { + switch (att_handle) { case Handle::SETUP_READ: - if ((ret = verify_write(buffer_size, sizeof(SetupPacket))) != 0) - { + if ((ret = verify_write(buffer_size, sizeof(SetupPacket))) != 0) { break; } profile_reader_.set_setup_packet(*reinterpret_cast(buffer)); break; case Handle::SETUP_WRITE: - if ((ret = verify_write(buffer_size, sizeof(SetupPacket))) != 0) - { + if ((ret = verify_write(buffer_size, sizeof(SetupPacket))) != 0) { break; } profile_writer_.set_setup_packet(*reinterpret_cast(buffer)); break; case Handle::PROFILE: - if ((ret = verify_write(buffer_size, profile_writer_.get_xfer_len())) != 0) - { + if ((ret = verify_write(buffer_size, profile_writer_.get_xfer_len())) != 0) { break; } - if (profile_writer_.set_profile_data(buffer, buffer_size) == sizeof(UserProfile)) - { + if (profile_writer_.set_profile_data(buffer, buffer_size) == sizeof(UserProfile)) { queue_disconnect(connection_handle, 500); profile_writer_.commit_profile(); } @@ -338,10 +296,8 @@ static int att_write_callback( hci_con_handle_t connection_handle, return ret; } -void init_server(Gamepad(&gamepads)[MAX_GAMEPADS]) -{ - for (uint8_t i = 0; i < MAX_GAMEPADS; i++) - { +void init_server(Gamepad(&gamepads)[MAX_GAMEPADS]) { + for (uint8_t i = 0; i < MAX_GAMEPADS; i++) { gamepads_[i] = &gamepads[i]; } diff --git a/Firmware/RP2040/src/BLEServer/BLEServer.h b/Firmware/RP2040/src/BLEServer/BLEServer.h index 567b6f9..c2b8925 100644 --- a/Firmware/RP2040/src/BLEServer/BLEServer.h +++ b/Firmware/RP2040/src/BLEServer/BLEServer.h @@ -1,13 +1,9 @@ -#ifndef BLE_SERVER_H -#define BLE_SERVER_H +#pragma once #include #include "Gamepad/Gamepad.h" -namespace BLEServer -{ +namespace BLEServer { void init_server(Gamepad(&gamepads)[MAX_GAMEPADS]); -} - -#endif // BLE_SERVER_H \ No newline at end of file +} \ No newline at end of file diff --git a/Firmware/RP2040/src/Bluepad32/Bluepad32.cpp b/Firmware/RP2040/src/Bluepad32/Bluepad32.cpp index 4c9b0a5..836811e 100644 --- a/Firmware/RP2040/src/Bluepad32/Bluepad32.cpp +++ b/Firmware/RP2040/src/Bluepad32/Bluepad32.cpp @@ -23,8 +23,7 @@ namespace bluepad32 { static constexpr uint32_t FEEDBACK_TIME_MS = 250; static constexpr uint32_t LED_CHECK_TIME_MS = 500; -struct BTDevice -{ +struct BTDevice { bool connected{false}; Gamepad* gamepad{nullptr}; }; @@ -123,78 +122,61 @@ static 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) -{ +static void init_complete_cb(void) { uni_bt_enable_new_connections_unsafe(true); - - uni_bt_del_keys_unsafe(); - + // uni_bt_del_keys_unsafe(); uni_property_dump_all(); } -static uni_error_t device_discovered_cb(bd_addr_t addr, const char* name, uint16_t cod, uint8_t rssi) -{ - if (!((cod & UNI_BT_COD_MINOR_MASK) & UNI_BT_COD_MINOR_GAMEPAD)) - { +static uni_error_t device_discovered_cb(bd_addr_t addr, const char* name, uint16_t cod, uint8_t rssi) { + if (!((cod & UNI_BT_COD_MINOR_MASK) & UNI_BT_COD_MINOR_GAMEPAD)) { return UNI_ERROR_IGNORE_DEVICE; } return UNI_ERROR_SUCCESS; } -static void device_connected_cb(uni_hid_device_t* device) -{ - +static void device_connected_cb(uni_hid_device_t* device) { } -static void device_disconnected_cb(uni_hid_device_t* device) -{ +static void device_disconnected_cb(uni_hid_device_t* device) { int idx = uni_hid_device_get_idx_for_instance(device); - if (idx >= MAX_GAMEPADS || idx < 0) - { + if (idx >= MAX_GAMEPADS || idx < 0) { return; } bt_devices_[idx].connected = false; bt_devices_[idx].gamepad->reset_pad_in(); - if (!led_timer_set_ && !any_connected()) - { + if (!led_timer_set_ && !any_connected()) { led_timer_set_ = true; led_timer_.process = check_led_cb; led_timer_.context = nullptr; btstack_run_loop_set_timer(&led_timer_, LED_CHECK_TIME_MS); btstack_run_loop_add_timer(&led_timer_); } - if (feedback_timer_set_ && !any_connected()) - { + 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) -{ +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_GAMEPADS || idx < 0) - { + if (idx >= MAX_GAMEPADS || idx < 0) { return UNI_ERROR_SUCCESS; } bt_devices_[idx].connected = true; - if (led_timer_set_) - { + if (led_timer_set_) { led_timer_set_ = false; btstack_run_loop_remove_timer(&led_timer_); board_api::set_led(true); } - if (!feedback_timer_set_) - { + if (!feedback_timer_set_) { feedback_timer_set_ = true; feedback_timer_.process = send_feedback_cb; feedback_timer_.context = nullptr; @@ -204,17 +186,14 @@ static uni_error_t device_ready_cb(uni_hid_device_t* device) return UNI_ERROR_SUCCESS; } -static void oob_event_cb(uni_platform_oob_event_t event, void* data) -{ +static void oob_event_cb(uni_platform_oob_event_t event, void* data) { return; } -static void controller_data_cb(uni_hid_device_t* device, uni_controller_t* controller) -{ +static void controller_data_cb(uni_hid_device_t* device, uni_controller_t* controller) { static uni_gamepad_t prev_uni_gp[MAX_GAMEPADS] = {}; - if (controller->klass != UNI_CONTROLLER_CLASS_GAMEPAD) - { + if (controller->klass != UNI_CONTROLLER_CLASS_GAMEPAD){ return; } diff --git a/Firmware/RP2040/src/Bluepad32/Bluepad32.h b/Firmware/RP2040/src/Bluepad32/Bluepad32.h index dfcec61..19b13a2 100644 --- a/Firmware/RP2040/src/Bluepad32/Bluepad32.h +++ b/Firmware/RP2040/src/Bluepad32/Bluepad32.h @@ -1,18 +1,14 @@ -#ifndef _BLUEPAD_32_H_ -#define _BLUEPAD_32_H_ +#pragma once #include #include #include "Gamepad/Gamepad.h" -#include "board_config.h" +#include "Board/Config.h" /* NOTE: Everything bluepad32/uni needs to be wrapped and kept away from tinyusb due to naming conflicts */ -namespace bluepad32 -{ +namespace bluepad32 { void run_task(Gamepad(&gamepads)[MAX_GAMEPADS]); -} - -#endif // _BLUEPAD_32_H_ \ No newline at end of file +} \ No newline at end of file diff --git a/Firmware/RP2040/src/Board/Config.h b/Firmware/RP2040/src/Board/Config.h new file mode 100644 index 0000000..658378e --- /dev/null +++ b/Firmware/RP2040/src/Board/Config.h @@ -0,0 +1,129 @@ +#ifndef _BOARD_CONFIG_H_ +#define _BOARD_CONFIG_H_ + +#define PI_PICO 0 +#define RP2040_ZERO 1 +#define ADAFRUIT_FEATHER 2 +#define PI_PICOW 3 +#define ESP32_BLUEPAD32_I2C 4 +#define ESP32_BLUERETRO_I2C 5 +#define EXTERNAL_4CH_I2C 6 +#define INTERNAL_4CH_I2C 7 +#define BOARDS_COUNT 8 + +#define SYSCLOCK_KHZ 240000 + +#ifndef MAX_GAMEPADS + #define MAX_GAMEPADS 1 +#endif + +#if defined(CONFIG_OGXM_BOARD_PI_PICO) || defined(CONFIG_OGXM_BOARD_PI_PICO2) + #define OGXM_BOARD PI_PICO + #define PIO_USB_DP_PIN 0 // DM = 1 + #define LED_INDICATOR_PIN 25 + +#elif defined(CONFIG_OGXM_BOARD_PI_PICOW) || defined(CONFIG_OGXM_BOARD_PI_PICO2W) + #define OGXM_BOARD PI_PICOW + +#elif defined(CONFIG_OGXM_BOARD_RP2040_ZERO) + #define OGXM_BOARD RP2040_ZERO + #define RGB_PXL_PIN 16 + #define PIO_USB_DP_PIN 10 // DM = 11 + #define LED_INDICATOR_PIN 14 + +#elif defined(CONFIG_OGXM_BOARD_ADAFRUIT_FEATHER) + #define OGXM_BOARD ADAFRUIT_FEATHER + #define RGB_PWR_PIN 20 + #define RGB_PXL_PIN 21 + + #define PIO_USB_DP_PIN 16 // DM = 17 + #define LED_INDICATOR_PIN 13 + #define VCC_EN_PIN 18 + +#elif defined(CONFIG_OGXM_BOARD_INTERNAL_4CH) + #define OGXM_BOARD INTERNAL_4CH_I2C + #define PIO_USB_DP_PIN 16 // DM = 17 + #define FOUR_CH_ENABLED 1 + #define I2C_SDA_PIN 10 + #define I2C_SCL_PIN 11 + #define SLAVE_ADDR_PIN_1 20 + #define SLAVE_ADDR_PIN_2 21 + +#elif defined(CONFIG_OGXM_BOARD_EXTERNAL_4CH) + #define OGXM_BOARD EXTERNAL_4CH_I2C + #define RGB_PXL_PIN 16 + #define FOUR_CH_ENABLED 1 + #define PIO_USB_DP_PIN 10 // DM = 11 + #define I2C_SDA_PIN 6 + #define I2C_SCL_PIN 7 + #define SLAVE_ADDR_PIN_1 13 + #define SLAVE_ADDR_PIN_2 14 + +#elif defined(CONFIG_OGXM_BOARD_ESP32_BLUEPAD32_I2C) + #define OGXM_BOARD ESP32_BLUEPAD32_I2C + #define I2C_SDA_PIN 18 + #define I2C_SCL_PIN 19 + #define UART0_TX_PIN 16 + #define UART0_RX_PIN 17 + #define MODE_SEL_PIN 21 + #define ESP_PROG_PIN 20 // ESP32 IO0 + #define ESP_RST_PIN 8 // ESP32 EN + + #if MAX_GAMEPADS > 1 + #undef MAX_GAMEPADS + #define MAX_GAMEPADS 1 + #endif + +#elif defined(CONFIG_OGXM_BOARD_ESP32_BLUERETRO_I2C) + #define OGXM_BOARD ESP32_BLUERETRO_I2C + #define I2C_SDA_PIN 18 + #define I2C_SCL_PIN 19 + #define UART0_TX_PIN 16 + #define UART0_RX_PIN 17 + #define MODE_SEL_PIN 21 + #define ESP_PROG_PIN 20 // ESP32 IO0 + #define ESP_RST_PIN 8 // ESP32 EN + + #if MAX_GAMEPADS > 1 + #undef MAX_GAMEPADS + #define MAX_GAMEPADS 1 + #endif + +#else + #error "Invalid OGXMini board selected" + +#endif + +#if defined(CONFIG_OGXM_DEBUG) + //Pins and port are defined in CMakeLists.txt + #define DEBUG_UART_PORT __CONCAT(uart,PICO_DEFAULT_UART) +#endif // defined(CONFIG_OGXM_DEBUG) + +#if defined(I2C_SDA_PIN) + #define I2C_BAUDRATE 400 * 1000 + #define I2C_PORT ((I2C_SDA_PIN == 2 ) || \ + (I2C_SDA_PIN == 6 ) || \ + (I2C_SDA_PIN == 10) || \ + (I2C_SDA_PIN == 14) || \ + (I2C_SDA_PIN == 18) || \ + (I2C_SDA_PIN == 26)) ? i2c1 : i2c0 +#endif // defined(I2C_SDA_PIN) + +#if defined(PIO_USB_DP_PIN) + #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 \ + } +#endif // defined(PIO_USB_DP_PIN) + +#endif // _BOARD_CONFIG_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/Board/board_api.cpp b/Firmware/RP2040/src/Board/board_api.cpp index 444c27d..fe78315 100644 --- a/Firmware/RP2040/src/Board/board_api.cpp +++ b/Firmware/RP2040/src/Board/board_api.cpp @@ -5,7 +5,7 @@ #include "tusb.h" -#include "board_config.h" +#include "Board/Config.h" #include "Board/board_api.h" #include "Board/ogxm_log.h" #include "Board/board_api_private/board_api_private.h" @@ -15,50 +15,15 @@ namespace board_api { mutex_t gpio_mutex_; -bool esp32::uart_bridge_mode() -{ - bool ret = false; - if (board_api_esp32::uart_bridge_mode) - { - mutex_enter_blocking(&gpio_mutex_); - ret = board_api_esp32::uart_bridge_mode(); - mutex_exit(&gpio_mutex_); - } - return ret; -} - -void esp32::enter_programming_mode() -{ - if (board_api_esp32::enter_programming_mode) - { - mutex_enter_blocking(&gpio_mutex_); - board_api_esp32::enter_programming_mode(); - mutex_exit(&gpio_mutex_); - } -} - -void esp32::reset() -{ - if (board_api_esp32::reset) - { - mutex_enter_blocking(&gpio_mutex_); - board_api_esp32::reset(); - mutex_exit(&gpio_mutex_); - } -} - -bool usb::host_connected() -{ - if (board_api_usbh::host_connected) - { +bool usb::host_connected() { + if (board_api_usbh::host_connected) { return board_api_usbh::host_connected(); } return false; } //Only call this from core0 -void usb::disconnect_all() -{ +void usb::disconnect_all() { OGXM_LOG("Disconnecting USB and resetting Core1\n"); TaskQueue::suspend_delayed_tasks(); @@ -69,28 +34,23 @@ void usb::disconnect_all() } // If using PicoW, only use this method from the core running btstack and after you've called init_bluetooth -void set_led(bool state) -{ +void set_led(bool state) { mutex_enter_blocking(&gpio_mutex_); - if (board_api_led::set_led) - { + if (board_api_led::set_led) { board_api_led::set_led(state); } - if (board_api_bt::set_led) - { + if (board_api_bt::set_led) { board_api_bt::set_led(state); } - if (board_api_rgb::set_led) - { + if (board_api_rgb::set_led) { board_api_rgb::set_led(state ? 0x00 : 0xFF, state ? 0xFF : 0x00, 0x00); } mutex_exit(&gpio_mutex_); } -void reboot() -{ +void reboot() { #define AIRCR_REG (*((volatile uint32_t *)(0xE000ED0C))) #define AIRCR_SYSRESETREQ (1 << 2) #define AIRCR_VECTKEY (0x5FA << 16) @@ -101,62 +61,46 @@ void reboot() while(1); } -uint32_t ms_since_boot() -{ +uint32_t ms_since_boot() { return to_ms_since_boot(get_absolute_time()); } //Call after board is initialized -void init_bluetooth() -{ - if (board_api_bt::init) - { +void init_bluetooth() { + if (board_api_bt::init) { board_api_bt::init(); } } //Call on core0 before any other method -void init_board() -{ - if (!set_sys_clock_khz(SYSCLOCK_KHZ, true)) - { - if (!set_sys_clock_khz((SYSCLOCK_KHZ / 2), true)) - { +void init_board() { + if (!set_sys_clock_khz(SYSCLOCK_KHZ, true)) { + if (!set_sys_clock_khz((SYSCLOCK_KHZ / 2), true)) { panic("Failed to set sys clock"); } } stdio_init_all(); - if (!mutex_is_initialized(&gpio_mutex_)) - { + if (!mutex_is_initialized(&gpio_mutex_)) { mutex_init(&gpio_mutex_); mutex_enter_blocking(&gpio_mutex_); - if (ogxm_log::init) - { + if (ogxm_log::init) { ogxm_log::init(); } - if (board_api_led::init) - { + if (board_api_led::init) { board_api_led::init(); } - if (board_api_rgb::init) - { + if (board_api_rgb::init) { board_api_rgb::init(); } - if (board_api_esp32::init) - { - board_api_esp32::init(); - } - if (board_api_usbh::init) - { + if (board_api_usbh::init) { board_api_usbh::init(); } mutex_exit(&gpio_mutex_); } - OGXM_LOG("Board initialized\n"); } diff --git a/Firmware/RP2040/src/Board/board_api.h b/Firmware/RP2040/src/Board/board_api.h index 4115dfa..e5f8232 100644 --- a/Firmware/RP2040/src/Board/board_api.h +++ b/Firmware/RP2040/src/Board/board_api.h @@ -4,26 +4,17 @@ #include #include -namespace board_api -{ +namespace board_api { void init_board(); void init_bluetooth(); void reboot(); void set_led(bool state); uint32_t ms_since_boot(); - namespace usb - { + namespace usb { bool host_connected(); void disconnect_all(); } - - namespace esp32 - { - bool uart_bridge_mode(); - void reset(); - void enter_programming_mode(); - } } #endif // _OGXM_BOARD_API_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/Board/board_api_private/board_api_bt.cpp b/Firmware/RP2040/src/Board/board_api_private/board_api_bt.cpp index 27d7562..c6f5d00 100644 --- a/Firmware/RP2040/src/Board/board_api_private/board_api_bt.cpp +++ b/Firmware/RP2040/src/Board/board_api_private/board_api_bt.cpp @@ -1,4 +1,4 @@ -#include "board_config.h" +#include "Board/Config.h" #if defined(CONFIG_EN_BLUETOOTH) #include @@ -14,22 +14,16 @@ namespace board_api_bt { std::atomic inited{false}; -void init() -{ - if (cyw43_arch_init() != 0) - { +void init() { + if (cyw43_arch_init() != 0) { panic("CYW43 init failed"); - } - else - { + } else { inited.store(true); } } -void set_led(bool state) -{ - if (!inited.load()) - { +void set_led(bool state) { + if (!inited.load()) { return; } cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, state ? 1 : 0); diff --git a/Firmware/RP2040/src/Board/board_api_private/board_api_led.cpp b/Firmware/RP2040/src/Board/board_api_private/board_api_led.cpp index 2cb9018..5570e2b 100644 --- a/Firmware/RP2040/src/Board/board_api_private/board_api_led.cpp +++ b/Firmware/RP2040/src/Board/board_api_private/board_api_led.cpp @@ -1,19 +1,17 @@ -#include "board_config.h" +#include "Board/Config.h" #if defined(LED_INDICATOR_PIN) #include namespace board_api_led { -void init() -{ +void init() { gpio_init(LED_INDICATOR_PIN); gpio_set_dir(LED_INDICATOR_PIN, GPIO_OUT); gpio_put(LED_INDICATOR_PIN, 0); } -void set_led(bool state) -{ +void set_led(bool state) { gpio_put(LED_INDICATOR_PIN, state ? 1 : 0); } diff --git a/Firmware/RP2040/src/Board/board_api_private/board_api_private.h b/Firmware/RP2040/src/Board/board_api_private/board_api_private.h index 65b8b1b..f2cb9c6 100644 --- a/Firmware/RP2040/src/Board/board_api_private/board_api_private.h +++ b/Firmware/RP2040/src/Board/board_api_private/board_api_private.h @@ -6,34 +6,22 @@ #include #include -namespace board_api_bt -{ +namespace board_api_bt { void init() __attribute__((weak)); void set_led(bool state) __attribute__((weak)); } -namespace board_api_led -{ +namespace board_api_led { void init() __attribute__((weak)); void set_led(bool state) __attribute__((weak)); } -namespace board_api_rgb -{ +namespace board_api_rgb { void init() __attribute__((weak)); void set_led(uint8_t r, uint8_t g, uint8_t b) __attribute__((weak)); } -namespace board_api_esp32 -{ - void init() __attribute__((weak)); - bool uart_bridge_mode() __attribute__((weak)); - void reset() __attribute__((weak)); - void enter_programming_mode() __attribute__((weak)); -} - -namespace board_api_usbh -{ +namespace board_api_usbh { void init() __attribute__((weak)); bool host_connected() __attribute__((weak)); } diff --git a/Firmware/RP2040/src/Board/board_api_private/board_api_rgb.cpp b/Firmware/RP2040/src/Board/board_api_private/board_api_rgb.cpp index abbc363..67fe629 100644 --- a/Firmware/RP2040/src/Board/board_api_private/board_api_rgb.cpp +++ b/Firmware/RP2040/src/Board/board_api_private/board_api_rgb.cpp @@ -1,4 +1,4 @@ -#include "board_config.h" +#include "Board/Config.h" #if defined(CONFIG_EN_RGB) #include @@ -8,14 +8,12 @@ namespace board_api_rgb { -WS2812& get_ws2812() -{ +WS2812& get_ws2812() { static WS2812 ws2812 = WS2812(RGB_PXL_PIN, 1, pio1, 0, WS2812::FORMAT_GRB); return ws2812; } -void init() -{ +void init() { #if defined(RGB_PWR_PIN) gpio_init(RGB_PWR_PIN); gpio_set_dir(RGB_PWR_PIN, GPIO_OUT); @@ -25,8 +23,7 @@ void init() set_led(0xFF, 0, 0); } -void set_led(uint8_t r, uint8_t g, uint8_t b) -{ +void set_led(uint8_t r, uint8_t g, uint8_t b) { get_ws2812().setPixelColor(0, WS2812::RGB(r, g, b)); get_ws2812().show(); } diff --git a/Firmware/RP2040/src/Board/board_api_private/board_api_usbh.cpp b/Firmware/RP2040/src/Board/board_api_private/board_api_usbh.cpp index 633ed81..ec20f5d 100644 --- a/Firmware/RP2040/src/Board/board_api_private/board_api_usbh.cpp +++ b/Firmware/RP2040/src/Board/board_api_private/board_api_usbh.cpp @@ -1,4 +1,4 @@ -#include "board_config.h" +#include "Board/Config.h" #if defined(CONFIG_EN_USB_HOST) #include @@ -10,22 +10,17 @@ namespace board_api_usbh { std::atomic host_connected_ = false; -void host_pin_isr(uint gpio, uint32_t events) -{ +void host_pin_isr(uint gpio, uint32_t events) { gpio_set_irq_enabled(PIO_USB_DP_PIN, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); gpio_set_irq_enabled(PIO_USB_DP_PIN + 1, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); - if (gpio == PIO_USB_DP_PIN || gpio == PIO_USB_DP_PIN + 1) - { + if (gpio == PIO_USB_DP_PIN || gpio == PIO_USB_DP_PIN + 1) { uint32_t dp_state = gpio_get(PIO_USB_DP_PIN); uint32_t dm_state = gpio_get(PIO_USB_DP_PIN + 1); - if (dp_state || dm_state) - { + if (dp_state || dm_state) { host_connected_.store(true); - } - else - { + } else { host_connected_.store(false); gpio_set_irq_enabled(PIO_USB_DP_PIN, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true); gpio_set_irq_enabled(PIO_USB_DP_PIN + 1, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true); @@ -33,13 +28,11 @@ void host_pin_isr(uint gpio, uint32_t events) } } -bool host_connected() -{ +bool host_connected() { return host_connected_.load(); } -void init() -{ +void init() { #if defined(VCC_EN_PIN) gpio_init(VCC_EN_PIN); gpio_set_dir(VCC_EN_PIN, GPIO_OUT); @@ -54,12 +47,9 @@ void init() gpio_set_dir(PIO_USB_DP_PIN + 1, GPIO_IN); gpio_pull_down(PIO_USB_DP_PIN + 1); - if (gpio_get(PIO_USB_DP_PIN) || gpio_get(PIO_USB_DP_PIN + 1)) - { + if (gpio_get(PIO_USB_DP_PIN) || gpio_get(PIO_USB_DP_PIN + 1)) { host_connected_.store(true); - } - else - { + } else { gpio_set_irq_enabled_with_callback(PIO_USB_DP_PIN, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &host_pin_isr); gpio_set_irq_enabled_with_callback(PIO_USB_DP_PIN + 1, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &host_pin_isr); } diff --git a/Firmware/RP2040/src/Board/board_api_private/board_api_esp32.cpp b/Firmware/RP2040/src/Board/esp32_api.cpp similarity index 77% rename from Firmware/RP2040/src/Board/board_api_private/board_api_esp32.cpp rename to Firmware/RP2040/src/Board/esp32_api.cpp index b4c1193..d8fc69b 100644 --- a/Firmware/RP2040/src/Board/board_api_private/board_api_esp32.cpp +++ b/Firmware/RP2040/src/Board/esp32_api.cpp @@ -1,20 +1,18 @@ -#include "board_config.h" +#include "Board/Config.h" #if defined(CONFIG_EN_ESP32) #include #include -#include "Board/board_api_private/board_api_private.h" +#include "Board/esp32_api.h" -namespace board_api_esp32 { - -bool uart_bridge_mode() +bool esp32_api::uart_bridge_mode() { gpio_pull_up(MODE_SEL_PIN); return (gpio_get(MODE_SEL_PIN) == 0); } -void reset() +void esp32_api::reset() { gpio_put(ESP_RST_PIN, 0); sleep_ms(500); @@ -22,7 +20,7 @@ void reset() sleep_ms(250); } -void enter_programming_mode() +void esp32_api::enter_programming_mode() { gpio_put(ESP_PROG_PIN, 1); sleep_ms(250); @@ -34,7 +32,7 @@ void enter_programming_mode() gpio_put(ESP_PROG_PIN, 1); } -void init() +void esp32_api::init() { gpio_init(ESP_PROG_PIN); gpio_set_dir(ESP_PROG_PIN, GPIO_OUT); @@ -49,6 +47,4 @@ void init() gpio_pull_up(MODE_SEL_PIN); } -} // namespace board_api_esp32 - #endif // defined(CONFIG_EN_ESP32) \ No newline at end of file diff --git a/Firmware/RP2040/src/Board/esp32_api.h b/Firmware/RP2040/src/Board/esp32_api.h new file mode 100644 index 0000000..69de5c6 --- /dev/null +++ b/Firmware/RP2040/src/Board/esp32_api.h @@ -0,0 +1,13 @@ +#include "Board/Config.h" +#if defined(CONFIG_EN_ESP32) + +#include + +namespace esp32_api { + bool uart_bridge_mode(); + void reset(); + void enter_programming_mode(); + void init(); +} // namespace board_api_esp32 + +#endif // defined(CONFIG_EN_ESP32) \ No newline at end of file diff --git a/Firmware/RP2040/src/Board/ogxm_log.cpp b/Firmware/RP2040/src/Board/ogxm_log.cpp index 75bbde4..6bb55c5 100644 --- a/Firmware/RP2040/src/Board/ogxm_log.cpp +++ b/Firmware/RP2040/src/Board/ogxm_log.cpp @@ -1,5 +1,5 @@ -#include "board_config.h" -#if defined(OGXM_DEBUG) +#include "Board/Config.h" +#if defined(CONFIG_OGXM_DEBUG) #include #include @@ -13,10 +13,8 @@ #include "USBDevice/DeviceDriver/DeviceDriverTypes.h" #include "Board/ogxm_log.h" -std::ostream& operator<<(std::ostream& os, DeviceDriverType type) -{ - switch (type) - { +std::ostream& operator<<(std::ostream& os, DeviceDriverType type) { + switch (type) { case DeviceDriverType::NONE: os << "NONE"; break; case DeviceDriverType::XBOXOG: os << "XBOXOG"; break; case DeviceDriverType::XBOXOG_SB: os << "XBOXOG_SB"; break; @@ -35,19 +33,16 @@ std::ostream& operator<<(std::ostream& os, DeviceDriverType type) namespace ogxm_log { -void init() -{ +void init() { 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); } -void log(const std::string& message) -{ +void log(const std::string& message) { static mutex_t log_mutex; - if (!mutex_is_initialized(&log_mutex)) - { + if (!mutex_is_initialized(&log_mutex)) { mutex_init(&log_mutex); } @@ -60,8 +55,7 @@ void log(const std::string& message) mutex_exit(&log_mutex); } -void log(const char* fmt, ...) -{ +void log(const char* fmt, ...) { va_list args; va_start(args, fmt); @@ -75,16 +69,13 @@ void log(const char* fmt, ...) va_end(args); } -void log_hex(const uint8_t* data, size_t size) -{ +void log_hex(const uint8_t* data, size_t size) { std::ostringstream hex_stream; hex_stream << std::hex << std::setfill('0'); int count = 0; - for (uint16_t i = 0; i < size; ++i) - { + for (uint16_t i = 0; i < size; ++i) { hex_stream << std::setw(2) << static_cast(data[i]) << " "; - if (++count == 16) - { + if (++count == 16) { hex_stream << "\n"; count = 0; } @@ -95,4 +86,4 @@ void log_hex(const uint8_t* data, size_t size) } // namespace ogxm_log -#endif // defined(OGXM_DEBUG) \ No newline at end of file +#endif // defined(CONFIG_OGXM_DEBUG) \ No newline at end of file diff --git a/Firmware/RP2040/src/Board/ogxm_log.h b/Firmware/RP2040/src/Board/ogxm_log.h index a0e64e8..c8d1335 100644 --- a/Firmware/RP2040/src/Board/ogxm_log.h +++ b/Firmware/RP2040/src/Board/ogxm_log.h @@ -3,8 +3,8 @@ #include -#include "board_config.h" -#if defined(OGXM_DEBUG) +#include "Board/Config.h" +#if defined(CONFIG_OGXM_DEBUG) #include #include @@ -15,22 +15,17 @@ std::ostream& operator<<(std::ostream& os, DeviceDriverType type); -namespace ogxm_log -{ +namespace ogxm_log { void init() __attribute__((weak)); - //Don't use this directly, use the OGXM_LOG macro void log(const std::string& message); - //Don't use this directly, use the OGXM_LOG macro void log(const char* fmt, ...); - //Don't use this directly, use the OGXM_LOG_HEX macro void log_hex(const uint8_t* data, size_t size); template - std::string to_string(const T& value) - { + std::string to_string(const T& value) { std::ostringstream stream; stream << value; return stream.str(); @@ -43,10 +38,9 @@ namespace ogxm_log #define OGXM_ASSERT_MSG(x, msg) if (!(x)) { OGXM_LOG("Assertion failed: " #x " " msg); while(1); } #define OGXM_TO_STRING ogxm_log::to_string -#else // OGXM_DEBUG +#else // CONFIG_OGXM_DEBUG -namespace ogxm_log -{ +namespace ogxm_log { void init() __attribute__((weak)); } @@ -56,6 +50,6 @@ namespace ogxm_log #define OGXM_ASSERT_MSG(x, msg) #define OGXM_TO_STRING(x) -#endif // OGXM_DEBUG +#endif // CONFIG_OGXM_DEBUG #endif // BOARD_API_LOG_H \ No newline at end of file diff --git a/Firmware/RP2040/src/Descriptors/DInput.h b/Firmware/RP2040/src/Descriptors/DInput.h index 39e072a..9434699 100644 --- a/Firmware/RP2040/src/Descriptors/DInput.h +++ b/Firmware/RP2040/src/Descriptors/DInput.h @@ -1,12 +1,11 @@ -#ifndef _DINPUT_DESCRIPTORS_H_ -#define _DINPUT_DESCRIPTORS_H_ +#pragma once #include #include #include "tusb.h" -#include "board_config.h" +#include "Board/Config.h" namespace DInput { @@ -228,8 +227,7 @@ namespace DInput // 0x0A, // bInterval 10 (unit depends on device speed) // }; - enum Itf - { + enum Itf { NUM_HID1 = 0, #if MAX_GAMEPADS > 1 NUM_HID2, @@ -297,6 +295,4 @@ namespace DInput #endif }; -}; // namespace DInput - -#endif // _DINPUT_DESCRIPTORS_H_ \ No newline at end of file +}; // namespace DInput \ No newline at end of file diff --git a/Firmware/RP2040/src/Gamepad/Gamepad.h b/Firmware/RP2040/src/Gamepad/Gamepad.h index 6b6465f..9f8cca5 100644 --- a/Firmware/RP2040/src/Gamepad/Gamepad.h +++ b/Firmware/RP2040/src/Gamepad/Gamepad.h @@ -96,16 +96,15 @@ public: #pragma pack(push, 1) struct PadIn { - uint8_t dpad; + 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; - // uint8_t chatpad[3]; - uint8_t analog[10]; + uint8_t trigger_l; + uint8_t trigger_r; + int16_t joystick_lx; + int16_t joystick_ly; + int16_t joystick_rx; + int16_t joystick_ry; + uint8_t analog[10]; PadIn() { diff --git a/Firmware/RP2040/src/I2CDriver/4Channel/I2CDriver.h b/Firmware/RP2040/src/I2CDriver/4Channel/I2CDriver.h deleted file mode 100644 index e97ea21..0000000 --- a/Firmware/RP2040/src/I2CDriver/4Channel/I2CDriver.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef I2C_DRIVER_4CH_H -#define I2C_DRIVER_4CH_H - -#include -#include - -#include "board_config.h" -#include "Gamepad.h" -#include "USBHost/HostDriver/HostDriverTypes.h" - -//Run on core0 -class I2CDriver -{ -public: - virtual ~I2CDriver() {}; - virtual void initialize(uint8_t address) = 0; - virtual void process(Gamepad (&gamepads)[MAX_GAMEPADS]) = 0; - virtual void notify_tuh(bool mounted, HostDriverType host_type = HostDriverType::UNKNOWN) = 0; - virtual void notify_xbox360w(bool connected, uint8_t idx) {}; - -protected: - enum class PacketID : uint8_t { UNKNOWN = 0, PAD, COMMAND }; - enum class Command : uint8_t { UNKNOWN = 0, STATUS, DISABLE }; - enum class Status : uint8_t { UNKNOWN = 0, NC, ERROR, OK, READY, NOT_READY }; - -#pragma pack(push, 1) - struct PacketIn - { - uint8_t packet_len{sizeof(PacketIn)}; - PacketID packet_id{PacketID::PAD}; - Gamepad::PadIn pad_in{Gamepad::PadIn()}; - Gamepad::ChatpadIn chatpad_in{0}; - std::array reserved{0}; - }; - static_assert(sizeof(PacketIn) == 32, "I2CDriver::PacketIn is misaligned"); - static_assert((sizeof(PacketIn) % 8) == 0, "I2CDriver::PacketIn is not a multiple of 8"); - - struct PacketOut - { - uint8_t packet_len{sizeof(PacketOut)}; - PacketID packet_id{PacketID::PAD}; - Gamepad::PadOut pad_out{Gamepad::PadOut()}; - std::array reserved{0}; - }; - static_assert(sizeof(PacketOut) == 8, "I2CDriver::PacketOut is misaligned"); - - struct PacketCMD - { - uint8_t packet_len{sizeof(PacketCMD)}; - PacketID packet_id{PacketID::COMMAND}; - Command command{Command::UNKNOWN}; - Status status{Status::UNKNOWN}; - std::array reserved{0}; - }; - static_assert(sizeof(PacketCMD) == 8, "I2CDriver::PacketCMD is misaligned"); -#pragma pack(pop) - - static constexpr size_t MAX_PACKET_SIZE = sizeof(PacketIn); -}; - -#endif // I2C_DRIVER_4CH_H \ No newline at end of file diff --git a/Firmware/RP2040/src/I2CDriver/4Channel/I2CManager.h b/Firmware/RP2040/src/I2CDriver/4Channel/I2CManager.h deleted file mode 100644 index a06b1a3..0000000 --- a/Firmware/RP2040/src/I2CDriver/4Channel/I2CManager.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef I2C_4CH_MANAGER_H -#define I2C_4CH_MANAGER_H - -#include -#include -#include -#include - -#include "board_config.h" -#include "Gamepad/Gamepad.h" -#include "I2CDriver/4Channel/I2CMaster.h" -#include "I2CDriver/4Channel/I2CSlave.h" -#include "I2CDriver/4Channel/I2CDriver.h" - -class I2CManager -{ -public: - I2CManager(const I2CManager&) = delete; - I2CManager& operator=(const I2CManager&) = delete; - - static I2CManager& get_instance() - { - static I2CManager instance; - return instance; - } - - bool initialize_driver() - { - uint8_t i2c_address = get_i2c_address(); - if (i2c_address == 0xFF) - { - return false; - } - if (i2c_address < 1) - { - is_master_.store(true); - driver_ = std::make_unique(); - } - else - { - driver_ = std::make_unique(); - } - driver_->initialize(i2c_address); - return true; - } - - I2CDriver* get_driver() - { - return driver_.get(); - } - - bool is_master() - { - return is_master_.load(); - } - -private: - I2CManager() {}; - ~I2CManager() {}; - - std::unique_ptr driver_{nullptr}; - std::atomic is_master_{false}; - - uint8_t get_i2c_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; - } - 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; - } -}; - -#endif // I2C_4CH_MANAGER_H \ No newline at end of file diff --git a/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.cpp b/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.cpp deleted file mode 100644 index 226328a..0000000 --- a/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.cpp +++ /dev/null @@ -1,146 +0,0 @@ -#include -#include - -#include "TaskQueue/TaskQueue.h" -#include "I2CDriver/4Channel/I2CMaster.h" - -void I2CMaster::initialize(uint8_t address) -{ - 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); - - for (uint8_t i = 0; i < NUM_SLAVES; ++i) - { - slaves_[i].address = address + i + 1; - } -} - -void I2CMaster::process(Gamepad (&gamepads)[MAX_GAMEPADS]) -{ - for (uint8_t i = 0; i < NUM_SLAVES; ++i) - { - Slave& slave = slaves_[i]; - - if (!slave.enabled.load() || !slave_detected(slave.address)) - { - continue; - } - - PacketCMD packet_cmd; - packet_cmd.packet_id = PacketID::COMMAND; - packet_cmd.command = Command::STATUS; - - if (!write_blocking(slave.address, &packet_cmd, sizeof(PacketCMD)) || - !read_blocking(slave.address, &packet_cmd, sizeof(PacketCMD))) - { - continue; - } - - if (packet_cmd.status == Status::READY) - { - Gamepad& gamepad = gamepads[i + 1]; - PacketIn packet_in; - packet_in.pad_in = gamepad.get_pad_in(); - packet_in.chatpad_in = gamepad.get_chatpad_in(); - - if (write_blocking(slave.address, &packet_in, sizeof(PacketIn))) - { - PacketOut packet_out; - if (read_blocking(slave.address, &packet_out, sizeof(PacketOut))) - { - gamepad.set_pad_out(packet_out.pad_out); - } - } - } - - sleep_us(100); - } -} - -void I2CMaster::notify_tuh(bool mounted, HostDriverType host_type) -{ - if (host_type != HostDriverType::XBOX360W) - { - return; - } - - i2c_enabled_.store(mounted); - - if (!mounted) - { - //Called from core1 so queue on core0 - TaskQueue::Core0::queue_task( - [this]() - { - for (auto& slave : slaves_) - { - notify_disable(slave.address); - } - }); - } -} - -void I2CMaster::notify_xbox360w(bool connected, uint8_t idx) -{ - if (idx < 1 || idx >= MAX_GAMEPADS) - { - return; - } - - slaves_[idx - 1].enabled.store(connected); - - if (!connected) - { - //Called from core1 so queue on core0 - TaskQueue::Core0::queue_task( - [this]() - { - for (auto& slave : slaves_) - { - notify_disable(slave.address); - } - }); - } -} - -bool I2CMaster::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 I2CMaster::notify_disable(uint8_t address) -{ - if (!slave_detected(address)) - { - return; - } - - int retries = 10; - - while (retries--) - { - PacketCMD packet_cmd; - packet_cmd.packet_id = PacketID::COMMAND; - packet_cmd.command = Command::DISABLE; - if (write_blocking(address, &packet_cmd, sizeof(PacketCMD))) - { - if (read_blocking(address, &packet_cmd, sizeof(PacketCMD))) - { - if (packet_cmd.status == Status::OK) - { - break; - } - } - } - sleep_ms(1); - } -} \ No newline at end of file diff --git a/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.h b/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.h deleted file mode 100644 index 2825c8d..0000000 --- a/Firmware/RP2040/src/I2CDriver/4Channel/I2CMaster.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef I2C_MASTER_4CH_H -#define I2C_MASTER_4CH_H - -#include -#include -#include -#include - -#include "board_config.h" -#include "Gamepad/Gamepad.h" -#include "I2CDriver/4Channel/I2CDriver.h" - -class I2CMaster : public I2CDriver -{ -public: - ~I2CMaster() = default; - void initialize(uint8_t address) override; - void process(Gamepad (&gamepads)[MAX_GAMEPADS]) override; - void notify_tuh(bool mounted, HostDriverType host_type) override; - void notify_xbox360w(bool connected, uint8_t idx) override; - -private: - struct Slave - { - uint8_t address{0xFF}; - Status status{Status::NC}; - std::atomic enabled{false}; - }; - - 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"); - - std::atomic i2c_enabled_{false}; - std::array slaves_; - - void notify_disable(uint8_t address); - - static bool slave_detected(uint8_t address); - - static inline bool read_blocking(uint8_t address, void* buffer, size_t len) - { - return (i2c_read_blocking(I2C_PORT, address, reinterpret_cast(buffer), len, false) == static_cast(len)); - } - static inline bool write_blocking(uint8_t address, void* buffer, size_t len) - { - return (i2c_write_blocking(I2C_PORT, address, reinterpret_cast(buffer), len, false) == static_cast(len)); - } -}; - -#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 deleted file mode 100644 index 0924cb2..0000000 --- a/Firmware/RP2040/src/I2CDriver/4Channel/I2CSlave.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include -#include -#include - -#include "OGXMini/OGXMini.h" -#include "I2CDriver/4Channel/I2CSlave.h" -#include "TaskQueue/TaskQueue.h" - -I2CSlave* I2CSlave::instance_ = nullptr; - -void I2CSlave::initialize(uint8_t address) -{ - instance_ = this; - - 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, address, &slave_handler); -} - -void I2CSlave::notify_tuh(bool mounted, HostDriverType host_type) -{ - tuh_mounted_.store(mounted); -} - -void I2CSlave::process(Gamepad (&gamepads)[MAX_GAMEPADS]) -{ - if (tuh_mounted_.load()) - { - return; - } - //Don't want to hang up the i2c bus by doing this in the slave handler - if (new_pad_in_.load()) - { - new_pad_in_.store(false); - gamepads[0].set_pad_in(packet_in_.pad_in); - gamepads[0].set_chatpad_in(packet_in_.chatpad_in); - } - - if (gamepads[0].new_pad_out()) - { - packet_out_.pad_out = gamepads[0].get_pad_out(); - } -} - -I2CSlave::PacketID I2CSlave::get_packet_id(uint8_t* buffer_in) -{ - switch (static_cast(buffer_in[1])) - { - case PacketID::PAD: - if (buffer_in[0] == sizeof(PacketIn)) - { - return PacketID::PAD; - } - break; - - case PacketID::COMMAND: - if (buffer_in[0] == sizeof(PacketCMD)) - { - return PacketID::COMMAND; - } - break; - - default: - break; - } - return PacketID::UNKNOWN; -} - -void I2CSlave::slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) -{ - static size_t count = 0; - static bool enabled = false; - static uint8_t buffer_in[MAX_PACKET_SIZE]; - static uint8_t buffer_out[MAX_PACKET_SIZE]; - - PacketIn *packet_in_p = reinterpret_cast(buffer_in); - PacketOut *packet_out_p = reinterpret_cast(buffer_out); - PacketCMD *packet_cmd_in_p = reinterpret_cast(buffer_in); - PacketCMD *packet_cmd_out_p = reinterpret_cast(buffer_out); - - switch (event) - { - case I2C_SLAVE_RECEIVE: // master has written - if (count < MAX_PACKET_SIZE) - { - buffer_in[count] = i2c_read_byte_raw(i2c); - ++count; - } - break; - - case I2C_SLAVE_FINISH: - // Each master write has an ID indicating the type of data to send back on the next read request - // Every write has an associated read - switch (get_packet_id(buffer_in)) - { - case PacketID::PAD: - instance_->packet_in_ = *packet_in_p; - *packet_out_p = instance_->packet_out_; - instance_->new_pad_in_.store(true); - break; - - case PacketID::COMMAND: - switch (packet_cmd_in_p->command) - { - case Command::DISABLE: - packet_cmd_out_p->packet_len = sizeof(PacketCMD); - packet_cmd_out_p->packet_id = PacketID::COMMAND; - packet_cmd_out_p->command = Command::DISABLE; - packet_cmd_out_p->status = Status::OK; - if (!instance_->tuh_mounted_.load()) - { - OGXMini::host_mounted(false); - } - break; - - case Command::STATUS: - packet_cmd_out_p->packet_len = sizeof(PacketCMD); - packet_cmd_out_p->packet_id = PacketID::COMMAND; - packet_cmd_out_p->command = Command::STATUS; - packet_cmd_out_p->status = instance_->tuh_mounted_.load() ? Status::NOT_READY : Status::READY; - if (!instance_->tuh_mounted_.load() && !enabled) - { - enabled = true; - OGXMini::host_mounted(true); - } - break; - - default: - break; - } - break; - } - count = 0; - std::memset(buffer_in, 0, sizeof(buffer_in)); - break; - - case I2C_SLAVE_REQUEST: - i2c_write_raw_blocking(i2c, buffer_out, buffer_out[0]); - break; - - 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 deleted file mode 100644 index 19ad2e0..0000000 --- a/Firmware/RP2040/src/I2CDriver/4Channel/I2CSlave.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef I2C_SLAVE_4CH_H -#define I2C_SLAVE_4CH_H - -#include -#include -#include -#include -#include - -#include "board_config.h" -#include "Gamepad/Gamepad.h" -#include "I2CDriver/4Channel/I2CDriver.h" - -class I2CSlave : public I2CDriver -{ -public: - ~I2CSlave() = default; - void initialize(uint8_t address) override; - void process(Gamepad (&gamepads)[MAX_GAMEPADS]) override; - void notify_tuh(bool mounted, HostDriverType host_type) override; - -private: - static I2CSlave* instance_; - - PacketIn packet_in_; - PacketOut packet_out_; - std::atomic new_pad_in_{false}; - std::atomic tuh_mounted_{false}; - - static PacketID get_packet_id(uint8_t* buffer_in); - static void slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event); -}; - -#endif // I2C_SLAVE_4CH_H \ No newline at end of file diff --git a/Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.cpp b/Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.cpp deleted file mode 100644 index edc16db..0000000 --- a/Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.cpp +++ /dev/null @@ -1,146 +0,0 @@ -#include -#include -#include -#include -#include - -#include "board_config.h" -#include "Board/board_api.h" -#include "I2CDriver/ESP32/I2CDriver.h" -#include "UserSettings/UserSettings.h" -#include "TaskQueue/TaskQueue.h" -#include "Board/ogxm_log.h" - -namespace I2CDriver { - -enum class PacketID : uint8_t { UNKNOWN = 0, SET_PAD, GET_PAD, SET_DRIVER }; - -#pragma pack(push, 1) -struct PacketIn -{ - uint8_t packet_len{sizeof(PacketIn)}; - PacketID packet_id{PacketID::SET_PAD}; - uint8_t index{0}; - DeviceDriverType device_type{DeviceDriverType::NONE}; - Gamepad::PadIn pad_in{Gamepad::PadIn()}; - std::array reserved{0}; -}; -static_assert(sizeof(PacketIn) == 32, "i2c_driver_esp::PacketIn size mismatch"); - -struct PacketOut -{ - uint8_t packet_len{sizeof(PacketOut)}; - PacketID packet_id{PacketID::GET_PAD}; - uint8_t index{0}; - Gamepad::PadOut pad_out{Gamepad::PadOut()}; - std::array reserved{0}; -}; -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]; - -static inline void slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) -{ - static size_t count = 0; - static PacketIn packet_in; - static PacketOut packet_out; - static DeviceDriverType current_device_type = UserSettings::get_instance().get_current_driver(); - - switch (event) - { - case I2C_SLAVE_RECEIVE: - if (count < sizeof(PacketIn)) - { - reinterpret_cast(&packet_in)[count] = i2c_read_byte_raw(i2c); - ++count; - } - break; - - case I2C_SLAVE_FINISH: - if (count == 0) - { - break; - } - switch (packet_in.packet_id) - { - case PacketID::SET_PAD: - if (packet_in.index < MAX_GAMEPADS) - { - gamepads_[packet_in.index]->set_pad_in(packet_in.pad_in); - } - break; - - case PacketID::SET_DRIVER: - if (packet_in.device_type != DeviceDriverType::NONE && - packet_in.device_type != current_device_type) - { - OGXM_LOG("I2C: Driver change detected.\n"); - - //Any writes to flash should be done on Core0 - TaskQueue::Core0::queue_delayed_task(TaskQueue::Core0::get_new_task_id(), 1000, false, - [new_device_type = packet_in.device_type] - { - UserSettings::get_instance().store_driver_type(new_device_type); - }); - } - break; - - default: - break; - } - count = 0; - break; - - case I2C_SLAVE_REQUEST: - if (packet_in.index < MAX_GAMEPADS) - { - packet_out.index = packet_in.index; - packet_out.pad_out = gamepads_[packet_in.index]->get_pad_out(); - } - // switch (packet_in.packet_id) - // { - // case PacketID::SET_PAD: - - i2c_write_raw_blocking(i2c, reinterpret_cast(&packet_out), packet_out.packet_len); - // break; - - // default: - // i2c_write_raw_blocking(i2c, reinterpret_cast(&packet_out), 1); - // break; - // } - - // packet_in = PacketIn(); - 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); - - OGXM_LOG("I2C Driver initialized\n"); -} - -} // namespace i2c_driver_esp32 \ No newline at end of file diff --git a/Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.h b/Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.h deleted file mode 100644 index 81a3b2b..0000000 --- a/Firmware/RP2040/src/I2CDriver/ESP32/I2CDriver.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _I2CDRIVER_ESP_H_ -#define _I2CDRIVER_ESP_H_ - -#include - -#include "Gamepad/Gamepad.h" - -namespace I2CDriver -{ - void initialize(Gamepad (&gamepads)[MAX_GAMEPADS]); -} - -#endif // _I2CDRIVER_ESP_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/Board/ESP32_Bluepad32_I2C.cpp b/Firmware/RP2040/src/OGXMini/Board/ESP32_Bluepad32_I2C.cpp new file mode 100644 index 0000000..b98203d --- /dev/null +++ b/Firmware/RP2040/src/OGXMini/Board/ESP32_Bluepad32_I2C.cpp @@ -0,0 +1,201 @@ +#include "Board/Config.h" +#include "OGXMini/Board/ESP32_Bluepad32_I2C.h" +#if (OGXM_BOARD == ESP32_BLUEPAD32_I2C) + +#include +#include +#include +#include +#include + +#include "tusb.h" +#include "bsp/board_api.h" + +#include "USBDevice/DeviceManager.h" +#include "UserSettings/UserSettings.h" +#include "Board/board_api.h" +#include "Board/esp32_api.h" +#include "Gamepad/Gamepad.h" +#include "TaskQueue/TaskQueue.h" + +enum class PacketID : uint8_t { + UNKNOWN = 0, + SET_PAD, + GET_PAD, + SET_DRIVER +}; + +#pragma pack(push, 1) +struct PacketIn { + uint8_t packet_len{sizeof(PacketIn)}; + PacketID packet_id{PacketID::SET_PAD}; + uint8_t index{0}; + DeviceDriverType device_type{DeviceDriverType::NONE}; + Gamepad::PadIn pad_in{Gamepad::PadIn()}; + uint8_t reserved[5]{0}; +}; +static_assert(sizeof(PacketIn) == 32, "i2c_driver_esp::PacketIn size mismatch"); + +struct PacketOut { + uint8_t packet_len{sizeof(PacketOut)}; + PacketID packet_id{PacketID::GET_PAD}; + uint8_t index{0}; + Gamepad::PadOut pad_out{Gamepad::PadOut()}; + uint8_t reserved[3]{0}; +}; +static_assert(sizeof(PacketOut) == 8, "i2c_driver_esp::PacketOut size mismatch"); +#pragma pack(pop) + +constexpr size_t MAX_BUFFER_SIZE = std::max(sizeof(PacketOut), sizeof(PacketIn)); +constexpr uint8_t I2C_ADDR = 0x01; + +static Gamepad _gamepads[MAX_GAMEPADS]; +static bool _uart_bridge_mode = false; + +static inline void slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) { + static size_t count = 0; + static PacketIn packet_in; + static PacketOut packet_out; + static DeviceDriverType current_device_type = + UserSettings::get_instance().get_current_driver(); + + switch (event) { + case I2C_SLAVE_RECEIVE: + if (count < sizeof(PacketIn)) { + reinterpret_cast(&packet_in)[count] = i2c_read_byte_raw(i2c); + ++count; + } + break; + case I2C_SLAVE_FINISH: + if (count == 0) { + break; + } + switch (packet_in.packet_id) { + case PacketID::SET_PAD: + if (packet_in.index < MAX_GAMEPADS) { + _gamepads[packet_in.index].set_pad_in(packet_in.pad_in); + } + break; + case PacketID::SET_DRIVER: + if (packet_in.device_type != DeviceDriverType::NONE && + packet_in.device_type != current_device_type) { + OGXM_LOG("I2C: Driver change detected.\n"); + //Any writes to flash should be done on Core0 + TaskQueue::Core0::queue_delayed_task( + TaskQueue::Core0::get_new_task_id(), 1000, false, + [new_device_type = packet_in.device_type] { + UserSettings::get_instance().store_driver_type(new_device_type); + } + ); + } + break; + default: + break; + } + count = 0; + break; + case I2C_SLAVE_REQUEST: + if (packet_in.index < MAX_GAMEPADS) { + packet_out.index = packet_in.index; + packet_out.pad_out = _gamepads[packet_in.index].get_pad_out(); + } + i2c_write_raw_blocking( i2c, + reinterpret_cast(&packet_out), + packet_out.packet_len); + break; + default: + break; + } +} + +static void core1_task() { + i2c_init(I2C_PORT, I2C_BAUDRATE); + + gpio_init(I2C_SDA_PIN); + gpio_init(I2C_SCL_PIN); + gpio_set_function(I2C_SDA_PIN, GPIO_FUNC_I2C); + gpio_set_function(I2C_SCL_PIN, GPIO_FUNC_I2C); + gpio_pull_up(I2C_SDA_PIN); + gpio_pull_up(I2C_SCL_PIN); + + i2c_slave_init(I2C_PORT, I2C_ADDR, &slave_handler); + + OGXM_LOG("I2C Driver initialized\n"); + + while (true) { + tight_loop_contents(); + } +} + +void run_uart_bridge() { + esp32_api::enter_programming_mode(); + + OGXM_LOG("Entering UART Bridge mode\n"); + + //Runs UART Bridge task, doesn't return unless programming is complete + DeviceManager::get_instance().get_driver()->process(0, _gamepads[0]); + + OGXM_LOG("Exiting UART Bridge mode\n"); + + board_api::usb::disconnect_all(); + UserSettings::get_instance().write_datetime(); + board_api::reboot(); +} + +bool update_needed(UserSettings& user_settings) { +#if defined(OGXM_RETAIL) + return !user_settings.verify_datetime(); +#endif + return false; +} + +void esp32_bp32_i2c::initialize() { + board_api::init_board(); + esp32_api::init(); + + UserSettings& user_settings = UserSettings::get_instance(); + user_settings.initialize_flash(); + + //MODE_SEL_PIN is used to determine if UART bridge should be run + _uart_bridge_mode = + (esp32_api::uart_bridge_mode() || update_needed(user_settings)); + + DeviceDriverType driver_type = + _uart_bridge_mode ? + DeviceDriverType::UART_BRIDGE : user_settings.get_current_driver(); + + DeviceManager::get_instance().initialize_driver(driver_type, _gamepads); +} + +void esp32_bp32_i2c::run() { + if (_uart_bridge_mode) { + run_uart_bridge(); + return; + } + + multicore_reset_core1(); + multicore_launch_core1(core1_task); + + esp32_api::reset(); + + 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]); + tud_task(); + } + sleep_ms(1); + } +} + +// #else // OGXM_BOARD == ESP32_BLUEPAD32_I2C + +// void esp32_bp32_i2c::initialize() {} +// void esp32_bp32_i2c::run() {} + +#endif // OGXM_BOARD == ESP32_BLUEPAD32_I2C \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/Board/ESP32_Bluepad32_I2C.h b/Firmware/RP2040/src/OGXMini/Board/ESP32_Bluepad32_I2C.h new file mode 100644 index 0000000..a0b61af --- /dev/null +++ b/Firmware/RP2040/src/OGXMini/Board/ESP32_Bluepad32_I2C.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace esp32_bp32_i2c { + void initialize(); + void run(); +} // namespace esp32_bp32_i2c \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/Board/ESP32_Blueretro_I2C.cpp b/Firmware/RP2040/src/OGXMini/Board/ESP32_Blueretro_I2C.cpp new file mode 100644 index 0000000..1a0f3ff --- /dev/null +++ b/Firmware/RP2040/src/OGXMini/Board/ESP32_Blueretro_I2C.cpp @@ -0,0 +1,200 @@ +#include "Board/Config.h" +#include "OGXMini/Board/ESP32_Blueretro_I2C.h" +#if (OGXM_BOARD == ESP32_BLUERETRO_I2C) + +#include +#include +#include + +#include "tusb.h" +#include "bsp/board_api.h" + +#include "UserSettings/UserSettings.h" +#include "USBDevice/DeviceManager.h" +#include "Board/board_api.h" +#include "Board/esp32_api.h" +#include "Gamepad/Gamepad.h" +#include "TaskQueue/TaskQueue.h" + +#pragma pack(push, 1) +struct PacketIn { + uint8_t len{sizeof(PacketIn)}; + uint8_t index{0}; + DeviceDriverType device_type{DeviceDriverType::NONE}; + uint8_t gp_data[13]{0}; +}; +static_assert(sizeof(PacketIn) == 16, "i2c_driver_esp::PacketIn size mismatch"); + +struct PacketOut { + uint8_t len{sizeof(PacketOut)}; + uint8_t rumble_l{0}; + uint8_t rumble_r{0}; + uint8_t reserved[5]{0}; +}; +static_assert(sizeof(PacketOut) == 8, "i2c_driver_esp::PacketOut size mismatch"); +#pragma pack(pop) + +constexpr uint8_t SLAVE_ADDR = 0x50; +constexpr uint32_t FEEDBACK_DELAY_MS = 250; + +static Gamepad _gamepads[MAX_GAMEPADS]; +static bool _uart_bridge_mode = false; + +static void core1_task() { + i2c_init(I2C_PORT, I2C_BAUDRATE); + + gpio_set_function(I2C_SCL_PIN, GPIO_FUNC_I2C); + gpio_set_function(I2C_SDA_PIN, GPIO_FUNC_I2C); + gpio_pull_up(I2C_SCL_PIN); + gpio_pull_up(I2C_SDA_PIN); + + bool slave_ready = false; + PacketIn packet_in; + PacketOut packet_out; + Gamepad::PadIn pad_in; + Gamepad& gamepad = _gamepads[0]; + uint32_t tid = TaskQueue::Core1::get_new_task_id(); + + sleep_ms(500); // Wait for ESP32 to start + + TaskQueue::Core1::queue_delayed_task(tid, FEEDBACK_DELAY_MS, true, + [&packet_out, &gamepad, &slave_ready] { + if (!slave_ready) { // Check if slave present + uint8_t addr = SLAVE_ADDR; + int result = i2c_read_blocking(I2C_PORT, SLAVE_ADDR, &addr, 1, false); + slave_ready = (result == 1); + + } else { // Update rumble + Gamepad::PadOut pad_out = gamepad.get_pad_out(); + packet_out.rumble_l = pad_out.rumble_l; + packet_out.rumble_r = pad_out.rumble_r; + int result = i2c_write_blocking(I2C_PORT, SLAVE_ADDR, + reinterpret_cast(&packet_out), + sizeof(PacketOut), false); + + if (result != sizeof(PacketOut)) { + OGXM_LOG("I2C write failed\n"); + } else { + OGXM_LOG("I2C sent rumble, L: %02X, R: %02X\n", + packet_out.rumble_l, packet_out.rumble_r); + sleep_ms(1); + } + } + }); + + OGXM_LOG("I2C Driver initialized\n"); + + //Wait for slave to be detected + while (!slave_ready) { + TaskQueue::Core1::process_tasks(); + sleep_ms(100); + } + + OGXM_LOG("I2C Slave ready\n"); + + while (true) { + TaskQueue::Core1::process_tasks(); + int result = i2c_read_blocking( I2C_PORT, SLAVE_ADDR, + reinterpret_cast(&packet_in), + sizeof(PacketIn), false); + + if (result == sizeof(PacketIn)) { + std::memcpy(reinterpret_cast(&pad_in), + packet_in.gp_data, + sizeof(packet_in.gp_data)); + gamepad.set_pad_in(pad_in); + + } else { + OGXM_LOG("I2C read failed\n"); + return; + } + sleep_ms(1); + } +} + +void set_gp_check_timer(uint32_t task_id) { + UserSettings& user_settings = UserSettings::get_instance(); + + 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])) { + OGXM_LOG("Driver change detected, storing new driver.\n"); + //This will store the new mode and reboot the pico + user_settings.store_driver_type(user_settings.get_current_driver()); + } + }); +} + +void run_uart_bridge() { + esp32_api::enter_programming_mode(); + + OGXM_LOG("Entering UART Bridge mode\n"); + + //Runs UART Bridge task, doesn't return unless programming is complete + DeviceManager::get_instance().get_driver()->process(0, _gamepads[0]); + + OGXM_LOG("Exiting UART Bridge mode\n"); + + board_api::usb::disconnect_all(); + UserSettings::get_instance().write_datetime(); + board_api::reboot(); +} + +bool update_needed(UserSettings& user_settings) { +#if defined(OGXM_RETAIL) + return !user_settings.verify_datetime(); +#endif + return false; +} + +void esp32_br_i2c::initialize() { + board_api::init_board(); + esp32_api::init(); + + UserSettings& user_settings = UserSettings::get_instance(); + user_settings.initialize_flash(); + + //MODE_SEL_PIN is used to determine if UART bridge should be run + _uart_bridge_mode = + (esp32_api::uart_bridge_mode() || update_needed(user_settings)); + + DeviceDriverType driver_type = + _uart_bridge_mode ? + DeviceDriverType::UART_BRIDGE : user_settings.get_current_driver(); + + DeviceManager::get_instance().initialize_driver(driver_type, _gamepads); +} + +void esp32_br_i2c::run() { + if (_uart_bridge_mode) { + run_uart_bridge(); + return; + } + + esp32_api::reset(); + + 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); + + DeviceDriver* device_driver = DeviceManager::get_instance().get_driver(); + + tud_init(BOARD_TUD_RHPORT); + + while (true) { + TaskQueue::Core0::process_tasks(); + device_driver->process(0, _gamepads[0]); + tud_task(); + sleep_ms(1); + } +} + +// #else // OGXM_BOARD == ESP32_BLUERETRO_I2C + +// void esp32_br_i2c::initialize() {} +// void esp32_br_i2c::run() {} + +#endif // OGXM_BOARD == ESP32_BLUERETRO_I2C \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/Board/ESP32_Blueretro_I2C.h b/Firmware/RP2040/src/OGXMini/Board/ESP32_Blueretro_I2C.h new file mode 100644 index 0000000..eac47a4 --- /dev/null +++ b/Firmware/RP2040/src/OGXMini/Board/ESP32_Blueretro_I2C.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace esp32_br_i2c { + void initialize(); + void run(); +} // namespace esp32_br_i2c \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/Board/Four_Channel_I2C.cpp b/Firmware/RP2040/src/OGXMini/Board/Four_Channel_I2C.cpp new file mode 100644 index 0000000..5b86f35 --- /dev/null +++ b/Firmware/RP2040/src/OGXMini/Board/Four_Channel_I2C.cpp @@ -0,0 +1,470 @@ +#include "Board/Config.h" +#include "OGXMini/Board/Four_Channel_I2C.h" +#if ((OGXM_BOARD == INTERNAL_4CH_I2C) || (OGXM_BOARD == EXTERNAL_4CH_I2C)) + +#include +#include +#include +#include +#include +#include + +#include "tusb.h" +#include "bsp/board_api.h" +#include "pio_usb.h" + +#include "USBDevice/DeviceManager.h" +#include "USBHost/HostManager.h" +#include "Board/board_api.h" +#include "Board/ogxm_log.h" +#include "UserSettings/UserSettings.h" +#include "Gamepad/Gamepad.h" +#include "TaskQueue/TaskQueue.h" + +constexpr uint32_t FEEDBACK_DELAY_MS = 250; + +Gamepad _gamepads[MAX_GAMEPADS]; + +namespace I2C { + enum class Role { + SLAVE = 0, + MASTER + }; + enum class PacketID : uint8_t { + UNKNOWN = 0, + PAD, + COMMAND + }; + enum class Command : uint8_t { + UNKNOWN = 0, + STATUS, + DISABLE + }; + enum class Status : uint8_t { + UNKNOWN = 0, + NC, + ERROR, + OK, + READY, + NOT_READY + }; + + #pragma pack(push, 1) + struct PacketIn { + uint8_t packet_len{sizeof(PacketIn)}; + PacketID packet_id{PacketID::PAD}; + Gamepad::PadIn pad_in{Gamepad::PadIn()}; + Gamepad::ChatpadIn chatpad_in{0}; + uint8_t reserved[4]{0}; + }; + static_assert(sizeof(PacketIn) == 32, "I2CDriver::PacketIn is misaligned"); + + struct PacketOut { + uint8_t packet_len{sizeof(PacketOut)}; + PacketID packet_id{PacketID::PAD}; + Gamepad::PadOut pad_out{Gamepad::PadOut()}; + uint8_t reserved[4]{0}; + }; + static_assert(sizeof(PacketOut) == 8, "I2CDriver::PacketOut is misaligned"); + + struct PacketCMD { + uint8_t packet_len{sizeof(PacketCMD)}; + PacketID packet_id{PacketID::COMMAND}; + Command command{Command::UNKNOWN}; + Status status{Status::UNKNOWN}; + uint8_t reserved[4]{0}; + }; + static_assert(sizeof(PacketCMD) == 8, "I2CDriver::PacketCMD is misaligned"); + #pragma pack(pop) + + constexpr size_t MAX_PACKET_SIZE = sizeof(PacketIn); + + static Role _i2c_role = Role::SLAVE; + + namespace Slave { + static inline PacketID get_packet_id(uint8_t* buffer_in) { + switch (static_cast(buffer_in[1])) { + case PacketID::PAD: + if (buffer_in[0] == sizeof(PacketIn)) { + return PacketID::PAD; + } + break; + case PacketID::COMMAND: + if (buffer_in[0] == sizeof(PacketCMD)) { + return PacketID::COMMAND; + } + break; + default: + break; + } + return PacketID::UNKNOWN; + } + + static void slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) { + static size_t count = 0; + static bool enabled = false; + static uint8_t buffer_in[MAX_PACKET_SIZE]; + static uint8_t buffer_out[MAX_PACKET_SIZE]; + + PacketIn *packet_in_p = reinterpret_cast(buffer_in); + PacketOut *packet_out_p = reinterpret_cast(buffer_out); + PacketCMD *packet_cmd_in_p = reinterpret_cast(buffer_in); + PacketCMD *packet_cmd_out_p = reinterpret_cast(buffer_out); + + switch (event) { + case I2C_SLAVE_RECEIVE: // master has written + if (count < MAX_PACKET_SIZE) { + buffer_in[count] = i2c_read_byte_raw(i2c); + ++count; + } + break; + + case I2C_SLAVE_FINISH: + // Each master write has an ID indicating the type of data to send back on the next read request + // Every write has an associated read + switch (get_packet_id(buffer_in)) { + case PacketID::PAD: + // instance_->packet_in_ = *packet_in_p; + // *packet_out_p = instance_->packet_out_; + // instance_->new_pad_in_.store(true); + _gamepads[0].set_pad_in(packet_in_p->pad_in); + if (_gamepads[0].new_pad_out()) { + packet_out_p->pad_out = _gamepads[0].get_pad_out(); + } + break; + + case PacketID::COMMAND: + switch (packet_cmd_in_p->command) { + case Command::DISABLE: + packet_cmd_out_p->packet_len = sizeof(PacketCMD); + packet_cmd_out_p->packet_id = PacketID::COMMAND; + packet_cmd_out_p->command = Command::DISABLE; + packet_cmd_out_p->status = Status::OK; + + if (!tuh_mounted(BOARD_TUH_RHPORT)) { + four_ch_i2c::host_mounted(false); + } + break; + + case Command::STATUS: + packet_cmd_out_p->packet_len = sizeof(PacketCMD); + packet_cmd_out_p->packet_id = PacketID::COMMAND; + packet_cmd_out_p->command = Command::STATUS; + packet_cmd_out_p->status = + tuh_mounted(BOARD_TUH_RHPORT) ? Status::NOT_READY : Status::READY; + + if (!tuh_mounted(BOARD_TUH_RHPORT) && !enabled) { + enabled = true; + four_ch_i2c::host_mounted(true); + } + break; + + default: + break; + } + break; + } + count = 0; + std::memset(buffer_in, 0, sizeof(buffer_in)); + break; + + case I2C_SLAVE_REQUEST: + i2c_write_raw_blocking(i2c, buffer_out, buffer_out[0]); + break; + + default: + break; + } + } + } // namespace Slave + + namespace Master { + struct Slave { + uint8_t address{0xFF}; + Status status{Status::NC}; + bool enabled{false}; + }; + + 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"); + + std::array _slaves; + + static inline bool read_blocking(uint8_t address, void* buffer, size_t len) { + return (i2c_read_blocking( I2C_PORT, address, reinterpret_cast(buffer), + len, false) == static_cast(len)); + } + + static inline bool write_blocking(uint8_t address, void* buffer, size_t len) { + return (i2c_write_blocking( I2C_PORT, address, reinterpret_cast(buffer), + len, false) == static_cast(len)); + } + + static inline bool slave_detected(uint8_t address) { + uint8_t dummy = 0; + int result = i2c_write_timeout_us(I2C_PORT, address, &dummy, 0, false, 1000); + return (result >= 0); + } + + static void notify_disable(uint8_t address) { + if (!slave_detected(address)) { + return; + } + int retries = 10; + + while (retries--) { + PacketCMD packet_cmd; + packet_cmd.packet_id = PacketID::COMMAND; + packet_cmd.command = Command::DISABLE; + + if (write_blocking(address, &packet_cmd, sizeof(PacketCMD))) { + if (read_blocking(address, &packet_cmd, sizeof(PacketCMD))) { + if (packet_cmd.status == Status::OK) { + break; + } + } + } + sleep_ms(1); + } + } + + static void process() { + for (uint8_t i = 0; i < NUM_SLAVES; ++i) { + Slave& slave = _slaves[i]; + + if (!slave.enabled || !slave_detected(slave.address)) { + continue; + } + + PacketCMD packet_cmd; + packet_cmd.packet_id = PacketID::COMMAND; + packet_cmd.command = Command::STATUS; + + if (!write_blocking(slave.address, &packet_cmd, sizeof(PacketCMD)) || + !read_blocking(slave.address, &packet_cmd, sizeof(PacketCMD))) { + continue; + } + + if (packet_cmd.status == Status::READY) { + Gamepad& gamepad = _gamepads[i + 1]; + PacketIn packet_in; + packet_in.pad_in = gamepad.get_pad_in(); + packet_in.chatpad_in = gamepad.get_chatpad_in(); + + if (write_blocking(slave.address, &packet_in, sizeof(PacketIn))) { + PacketOut packet_out; + if (read_blocking(slave.address, &packet_out, sizeof(PacketOut))) { + gamepad.set_pad_out(packet_out.pad_out); + } + } + } + sleep_ms(1); + } + } + + static void xbox360w_connect(bool connected, uint8_t idx) { + if (idx < 1 || idx >= MAX_GAMEPADS) { + return; + } + // This function can be called from core1 + // so queue on core0 (i2c thread) + TaskQueue::Core0::queue_task( + [&slave = _slaves[idx - 1], connected]() { + slave.enabled = connected; + if (!connected) { + notify_disable(slave.address); + } + }); + } + + static void tuh_connect(bool connected, HostDriverType host_type) { + if (host_type != HostDriverType::XBOX360W) { + return; + } + if (!connected) { + //Called from core1 so queue on core0 + TaskQueue::Core0::queue_task( + []() { + for (auto& slave : _slaves) { + slave.enabled = false; + notify_disable(slave.address); + } + }); + } + } + } // namespace Master + + Role role() { + return _i2c_role; + } + + 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) && gpio_get(SLAVE_ADDR_PIN_2)) { + return 0x00; + } + else if (gpio_get(SLAVE_ADDR_PIN_1) && !gpio_get(SLAVE_ADDR_PIN_2)) { + return 0x01; + } + else if (!gpio_get(SLAVE_ADDR_PIN_1) && gpio_get(SLAVE_ADDR_PIN_2)) { + return 0x02; + } + else if (!gpio_get(SLAVE_ADDR_PIN_1) && !gpio_get(SLAVE_ADDR_PIN_2)) { + return 0x03; + } + return 0xFF; + } + + void initialize() { + uint8_t i2c_address = get_address(); + _i2c_role = (i2c_address == 0xFF) ? Role::MASTER : _i2c_role = Role::SLAVE; + + i2c_init(I2C_PORT, I2C_BAUDRATE); + + gpio_init(I2C_SDA_PIN); + gpio_init(I2C_SCL_PIN); + gpio_set_function(I2C_SDA_PIN, GPIO_FUNC_I2C); + gpio_set_function(I2C_SCL_PIN, GPIO_FUNC_I2C); + gpio_pull_up(I2C_SDA_PIN); + gpio_pull_up(I2C_SCL_PIN); + + if (_i2c_role == Role::SLAVE) { + i2c_slave_init(I2C_PORT, i2c_address, &Slave::slave_handler); + } + } +} // namespace I2C + +void core1_task() { + HostManager& host_manager = HostManager::get_instance(); + host_manager.initialize(_gamepads); + + //Pico-PIO-USB will not reliably detect a hot plug on some boards, + //so monitor pins and init host stack after connection + while(!board_api::usb::host_connected()) { + sleep_ms(100); + } + + pio_usb_configuration_t pio_cfg = PIO_USB_CONFIG; + tuh_configure(BOARD_TUH_RHPORT, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg); + + tuh_init(BOARD_TUH_RHPORT); + + 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(); + } +} + +void set_gp_check_timer(uint32_t task_id) { + UserSettings& user_settings = UserSettings::get_instance(); + 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(user_settings.get_current_driver()); + } + }); +} + +void four_ch_i2c::wireless_connected(bool connected, uint8_t idx) { + if (I2C::role() == I2C::Role::MASTER) { + I2C::Master::xbox360w_connect(connected, idx); + } +} + +void four_ch_i2c::host_mounted(bool mounted) { + static std::atomic tud_is_inited = false; + + board_api::set_led(mounted); + + if (!mounted && tud_is_inited.load()) { + TaskQueue::Core0::queue_task([]() { + OGXM_LOG("Disconnecting USB and rebooting.\n"); + board_api::usb::disconnect_all(); + board_api::reboot(); + }); + } else if (!tud_is_inited.load() && mounted) { + TaskQueue::Core0::queue_task([]() { + OGXM_LOG("Initializing USB device stack.\n"); + tud_init(BOARD_TUD_RHPORT); + tud_is_inited.store(true); + }); + } +} + +void four_ch_i2c::host_mounted_w_type(bool mounted, HostDriverType host_type) { + host_mounted(mounted); + if (I2C::role() == I2C::Role::MASTER) { + I2C::Master::tuh_connect(mounted, host_type); + } +} + +void four_ch_i2c::initialize() { + UserSettings& user_settings = UserSettings::get_instance(); + 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); +} + +void four_ch_i2c::run() { + I2C::initialize(); + + multicore_reset_core1(); + multicore_launch_core1(core1_task); + + //Wait for something to call tud_init + while (!tud_inited()) { + TaskQueue::Core0::process_tasks(); + sleep_ms(100); + } + + uint32_t tid_gp_check = TaskQueue::Core0::get_new_task_id(); + set_gp_check_timer(tid_gp_check); + + DeviceDriver* device_driver = DeviceManager::get_instance().get_driver(); + + if (I2C::role() == I2C::Role::MASTER) { + while (true) { + TaskQueue::Core0::process_tasks(); + I2C::Master::process(); + device_driver->process(0, _gamepads[0]); + tud_task(); + sleep_ms(1); + } + } else { + while (true) { + TaskQueue::Core0::process_tasks(); + device_driver->process(0, _gamepads[0]); + tud_task(); + sleep_ms(1); + } + } +} + +// #else // OGXM_BOARD == INTERNAL_4CH_I2C || OGXM_BOARD == EXTERNAL_4CH_I2C + +// void four_ch_i2c::initialize() {} +// void four_ch_i2c::run() {} +// void four_ch_i2c::host_mounted_w_type(bool mounted, HostDriverType host_type) {} +// void four_ch_i2c::host_mounted(bool mounted) {} +// void four_ch_i2c::wireless_connected(bool connected, uint8_t idx) {} + +#endif // OGXM_BOARD == INTERNAL_4CH || OGXM_BOARD == EXTERNAL_4CH \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/Board/Four_Channel_I2C.h b/Firmware/RP2040/src/OGXMini/Board/Four_Channel_I2C.h new file mode 100644 index 0000000..4c96229 --- /dev/null +++ b/Firmware/RP2040/src/OGXMini/Board/Four_Channel_I2C.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#include "USBHost/HostDriver/HostDriverTypes.h" + +namespace four_ch_i2c { + void initialize(); + void run(); + void host_mounted_w_type(bool mounted, HostDriverType host_type); + void host_mounted(bool mounted); + void wireless_connected(bool connected, uint8_t idx); +} // namespace ext_4ch_i2c \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/OGXMini_PicoW.cpp b/Firmware/RP2040/src/OGXMini/Board/PicoW.cpp similarity index 55% rename from Firmware/RP2040/src/OGXMini/OGXMini_PicoW.cpp rename to Firmware/RP2040/src/OGXMini/Board/PicoW.cpp index 72f13ea..929d249 100644 --- a/Firmware/RP2040/src/OGXMini/OGXMini_PicoW.cpp +++ b/Firmware/RP2040/src/OGXMini/Board/PicoW.cpp @@ -1,5 +1,6 @@ -#include "board_config.h" -#if (OGXM_BOARD == PI_PICOW) || (OGXM_BOARD == PI_PICO2W) +#include "Board/Config.h" +#include "OGXMini/Board/PicoW.h" +#if (OGXM_BOARD == PI_PICOW) #include #include @@ -8,80 +9,73 @@ #include "bsp/board_api.h" #include "USBDevice/DeviceManager.h" +#include "UserSettings/UserSettings.h" #include "Board/board_api.h" #include "Bluepad32/Bluepad32.h" -#include "OGXMini/OGXMini.h" #include "BLEServer/BLEServer.h" #include "Gamepad/Gamepad.h" #include "TaskQueue/TaskQueue.h" -namespace OGXMini { +Gamepad _gamepads[MAX_GAMEPADS]; -Gamepad gamepads_[MAX_GAMEPADS]; - -//Not using this for Pico W currently -void host_mounted(bool host_mounted) { } - -void core1_task() -{ +void core1_task() { board_api::init_bluetooth(); board_api::set_led(true); - BLEServer::init_server(gamepads_); - bluepad32::run_task(gamepads_); + BLEServer::init_server(_gamepads); + bluepad32::run_task(_gamepads); } -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] - { +void set_gp_check_timer(uint32_t task_id) { + UserSettings& user_settings = UserSettings::get_instance(); + 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])) - { + if (user_settings.check_for_driver_change(_gamepads[0])) { //This will store the new mode and reboot the pico user_settings.store_driver_type(user_settings.get_current_driver()); } }); } -void run_program() -{ +void pico_w::initialize() { board_api::init_board(); UserSettings& user_settings = UserSettings::get_instance(); user_settings.initialize_flash(); - for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) - { - gamepads_[i].set_profile(user_settings.get_profile_by_index(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(), gamepads_); + device_manager.initialize_driver(user_settings.get_current_driver(), _gamepads); +} +void pico_w::run() { 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); + set_gp_check_timer(tid_gp_check); - DeviceDriver* device_driver = device_manager.get_driver(); + DeviceDriver* device_driver = DeviceManager::get_instance().get_driver(); tud_init(BOARD_TUD_RHPORT); - while (true) - { + while (true) { TaskQueue::Core0::process_tasks(); - for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) - { - device_driver->process(i, gamepads_[i]); + for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) { + device_driver->process(i, _gamepads[i]); tud_task(); } - - sleep_us(100); + sleep_ms(1); } } -} // namespace OGXMini +// #else // (OGXM_BOARD == PI_PICOW) + +// void pico_w::initialize() {} +// void pico_w::run() {} #endif // (OGXM_BOARD == PI_PICOW) diff --git a/Firmware/RP2040/src/OGXMini/Board/PicoW.h b/Firmware/RP2040/src/OGXMini/Board/PicoW.h new file mode 100644 index 0000000..2a15303 --- /dev/null +++ b/Firmware/RP2040/src/OGXMini/Board/PicoW.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace pico_w { + void initialize(); + void run(); +} // namespace pico_w \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/OGXMini_Standard.cpp b/Firmware/RP2040/src/OGXMini/Board/Standard.cpp similarity index 52% rename from Firmware/RP2040/src/OGXMini/OGXMini_Standard.cpp rename to Firmware/RP2040/src/OGXMini/Board/Standard.cpp index 7162282..1db4f58 100644 --- a/Firmware/RP2040/src/OGXMini/OGXMini_Standard.cpp +++ b/Firmware/RP2040/src/OGXMini/Board/Standard.cpp @@ -1,5 +1,6 @@ -#include "board_config.h" -#if (OGXM_BOARD == ADA_FEATHER) || (OGXM_BOARD == RP_ZERO) || (OGXM_BOARD == PI_PICO) || (OGXM_BOARD == PI_PICO2) +#include "Board/Config.h" +#include "OGXMini/Board/Standard.h" +#if ((OGXM_BOARD == PI_PICO) || (OGXM_BOARD == RP2040_ZERO) || (OGXM_BOARD == ADAFRUIT_FEATHER)) #include @@ -9,50 +10,22 @@ #include "USBHost/HostManager.h" #include "USBDevice/DeviceManager.h" -#include "OGXMini/OGXMini.h" #include "TaskQueue/TaskQueue.h" #include "Gamepad/Gamepad.h" #include "Board/board_api.h" #include "Board/ogxm_log.h" -namespace OGXMini { +constexpr uint32_t FEEDBACK_DELAY_MS = 200; -Gamepad gamepads_[MAX_GAMEPADS]; +Gamepad _gamepads[MAX_GAMEPADS]; -//Called by tusb host so we know to connect or disconnect usb -void host_mounted(bool host_mounted) -{ - static std::atomic tud_is_inited = false; - - board_api::set_led(host_mounted); - - if (!host_mounted && tud_is_inited.load()) - { - TaskQueue::Core0::queue_task([]() - { - OGXM_LOG("USB disconnected, rebooting.\n"); - board_api::usb::disconnect_all(); - board_api::reboot(); - }); - } - else if (!tud_is_inited.load()) - { - TaskQueue::Core0::queue_task([]() - { - tud_init(BOARD_TUD_RHPORT); - tud_is_inited.store(true); - }); - } -} - -void core1_task() -{ +void core1_task() { HostManager& host_manager = HostManager::get_instance(); - host_manager.initialize(gamepads_); + host_manager.initialize(_gamepads); - //Pico-PIO-USB will not reliably detect a hot plug on some boards, monitor and init host stack after connection - while(!board_api::usb::host_connected()) - { + //Pico-PIO-USB will not reliably detect a hot plug on some boards, + //monitor and init host stack after connection + while(!board_api::usb::host_connected()) { sleep_ms(100); } @@ -62,25 +35,24 @@ void core1_task() tuh_init(BOARD_TUH_RHPORT); uint32_t tid_feedback = TaskQueue::Core1::get_new_task_id(); - TaskQueue::Core1::queue_delayed_task(tid_feedback, FEEDBACK_DELAY_MS, true, [&host_manager] - { + TaskQueue::Core1::queue_delayed_task(tid_feedback, FEEDBACK_DELAY_MS, true, + [&host_manager] { host_manager.send_feedback(); }); - while (true) - { + while (true) { TaskQueue::Core1::process_tasks(); tuh_task(); } } -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] - { +void set_gp_check_timer(uint32_t task_id) { + UserSettings& user_settings = UserSettings::get_instance(); + + 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])) - { + if (user_settings.check_for_driver_change(_gamepads[0])) { OGXM_LOG("Driver change detected, storing new driver.\n"); //This will store the new mode and reboot the pico user_settings.store_driver_type(user_settings.get_current_driver()); @@ -88,58 +60,75 @@ void set_gp_check_timer(uint32_t task_id, UserSettings& user_settings) }); } -void run_program() -{ +//Called by tusb host so we know to connect or disconnect usb +void standard::host_mounted(bool host_mounted) { + static std::atomic tud_is_inited = false; + board_api::set_led(host_mounted); + + if (!host_mounted && tud_is_inited.load()) { + TaskQueue::Core0::queue_task([]() { + OGXM_LOG("USB disconnected, rebooting.\n"); + board_api::usb::disconnect_all(); + board_api::reboot(); + }); + } else if (!tud_is_inited.load()) { + TaskQueue::Core0::queue_task([]() { + tud_init(BOARD_TUD_RHPORT); + tud_is_inited.store(true); + }); + } +} + +void standard::initialize() { board_api::init_board(); UserSettings& user_settings = UserSettings::get_instance(); user_settings.initialize_flash(); - for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) - { - gamepads_[i].set_profile(user_settings.get_profile_by_index(i)); + for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) { + _gamepads[i].set_profile(user_settings.get_profile_by_index(i)); } - DeviceDriverType current_driver = user_settings.get_current_driver(); - DeviceManager& device_manager = DeviceManager::get_instance(); - device_manager.initialize_driver(current_driver, gamepads_); + DeviceManager::get_instance().initialize_driver(user_settings.get_current_driver(), _gamepads); +} +void standard::run() { multicore_reset_core1(); multicore_launch_core1(core1_task); - if (current_driver != DeviceDriverType::WEBAPP) - { + DeviceDriverType current_driver = UserSettings::get_instance().get_current_driver(); + + if (current_driver != DeviceDriverType::WEBAPP) { // Wait for something to call host_mounted() - while (!tud_inited()) - { + while (!tud_inited()) { TaskQueue::Core0::process_tasks(); sleep_ms(100); } - } - else //Connect immediately in WebApp mode - { + } else { + //Connect immediately in WebApp mode host_mounted(true); } uint32_t tid_gp_check = TaskQueue::Core0::get_new_task_id(); - set_gp_check_timer(tid_gp_check, user_settings); + set_gp_check_timer(tid_gp_check); - DeviceDriver* device_driver = device_manager.get_driver(); + DeviceDriver* device_driver = DeviceManager::get_instance().get_driver(); - while (true) - { + while (true) { TaskQueue::Core0::process_tasks(); - for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) - { - device_driver->process(i, gamepads_[i]); + for (uint8_t i = 0; i < MAX_GAMEPADS; ++i) { + device_driver->process(i, _gamepads[i]); } - tud_task(); - sleep_us(100); + sleep_ms(1); } } -} // namespace OGXMini +// #else // OGXM_BOARD == PI_PICO || OGXM_BOARD == RP2040_ZERO || OGXM_BOARD == ADAFRUIT_FEATHER -#endif // (OGXM_BOARD == ADA_FEATHER) || (OGXM_BOARD == RP_ZERO) || (OGXM_BOARD == PI_PICO) || (OGXM_BOARD == PI_PICO2) \ No newline at end of file +// void standard::host_mounted(bool host_mounted) {} +// void standard::initialize() {} +// void standard::run() {} + +#endif // OGXM_BOARD == PI_PICO || OGXM_BOARD == RP2040_ZERO || OGXM_BOARD == ADAFRUIT_FEATHER \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/Board/Standard.h b/Firmware/RP2040/src/OGXMini/Board/Standard.h new file mode 100644 index 0000000..d8f8fb3 --- /dev/null +++ b/Firmware/RP2040/src/OGXMini/Board/Standard.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace standard { + void initialize(); + void run(); + void host_mounted(bool mounted); +} // namespace standard \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/OGXMini.cpp b/Firmware/RP2040/src/OGXMini/OGXMini.cpp new file mode 100644 index 0000000..a754c63 --- /dev/null +++ b/Firmware/RP2040/src/OGXMini/OGXMini.cpp @@ -0,0 +1,103 @@ +#include "Board/Config.h" +#include "OGXMini/Board/Standard.h" +#include "OGXMini/Board/PicoW.h" +#include "OGXMini/Board/Four_Channel_I2C.h" +#include "OGXMini/Board/ESP32_Blueretro_I2C.h" +#include "OGXMini/Board/ESP32_Bluepad32_I2C.h" +#include "OGXMini/OGXMini.h" + +namespace OGXMini { + typedef void (*InitFunc)(); + typedef void (*RunFunc)(); + typedef void (*HostMountedFunc)(bool mounted); + typedef void (*HostMountedWTypeFunc)(bool mounted, HostDriverType host_type); + typedef void (*WirelessConnectedFunc)(bool connected, uint8_t idx); + + static constexpr InitFunc init_func[BOARDS_COUNT] = { + standard::initialize, // PI_PICO + standard::initialize, // RP2040_ZERO + standard::initialize, // ADAFRUIT_FEATHER + pico_w::initialize, // PI_PICOW + esp32_bp32_i2c::initialize, // ESP32_BLUEPAD32_I2C + esp32_br_i2c::initialize, // ESP32_BLUERETRO_I2C + four_ch_i2c::initialize, // EXTERNAL_4CH_I2C + four_ch_i2c::initialize, // INTERNAL_4CH_I2C + }; + + static constexpr RunFunc run_func[BOARDS_COUNT] = { + standard::run, // PI_PICO + standard::run, // RP2040_ZERO + standard::run, // ADAFRUIT_FEATHER + pico_w::run, // PI_PICOW + esp32_bp32_i2c::run, // ESP32_BLUEPAD32_I2C + esp32_br_i2c::run, // ESP32_BLUERETRO_I2C + four_ch_i2c::run, // EXTERNAL_4CH_I2C + four_ch_i2c::run, // INTERNAL_4CH_I2C + }; + + static constexpr HostMountedFunc host_mount_func[BOARDS_COUNT] = { + standard::host_mounted, // PI_PICO + standard::host_mounted, // RP2040_ZERO + standard::host_mounted, // ADAFRUIT_FEATHER + nullptr, // PI_PICOW + nullptr, // ESP32_BLUEPAD32_I2C + nullptr, // ESP32_BLUERETRO_I2C + four_ch_i2c::host_mounted, // EXTERNAL_4CH_I2C + four_ch_i2c::host_mounted, // INTERNAL_4CH_I2C + }; + + static constexpr HostMountedWTypeFunc host_mount_w_type_func[BOARDS_COUNT] = { + nullptr, // PI_PICO + nullptr, // RP2040_ZERO + nullptr, // ADAFRUIT_FEATHER + nullptr, // PI_PICOW + nullptr, // ESP32_BLUEPAD32_I2C + nullptr, // ESP32_BLUERETRO_I2C + four_ch_i2c::host_mounted_w_type, // EXTERNAL_4CH_I2C + four_ch_i2c::host_mounted_w_type, // INTERNAL_4CH_I2C + }; + + static constexpr WirelessConnectedFunc wl_conn_func[BOARDS_COUNT] = { + nullptr, // PI_PICO + nullptr, // RP2040_ZERO + nullptr, // ADAFRUIT_FEATHER + nullptr, // PI_PICOW + nullptr, // ESP32_BLUEPAD32_I2C + nullptr, // ESP32_BLUERETRO_I2C + four_ch_i2c::wireless_connected, // EXTERNAL_4CH_I2C + four_ch_i2c::wireless_connected, // INTERNAL_4CH_I2C + }; + + void initialize() { + if (init_func[OGXM_BOARD] != nullptr) { + init_func[OGXM_BOARD](); + } + } + + void run() { + if (run_func[OGXM_BOARD] != nullptr) { + run_func[OGXM_BOARD](); + } + } + + void host_mounted(bool mounted, HostDriverType host_type) { + if (host_mount_w_type_func[OGXM_BOARD] != nullptr) { + host_mount_w_type_func[OGXM_BOARD](mounted, host_type); + } else if (host_mount_func[OGXM_BOARD] != nullptr) { + host_mount_func[OGXM_BOARD](mounted); + } + } + + void host_mounted(bool mounted) { + if (host_mount_func[OGXM_BOARD] != nullptr) { + host_mount_func[OGXM_BOARD](mounted); + } + } + + void wireless_connected(bool connected, uint8_t idx) { + if (wl_conn_func[OGXM_BOARD] != nullptr) { + wl_conn_func[OGXM_BOARD](connected, idx); + } + } + +} // namespace OGXMini \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/OGXMini.h b/Firmware/RP2040/src/OGXMini/OGXMini.h index bb136fe..aa0798a 100644 --- a/Firmware/RP2040/src/OGXMini/OGXMini.h +++ b/Firmware/RP2040/src/OGXMini/OGXMini.h @@ -1,18 +1,13 @@ -#ifndef _OGX_MINI_H_ -#define _OGX_MINI_H_ +#pragma once #include -#include "UserSettings/UserSettings.h" +#include "USBHost/HostDriver/HostDriverTypes.h" -namespace OGXMini -{ - static constexpr int32_t FEEDBACK_DELAY_MS = 150; - static constexpr int32_t TUD_CHECK_DELAY_MS = 500; - - void run_program(); +namespace OGXMini { + void initialize(); + void run(); + void host_mounted(bool mounted, HostDriverType host_type); void host_mounted(bool mounted); - -} // namespace OGXMini - -#endif // _OGX_MINI_H_ \ No newline at end of file + void wireless_connected(bool connected, uint8_t idx); +} // namespace OGXMini \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/OGXMini_4Channel.cpp b/Firmware/RP2040/src/OGXMini/OGXMini_4Channel.cpp deleted file mode 100644 index 7ec3e7c..0000000 --- a/Firmware/RP2040/src/OGXMini/OGXMini_4Channel.cpp +++ /dev/null @@ -1,141 +0,0 @@ -#include "board_config.h" -#if OGXM_BOARD == INTERNAL_4CH || OGXM_BOARD == EXTERNAL_4CH - -#include - -#include "tusb.h" -#include "bsp/board_api.h" -#include "pio_usb.h" - -#include "USBDevice/DeviceManager.h" -#include "USBHost/HostManager.h" -#include "Board/board_api.h" -#include "Board/ogxm_log.h" -#include "OGXMini/OGXMini.h" -#include "I2CDriver/4Channel/I2CManager.h" -#include "Gamepad.h" -#include "TaskQueue/TaskQueue.h" - -namespace OGXMini { - -Gamepad gamepads_[MAX_GAMEPADS]; - -//Called by tusb host or i2c driver so we know to connect or disconnect usb -void host_mounted(bool host_mounted) -{ - static std::atomic tud_is_inited = false; - - board_api::set_led(host_mounted); - - if (!host_mounted && tud_is_inited.load()) - { - TaskQueue::Core0::queue_task([]() - { - OGXM_LOG("Disconnecting USB and rebooting.\n"); - board_api::usb::disconnect_all(); - board_api::reboot(); - }); - } - else if (!tud_is_inited.load() && host_mounted) - { - TaskQueue::Core0::queue_task([]() - { - OGXM_LOG("Initializing USB stack.\n"); - tud_init(BOARD_TUD_RHPORT); - tud_is_inited.store(true); - }); - } -} - -void core1_task() -{ - HostManager& host_manager = HostManager::get_instance(); - host_manager.initialize(gamepads_); - - //Pico-PIO-USB will not reliably detect a hot plug on some boards, so monitor and init host stack after connection - while(!board_api::usb::host_connected()) - { - sleep_ms(100); - } - - pio_usb_configuration_t pio_cfg = PIO_USB_CONFIG; - tuh_configure(BOARD_TUH_RHPORT, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg); - - tuh_init(BOARD_TUH_RHPORT); - - 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(); - } -} - -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(user_settings.get_current_driver()); - } - }); -} - -void run_program() -{ - UserSettings& user_settings = UserSettings::get_instance(); - 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& device_manager = DeviceManager::get_instance(); - device_manager.initialize_driver(user_settings.get_current_driver(), gamepads_); - - I2CManager& i2c_manager = I2CManager::get_instance(); - i2c_manager.initialize_driver(); - - multicore_reset_core1(); - multicore_launch_core1(core1_task); - - //Wait for something to call tud_init - while (!tud_inited()) - { - TaskQueue::Core0::process_tasks(); - sleep_ms(10); - } - - 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(); - I2CDriver* i2c_driver = i2c_manager.get_driver(); - - while (true) - { - TaskQueue::Core0::process_tasks(); - - i2c_driver->process(gamepads_); - device_driver->process(0, gamepads_[0]); - - tud_task(); - sleep_us(100); - } -} - -} // namespace OGXMini - -#endif // OGXM_BOARD == INTERNAL_4CH || OGXM_BOARD == EXTERNAL_4CH \ No newline at end of file diff --git a/Firmware/RP2040/src/OGXMini/OGXMini_ESP32.cpp b/Firmware/RP2040/src/OGXMini/OGXMini_ESP32.cpp deleted file mode 100644 index 47889a4..0000000 --- a/Firmware/RP2040/src/OGXMini/OGXMini_ESP32.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include "board_config.h" -#if (OGXM_BOARD == PICO_ESP32) - -#include - -#include "tusb.h" -#include "bsp/board_api.h" - -#include "USBDevice/DeviceManager.h" -#include "Board/board_api.h" -#include "OGXMini/OGXMini.h" -#include "I2CDriver/ESP32/I2CDriver.h" -#include "Gamepad/Gamepad.h" -#include "TaskQueue/TaskQueue.h" - -namespace OGXMini { - -static Gamepad gamepads_[MAX_GAMEPADS]; - -//Not using this for ESP32 currently -void host_mounted(bool host_mounted) { } - -void core1_task() -{ - I2CDriver::initialize(gamepads_); - - while (true) - { - tight_loop_contents(); - } -} - -void run_uart_bridge(UserSettings& user_settings) -{ - DeviceManager& device_manager = DeviceManager::get_instance(); - device_manager.initialize_driver(DeviceDriverType::UART_BRIDGE, gamepads_); - - board_api::esp32::enter_programming_mode(); - - OGXM_LOG("Entering UART Bridge mode\n"); - - device_manager.get_driver()->process(0, gamepads_[0]); //Runs UART Bridge task, doesn't return unless programming is complete - - OGXM_LOG("Exiting UART Bridge mode\n"); - - board_api::usb::disconnect_all(); - user_settings.write_datetime(); - board_api::reboot(); -} - -bool update_needed(UserSettings& user_settings) -{ -#if defined(OGXM_ESP32_RETAIL) - return !user_settings.verify_datetime(); -#endif - return false; -} - -void run_program() -{ - board_api::init_board(); - - UserSettings& user_settings = UserSettings::get_instance(); - user_settings.initialize_flash(); - - //MODE_SEL_PIN is used to determine if UART bridge should be run - if (board_api::esp32::uart_bridge_mode() || update_needed(user_settings)) - { - run_uart_bridge(user_settings); - return; - } - - DeviceManager& device_manager = DeviceManager::get_instance(); - device_manager.initialize_driver(user_settings.get_current_driver(), gamepads_); - - multicore_reset_core1(); - multicore_launch_core1(core1_task); - - // board_api::esp32::reset(); - - DeviceDriver* device_driver = device_manager.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]); - tud_task(); - } - - sleep_us(100); - } -} - -} // namespace OGXMini - -#endif // OGXM_BOARD == W_ESP32 \ No newline at end of file diff --git a/Firmware/RP2040/src/TaskQueue/TaskQueue.cpp b/Firmware/RP2040/src/TaskQueue/TaskQueue.cpp index ed2af89..2e8fbc1 100644 --- a/Firmware/RP2040/src/TaskQueue/TaskQueue.cpp +++ b/Firmware/RP2040/src/TaskQueue/TaskQueue.cpp @@ -3,7 +3,7 @@ TaskQueue::TaskQueue(CoreNum core_num) { alarm_num_ = (core_num == CoreNum::Core0) ? 0 : 1; - alarm_num_ += ((OGXM_BOARD == PI_PICOW) || (OGXM_BOARD == PI_PICO2W)) ? 1 : 0; //BTStack uses alarm 0 + alarm_num_ += (OGXM_BOARD == PI_PICOW) ? 1 : 0; //BTStack uses alarm 0 hw_set_bits(&timer_hw->inte, 1u << alarm_num_); diff --git a/Firmware/RP2040/src/TaskQueue/TaskQueue.h b/Firmware/RP2040/src/TaskQueue/TaskQueue.h index d094b09..7ee2e0c 100644 --- a/Firmware/RP2040/src/TaskQueue/TaskQueue.h +++ b/Firmware/RP2040/src/TaskQueue/TaskQueue.h @@ -9,7 +9,7 @@ #include #include -#include "board_config.h" +#include "Board/Config.h" class TaskQueue { @@ -46,7 +46,7 @@ public: } }; -#if (OGXM_BOARD != PI_PICOW) && (OGXM_BOARD != PI_PICO2W) //BTstack uses core1 +#if (OGXM_BOARD != PI_PICOW) //BTstack uses core1 struct Core1 { static inline uint32_t get_new_task_id() diff --git a/Firmware/RP2040/src/USBDevice/DeviceDriver/DInput/DInput.h b/Firmware/RP2040/src/USBDevice/DeviceDriver/DInput/DInput.h index 537351e..8d73577 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceDriver/DInput/DInput.h +++ b/Firmware/RP2040/src/USBDevice/DeviceDriver/DInput/DInput.h @@ -4,7 +4,7 @@ #include #include -#include "board_config.h" +#include "Board/Config.h" #include "USBDevice/DeviceDriver/DeviceDriver.h" #include "Descriptors/DInput.h" diff --git a/Firmware/RP2040/src/USBDevice/DeviceManager.cpp b/Firmware/RP2040/src/USBDevice/DeviceManager.cpp index 96ae298..ef66053 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceManager.cpp +++ b/Firmware/RP2040/src/USBDevice/DeviceManager.cpp @@ -1,6 +1,6 @@ #include "tusb.h" -#include "board_config.h" +#include "Board/Config.h" #include "USBDevice/DeviceDriver/PSClassic/PSClassic.h" #include "USBDevice/DeviceDriver/XInput/XInput.h" #include "USBDevice/DeviceDriver/Switch/Switch.h" @@ -16,11 +16,12 @@ #include "USBDevice/DeviceDriver/UARTBridge/UARTBridge.h" #endif // defined(CONFIG_EN_UART_BRIDGE) -void DeviceManager::initialize_driver(DeviceDriverType driver_type, Gamepad(&gamepads)[MAX_GAMEPADS]) -{ - bool has_analog = false; //TODO: Put gamepad setup in the drivers themselves - switch (driver_type) - { +void DeviceManager::initialize_driver( DeviceDriverType driver_type, + Gamepad(&gamepads)[MAX_GAMEPADS]) { + //TODO: Put gamepad setup in the drivers themselves + bool has_analog = false; + + switch (driver_type) { case DeviceDriverType::DINPUT: has_analog = true; device_driver_ = std::make_unique(); @@ -60,10 +61,8 @@ void DeviceManager::initialize_driver(DeviceDriverType driver_type, Gamepad(&gam return; } - if (has_analog) - { - for (size_t i = 0; i < MAX_GAMEPADS; ++i) - { + if (has_analog) { + for (size_t i = 0; i < MAX_GAMEPADS; ++i) { gamepads[i].set_analog_device(true); } } diff --git a/Firmware/RP2040/src/USBDevice/DeviceManager.h b/Firmware/RP2040/src/USBDevice/DeviceManager.h index 6a76853..8cb6b5a 100644 --- a/Firmware/RP2040/src/USBDevice/DeviceManager.h +++ b/Firmware/RP2040/src/USBDevice/DeviceManager.h @@ -7,14 +7,12 @@ #include "USBDevice/DeviceDriver/DeviceDriverTypes.h" #include "USBDevice/DeviceDriver/DeviceDriver.h" -class DeviceManager -{ +class DeviceManager { public: DeviceManager(DeviceManager const&) = delete; void operator=(DeviceManager const&) = delete; - static DeviceManager& get_instance() - { + static DeviceManager& get_instance() { static DeviceManager instance; return instance; } diff --git a/Firmware/RP2040/src/USBHost/HostManager.h b/Firmware/RP2040/src/USBHost/HostManager.h index d15ab57..e8638fb 100644 --- a/Firmware/RP2040/src/USBHost/HostManager.h +++ b/Firmware/RP2040/src/USBHost/HostManager.h @@ -8,7 +8,7 @@ #include #include -#include "board_config.h" +#include "Board/Config.h" #include "USBHost/HardwareIDs.h" #include "USBHost/HostDriver/XInput/tuh_xinput/tuh_xinput.h" #include "USBHost/HostDriver/HostDriver.h" diff --git a/Firmware/RP2040/src/USBHost/tuh_callbacks.cpp b/Firmware/RP2040/src/USBHost/tuh_callbacks.cpp index f0af110..379e795 100644 --- a/Firmware/RP2040/src/USBHost/tuh_callbacks.cpp +++ b/Firmware/RP2040/src/USBHost/tuh_callbacks.cpp @@ -1,6 +1,4 @@ #include -#include -#include #include "tusb.h" #include "host/usbh.h" @@ -10,108 +8,71 @@ #include "USBHost/HostManager.h" #include "OGXMini/OGXMini.h" -#if defined(CONFIG_EN_4CH) -#include "I2CDriver/4Channel/I2CManager.h" -#endif - -usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count) -{ +usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count) { *driver_count = 1; return tuh_xinput::class_driver(); } //HID -void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) -{ +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { uint16_t vid, pid; tuh_vid_pid_get(dev_addr, &vid, &pid); HostManager& host_manager = HostManager::get_instance(); - if (host_manager.setup_driver(HostManager::get_type({ vid, pid }), dev_addr, instance, desc_report, desc_len)) - { -#if defined(CONFIG_EN_4CH) - I2CManager::get_instance().get_driver()->notify_tuh(true); -#endif - + if (host_manager.setup_driver(HostManager::get_type({ vid, pid }), dev_addr, instance, desc_report, desc_len)) { OGXMini::host_mounted(true); } } -void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) -{ +void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) { HostManager& host_manager = HostManager::get_instance(); host_manager.deinit_driver(HostManager::DriverClass::HID, dev_addr, instance); - if (!host_manager.any_mounted()) - { -#if defined(CONFIG_EN_4CH) - I2CManager::get_instance().get_driver()->notify_tuh(false); -#endif - + if (!host_manager.any_mounted()) { OGXMini::host_mounted(false); } } -void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) -{ +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) { HostManager::get_instance().process_report(dev_addr, instance, report, len); } //XINPUT -void tuh_xinput::mount_cb(uint8_t dev_addr, uint8_t instance, const tuh_xinput::Interface* interface) -{ +void tuh_xinput::mount_cb(uint8_t dev_addr, uint8_t instance, const tuh_xinput::Interface* interface) { HostManager& host_manager = HostManager::get_instance(); HostDriverType host_type = HostManager::get_type(interface->dev_type); - if (host_manager.setup_driver(host_type, dev_addr, instance)) - { -#if defined(CONFIG_EN_4CH) - I2CManager::get_instance().get_driver()->notify_tuh(true, host_type); -#endif - - OGXMini::host_mounted(true); + if (host_manager.setup_driver(host_type, dev_addr, instance)) { + OGXMini::host_mounted(true, host_type); } } -void tuh_xinput::unmount_cb(uint8_t dev_addr, uint8_t instance, const tuh_xinput::Interface* interface) -{ +void tuh_xinput::unmount_cb(uint8_t dev_addr, uint8_t instance, const tuh_xinput::Interface* interface) { HostManager& host_manager = HostManager::get_instance(); host_manager.deinit_driver(HostManager::DriverClass::XINPUT, dev_addr, instance); - if (!host_manager.any_mounted()) - { -#if defined(CONFIG_EN_4CH) - I2CManager::get_instance().get_driver()->notify_tuh(false, host_manager.get_type(interface->dev_type)); -#endif - + if (!host_manager.any_mounted()) { OGXMini::host_mounted(false); } } -void tuh_xinput::report_received_cb(uint8_t dev_addr, uint8_t instance, const uint8_t* report, uint16_t len) -{ +void tuh_xinput::report_received_cb(uint8_t dev_addr, uint8_t instance, const uint8_t* report, uint16_t len) { HostManager::get_instance().process_report(dev_addr, instance, report, len); } -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(true, idx); -#endif - +void tuh_xinput::xbox360w_connect_cb(uint8_t dev_addr, uint8_t instance) { + uint8_t idx = HostManager::get_instance().get_gamepad_idx( HostManager::DriverClass::XINPUT, + dev_addr, instance); + OGXMini::wireless_connected(true, idx); HostManager::get_instance().connect_cb(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(false, idx); -#endif - +void tuh_xinput::xbox360w_disconnect_cb(uint8_t dev_addr, uint8_t instance) { + uint8_t idx = HostManager::get_instance().get_gamepad_idx( HostManager::DriverClass::XINPUT, + dev_addr, instance); + OGXMini::wireless_connected(false, idx); HostManager::get_instance().disconnect_cb(dev_addr, instance); } \ No newline at end of file diff --git a/Firmware/RP2040/src/UserSettings/NVSTool.h b/Firmware/RP2040/src/UserSettings/NVSTool.h index 1cce5a2..0b88574 100644 --- a/Firmware/RP2040/src/UserSettings/NVSTool.h +++ b/Firmware/RP2040/src/UserSettings/NVSTool.h @@ -13,8 +13,8 @@ class NVSTool { public: - static constexpr size_t KEY_LEN_MAX = 16; //Including null terminator - static constexpr size_t VALUE_LEN_MAX = FLASH_PAGE_SIZE - KEY_LEN_MAX; + static constexpr size_t KEY_LEN_MAX = 16; //Including null terminator + static constexpr size_t VALUE_LEN_MAX = FLASH_PAGE_SIZE - KEY_LEN_MAX; static constexpr uint32_t MAX_ENTRIES = ((NVS_SECTORS * FLASH_SECTOR_SIZE) / FLASH_PAGE_SIZE) - 1; static NVSTool& get_instance() diff --git a/Firmware/RP2040/src/UserSettings/UserSettings.cpp b/Firmware/RP2040/src/UserSettings/UserSettings.cpp index b199eeb..b0cd180 100644 --- a/Firmware/RP2040/src/UserSettings/UserSettings.cpp +++ b/Firmware/RP2040/src/UserSettings/UserSettings.cpp @@ -9,13 +9,11 @@ #include "Board/board_api.h" #include "UserSettings/UserSettings.h" -static constexpr uint32_t BUTTON_COMBO(const uint16_t& buttons, const uint8_t& dpad = 0) -{ +static constexpr uint32_t BUTTON_COMBO(const uint16_t& buttons, const uint8_t& dpad = 0) { return (static_cast(buttons) << 16) | static_cast(dpad); } -namespace ButtonCombo -{ +namespace ButtonCombo { static constexpr uint32_t PS3 = BUTTON_COMBO(Gamepad::BUTTON_START, Gamepad::DPAD_LEFT); static constexpr uint32_t DINPUT = BUTTON_COMBO(Gamepad::BUTTON_START | Gamepad::BUTTON_RB, Gamepad::DPAD_LEFT); static constexpr uint32_t XINPUT = BUTTON_COMBO(Gamepad::BUTTON_START, Gamepad::DPAD_UP); @@ -27,8 +25,7 @@ namespace ButtonCombo static constexpr uint32_t WEBAPP = BUTTON_COMBO(Gamepad::BUTTON_START | Gamepad::BUTTON_LB | Gamepad::BUTTON_RB); }; -static constexpr DeviceDriverType VALID_DRIVER_TYPES[] = -{ +static constexpr DeviceDriverType VALID_DRIVER_TYPES[] = { #if defined(CONFIG_EN_4CH) DeviceDriverType::XBOXOG, DeviceDriverType::XBOXOG_SB, @@ -61,9 +58,12 @@ static constexpr DeviceDriverType VALID_DRIVER_TYPES[] = #endif }; -struct ComboMap { uint32_t combo; DeviceDriverType driver; }; -static constexpr std::array BUTTON_COMBO_MAP = -{{ +struct ComboMap { + uint32_t combo; + DeviceDriverType driver; +}; + +static constexpr std::array BUTTON_COMBO_MAP = {{ { ButtonCombo::XBOXOG, DeviceDriverType::XBOXOG }, { ButtonCombo::XBOXOG_SB, DeviceDriverType::XBOXOG_SB }, { ButtonCombo::XBOXOG_XR, DeviceDriverType::XBOXOG_XR }, diff --git a/Firmware/RP2040/src/UserSettings/UserSettings.h b/Firmware/RP2040/src/UserSettings/UserSettings.h index f65c4f3..ae40694 100644 --- a/Firmware/RP2040/src/UserSettings/UserSettings.h +++ b/Firmware/RP2040/src/UserSettings/UserSettings.h @@ -4,7 +4,7 @@ #include #include -#include "board_config.h" +#include "Board/Config.h" #include "USBDevice/DeviceDriver/DeviceDriverTypes.h" #include "UserSettings/UserProfile.h" #include "UserSettings/NVSTool.h" diff --git a/Firmware/RP2040/src/board_config.h b/Firmware/RP2040/src/board_config.h deleted file mode 100644 index bb48951..0000000 --- a/Firmware/RP2040/src/board_config.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef _OGXM_BOARD_CONFIG_H_ -#define _OGXM_BOARD_CONFIG_H_ - -/* 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 PI_PICO 1 -#define PI_PICO2 2 -#define PI_PICOW 3 -#define PI_PICO2W 4 -#define RP_ZERO 5 -#define ADA_FEATHER 6 -#define INTERNAL_4CH 7 -#define EXTERNAL_4CH 8 -#define PICO_ESP32 9 - -#define SYSCLOCK_KHZ 240000 - -#ifdef PICO_BOARD - #define O_BOARD PICO_BOARD -#endif - -#ifndef MAX_GAMEPADS - #define MAX_GAMEPADS 1 -#endif - -#ifndef OGXM_BOARD - #define OGXM_BOARD PI_PICO -#endif - -#if OGXM_BOARD == PI_PICO || OGXM_BOARD == PI_PICO2 - #define PIO_USB_DP_PIN 0 // DM = 1 - #define LED_INDICATOR_PIN 25 - -#elif OGXM_BOARD == PI_PICOW - -#elif OGXM_BOARD == PI_PICO2W - // #define LED_INDICATOR_PIN 0 - -#elif OGXM_BOARD == RP_ZERO - #define RGB_PXL_PIN 16 - - #define PIO_USB_DP_PIN 10 // DM = 11 - #define LED_INDICATOR_PIN 14 - -#elif OGXM_BOARD == ADA_FEATHER - #define RGB_PWR_PIN 20 - #define RGB_PXL_PIN 21 - - #define PIO_USB_DP_PIN 16 // DM = 17 - #define LED_INDICATOR_PIN 13 - #define VCC_EN_PIN 18 - -#elif OGXM_BOARD == INTERNAL_4CH - #define PIO_USB_DP_PIN 16 // DM = 17 - #define FOUR_CH_ENABLED 1 - #define I2C_SDA_PIN 10 // SCL = 11 - #define SLAVE_ADDR_PIN_1 20 - #define SLAVE_ADDR_PIN_2 21 - -#elif OGXM_BOARD == EXTERNAL_4CH - #define RGB_PXL_PIN 16 - #define FOUR_CH_ENABLED 1 - #define PIO_USB_DP_PIN 10 // DM = 11 - - #define I2C_SDA_PIN 6 // SCL = 7 - #define SLAVE_ADDR_PIN_1 13 - #define SLAVE_ADDR_PIN_2 14 - -#elif OGXM_BOARD == PICO_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 - - #if MAX_GAMEPADS > 1 - #undef MAX_GAMEPADS - #define MAX_GAMEPADS 1 - #endif - -#endif // OGXM_BOARD - -#if defined(I2C_SDA_PIN) - #define I2C_BAUDRATE 1000 * 1000 - #define I2C_SCL_PIN (I2C_SDA_PIN + 1) - #define I2C_PORT ((I2C_SDA_PIN == 2 ) || \ - (I2C_SDA_PIN == 6 ) || \ - (I2C_SDA_PIN == 10) || \ - (I2C_SDA_PIN == 14) || \ - (I2C_SDA_PIN == 18) || \ - (I2C_SDA_PIN == 26)) ? i2c1 : i2c0 -#endif // defined(I2C_SDA_PIN) - -#if defined(CONFIG_EN_4CH) - #if MAX_GAMEPADS < 4 - #undef MAX_GAMEPADS - #define MAX_GAMEPADS 4 - #endif -#endif // FOUR_CH_ENABLED - -#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 \ - } -#endif // PIO_USB_DP_PIN - -#if defined(OGXM_DEBUG) - //Pins and port are defined in CMakeLists.txt - #define DEBUG_UART_PORT __CONCAT(uart,PICO_DEFAULT_UART) -#endif // defined(OGXM_DEBUG) - -#endif // _OGXM_BOARD_CONFIG_H_ \ No newline at end of file diff --git a/Firmware/RP2040/src/main.cpp b/Firmware/RP2040/src/main.cpp index 4a87066..afdb49d 100644 --- a/Firmware/RP2040/src/main.cpp +++ b/Firmware/RP2040/src/main.cpp @@ -1,10 +1,9 @@ #include -#include #include "OGXMini/OGXMini.h" -#include "board_config.h" -int main() -{ - OGXMini::run_program(); +int main() { + OGXMini::initialize(); + OGXMini::run(); + return 0; } \ No newline at end of file diff --git a/Firmware/RP2040/src/sdkconfig.h b/Firmware/RP2040/src/sdkconfig.h index 5d0506f..cb3ffce 100644 --- a/Firmware/RP2040/src/sdkconfig.h +++ b/Firmware/RP2040/src/sdkconfig.h @@ -1,7 +1,7 @@ #ifndef _SDK_CONFIG_H_ #define _SDK_CONFIG_H_ -#include "board_config.h" +#include "Board/Config.h" // // Emulate "menuconfig" diff --git a/Firmware/RP2040/src/tusb_config.h b/Firmware/RP2040/src/tusb_config.h index 4ad3b37..2021a81 100644 --- a/Firmware/RP2040/src/tusb_config.h +++ b/Firmware/RP2040/src/tusb_config.h @@ -26,7 +26,7 @@ #ifndef _TUSB_CONFIG_H_ #define _TUSB_CONFIG_H_ -#include "board_config.h" +#include "Board/Config.h" #ifdef __cplusplus extern "C" { @@ -127,7 +127,10 @@ // Enable host stack with pio-usb if Pico-PIO-USB library is available #define CFG_TUH_ENABLED 1 + +#if defined(PIO_USB_CONFIG) #define CFG_TUH_RPI_PIO_USB 1 +#endif #define TUH_OPT_RHPORT 1