From bb72819cda4c185cff52ef0080d7d23ae3443e37 Mon Sep 17 00:00:00 2001 From: Robin Avery Date: Mon, 28 Nov 2022 14:21:01 -0500 Subject: [PATCH] Create initial B0XX R4 config Uses `pico` as a base. Face buttons are confirmed but I did not attempt to get nunchuk or keyboard modes working. --- config/b0xx_r4/config.cpp | 164 ++++++++++++++++++++++++++++++++++++++ config/b0xx_r4/env.ini | 5 ++ 2 files changed, 169 insertions(+) create mode 100644 config/b0xx_r4/config.cpp create mode 100644 config/b0xx_r4/env.ini diff --git a/config/b0xx_r4/config.cpp b/config/b0xx_r4/config.cpp new file mode 100644 index 00000000..383e3c83 --- /dev/null +++ b/config/b0xx_r4/config.cpp @@ -0,0 +1,164 @@ +#include "comms/B0XXInputViewer.hpp" +#include "comms/DInputBackend.hpp" +#include "comms/GamecubeBackend.hpp" +#include "comms/N64Backend.hpp" +#include "comms/NintendoSwitchBackend.hpp" +#include "comms/XInputBackend.hpp" +#include "config/mode_selection.hpp" +#include "core/CommunicationBackend.hpp" +#include "core/InputMode.hpp" +#include "core/KeyboardMode.hpp" +#include "core/pinout.hpp" +#include "core/socd.hpp" +#include "core/state.hpp" +#include "input/GpioButtonInput.hpp" +#include "input/NunchukInput.hpp" +#include "joybus_utils.hpp" +#include "modes/Melee20Button.hpp" +#include "stdlib.hpp" + +#include + +CommunicationBackend **backends = nullptr; +size_t backend_count; +KeyboardMode *current_kb_mode = nullptr; + +GpioButtonMapping button_mappings[] = { + {&InputState::l, 6 }, + { &InputState::left, 7 }, + { &InputState::down, 8 }, + { &InputState::right, 9 }, + + { &InputState::mod_x, 10}, + { &InputState::mod_y, 11}, + + { &InputState::start, 12}, + + { &InputState::c_left, 14}, + { &InputState::c_up, 13}, + { &InputState::c_down, 27}, + { &InputState::a, 28}, + { &InputState::c_right, 15}, + + { &InputState::b, 19}, + { &InputState::x, 18}, + { &InputState::z, 17}, + { &InputState::up, 16}, + + { &InputState::r, 26}, + { &InputState::y, 22}, + { &InputState::lightshield, 21}, + { &InputState::midshield, 20}, +}; +size_t button_count = sizeof(button_mappings) / sizeof(GpioButtonMapping); + +const Pinout pinout = { + .joybus_data = 28, + .mux = -1, + .nunchuk_detect = -1, + .nunchuk_sda = -1, + .nunchuk_scl = -1, +}; + +void setup() { + // Create GPIO input source and use it to read button states for checking button holds. + GpioButtonInput *gpio_input = new GpioButtonInput(button_mappings, button_count); + + InputState button_holds; + gpio_input->UpdateInputs(button_holds); + + // Bootsel button hold as early as possible for safety. + if (button_holds.start) { + reset_usb_boot(0, 0); + } + + // Turn on LED to indicate firmware booted. + gpio_init(PICO_DEFAULT_LED_PIN); + gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); + gpio_put(PICO_DEFAULT_LED_PIN, 1); + + // Create array of input sources to be used. + static InputSource *input_sources[] = { gpio_input }; + size_t input_source_count = sizeof(input_sources) / sizeof(InputSource *); + + ConnectedConsole console = detect_console(pinout.joybus_data); + + /* Select communication backend. */ + CommunicationBackend *primary_backend; + if (console == ConnectedConsole::NONE) { + if (button_holds.x) { + // If no console detected and X is held on plugin then use Switch USB backend. + NintendoSwitchBackend::RegisterDescriptor(); + backend_count = 1; + primary_backend = new NintendoSwitchBackend(input_sources, input_source_count); + backends = new CommunicationBackend *[backend_count] { primary_backend }; + + // Default to Ultimate mode on Switch. + primary_backend->SetGameMode(new Ultimate(socd::SOCD_2IP)); + return; + } else if (button_holds.z) { + // If no console detected and Z is held on plugin then use DInput backend. + TUGamepad::registerDescriptor(); + TUKeyboard::registerDescriptor(); + backend_count = 2; + primary_backend = new DInputBackend(input_sources, input_source_count); + backends = new CommunicationBackend *[backend_count] { + primary_backend, new B0XXInputViewer(input_sources, input_source_count) + }; + } else { + // Default to XInput mode if no console detected and no other mode forced. + backend_count = 2; + primary_backend = new XInputBackend(input_sources, input_source_count); + backends = new CommunicationBackend *[backend_count] { + primary_backend, new B0XXInputViewer(input_sources, input_source_count) + }; + } + } else { + if (console == ConnectedConsole::GAMECUBE) { + primary_backend = + new GamecubeBackend(input_sources, input_source_count, pinout.joybus_data); + } else if (console == ConnectedConsole::N64) { + primary_backend = new N64Backend(input_sources, input_source_count, pinout.joybus_data); + } + + // If console then only using 1 backend (no input viewer). + backend_count = 1; + backends = new CommunicationBackend *[backend_count] { primary_backend }; + } + + // Default to Melee mode. + primary_backend->SetGameMode( + new Melee20Button(socd::SOCD_2IP_NO_REAC, { .crouch_walk_os = false }) + ); +} + +void loop() { + select_mode(backends[0]); + + for (size_t i = 0; i < backend_count; i++) { + backends[i]->SendReport(); + } + + if (current_kb_mode != nullptr) { + current_kb_mode->SendReport(backends[0]->GetInputs()); + } +} + +/* Nunchuk code runs on the second core */ +NunchukInput *nunchuk = nullptr; + +void setup1() { + while (backends == nullptr) { + tight_loop_contents(); + } + + // Create Nunchuk input source. + nunchuk = new NunchukInput(Wire, pinout.nunchuk_detect, pinout.nunchuk_sda, pinout.nunchuk_scl); +} + +void loop1() { + if (backends != nullptr) { + nunchuk->UpdateInputs(backends[0]->GetInputs()); + busy_wait_us(50); + } +} diff --git a/config/b0xx_r4/env.ini b/config/b0xx_r4/env.ini new file mode 100644 index 00000000..8b6d2ea8 --- /dev/null +++ b/config/b0xx_r4/env.ini @@ -0,0 +1,5 @@ +[env:b0xx_r4] +extends = arduino_pico_base +build_src_filter = + ${arduino_pico_base.build_src_filter} + +