v1.0.0-alpha
This commit is contained in:
@@ -27,8 +27,8 @@ static constexpr uint32_t LED_TIME_MS = 500;
|
|||||||
struct Device
|
struct Device
|
||||||
{
|
{
|
||||||
std::atomic<bool> connected{false};
|
std::atomic<bool> connected{false};
|
||||||
std::atomic<ReportIn> report_in;
|
std::atomic<ReportIn> report_in{ReportIn()};
|
||||||
std::atomic<ReportOut> report_out;
|
std::atomic<ReportOut> report_out{ReportOut()};
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<Device, CONFIG_BLUEPAD32_MAX_DEVICES> devices_;
|
std::array<Device, CONFIG_BLUEPAD32_MAX_DEVICES> devices_;
|
||||||
@@ -46,9 +46,13 @@ static inline void send_feedback_cb(btstack_timer_source *ts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReportOut report_out = devices_[i].report_out.load();
|
ReportOut report_out = devices_[i].report_out.load();
|
||||||
|
if (!report_out.rumble_l && !report_out.rumble_r)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
bp_device->report_parser.play_dual_rumble(bp_device, 0, FEEDBACK_TIME_MS, report_out.rumble_l, report_out.rumble_r);
|
bp_device->report_parser.play_dual_rumble(bp_device, 0, FEEDBACK_TIME_MS, report_out.rumble_l, report_out.rumble_r);
|
||||||
}
|
}
|
||||||
// btstack_run_loop_remove_timer(ts);
|
|
||||||
btstack_run_loop_set_timer(ts, FEEDBACK_TIME_MS);
|
btstack_run_loop_set_timer(ts, FEEDBACK_TIME_MS);
|
||||||
btstack_run_loop_add_timer(ts);
|
btstack_run_loop_add_timer(ts);
|
||||||
}
|
}
|
||||||
@@ -69,7 +73,7 @@ static inline void check_led_cb(btstack_timer_source *ts)
|
|||||||
board_api::set_led(i, devices_[i].connected.load() ? 1 : (led_state ? 1 : 0));
|
board_api::set_led(i, devices_[i].connected.load() ? 1 : (led_state ? 1 : 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// btstack_run_loop_remove_timer(ts);
|
|
||||||
btstack_run_loop_set_timer(ts, LED_TIME_MS);
|
btstack_run_loop_set_timer(ts, LED_TIME_MS);
|
||||||
btstack_run_loop_add_timer(ts);
|
btstack_run_loop_add_timer(ts);
|
||||||
}
|
}
|
||||||
@@ -85,15 +89,15 @@ static void init_complete_cb(void)
|
|||||||
{
|
{
|
||||||
uni_bt_enable_new_connections_unsafe(true);
|
uni_bt_enable_new_connections_unsafe(true);
|
||||||
|
|
||||||
// Based on runtime condition, you can delete or list the stored BT keys.
|
// // Based on runtime condition, you can delete or list the stored BT keys.
|
||||||
if (1)
|
// if (1)
|
||||||
{
|
// {
|
||||||
uni_bt_del_keys_unsafe();
|
// uni_bt_del_keys_unsafe();
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
uni_bt_list_keys_unsafe();
|
// uni_bt_list_keys_unsafe();
|
||||||
}
|
// }
|
||||||
|
|
||||||
uni_property_dump_all();
|
uni_property_dump_all();
|
||||||
}
|
}
|
||||||
@@ -132,8 +136,8 @@ static void device_disconnected_cb(uni_hid_device_t* device)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReportIn report_in;
|
ReportIn report_in = ReportIn();
|
||||||
report_in.index = static_cast<uint8_t>(idx);
|
report_in.index = static_cast<uint8_t>(idx);
|
||||||
devices_[idx].report_in.store(report_in);
|
devices_[idx].report_in.store(report_in);
|
||||||
devices_[idx].connected.store(false);
|
devices_[idx].connected.store(false);
|
||||||
@@ -252,10 +256,6 @@ uni_platform* get_driver()
|
|||||||
|
|
||||||
ReportIn get_report_in(uint8_t index)
|
ReportIn get_report_in(uint8_t index)
|
||||||
{
|
{
|
||||||
// if (index >= CONFIG_BLUEPAD32_MAX_DEVICES)
|
|
||||||
// {
|
|
||||||
// return ReportIn();
|
|
||||||
// }
|
|
||||||
return devices_[index].report_in.load();
|
return devices_[index].report_in.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,6 +270,14 @@ void set_report_out(const ReportOut& report_out)
|
|||||||
|
|
||||||
void run_task()
|
void run_task()
|
||||||
{
|
{
|
||||||
|
for (uint8_t i = 0; i < CONFIG_BLUEPAD32_MAX_DEVICES; ++i)
|
||||||
|
{
|
||||||
|
ReportIn report_in;
|
||||||
|
report_in.index = i;
|
||||||
|
devices_[i].report_in.store(report_in);
|
||||||
|
devices_[i].report_out.store(ReportOut());
|
||||||
|
}
|
||||||
|
|
||||||
board_api::init_pins();
|
board_api::init_pins();
|
||||||
|
|
||||||
btstack_init();
|
btstack_init();
|
||||||
@@ -312,333 +320,4 @@ bool connected(uint8_t index)
|
|||||||
return devices_[index].connected.load();
|
return devices_[index].connected.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace bluepad32
|
} // namespace bluepad32
|
||||||
|
|
||||||
// #include <cstdint>
|
|
||||||
// #include <atomic>
|
|
||||||
// #include <cstring>
|
|
||||||
// #include <array>
|
|
||||||
// #include <freertos/FreeRTOS.h>
|
|
||||||
// #include <freertos/task.h>
|
|
||||||
// #include <freertos/timers.h>
|
|
||||||
// #include <freertos/queue.h>
|
|
||||||
// #include <esp_log.h>
|
|
||||||
|
|
||||||
// #include "btstack_port_esp32.h"
|
|
||||||
// #include "btstack_run_loop.h"
|
|
||||||
// #include "btstack_stdio_esp32.h"
|
|
||||||
// #include "uni.h"
|
|
||||||
|
|
||||||
// #include "sdkconfig.h"
|
|
||||||
// #include "Board/board_api.h"
|
|
||||||
// #include "I2CDriver/I2CDriver.h"
|
|
||||||
// #include "Bluepad32/Gamepad.h"
|
|
||||||
// #include "Bluepad32/Bluepad32.h"
|
|
||||||
|
|
||||||
// namespace bluepad32 {
|
|
||||||
|
|
||||||
// static constexpr uint32_t FEEDBACK_TIME_MS = 200;
|
|
||||||
// static constexpr uint32_t LED_TIME_MS = 500;
|
|
||||||
|
|
||||||
// struct Device
|
|
||||||
// {
|
|
||||||
// std::atomic<bool> connected{false};
|
|
||||||
// std::atomic<ReportIn> report_in;
|
|
||||||
// std::atomic<bool> new_report_in{false};
|
|
||||||
// std::atomic<ReportOut> report_out;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// std::array<Device, CONFIG_BLUEPAD32_MAX_DEVICES> devices_;
|
|
||||||
|
|
||||||
// static inline void send_feedback_cb(btstack_timer_source *ts)
|
|
||||||
// {
|
|
||||||
// uni_hid_device_t* bp_device;
|
|
||||||
|
|
||||||
// for (uint8_t i = 0; i < CONFIG_BLUEPAD32_MAX_DEVICES; ++i)
|
|
||||||
// {
|
|
||||||
// bp_device = uni_hid_device_get_instance_for_idx(i);
|
|
||||||
// if (!bp_device || !bp_device->report_parser.play_dual_rumble)
|
|
||||||
// {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ReportOut report_out = devices_[i].report_out.load();
|
|
||||||
// bp_device->report_parser.play_dual_rumble(bp_device, 0, FEEDBACK_TIME_MS, report_out.rumble_l, report_out.rumble_r);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// btstack_run_loop_remove_timer(ts);
|
|
||||||
// btstack_run_loop_set_timer(ts, FEEDBACK_TIME_MS);
|
|
||||||
// btstack_run_loop_add_timer(ts);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static inline void check_led_cb(btstack_timer_source *ts)
|
|
||||||
// {
|
|
||||||
// static bool led_state = false;
|
|
||||||
// led_state = !led_state;
|
|
||||||
|
|
||||||
// if constexpr (board_api::NUM_LEDS == 1)
|
|
||||||
// {
|
|
||||||
// board_api::set_led(any_connected() ? 1 : (led_state ? 1 : 0));
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// for (uint8_t i = 0; i < board_api::NUM_LEDS; ++i)
|
|
||||||
// {
|
|
||||||
// board_api::set_led(i, devices_[i].connected.load() ? 1 : (led_state ? 1 : 0));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// btstack_run_loop_remove_timer(ts);
|
|
||||||
// btstack_run_loop_set_timer(ts, LED_TIME_MS);
|
|
||||||
// btstack_run_loop_add_timer(ts);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //BT Driver
|
|
||||||
|
|
||||||
// static void init(int argc, const char** arg_V)
|
|
||||||
// {
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void init_complete_cb(void)
|
|
||||||
// {
|
|
||||||
// uni_bt_enable_new_connections_unsafe(true);
|
|
||||||
|
|
||||||
// // Based on runtime condition, you can delete or list the stored BT keys.
|
|
||||||
// if (1)
|
|
||||||
// {
|
|
||||||
// uni_bt_del_keys_unsafe();
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// uni_bt_list_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))
|
|
||||||
// {
|
|
||||||
// return UNI_ERROR_IGNORE_DEVICE;
|
|
||||||
// }
|
|
||||||
// return UNI_ERROR_SUCCESS;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void device_connected_cb(uni_hid_device_t* device)
|
|
||||||
// {
|
|
||||||
// #ifdef CONFIG_BLUEPAD32_USB_CONSOLE_ENABLE
|
|
||||||
// logd("BP32", "Device connected, addr: %p, index: %i\n", device, uni_hid_device_get_idx_for_instance(device));
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// int idx = uni_hid_device_get_idx_for_instance(device);
|
|
||||||
// if (idx >= CONFIG_BLUEPAD32_MAX_DEVICES || idx < 0)
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// devices_[idx].connected.store(true);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void device_disconnected_cb(uni_hid_device_t* device)
|
|
||||||
// {
|
|
||||||
// #ifdef CONFIG_BLUEPAD32_USB_CONSOLE_ENABLE
|
|
||||||
// logd("BP32", "Device disconnected, addr: %p, index: %i\n", device, uni_hid_device_get_idx_for_instance(device));
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// int idx = uni_hid_device_get_idx_for_instance(device);
|
|
||||||
// if (idx >= CONFIG_BLUEPAD32_MAX_DEVICES || idx < 0)
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ReportIn report_in = ReportIn();
|
|
||||||
// report_in.index = static_cast<uint8_t>(idx);
|
|
||||||
// devices_[idx].report_in.store(report_in);
|
|
||||||
// devices_[idx].connected.store(false);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void controller_data_cb(uni_hid_device_t* device, uni_controller_t* controller)
|
|
||||||
// {
|
|
||||||
// static uni_gamepad_t prev_uni_gp[CONFIG_BLUEPAD32_MAX_DEVICES] = {};
|
|
||||||
|
|
||||||
// if (!device || !controller || controller->klass != UNI_CONTROLLER_CLASS_GAMEPAD)
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// uni_gamepad_t *uni_gp = &controller->gamepad;
|
|
||||||
// int idx = uni_hid_device_get_idx_for_instance(device);
|
|
||||||
|
|
||||||
// if (idx >= CONFIG_BLUEPAD32_MAX_DEVICES || idx < 0 || std::memcmp(uni_gp, &prev_uni_gp[idx], sizeof(uni_gamepad_t)) == 0)
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #ifdef CONFIG_BLUEPAD32_USB_CONSOLE_ENABLE
|
|
||||||
// logi("BP32 Stack", "Remaining stack: %d\n", uxTaskGetStackHighWaterMark(NULL));
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// ReportIn report_in;
|
|
||||||
// report_in.index = static_cast<uint8_t>(idx);
|
|
||||||
|
|
||||||
// switch (uni_gp->dpad)
|
|
||||||
// {
|
|
||||||
// case DPAD_UP:
|
|
||||||
// report_in.dpad = Gamepad::DPad::UP;
|
|
||||||
// break;
|
|
||||||
// case DPAD_DOWN:
|
|
||||||
// report_in.dpad = Gamepad::DPad::DOWN;
|
|
||||||
// break;
|
|
||||||
// case DPAD_LEFT:
|
|
||||||
// report_in.dpad = Gamepad::DPad::LEFT;
|
|
||||||
// break;
|
|
||||||
// case DPAD_RIGHT:
|
|
||||||
// report_in.dpad = Gamepad::DPad::RIGHT;
|
|
||||||
// break;
|
|
||||||
// case DPAD_UP | DPAD_RIGHT:
|
|
||||||
// report_in.dpad = Gamepad::DPad::UP_RIGHT;
|
|
||||||
// break;
|
|
||||||
// case DPAD_DOWN | DPAD_RIGHT:
|
|
||||||
// report_in.dpad = Gamepad::DPad::DOWN_RIGHT;
|
|
||||||
// break;
|
|
||||||
// case DPAD_DOWN | DPAD_LEFT:
|
|
||||||
// report_in.dpad = Gamepad::DPad::DOWN_LEFT;
|
|
||||||
// break;
|
|
||||||
// case DPAD_UP | DPAD_LEFT:
|
|
||||||
// report_in.dpad = Gamepad::DPad::UP_LEFT;
|
|
||||||
// break;
|
|
||||||
// default:
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (uni_gp->buttons & BUTTON_A) report_in.buttons |= Gamepad::Button::A;
|
|
||||||
// if (uni_gp->buttons & BUTTON_B) report_in.buttons |= Gamepad::Button::B;
|
|
||||||
// if (uni_gp->buttons & BUTTON_X) report_in.buttons |= Gamepad::Button::X;
|
|
||||||
// if (uni_gp->buttons & BUTTON_Y) report_in.buttons |= Gamepad::Button::Y;
|
|
||||||
// if (uni_gp->buttons & BUTTON_SHOULDER_L) report_in.buttons |= Gamepad::Button::LB;
|
|
||||||
// if (uni_gp->buttons & BUTTON_SHOULDER_R) report_in.buttons |= Gamepad::Button::RB;
|
|
||||||
// if (uni_gp->buttons & BUTTON_THUMB_L) report_in.buttons |= Gamepad::Button::L3;
|
|
||||||
// if (uni_gp->buttons & BUTTON_THUMB_R) report_in.buttons |= Gamepad::Button::R3;
|
|
||||||
// if (uni_gp->misc_buttons & MISC_BUTTON_BACK) report_in.buttons |= Gamepad::Button::BACK;
|
|
||||||
// if (uni_gp->misc_buttons & MISC_BUTTON_START) report_in.buttons |= Gamepad::Button::START;
|
|
||||||
// if (uni_gp->misc_buttons & MISC_BUTTON_SYSTEM) report_in.buttons |= Gamepad::Button::SYS;
|
|
||||||
// if (uni_gp->misc_buttons & MISC_BUTTON_CAPTURE) report_in.buttons |= Gamepad::Button::MISC;
|
|
||||||
|
|
||||||
// report_in.trigger_l = Gamepad::scale_trigger(uni_gp->brake);
|
|
||||||
// report_in.trigger_r = Gamepad::scale_trigger(uni_gp->throttle);
|
|
||||||
|
|
||||||
// report_in.joystick_lx = static_cast<int16_t>(uni_gp->axis_x);
|
|
||||||
// report_in.joystick_ly = static_cast<int16_t>(uni_gp->axis_y);
|
|
||||||
// report_in.joystick_rx = static_cast<int16_t>(uni_gp->axis_rx);
|
|
||||||
// report_in.joystick_ry = static_cast<int16_t>(uni_gp->axis_ry);
|
|
||||||
|
|
||||||
// devices_[idx].report_in.store(report_in);
|
|
||||||
// devices_[idx].new_report_in.store(true);
|
|
||||||
|
|
||||||
// std::memcpy(uni_gp, &prev_uni_gp[idx], sizeof(uni_gamepad_t));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const uni_property_t* get_property_cb(uni_property_idx_t idx)
|
|
||||||
// {
|
|
||||||
// return nullptr;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// uni_platform* get_driver()
|
|
||||||
// {
|
|
||||||
// static uni_platform driver =
|
|
||||||
// {
|
|
||||||
// .name = "OGXMiniW",
|
|
||||||
// .init = init,
|
|
||||||
// .on_init_complete = init_complete_cb,
|
|
||||||
// .on_device_discovered = device_discovered_cb,
|
|
||||||
// .on_device_connected = device_connected_cb,
|
|
||||||
// .on_device_disconnected = device_disconnected_cb,
|
|
||||||
// .on_device_ready = device_ready_cb,
|
|
||||||
// .on_controller_data = controller_data_cb,
|
|
||||||
// .get_property = get_property_cb,
|
|
||||||
// .on_oob_event = oob_event_cb,
|
|
||||||
// };
|
|
||||||
// return &driver;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //Public
|
|
||||||
|
|
||||||
// void run_task()
|
|
||||||
// {
|
|
||||||
// board_api::init_pins();
|
|
||||||
|
|
||||||
// btstack_init();
|
|
||||||
|
|
||||||
// uni_platform_set_custom(get_driver());
|
|
||||||
// uni_init(0, nullptr);
|
|
||||||
|
|
||||||
// btstack_timer_source_t feedback_timer;
|
|
||||||
// feedback_timer.process = send_feedback_cb;
|
|
||||||
// feedback_timer.context = nullptr;
|
|
||||||
|
|
||||||
// btstack_run_loop_set_timer(&feedback_timer, FEEDBACK_TIME_MS);
|
|
||||||
// btstack_run_loop_add_timer(&feedback_timer);
|
|
||||||
|
|
||||||
// btstack_timer_source_t led_timer;
|
|
||||||
// led_timer.process = check_led_cb;
|
|
||||||
// led_timer.context = nullptr;
|
|
||||||
|
|
||||||
// btstack_run_loop_set_timer(&led_timer, LED_TIME_MS);
|
|
||||||
// btstack_run_loop_add_timer(&led_timer);
|
|
||||||
|
|
||||||
// btstack_run_loop_execute();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //Thread safe
|
|
||||||
// bool any_connected()
|
|
||||||
// {
|
|
||||||
// for (auto& device : devices_)
|
|
||||||
// {
|
|
||||||
// if (device.connected.load())
|
|
||||||
// {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// bool connected(uint8_t index)
|
|
||||||
// {
|
|
||||||
// return devices_[index].connected.load();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// bool get_report_in(uint8_t index, ReportIn& report)
|
|
||||||
// {
|
|
||||||
// if (index >= CONFIG_BLUEPAD32_MAX_DEVICES)
|
|
||||||
// {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// if (devices_[index].new_report_in.exchange(false))
|
|
||||||
// {
|
|
||||||
// report = devices_[index].report_in.load();
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void set_report_out(const ReportOut& report)
|
|
||||||
// {
|
|
||||||
// if (report.index >= CONFIG_BLUEPAD32_MAX_DEVICES)
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// devices_[report.index].report_out.store(report);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// } // namespace bluepad32
|
|
||||||
@@ -1,149 +1,3 @@
|
|||||||
// #include <cstring>
|
|
||||||
// #include <atomic>
|
|
||||||
// #include <array>
|
|
||||||
// #include <freertos/FreeRTOS.h>
|
|
||||||
// #include <freertos/task.h>
|
|
||||||
// #include <freertos/timers.h>
|
|
||||||
// #include <driver/i2c.h>
|
|
||||||
// #include <driver/gpio.h>
|
|
||||||
// #include <esp_log.h>
|
|
||||||
|
|
||||||
// #include "sdkconfig.h"
|
|
||||||
// #include "Board/board_api.h"
|
|
||||||
// #include "I2CDriver/I2CDriver.h"
|
|
||||||
// #include "Bluepad32/Bluepad32.h"
|
|
||||||
|
|
||||||
// namespace i2c_driver {
|
|
||||||
|
|
||||||
// static constexpr bool MULTI_SLAVE =
|
|
||||||
// #if CONFIG_MULTI_SLAVE_MODE == 0
|
|
||||||
// false;
|
|
||||||
// #else
|
|
||||||
// true;
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// std::atomic<bool> poll_rumble_{false};
|
|
||||||
|
|
||||||
// void i2c_initialize()
|
|
||||||
// {
|
|
||||||
// i2c_config_t conf;
|
|
||||||
// std::memset(&conf, 0, sizeof(i2c_config_t));
|
|
||||||
// conf.mode = I2C_MODE_MASTER;
|
|
||||||
// conf.sda_io_num = GPIO_NUM_21;
|
|
||||||
// conf.scl_io_num = GPIO_NUM_22;
|
|
||||||
// conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
|
||||||
// conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
|
||||||
// conf.master.clk_speed = 400 * 1000;
|
|
||||||
|
|
||||||
// i2c_param_config(I2C_NUM_0, &conf);
|
|
||||||
// i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0);
|
|
||||||
|
|
||||||
// ESP_LOGD("I2C", "I2C initialized at pins {SDA: %d, SCL: %d}", conf.sda_io_num, conf.scl_io_num);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static inline esp_err_t i2c_write_blocking(uint8_t slave_address, uint8_t* data, size_t data_len)
|
|
||||||
// {
|
|
||||||
// i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
||||||
// i2c_master_start(cmd);
|
|
||||||
// i2c_master_write_byte(cmd, (slave_address << 1) | I2C_MASTER_WRITE, true);
|
|
||||||
// i2c_master_write(cmd, data, data_len, true);
|
|
||||||
// i2c_master_stop(cmd);
|
|
||||||
|
|
||||||
// esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, pdMS_TO_TICKS(2));
|
|
||||||
// i2c_cmd_link_delete(cmd);
|
|
||||||
// return ret;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static inline esp_err_t i2c_read_blocking(uint8_t slave_address, uint8_t* data, size_t data_len)
|
|
||||||
// {
|
|
||||||
// i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
||||||
// i2c_master_start(cmd);
|
|
||||||
// i2c_master_write_byte(cmd, (slave_address << 1) | I2C_MASTER_READ, true);
|
|
||||||
|
|
||||||
// if (data_len > 1)
|
|
||||||
// {
|
|
||||||
// i2c_master_read(cmd, data, data_len - 1, I2C_MASTER_ACK);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// i2c_master_read_byte(cmd, data + data_len - 1, I2C_MASTER_NACK);
|
|
||||||
// i2c_master_stop(cmd);
|
|
||||||
|
|
||||||
// esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, pdMS_TO_TICKS(2));
|
|
||||||
// i2c_cmd_link_delete(cmd);
|
|
||||||
// return ret;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void run_loop(void* queue)
|
|
||||||
// {
|
|
||||||
// ReportIn report_in = ReportIn();
|
|
||||||
// ReportOut report_out = ReportOut();
|
|
||||||
|
|
||||||
// i2c_initialize();
|
|
||||||
|
|
||||||
// ESP_LOGD("I2C Stack", "Remaining stack: %d", uxTaskGetStackHighWaterMark(NULL));
|
|
||||||
|
|
||||||
// while (true)
|
|
||||||
// {
|
|
||||||
// for (uint8_t i = 0; i < CONFIG_BLUEPAD32_MAX_DEVICES; ++i)
|
|
||||||
// {
|
|
||||||
// vTaskDelay(1);
|
|
||||||
|
|
||||||
// if (!bluepad32::connected(i))
|
|
||||||
// {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// report_in = bluepad32::get_report_in(i);
|
|
||||||
// if (i2c_write_blocking(MULTI_SLAVE ? (report_in.index + 1) : 0x01, reinterpret_cast<uint8_t*>(&report_in), sizeof(ReportIn)) != ESP_OK)
|
|
||||||
// {
|
|
||||||
// ESP_LOGD("I2C", "Failed to write report_in");
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// vTaskDelay(1);
|
|
||||||
|
|
||||||
// if (i2c_read_blocking(MULTI_SLAVE ? (report_in.index + 1) : 0x01, reinterpret_cast<uint8_t*>(&report_out), sizeof(ReportOut)) != ESP_OK)
|
|
||||||
// {
|
|
||||||
// ESP_LOGD("I2C", "Failed to read report_out");
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// bluepad32::set_report_out(report_out);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // void run_loop()
|
|
||||||
// // {
|
|
||||||
// // ESP_LOGD("Stack", "Remaining stack: %d", uxTaskGetStackHighWaterMark(NULL));
|
|
||||||
|
|
||||||
// // ReportIn report_in = ReportIn();
|
|
||||||
|
|
||||||
// // ESP_LOGD("I2C", "ReportIn 1 created: size: %d", sizeof(report_in));
|
|
||||||
// // ESP_LOGD("Stack", "Remaining stack: %d", uxTaskGetStackHighWaterMark(NULL));
|
|
||||||
|
|
||||||
// // ReportIn different_rep = ReportIn();
|
|
||||||
|
|
||||||
// // ESP_LOGD("I2C", "ReportIn 2 created: size: %d", sizeof(different_rep));
|
|
||||||
// // ESP_LOGD("Stack", "Remaining stack: %d", uxTaskGetStackHighWaterMark(NULL));
|
|
||||||
|
|
||||||
// // ReportOut report_out = ReportOut();
|
|
||||||
|
|
||||||
// // ESP_LOGD("I2C", "ReportOut created: size: %d", sizeof(report_out));
|
|
||||||
// // ESP_LOGD("Stack", "Remaining stack: %d", uxTaskGetStackHighWaterMark(NULL));
|
|
||||||
|
|
||||||
// // i2c_initialize();
|
|
||||||
// // ESP_LOGD("Stack", "Remaining stack: %d", uxTaskGetStackHighWaterMark(NULL));
|
|
||||||
|
|
||||||
// // while (true)
|
|
||||||
// // {
|
|
||||||
// // i2c_write_blocking(MULTI_SLAVE ? (report_in.index + 1) : 0x01, reinterpret_cast<uint8_t*>(&report_in), sizeof(ReportIn));
|
|
||||||
// // vTaskDelay(1);
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// } // namespace I2CDriver
|
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
@@ -186,14 +40,12 @@ void I2CDriver::run_task()
|
|||||||
vTaskDelay(1);
|
vTaskDelay(1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// if (bluepad32::get_report_in(i, report_in))
|
|
||||||
// {
|
|
||||||
report_in = bluepad32::get_report_in(i);
|
report_in = bluepad32::get_report_in(i);
|
||||||
if (i2c_write_blocking(MULTI_SLAVE ? (i + 1) : 0x01, reinterpret_cast<const uint8_t*>(&report_in), sizeof(ReportIn)) != ESP_OK)
|
if (i2c_write_blocking(MULTI_SLAVE ? (i + 1) : 0x01, reinterpret_cast<const uint8_t*>(&report_in), sizeof(ReportIn)) != ESP_OK)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
vTaskDelay(1);
|
vTaskDelay(1);
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "Reports.h"
|
#include "Reports.h"
|
||||||
|
|
||||||
|
//Will probably refactor this to be event driven
|
||||||
class I2CDriver
|
class I2CDriver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -23,6 +24,9 @@ private:
|
|||||||
#else
|
#else
|
||||||
true;
|
true;
|
||||||
#endif
|
#endif
|
||||||
|
// std::array<ReportIn, CONFIG_BLUEPAD32_MAX_DEVICES> report_in_buffer_{};
|
||||||
|
// std::array<std::atomic<bool>, CONFIG_BLUEPAD32_MAX_DEVICES> new_report_in_{false};
|
||||||
|
// std::array<ReportOut, CONFIG_BLUEPAD32_MAX_DEVICES> report_out_buffer_{};
|
||||||
|
|
||||||
void initialize_i2c();
|
void initialize_i2c();
|
||||||
|
|
||||||
|
|||||||
@@ -1383,19 +1383,20 @@ CONFIG_HEAP_TRACING_OFF=y
|
|||||||
#
|
#
|
||||||
# Log output
|
# Log output
|
||||||
#
|
#
|
||||||
# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set
|
CONFIG_LOG_DEFAULT_LEVEL_NONE=y
|
||||||
CONFIG_LOG_DEFAULT_LEVEL_ERROR=y
|
# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set
|
||||||
# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set
|
# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set
|
||||||
# CONFIG_LOG_DEFAULT_LEVEL_INFO is not set
|
# CONFIG_LOG_DEFAULT_LEVEL_INFO is not set
|
||||||
# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set
|
# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set
|
||||||
# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set
|
# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set
|
||||||
CONFIG_LOG_DEFAULT_LEVEL=1
|
CONFIG_LOG_DEFAULT_LEVEL=0
|
||||||
CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y
|
CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y
|
||||||
|
# CONFIG_LOG_MAXIMUM_LEVEL_ERROR is not set
|
||||||
# CONFIG_LOG_MAXIMUM_LEVEL_WARN is not set
|
# CONFIG_LOG_MAXIMUM_LEVEL_WARN is not set
|
||||||
# CONFIG_LOG_MAXIMUM_LEVEL_INFO is not set
|
# CONFIG_LOG_MAXIMUM_LEVEL_INFO is not set
|
||||||
# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set
|
# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set
|
||||||
# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set
|
# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set
|
||||||
CONFIG_LOG_MAXIMUM_LEVEL=1
|
CONFIG_LOG_MAXIMUM_LEVEL=0
|
||||||
CONFIG_LOG_COLORS=y
|
CONFIG_LOG_COLORS=y
|
||||||
CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y
|
CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y
|
||||||
# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set
|
# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set
|
||||||
|
|||||||
@@ -272,16 +272,13 @@ uni_platform* get_driver()
|
|||||||
|
|
||||||
//Public API
|
//Public API
|
||||||
|
|
||||||
void initialize(std::array<Gamepad, MAX_GAMEPADS>& gamepads)
|
void run_task(std::array<Gamepad, MAX_GAMEPADS>& gamepads)
|
||||||
{
|
{
|
||||||
for (uint8_t i = 0; i < MAX_GAMEPADS; ++i)
|
for (uint8_t i = 0; i < MAX_GAMEPADS; ++i)
|
||||||
{
|
{
|
||||||
devices_[i].gamepad = &gamepads[i];
|
devices_[i].gamepad = &gamepads[i];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void run_loop()
|
|
||||||
{
|
|
||||||
uni_platform_set_custom(get_driver());
|
uni_platform_set_custom(get_driver());
|
||||||
uni_init(0, nullptr);
|
uni_init(0, nullptr);
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,9 @@
|
|||||||
/* NOTE: Everything bluepad32/uni needs to be wrapped
|
/* NOTE: Everything bluepad32/uni needs to be wrapped
|
||||||
and kept away from tinyusb due to naming conflicts */
|
and kept away from tinyusb due to naming conflicts */
|
||||||
|
|
||||||
namespace bluepad32 {
|
namespace bluepad32
|
||||||
|
{
|
||||||
void initialize(std::array<Gamepad, MAX_GAMEPADS>& gamepads);
|
void run_task(std::array<Gamepad, MAX_GAMEPADS>& gamepads);
|
||||||
void run_loop();
|
|
||||||
std::array<bool, MAX_GAMEPADS> get_connected_map();
|
std::array<bool, MAX_GAMEPADS> get_connected_map();
|
||||||
bool any_connected();
|
bool any_connected();
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ static constexpr size_t MAX_BUFFER_SIZE = std::max(sizeof(ReportOut), sizeof(Rep
|
|||||||
static constexpr uint8_t I2C_ADDR = 0x01;
|
static constexpr uint8_t I2C_ADDR = 0x01;
|
||||||
|
|
||||||
std::array<Gamepad*, MAX_GAMEPADS> gamepads_{nullptr};
|
std::array<Gamepad*, MAX_GAMEPADS> gamepads_{nullptr};
|
||||||
std::atomic<bool> pad_connected_ = false;
|
// std::atomic<bool> pad_connected_ = false;
|
||||||
|
|
||||||
inline void process_in_report(ReportIn* report_in)
|
inline void process_in_report(ReportIn* report_in)
|
||||||
{
|
{
|
||||||
@@ -174,108 +174,9 @@ void initialize(std::array<Gamepad, MAX_GAMEPADS>& gamepad)
|
|||||||
i2c_slave_init(I2C_PORT, I2C_ADDR, &slave_handler);
|
i2c_slave_init(I2C_PORT, I2C_ADDR, &slave_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pad_connected()
|
// bool pad_connected()
|
||||||
{
|
|
||||||
return pad_connected_.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace i2c_driver_esp
|
|
||||||
|
|
||||||
// #include <array>
|
|
||||||
// #include <cstring>
|
|
||||||
// #include <pico/i2c_slave.h>
|
|
||||||
// #include <hardware/gpio.h>
|
|
||||||
// #include <hardware/i2c.h>
|
|
||||||
|
|
||||||
// #include "Gamepad.h"
|
|
||||||
// #include "board_config.h"
|
|
||||||
// #include "Board/board_api.h"
|
|
||||||
// #include "I2CDriver/I2CDriver_ESP.h"
|
|
||||||
|
|
||||||
// namespace i2c_driver_esp {
|
|
||||||
|
|
||||||
// #pragma pack(push, 1)
|
|
||||||
// struct ReportIn
|
|
||||||
// {
|
// {
|
||||||
// uint8_t dpad;
|
// return pad_connected_.load();
|
||||||
// uint16_t buttons;
|
|
||||||
// uint8_t trigger_l;
|
|
||||||
// uint8_t trigger_r;
|
|
||||||
// int16_t joystick_lx;
|
|
||||||
// int16_t joystick_ly;
|
|
||||||
// int16_t joystick_rx;
|
|
||||||
// int16_t joystick_ry;
|
|
||||||
|
|
||||||
// ReportIn()
|
|
||||||
// {
|
|
||||||
// std::memset(this, 0, sizeof(ReportIn));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// static_assert(sizeof(ReportIn) == 13, "i2c_driver_esp::ReportIn size mismatch");
|
|
||||||
|
|
||||||
// struct ReportOut
|
|
||||||
// {
|
|
||||||
// uint8_t rumble_l;
|
|
||||||
// uint8_t rumble_r;
|
|
||||||
|
|
||||||
// ReportOut()
|
|
||||||
// {
|
|
||||||
// std::memset(this, 0, sizeof(ReportOut));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// static_assert(sizeof(ReportOut) == 2, "i2c_driver_esp::ReportOut size mismatch");
|
|
||||||
// #pragma pack(pop)
|
|
||||||
|
|
||||||
// static constexpr uint8_t I2C_ADDR = 0x50;
|
|
||||||
|
|
||||||
// Gamepad* gamepad_ = nullptr;
|
|
||||||
|
|
||||||
// inline void get_in_report()
|
|
||||||
// {
|
|
||||||
// static ReportIn report_in = ReportIn();
|
|
||||||
// int count = i2c_read_timeout_us(I2C_PORT, I2C_ADDR, reinterpret_cast<uint8_t*>(&report_in), sizeof(ReportIn), false, 1000);
|
|
||||||
// if (count > 0)
|
|
||||||
// {
|
|
||||||
// gamepad_->set_buttons(report_in.buttons);
|
|
||||||
// gamepad_->set_dpad(report_in.dpad);
|
|
||||||
// gamepad_->set_trigger_l(report_in.trigger_l);
|
|
||||||
// gamepad_->set_trigger_r(report_in.trigger_r);
|
|
||||||
// gamepad_->set_joystick_lx_int10(report_in.joystick_lx);
|
|
||||||
// gamepad_->set_joystick_ly_int10(report_in.joystick_ly);
|
|
||||||
// gamepad_->set_joystick_rx_int10(report_in.joystick_rx);
|
|
||||||
// gamepad_->set_joystick_ry_int10(report_in.joystick_ry);
|
|
||||||
// }
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// inline void set_out_report()
|
} // namespace i2c_driver_esp32
|
||||||
// {
|
|
||||||
// static ReportOut report_out = ReportOut();
|
|
||||||
// report_out.rumble_l = gamepad_->get_rumble_l().uint8();
|
|
||||||
// report_out.rumble_r = gamepad_->get_rumble_r().uint8();
|
|
||||||
// i2c_write_timeout_us(I2C_PORT, I2C_ADDR, reinterpret_cast<uint8_t*>(&report_out), sizeof(ReportOut), false, 1000);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void initialize(std::array<Gamepad, MAX_GAMEPADS>& gamepad)
|
|
||||||
// {
|
|
||||||
// gamepad_ = &gamepad[0];
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void task()
|
|
||||||
// {
|
|
||||||
// get_in_report();
|
|
||||||
// sleep_us(100);
|
|
||||||
// // set_out_report();
|
|
||||||
// // sleep_us(100);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// } // namespace i2c_driver_esp
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
namespace i2c_driver_esp32
|
namespace i2c_driver_esp32
|
||||||
{
|
{
|
||||||
void initialize(std::array<Gamepad, MAX_GAMEPADS>& gamepad);
|
void initialize(std::array<Gamepad, MAX_GAMEPADS>& gamepad);
|
||||||
bool pad_connected();
|
// bool pad_connected();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // _I2CDRIVER_ESP_H_
|
#endif // _I2CDRIVER_ESP_H_
|
||||||
@@ -13,79 +13,24 @@
|
|||||||
#include "USBDevice/DeviceManager.h"
|
#include "USBDevice/DeviceManager.h"
|
||||||
#include "Board/board_api.h"
|
#include "Board/board_api.h"
|
||||||
#include "OGXMini/OGXMini.h"
|
#include "OGXMini/OGXMini.h"
|
||||||
#include "I2CDriver/I2CDriver_ESP.h"
|
#include "I2CDriver/i2c_driver_esp32.h"
|
||||||
#include "Gamepad.h"
|
#include "Gamepad.h"
|
||||||
|
|
||||||
namespace OGXMini {
|
namespace OGXMini {
|
||||||
|
|
||||||
std::array<Gamepad, MAX_GAMEPADS> gamepads_;
|
std::array<Gamepad, MAX_GAMEPADS> gamepads_;
|
||||||
|
|
||||||
// void init_esp32_gpio()
|
|
||||||
// {
|
|
||||||
// gpio_init(ESP_PROG_PIN);
|
|
||||||
// gpio_set_dir(ESP_PROG_PIN, GPIO_IN);
|
|
||||||
// gpio_pull_up(ESP_PROG_PIN);
|
|
||||||
|
|
||||||
// gpio_init(ESP_RST_PIN);
|
|
||||||
// gpio_set_dir(ESP_RST_PIN, GPIO_IN);
|
|
||||||
// gpio_pull_up(ESP_RST_PIN);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// bool uart_passthrough_mode()
|
|
||||||
// {
|
|
||||||
// gpio_init(MODE_SEL_PIN);
|
|
||||||
// gpio_set_dir(MODE_SEL_PIN, GPIO_IN);
|
|
||||||
// gpio_pull_up(MODE_SEL_PIN);
|
|
||||||
|
|
||||||
// if (gpio_get(MODE_SEL_PIN) == 0)
|
|
||||||
// {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void reset_esp32()
|
|
||||||
// {
|
|
||||||
// gpio_init(ESP_RST_PIN);
|
|
||||||
// gpio_set_dir(ESP_RST_PIN, GPIO_OUT);
|
|
||||||
// gpio_put(ESP_RST_PIN, 0);
|
|
||||||
// sleep_ms(500);
|
|
||||||
// gpio_put(ESP_RST_PIN, 1);
|
|
||||||
// sleep_ms(250);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void reset_esp32()
|
|
||||||
// {
|
|
||||||
// gpio_init(ESP_PROG_PIN);
|
|
||||||
// gpio_set_dir(ESP_PROG_PIN, GPIO_OUT);
|
|
||||||
// gpio_put(ESP_PROG_PIN, 1);
|
|
||||||
|
|
||||||
// gpio_init(ESP_RST_PIN);
|
|
||||||
// gpio_set_dir(ESP_RST_PIN, GPIO_OUT);
|
|
||||||
// gpio_put(ESP_PROG_PIN, 1);
|
|
||||||
|
|
||||||
// gpio_put(ESP_PROG_PIN, 0);
|
|
||||||
// sleep_ms(250);
|
|
||||||
|
|
||||||
// gpio_put(ESP_RST_PIN, 0);
|
|
||||||
// sleep_ms(500);
|
|
||||||
// gpio_put(ESP_RST_PIN, 1);
|
|
||||||
// sleep_ms(250);
|
|
||||||
// gpio_put(ESP_PROG_PIN, 1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
void run_esp32_uart_bridge()
|
void run_esp32_uart_bridge()
|
||||||
{
|
{
|
||||||
DeviceManager& device_manager = DeviceManager::get_instance();
|
DeviceManager& device_manager = DeviceManager::get_instance();
|
||||||
device_manager.initialize_driver(DeviceDriver::Type::UART_BRIDGE);
|
device_manager.initialize_driver(DeviceDriver::Type::UART_BRIDGE);
|
||||||
board_api::enter_esp32_prog_mode();
|
board_api::enter_esp32_prog_mode();
|
||||||
// reset_esp32();
|
|
||||||
device_manager.get_driver()->process(0, gamepads_.front()); //Runs UART Bridge task
|
device_manager.get_driver()->process(0, gamepads_.front()); //Runs UART Bridge task
|
||||||
}
|
}
|
||||||
|
|
||||||
void core1_task()
|
void core1_task()
|
||||||
{
|
{
|
||||||
i2c_driver_esp::initialize(gamepads_);
|
i2c_driver_esp32::initialize(gamepads_);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@@ -107,10 +52,7 @@ void run_program()
|
|||||||
|
|
||||||
board_api::init_gpio();
|
board_api::init_gpio();
|
||||||
|
|
||||||
// init_esp32_gpio();
|
|
||||||
|
|
||||||
if (board_api::uart_bridge_mode())
|
if (board_api::uart_bridge_mode())
|
||||||
// if (uart_passthrough_mode())
|
|
||||||
{
|
{
|
||||||
run_esp32_uart_bridge();
|
run_esp32_uart_bridge();
|
||||||
return;
|
return;
|
||||||
@@ -119,8 +61,6 @@ void run_program()
|
|||||||
// {
|
// {
|
||||||
// user_settings.write_firmware_version();
|
// user_settings.write_firmware_version();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// user_settings.initialize_flash();
|
|
||||||
|
|
||||||
board_init();
|
board_init();
|
||||||
|
|
||||||
@@ -130,18 +70,16 @@ void run_program()
|
|||||||
}
|
}
|
||||||
|
|
||||||
DeviceManager& device_manager = DeviceManager::get_instance();
|
DeviceManager& device_manager = DeviceManager::get_instance();
|
||||||
// device_manager.initialize_driver(user_settings.get_current_driver());
|
device_manager.initialize_driver(user_settings.get_current_driver());
|
||||||
device_manager.initialize_driver(DeviceDriver::Type::XINPUT);
|
|
||||||
|
|
||||||
multicore_reset_core1();
|
multicore_reset_core1();
|
||||||
multicore_launch_core1(core1_task);
|
multicore_launch_core1(core1_task);
|
||||||
|
|
||||||
board_api::reset_esp32();
|
board_api::reset_esp32();
|
||||||
// reset_esp32();
|
|
||||||
|
|
||||||
// GPCheckContext gp_check_ctx = { false, user_settings };
|
GPCheckContext gp_check_ctx = { false, user_settings };
|
||||||
// repeating_timer_t gp_check_timer;
|
repeating_timer_t gp_check_timer;
|
||||||
// add_repeating_timer_ms(UserSettings::GP_CHECK_DELAY_MS, gp_check_cb, &gp_check_ctx, &gp_check_timer);
|
add_repeating_timer_ms(UserSettings::GP_CHECK_DELAY_MS, gp_check_cb, &gp_check_ctx, &gp_check_timer);
|
||||||
|
|
||||||
DeviceDriver* device_driver = device_manager.get_driver();
|
DeviceDriver* device_driver = device_manager.get_driver();
|
||||||
|
|
||||||
@@ -154,16 +92,14 @@ void run_program()
|
|||||||
device_driver->process(i, gamepads_[i]);
|
device_driver->process(i, gamepads_[i]);
|
||||||
tud_task();
|
tud_task();
|
||||||
}
|
}
|
||||||
// device_driver->process(0, gamepads_.front());
|
|
||||||
// tud_task();
|
|
||||||
|
|
||||||
sleep_us(100);
|
sleep_us(100);
|
||||||
|
|
||||||
// if (gp_check_ctx.driver_changed)
|
if (gp_check_ctx.driver_changed)
|
||||||
// {
|
{
|
||||||
// cancel_repeating_timer(&gp_check_timer);
|
cancel_repeating_timer(&gp_check_timer);
|
||||||
// user_settings.store_driver_type_safe(user_settings.get_current_driver());
|
user_settings.store_driver_type_safe(user_settings.get_current_driver());
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
#if (OGXM_BOARD == PI_PICOW)
|
#if (OGXM_BOARD == PI_PICOW)
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <pico/multicore.h>
|
#include <pico/multicore.h>
|
||||||
#include <hardware/gpio.h>
|
#include <hardware/gpio.h>
|
||||||
#include <hardware/clocks.h>
|
#include <hardware/clocks.h>
|
||||||
@@ -28,8 +26,7 @@ void core1_task()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bluepad32::initialize(gamepads_);
|
bluepad32::run_task(gamepads_);
|
||||||
bluepad32::run_loop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gp_check_cb(repeating_timer_t* rt)
|
bool gp_check_cb(repeating_timer_t* rt)
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "tusb_option.h"
|
#include "tusb_option.h"
|
||||||
|
#include "tusb.h"
|
||||||
|
#include "host/usbh.h"
|
||||||
|
#include "host/usbh_pvt.h"
|
||||||
#include "class/hid/hid_host.h"
|
#include "class/hid/hid_host.h"
|
||||||
|
|
||||||
#include "USBHost/HostDriver/tuh_uni/tuh_uni.h"
|
#include "USBHost/HostDriver/tuh_uni/tuh_uni.h"
|
||||||
@@ -11,44 +14,63 @@ namespace tuh_uni {
|
|||||||
enum class HostType { UNKNOWN = 0, HID, XINPUT };
|
enum class HostType { UNKNOWN = 0, HID, XINPUT };
|
||||||
|
|
||||||
static std::array<HostType, CFG_TUH_DEVICE_MAX> host_type_;
|
static std::array<HostType, CFG_TUH_DEVICE_MAX> host_type_;
|
||||||
// const usbh_class_driver_t* xinput_class_driver_ = nullptr;
|
const usbh_class_driver_t* xinput_class_driver_ = nullptr;
|
||||||
|
|
||||||
|
static inline HostType& get_host_type(uint8_t dev_addr)
|
||||||
|
{
|
||||||
|
return host_type_[dev_addr - 1];
|
||||||
|
}
|
||||||
|
|
||||||
bool init()
|
bool init()
|
||||||
{
|
{
|
||||||
host_type_.fill(HostType::UNKNOWN);
|
host_type_.fill(HostType::UNKNOWN);
|
||||||
hidh_init();
|
hidh_init();
|
||||||
tuh_xinput::class_driver()->init();
|
xinput_class_driver_ = tuh_xinput::class_driver();
|
||||||
|
xinput_class_driver_->init();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool deinit()
|
bool deinit()
|
||||||
{
|
{
|
||||||
hidh_deinit();
|
hidh_deinit();
|
||||||
tuh_xinput::class_driver()->deinit();
|
xinput_class_driver_->deinit();
|
||||||
host_type_.fill(HostType::UNKNOWN);
|
host_type_.fill(HostType::UNKNOWN);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len)
|
bool open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len)
|
||||||
{
|
{
|
||||||
if (tuh_xinput::class_driver()->open(rhport, dev_addr, desc_itf, max_len))
|
HostType& host_type = get_host_type(dev_addr);
|
||||||
|
switch (host_type)
|
||||||
{
|
{
|
||||||
host_type_[dev_addr - 1] = HostType::XINPUT;
|
case HostType::HID:
|
||||||
return true;
|
return hidh_open(rhport, dev_addr, desc_itf, max_len);
|
||||||
|
case HostType::XINPUT:
|
||||||
|
return xinput_class_driver_->open(rhport, dev_addr, desc_itf, max_len);
|
||||||
|
default:
|
||||||
|
if (xinput_class_driver_->open(rhport, dev_addr, desc_itf, max_len))
|
||||||
|
{
|
||||||
|
host_type = HostType::XINPUT;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (hidh_open(rhport, dev_addr, desc_itf, max_len))
|
||||||
|
{
|
||||||
|
host_type = HostType::HID;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
host_type_[dev_addr - 1] = HostType::HID;
|
|
||||||
return hidh_open(rhport, dev_addr, desc_itf, max_len);;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool set_config(uint8_t dev_addr, uint8_t itf_num)
|
bool set_config(uint8_t dev_addr, uint8_t itf_num)
|
||||||
{
|
{
|
||||||
switch (host_type_[dev_addr - 1])
|
switch (get_host_type(dev_addr))
|
||||||
{
|
{
|
||||||
case HostType::HID:
|
case HostType::HID:
|
||||||
return hidh_set_config(dev_addr, itf_num);
|
return hidh_set_config(dev_addr, itf_num);
|
||||||
case HostType::XINPUT:
|
case HostType::XINPUT:
|
||||||
return tuh_xinput::class_driver()->set_config(dev_addr, itf_num);
|
return xinput_class_driver_->set_config(dev_addr, itf_num);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -56,12 +78,12 @@ bool set_config(uint8_t dev_addr, uint8_t itf_num)
|
|||||||
|
|
||||||
bool xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
|
bool xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
|
||||||
{
|
{
|
||||||
switch (host_type_[dev_addr - 1])
|
switch (get_host_type(dev_addr))
|
||||||
{
|
{
|
||||||
case HostType::HID:
|
case HostType::HID:
|
||||||
return hidh_xfer_cb(dev_addr, ep_addr, result, xferred_bytes);
|
return hidh_xfer_cb(dev_addr, ep_addr, result, xferred_bytes);
|
||||||
case HostType::XINPUT:
|
case HostType::XINPUT:
|
||||||
return tuh_xinput::class_driver()->xfer_cb(dev_addr, ep_addr, result, xferred_bytes);
|
return xinput_class_driver_->xfer_cb(dev_addr, ep_addr, result, xferred_bytes);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -69,17 +91,19 @@ bool xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t x
|
|||||||
|
|
||||||
void close(uint8_t dev_addr)
|
void close(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
switch (host_type_[dev_addr - 1])
|
HostType& host_type = get_host_type(dev_addr);
|
||||||
|
switch (host_type)
|
||||||
{
|
{
|
||||||
case HostType::HID:
|
case HostType::HID:
|
||||||
hidh_close(dev_addr);
|
hidh_close(dev_addr);
|
||||||
break;
|
break;
|
||||||
case HostType::XINPUT:
|
case HostType::XINPUT:
|
||||||
tuh_xinput::class_driver()->close(dev_addr);
|
xinput_class_driver_->close(dev_addr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
host_type = HostType::UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
const usbh_class_driver_t* class_driver()
|
const usbh_class_driver_t* class_driver()
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
|
#include "host/usbh.h"
|
||||||
#include "host/usbh_pvt.h"
|
#include "host/usbh_pvt.h"
|
||||||
|
|
||||||
/* This solves a conflict with tinyusb using multiple host class drivers */
|
/* There seems to be a conflict with tinyusb using multiple host class drivers */
|
||||||
namespace tuh_uni
|
namespace tuh_uni
|
||||||
{
|
{
|
||||||
const usbh_class_driver_t* class_driver();
|
const usbh_class_driver_t* class_driver();
|
||||||
|
|||||||
@@ -175,14 +175,14 @@ public:
|
|||||||
{
|
{
|
||||||
for (auto& host_slot : host_slots_)
|
for (auto& host_slot : host_slots_)
|
||||||
{
|
{
|
||||||
// if (host_slot.driver_class == driver_class && host_slot.address == address)
|
if (host_slot.driver_class == driver_class && host_slot.address == address)
|
||||||
// {
|
|
||||||
// host_slot.reset();
|
|
||||||
// }
|
|
||||||
if (host_slot.address == address)
|
|
||||||
{
|
{
|
||||||
host_slot.reset();
|
host_slot.reset();
|
||||||
}
|
}
|
||||||
|
// if (host_slot.address == address)
|
||||||
|
// {
|
||||||
|
// host_slot.reset();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OGXMini::update_tuh_status)
|
if (OGXMini::update_tuh_status)
|
||||||
|
|||||||
@@ -31,10 +31,6 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
|
|||||||
tuh_vid_pid_get(dev_addr, &vid, &pid);
|
tuh_vid_pid_get(dev_addr, &vid, &pid);
|
||||||
|
|
||||||
HostManager& host_manager = HostManager::get_instance();
|
HostManager& host_manager = HostManager::get_instance();
|
||||||
// if (host_manager.setup_driver(HostDriver::Type::HID_GENERIC, dev_addr, instance, desc_report, desc_len))
|
|
||||||
// {
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (host_manager.setup_driver(HostManager::get_type({ vid, pid }), dev_addr, instance, desc_report, desc_len))
|
if (host_manager.setup_driver(HostManager::get_type({ vid, pid }), dev_addr, instance, desc_report, desc_len))
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_EN_4CH)
|
#if defined(CONFIG_EN_4CH)
|
||||||
|
|||||||
8
LICENSE
8
LICENSE
@@ -1,5 +1,11 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
|
Note: Wired configurations of this project exclusively contain MIT licensed
|
||||||
|
code, configurations using Bluetooth libraries/functionality are licensed
|
||||||
|
under Apache 2.0 (Bluepad32) and BTStack's proprietary (non-commercial)
|
||||||
|
license. For full details, please refer to the repositories contained in the
|
||||||
|
Firmware/external directory of this project.
|
||||||
|
|
||||||
Copyright (c) 2024 wiredOpposite (wiredopposite.com)
|
Copyright (c) 2024 wiredOpposite (wiredopposite.com)
|
||||||
Copyright (c) 2024 OpenStickCommunity (gp2040-ce.info)
|
Copyright (c) 2024 OpenStickCommunity (gp2040-ce.info)
|
||||||
Copyright (c) 2021 Jason Skuby (mytechtoybox.com)
|
Copyright (c) 2021 Jason Skuby (mytechtoybox.com)
|
||||||
@@ -21,4 +27,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
50
README.md
50
README.md
@@ -1,13 +1,13 @@
|
|||||||
# OGX-Mini
|
# OGX-Mini
|
||||||

|

|
||||||
|
|
||||||
Firmware for the RP2040, capable of emulating gamepads for several consoles. The firmware now comes in 3 flavors, for the [Adafruit Feather USB Host board](https://www.adafruit.com/product/5723), the Pi Pico, and the Waveshare RP2040-Zero.
|
Firmware for the RP2040, capable of emulating gamepads for several game consoles. The firmware comes in 6 flavors, the [Adafruit Feather USB Host board](https://www.adafruit.com/product/5723), Pi Pico, Waveshare RP2040-Zero, Pi Pico W, RP2040/ESP32 hybrid, and 4-Channel RP2040-Zero.
|
||||||
|
|
||||||
## Supported platforms
|
## Supported platforms
|
||||||
- Original Xbox
|
- Original Xbox
|
||||||
- Playstation 3
|
- Playstation 3
|
||||||
- Nintendo Switch (docked)
|
- Nintendo Switch (docked)
|
||||||
- XInput (not Xbox 360)
|
- XInput (use [UsbdSecPatch](https://github.com/InvoxiPlayGames/UsbdSecPatch) for Xbox 360)
|
||||||
- Playstation Classic
|
- Playstation Classic
|
||||||
|
|
||||||
## Supported devices
|
## Supported devices
|
||||||
@@ -16,19 +16,31 @@ Firmware for the RP2040, capable of emulating gamepads for several consoles. The
|
|||||||
- Xbox 360, One, Series, and Elite
|
- Xbox 360, One, Series, and Elite
|
||||||
- Dualshock 3 (PS3)
|
- Dualshock 3 (PS3)
|
||||||
- Dualshock 4 (PS4)
|
- Dualshock 4 (PS4)
|
||||||
- Dualsense (PS5, Dualsense Edge should work but it's untested)
|
- Dualsense (PS5)
|
||||||
- Nintendo Switch Pro
|
- Nintendo Switch Pro
|
||||||
- Nintendo Switch wired (tested with PowerA brand)
|
- Nintendo Switch wired
|
||||||
- Nintendo 64 USB (experimental, tested with RetroLink brand)
|
- Nintendo 64 Generic USB
|
||||||
- Playstation Classic
|
- Playstation Classic
|
||||||
- Generic DInput
|
- Generic DInput
|
||||||
|
- Generic HID (Limited)
|
||||||
|
|
||||||
|
Note: There are some third party controllers that can change their VID/PID, these might not work correctly.
|
||||||
|
|
||||||
### Wireless adapters
|
### Wireless adapters
|
||||||
- Xbox 360 PC adapter (Microsoft or clones, syncs 1 controller)
|
- Xbox 360 PC adapter (Microsoft or clones, syncs 1 controller)
|
||||||
- 8Bitdo v1 and v2 Bluetooth adapters (set to XInput mode)
|
- 8Bitdo v1 and v2 Bluetooth adapters (set to XInput mode)
|
||||||
- Most wireless adapters that present themselves as Switch/XInput/PlayStation controllers should work
|
- Most wireless adapters that present themselves as Switch/XInput/PlayStation controllers should work
|
||||||
|
|
||||||
Note: There are some third party controllers that can change their VID/PID, these might not work correctly.
|
### Wireless Bluetooth controllers (Pico W & ESP32)
|
||||||
|
Note: Bluetooth functionality is in early testing, some may have quirks.
|
||||||
|
- Xbox Series, One, and Elite 2
|
||||||
|
- Dualshock 3
|
||||||
|
- Dualshock 4
|
||||||
|
- Dualsense
|
||||||
|
- Switch Pro
|
||||||
|
- Steam
|
||||||
|
- Stadia
|
||||||
|
Please visit [this page](https://bluepad32.readthedocs.io/en/latest/supported_gamepads/) for a more comprehensive list of supported controllers.
|
||||||
|
|
||||||
## Changing input mode
|
## Changing input mode
|
||||||
By default the input mode is set to OG Xbox, you must hold a button combo for 3 seconds to change which platform you want to play on. Your chosen input mode will persist after powering off the device.
|
By default the input mode is set to OG Xbox, you must hold a button combo for 3 seconds to change which platform you want to play on. Your chosen input mode will persist after powering off the device.
|
||||||
@@ -48,28 +60,30 @@ Start + A (Cross for PlayStation and B for Switch gamepads)
|
|||||||
|
|
||||||
After a new mode is stored, the RP2040 will reset itself so you don't need to unplug it.
|
After a new mode is stored, the RP2040 will reset itself so you don't need to unplug it.
|
||||||
|
|
||||||
|
## Features new to v1.0.0
|
||||||
|
- Web application for configuring deadzones and buttons mappings, supports up to 8 saved configurations.
|
||||||
|
- Bluetooth functionality for the Pico W and ESP32 (in combination with an RP2040).
|
||||||
|
- 4 channel functionality, connect 4 Picos via I2C and use your Xbox 360 wireless adapter.
|
||||||
|
- Delayed USB mount until a controller is plugged in, useful for internal installation.
|
||||||
|
- Generic HID controller support.
|
||||||
|
- Steel Battalion controller emulation with a wireless Xbox 360 chatpad.
|
||||||
|
- Xbox DVD dongle emulation.
|
||||||
|
|
||||||
## Hardware
|
## Hardware
|
||||||
|
For the Pi Pico, RP2040-Zero, 4 channel, and ESP32 configurations, please see the hardware folder for diagrams.
|
||||||
|
|
||||||
I've designed a PCB for the RP2040-Zero so you can make a small form-factor adapter yourself. The gerber files, schematic, and BOM are in Hardware folder.
|
I've designed a PCB for the RP2040-Zero so you can make a small form-factor adapter yourself. The gerber files, schematic, and BOM are in Hardware folder.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
If you would like a prebuilt unit, you can purchase one, with cable and Xbox adapter included, from my website [wiredopposite.com](https://wiredopposite.com/product/ogx-mini-controller-adapter-for-original-xbox-playstation-3-and-switch-ogx360/) or my [Etsy store](https://www.etsy.com/listing/1426992904/ogx-mini-controller-adapter-for-original).
|
If you would like a prebuilt unit, you can purchase one, with cable and Xbox adapter included, from my [Etsy store](https://www.etsy.com/listing/1426992904/ogx-mini-controller-adapter-for-original).
|
||||||
|
|
||||||
For the Pi Pico, this is a diagram of how you'd connect the extra USB port:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
For the [Adafruit Feather USB Host board](https://www.adafruit.com/product/5723), no extra work is needed.
|
|
||||||
|
|
||||||
## Adding supported controllers
|
## Adding supported controllers
|
||||||
If your third party controller isn't working, but the original version is listed above, send me the device's VID and PID and I'll add it so it's recognized properly.
|
If your third party controller isn't working, but the original version is listed above, send me the device's VID and PID and I'll add it so it's recognized properly.
|
||||||
|
|
||||||
## Compiling
|
## Compiling
|
||||||
You can compile this for different boards by changing USBD_BOARD in the usbd_config.h file, you can also adjust USBD_MAX_GAMEPADS to enable more controllers on PlayStation 3 (this is experimental).
|
You can compile this for different boards with CMake arguments while configuring the project.
|
||||||
|
|
||||||
Choosing OGXM_PI_PICO will set the D+ and D- host pins to GPIO 0 and 1.
|
Choosing OGXM_PI_PICO will set the D+ and D- host pins to GPIO 0 and 1.
|
||||||
|
|
||||||
You can also choose OGXM_RPZERO_INTERPOSER for the RP2040-Zero and that will set D+ and D- to GPIO 10 and 11, so connecting a USB port is easier. You can still use the Pi Pico firmware on the RP2040-Zero (the other way around has not been tested though).
|
You can also choose OGXM_RPZERO_INTERPOSER for the RP2040-Zero and that will set D+ and D- to GPIO 10 and 11, so connecting a USB port is easier. You can still use the Pi Pico firmware on the RP2040-Zero (the other way around has not been tested though).
|
||||||
|
|
||||||
## Special thanks
|
|
||||||
Thank you to Ryzee119 and the OpenStickCommunity, without their work this project would not exist.
|
|
||||||
Reference in New Issue
Block a user