diff --git a/examples/pico-sdk/gcn-controller-target/usb_serial/.gitignore b/examples/pico-sdk/gcn-controller-target/usb_serial/.gitignore new file mode 100644 index 0000000..d163863 --- /dev/null +++ b/examples/pico-sdk/gcn-controller-target/usb_serial/.gitignore @@ -0,0 +1 @@ +build/ \ No newline at end of file diff --git a/examples/pico-sdk/gcn-controller-target/usb_serial/CMakeLists.txt b/examples/pico-sdk/gcn-controller-target/usb_serial/CMakeLists.txt new file mode 100644 index 0000000..d7f3c30 --- /dev/null +++ b/examples/pico-sdk/gcn-controller-target/usb_serial/CMakeLists.txt @@ -0,0 +1,49 @@ +cmake_minimum_required(VERSION 3.20) + +set(JOYBUS_BACKEND_RP2XXX TRUE) +set(LIBJOYBUS_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../..) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +if(WIN32) + set(USERHOME $ENV{USERPROFILE}) +else() + set(USERHOME $ENV{HOME}) +endif() +set(sdkVersion 2.2.0) +set(toolchainVersion 14_2_Rel1) +set(picotoolVersion 2.2.0-a4) +set(picoVscode ${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake) +if (EXISTS ${picoVscode}) + include(${picoVscode}) +endif() +include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake) + +set(PICO_BOARD pico2 CACHE STRING "Board type") + +project(usb_serial C CXX ASM) + +# Initialise the Raspberry Pi Pico SDK +pico_sdk_init() + +add_subdirectory(${LIBJOYBUS_ROOT} ${CMAKE_BINARY_DIR}/_deps/libjoybus-build) + +# Add executable. Default name is the project name, version 0.1 + +add_executable(usb_serial main.c) + +pico_enable_stdio_usb(usb_serial 1) +pico_enable_stdio_uart(usb_serial 0) + +target_link_libraries(usb_serial pico_stdlib) +pico_add_extra_outputs(usb_serial) + +# pull in common dependencies +target_link_libraries(usb_serial pico_stdlib joybus) + +# create map/bin/hex/uf2 file etc. +pico_add_extra_outputs(usb_serial) + +# add url via pico_set_program_url diff --git a/examples/pico-sdk/gcn-controller-target/usb_serial/README.txt b/examples/pico-sdk/gcn-controller-target/usb_serial/README.txt new file mode 100644 index 0000000..851af0f --- /dev/null +++ b/examples/pico-sdk/gcn-controller-target/usb_serial/README.txt @@ -0,0 +1,21 @@ +# Pico SDK GameCube Controller Target USB Serial Example + +Act as a GameCube controller on RP2XXX devices using the Pico SDK using a serial interface. Simulates button presses when an input is sent over a usb serial connection. + +## Building + +```bash +cmake -B build -DPICO_ENABLE_STDIO_USB=1 -DPICO_ENABLE_STDIO_UART=0 -DPICO_BOARD=pico2 -DPICO_PLATFORM=rp2350 . && cmake --build build +``` +or +```bash +cmake -B build -DPICO_ENABLE_STDIO_USB=1 -DPICO_ENABLE_STDIO_UART=0 . && cmake --build build +``` + +## Flashing + +Enter bootloader mode by holding the BOOTSEL button while plugging in the Pico. Then copy the generated `build/usb_serial.uf2` file to the RPI-RP2 drive that appears, or use `picotool`: + +```bash +picotool load -f build/usb_serial.uf2 +``` \ No newline at end of file diff --git a/examples/pico-sdk/gcn-controller-target/usb_serial/main.c b/examples/pico-sdk/gcn-controller-target/usb_serial/main.c new file mode 100644 index 0000000..2c5690d --- /dev/null +++ b/examples/pico-sdk/gcn-controller-target/usb_serial/main.c @@ -0,0 +1,67 @@ +#include +#include "pico/stdlib.h" + +#include +#include + +#define SI_DATA_GPIO 12 + +struct joybus_rp2xxx rp2xxx_bus; +struct joybus *bus = JOYBUS(&rp2xxx_bus); + +static struct joybus_gc_controller gc_controller; + +int main() +{ + stdio_init_all(); // USB serial + sleep_ms(2000); // allow time to connect + + // Initialize Joybus + joybus_rp2xxx_init(&rp2xxx_bus, SI_DATA_GPIO, pio0); + joybus_enable(bus); + + // Initialize controller target + joybus_gc_controller_init(&gc_controller, JOYBUS_GAMECUBE_CONTROLLER); + + // Register the target on the bus + joybus_target_register(bus, JOYBUS_TARGET(&gc_controller)); + + while (1) { + // Clear previous button state + gc_controller.input.buttons &= ~JOYBUS_GCN_BUTTON_MASK; + + // Read USB serial input (non-blocking) + int ch = getchar_timeout_us(0); + + if (ch != PICO_ERROR_TIMEOUT) { + if (ch == 'a') + gc_controller.input.buttons |= JOYBUS_GCN_BUTTON_A; + if (ch == 'b') + gc_controller.input.buttons |= JOYBUS_GCN_BUTTON_B; + if (ch == 'x') + gc_controller.input.buttons |= JOYBUS_GCN_BUTTON_X; + if (ch == 'y') + gc_controller.input.buttons |= JOYBUS_GCN_BUTTON_Y; + if (ch == 's') + gc_controller.input.buttons |= JOYBUS_GCN_BUTTON_START; + if (ch == 'z') + gc_controller.input.buttons |= JOYBUS_GCN_BUTTON_Z; + if (ch == 'l') + gc_controller.input.buttons |= JOYBUS_GCN_BUTTON_L; + if (ch == 'r') + gc_controller.input.buttons |= JOYBUS_GCN_BUTTON_R; + if (ch == 'u') + gc_controller.input.buttons |= JOYBUS_GCN_BUTTON_UP; + if (ch == 'd') + gc_controller.input.buttons |= JOYBUS_GCN_BUTTON_DOWN; + if (ch == 'L') + gc_controller.input.buttons |= JOYBUS_GCN_BUTTON_LEFT; + if (ch == 'R') + gc_controller.input.buttons |= JOYBUS_GCN_BUTTON_RIGHT; + } + + sleep_ms(10); + } + + return 0; +}