### Start OpenOCD Server Source: https://github.com/ricardoquesada/bluepad32/blob/main/examples/pico_w/README.md Starts the OpenOCD server, which is required to establish a debugging connection with the Pico W. This command requires sudo privileges. ```shell sudo openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000" ``` -------------------------------- ### Install esptool.py Source: https://github.com/ricardoquesada/bluepad32/blob/main/tools/fw/template-README-airlift.md Installs the esptool.py utility, which is required for flashing firmware onto ESP32 devices. Installation methods vary by operating system. ```shell # Linux sudo apt install esptool ``` ```shell # macOS brew install esptool ``` ```shell # Windows and other OSs pip install esptool ``` -------------------------------- ### Setup ESP-IDF Environment Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/firmware_setup.md Clones the specific ESP-IDF version required for the project and executes the installation script to set up the toolchain. ```bash mkdir ~/esp && cd ~/esp git clone -b release/v4.4 --recursive https://github.com/espressif/esp-idf.git cd ~/esp/esp-idf ./install.sh ``` -------------------------------- ### Install Pico SDK on Linux/macOS Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/plat_picow.md Commands to clone the Raspberry Pi Pico SDK repository and initialize submodules. It also includes setting the required PICO_SDK_PATH environment variable. ```sh mkdir ~/pico && cd ~/pico git clone https://github.com/raspberrypi/pico-sdk.git --branch master cd pico-sdk git submodule update --init export PICO_SDK_PATH=$HOME/pico/pico-sdk/ ``` -------------------------------- ### Flash Bluepad32 Firmware using esptool.py (Command Line) Source: https://github.com/ricardoquesada/bluepad32/blob/main/tools/fw/template-README-unijoysticle.md This snippet demonstrates how to flash the Bluepad32 firmware using the esptool.py command-line utility. It covers setting the serial port environment variable for different operating systems (macOS, Linux, Windows) and then executing the esptool.py command to write the firmware binary to the specified address. Ensure you have esptool.py installed and the correct serial port identified. ```shell # macOS $ export ESPPORT=/dev/cu.SLAB_USBtoUART # Linux $ export ESPPORT=/dev/ttyUSB0 # Windows $ export ESPPORT=COM?? #??? Try different ones $ esptool.py --port ${ESPPORT} --baud 115200 --before default_reset --after hard_reset write_flash 0x0000 bluepad32-unijoysticle-full.bin ``` -------------------------------- ### Clone Bluepad32 Repository Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/plat_picow.md Clones the Bluepad32 repository including all necessary submodules required for the project. ```sh git clone --recursive https://github.com/ricardoquesada/bluepad32.git ``` -------------------------------- ### Build and Run Posix Example Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/developer_notes.md Steps to build and run the POSIX example for Bluetooth packet analysis. Generates a HCI dump file for Wireshark. ```sh cd example/posix mkdir build && cd build cmake .. make -j sudo ./bluepad32_posix_example_app ``` ```sh wireshark /tmp/hci_dump.pklg ``` -------------------------------- ### Install HIDAPI Dependencies Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/pair_ds3.md Commands to install the HIDAPI development library required for the sixaxispairer tool on various operating systems. ```bash sudo apt install libhidapi-dev ``` ```bash sudo emerge dev-libs/hidapi ``` ```bash brew install hidapi ``` -------------------------------- ### Build Bluepad32 Firmware (Pico 2 W) Source: https://github.com/ricardoquesada/bluepad32/blob/main/examples/pico_w/README.md Commands to configure and build the Bluepad32 project specifically for the Pico 2 W board. Requires the build directory to be created first. ```shell # From the recently crated "build" folder cmake -DPICO_BOARD=pico2_w .. make -j ``` -------------------------------- ### Connect to Serial Console (Linux) Source: https://github.com/ricardoquesada/bluepad32/blob/main/examples/pico_w/README.md Opens a serial connection to the Pico W using the 'tio' utility on Linux for viewing console output during debugging. ```shell # Linux tio /dev/ttyACM0 ``` -------------------------------- ### Connect to Target and Continue Execution (GDB) Source: https://github.com/ricardoquesada/bluepad32/blob/main/examples/pico_w/README.md Connects to the OpenOCD server using arm-none-eabi-gdb, initializes the target, and continues program execution. This is part of the GDB debugging workflow. ```shell arm-none-eabi-gdb bluepad32_picow_example_app.elf > target remote :3333 > monitor reset init > continue ``` -------------------------------- ### Build Bluepad32 Firmware Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/plat_picow.md Uses CMake and Make to compile the project and generate a .uf2 file for flashing onto the Pico W hardware. ```sh mkdir build cd build cmake .. make -j ``` -------------------------------- ### Install System Dependencies and Configure Permissions Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/firmware_setup.md Installs necessary build tools and libraries for ESP-IDF on Debian-based systems and adds the current user to the dialout group to access serial devices. ```bash sudo apt-get install git wget flex bison gperf python3 python3-pip python3-setuptools cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 sudo usermod -a -G dialout $USER ``` -------------------------------- ### Connect to Serial Console (macOS) Source: https://github.com/ricardoquesada/bluepad32/blob/main/examples/pico_w/README.md Opens a serial connection to the Pico W using the 'tio' utility on macOS for viewing console output during debugging. ```shell # macOS tio /dev/tty.usbmodem21202 ``` -------------------------------- ### Initialize Bluepad32 Library Source: https://context7.com/ricardoquesada/bluepad32/llms.txt Demonstrates the initialization sequence for the Bluepad32 library on an ESP32 platform. It involves configuring the BTstack, registering a custom platform, and starting the execution loop. ```c #include #include #include struct uni_platform* get_my_platform(void); int app_main(void) { btstack_init(); uni_platform_set_custom(get_my_platform()); uni_init(0, NULL); btstack_run_loop_execute(); return 0; } ``` -------------------------------- ### Set Pico SDK Path (Linux/macOS) Source: https://github.com/ricardoquesada/bluepad32/blob/main/examples/pico_w/README.md Exports the PICO_SDK_PATH environment variable to point to the Pico SDK directory. This is a prerequisite for building the project on Linux or macOS. ```shell # set PICO_SDK_PATH to the correct path export PICO_SDK_PATH=$HOME/pico-sdk/ ``` -------------------------------- ### Configure Makefile for macOS HIDAPI Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/pair_ds3.md Example Makefile configuration for compiling the sixaxispairer tool on macOS, specifying include and library paths for Homebrew-installed HIDAPI. ```makefile INCLUDES := -I/opt/homebrew/Cellar/hidapi/0.13.1/include LIBS := -L/opt/homebrew/Cellar/hidapi/0.13.1/lib -lhidapi sixaxispairer: sixaxispairer.o ${CC} $^ $(LIBS) -o $@ sixaxispairer.o: sixaxispairer.c ${CC} -c $(INCLUDES) $< -o $@ clean: rm sixaxispairer sixaxispairer.o ``` -------------------------------- ### Debug Pico W with OpenOCD and GDB Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/developer_notes.md Setup for debugging the Pico W using OpenOCD and GDB across multiple terminals. Includes starting OpenOCD, connecting GDB, and controlling execution. ```sh sudo openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000" ``` ```gdb arm-none-eabi-gdb bluepad32_picow_example_app.elf (gdb) target remote localhost:3333 (gdb) cont ``` ```gdb arm-none-eabi-gdb bluepad32_picow_example_app.elf (gdb) target remote localhost:3334 (gdb) monitor reset init (gdb) cont ``` ```sh tio /dev/ttyACM0 ``` -------------------------------- ### Patch BTstack Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/plat_picow.md Applies required patches to the BTstack library located within the Bluepad32 source tree. ```sh cd ${BLUEPAD32_SRC}/external/btstack git apply ../patches/*.patch ``` -------------------------------- ### Compile and Flash Bluepad32 for Unijoysticle Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/plat_unijoysticle.md This sequence of commands navigates to the source directory, configures the build for the Unijoysticle target platform, compiles the project, and flashes the binary to the ESP32 device. ```shell cd {BLUEPAD32}/src # Select Unijoysticle platform: # Components config -> Bluepad32 -> Target Platform -> Unijoysticle idf.py menuconfig # Compile it idf.py build # ... and flash it! # Port my vary export ESPPORT=/dev/ttyUSB0 idf.py flash ``` -------------------------------- ### Create New ESP-IDF Project from Template Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/developer_notes.md Clones the ESP-IDF template project to start a new project. Includes recursive cloning for submodules. ```sh # One simple way to start a new ESP-IDF project, is to clone the "template" project git clone --recursive https://github.com/espressif/esp-idf-template my_project ``` -------------------------------- ### Bluepad32 Initialization with Custom Platform (C) Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/adding_new_platform.md This code snippet demonstrates the essential structure of the `app_main` function in `main.c` for initializing Bluepad32 with a custom platform. It includes initializing the Bluetooth stack, setting the custom platform, initializing Bluepad32, and starting the run loop. This is a prerequisite for using custom platform implementations. ```c // main.c int app_main(void) { btstack_init(); // Must be called before uni_init() uni_platform_set_custom(get_my_platform()); // Init Bluepad32. uni_init(0 /* argc */, NULL /* argv */); // Does not return. btstack_run_loop_execute(); return 0; } ``` -------------------------------- ### Compile Bluepad32 in Debug Mode Source: https://github.com/ricardoquesada/bluepad32/blob/main/examples/pico_w/README.md Compiles the Bluepad32 project with the debug build type enabled, preparing it for debugging with GDB. Requires the build directory to be created. ```shell mkdir build cd build cmake -DPICO_BOARD=pico_w -DCMAKE_BUILD_TYPE=Debug .. make -j ``` -------------------------------- ### Install Arduino Component for ESP-IDF Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/developer_notes.md Clones the esp32-arduino component into the project's components directory. ```sh cd ${MYPROJECT}/components/ git clone --recursive https://github.com/espressif/arduino-esp32.git arduino ``` -------------------------------- ### Enable UART Console and Disable USB Console (CMakeLists.txt) Source: https://github.com/ricardoquesada/bluepad32/blob/main/examples/pico_w/README.md Modifies the CMakeLists.txt file to enable UART for console output and disable USB for console output, which is necessary for GDB debugging. ```cmake > pico_enable_stdio_usb(bluepad32_picow_example_app 0) > pico_enable_stdio_uart(bluepad32_picow_example_app 1) ``` -------------------------------- ### Install Bluepad32 Components for ESP-IDF Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/developer_notes.md Copies the bluepad32 and bluepad32_arduino components into the project's components directory. ```sh # Just copy bluepad32 component to your project's component folder cp -r ${BLUEPAD32}/src/components/bluepad32 ${MYPROJECT}/components cp -r ${BLUEPAD32}/src/components/bluepad32_arduino ${MYPROJECT}/components ``` -------------------------------- ### Compile and Execute Sixaxis Pairer Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/pair_ds3.md Commands to build the pairing utility and execute it with the target Bluetooth address retrieved from the device logs. ```bash cd bluepad32/tools make sixaxispairer sudo ./sixaxispairer CC:50:E3:AF:E2:96 ``` -------------------------------- ### Configure Pico W for UART Output Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/developer_notes.md CMakeLists.txt configuration to disable USB output and enable UART output for the Pico W example. ```cmake # Disable USB output pico_enable_stdio_usb(bluepad32_picow_example_app 0) # Enable UART output pico_enable_stdio_uart(bluepad32_picow_example_app 1) ``` -------------------------------- ### Retrieve and Inspect Device Information Source: https://context7.com/ricardoquesada/bluepad32/llms.txt Provides methods to access device metadata such as vendor ID, product ID, and device type. Includes examples for retrieving instances by index and dumping controller state. ```c void inspect_device(uni_hid_device_t* d) { int idx = uni_hid_device_get_idx_for_instance(d); logi("Device index: %d\n", idx); uint16_t vid = uni_hid_device_get_vendor_id(d); uint16_t pid = uni_hid_device_get_product_id(d); logi("VID: 0x%04x, PID: 0x%04x\n", vid, pid); if (uni_hid_device_has_name(d)) { logi("Name: %s\n", d->name); } if (uni_hid_device_is_gamepad(d)) { logi("Device is a gamepad\n"); const char* model = uni_gamepad_get_model_name(d->controller_type); logi("Controller model: %s\n", model); } uni_hid_device_dump_device(d); uni_controller_dump(&d->controller); } void get_device_by_index(int idx) { uni_hid_device_t* d = uni_hid_device_get_instance_for_idx(idx); if (d != NULL) { inspect_device(d); } } ``` -------------------------------- ### Clone Bluepad32 Template Project Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/plat_arduino.md Initializes the project by cloning the repository and its submodules from GitHub. ```shell git clone --recursive https://github.com/ricardoquesada/esp-idf-arduino-bluepad32-template.git my_project ``` -------------------------------- ### Compile and Flash ESP-IDF Project Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/plat_arduino.md Commands to navigate to the project directory, build the firmware, and flash it to the target device using the ESP-IDF toolchain. ```shell cd my_project idf.py build idf.py flash monitor ``` -------------------------------- ### Integrate BTstack and Compile Firmware Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/firmware_setup.md Configures the BTstack component within the Bluepad32 project structure and triggers the build process for the firmware. ```bash cd ${BLUEPAD32}/external/btstack/port/esp32 IDF_PATH=../../../../src ./integrate_btstack.py cd ${BLUEPAD32}/tools/fw ./build.py all ``` -------------------------------- ### Configure ESP-IDF Project Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/plat_arduino.md Launches the menu-based configuration interface to manage project components and settings. ```shell idf.py menuconfig ``` -------------------------------- ### PlatformIO Cleanup Command Source: https://github.com/ricardoquesada/bluepad32/blob/main/CHANGELOG.md A shell command used to remove the local PlatformIO configuration directory to resolve dependency or installation conflicts. ```bash rm -rf ~/.platformio ``` -------------------------------- ### Define and Use Custom Instance Data in C Source: https://context7.com/ricardoquesada/bluepad32/llms.txt This C code defines a custom structure `my_platform_instance_t` to hold device-specific data, provides a helper function `get_my_platform_instance` to access it, and demonstrates its initialization in `my_platform_on_device_ready` and usage in `my_platform_on_controller_data`. It utilizes the `platform_data` field of `uni_hid_device_t` for storage, offering 256 bytes per device. This pattern is crucial for managing unique states or settings for individual controllers. ```c // Define custom instance structure typedef struct my_platform_instance_s { uni_gamepad_seat_t gamepad_seat; uint32_t button_press_count; bool rumble_enabled; uint8_t player_number; } my_platform_instance_t; // Helper to access instance data static my_platform_instance_t* get_my_platform_instance(uni_hid_device_t* d) { return (my_platform_instance_t*)&d->platform_data[0]; } // Initialize instance when device is ready static uni_error_t my_platform_on_device_ready(uni_hid_device_t* d) { my_platform_instance_t* ins = get_my_platform_instance(d); // Initialize instance data ins->gamepad_seat = GAMEPAD_SEAT_A; ins->button_press_count = 0; ins->rumble_enabled = true; ins->player_number = uni_hid_device_get_idx_for_instance(d) + 1; // Set player LED to match player number if (d->report_parser.set_player_leds != NULL) { d->report_parser.set_player_leds(d, ins->player_number); } return UNI_ERROR_SUCCESS; } // Use instance data in controller callback static void my_platform_on_controller_data(uni_hid_device_t* d, uni_controller_t* ctl) { if (ctl->klass != UNI_CONTROLLER_CLASS_GAMEPAD) return; my_platform_instance_t* ins = get_my_platform_instance(d); uni_gamepad_t* gp = &ctl->gamepad; // Count button presses if (gp->buttons != 0) { ins->button_press_count++; } // Use instance settings if ((gp->buttons & BUTTON_A) && ins->rumble_enabled) { if (d->report_parser.play_dual_rumble != NULL) { d->report_parser.play_dual_rumble(d, 0, 100, 128, 64); } } } ``` -------------------------------- ### Generate Binaries for Release Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/developer_notes.md Script to generate release binaries using the build system. Requires navigating to the tools/fw directory. ```sh cd tools/fw ./build.py --set-version v2.4.0 all ``` -------------------------------- ### Schedule Thread-Safe Callback in Bluepad32 Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/programmers_guide_raw.md Demonstrates how to safely trigger a Bluepad32 function (like rumble) from a non-BTstack thread using btstack_run_loop_execute_on_main_thread to schedule a context-aware callback. ```c static btstack_context_callback_registration_t callback_registration; // Safe to call any Bluepad32 / BTstack from this callback function static void on_enable_rumble(void* context) { uni_hid_device_t* d; int idx = (int)context; d = uni_hid_device_get_instance_for_idx(idx); // Safety checks in case the gamepad got disconnected while the callback was scheduled if (!d) return; if (!uni_bt_conn_is_connected(&d->conn)) return; if (d->report_parser.play_dual_rumble != NULL) d->report_parser.play_dual_rumble(d, 0, 0, 0x80, 0x80); } // My Task is a FreeRTOS task, meaning that it is not running on the BTstack thread (task) void my_task() { if (need_to_play_rumble) { callback_registration.callback = &on_enable_rumble; callback_registration.context = (void*)(gamepad_idx); btstack_run_loop_execute_on_main_thread(&callback_registration); } } ``` -------------------------------- ### Control Rumble and LED Features in C Source: https://context7.com/ricardoquesada/bluepad32/llms.txt Shows how to interact with controller hardware features like haptic rumble, player indicator LEDs, and lightbars. It emphasizes checking for function pointer availability in the report_parser before execution. ```c static void control_gamepad_features(uni_hid_device_t* d, uni_gamepad_t* gp) { // Play rumble when Button A is pressed if ((gp->buttons & BUTTON_A) && d->report_parser.play_dual_rumble != NULL) { d->report_parser.play_dual_rumble(d, 0, 250, 128, 64); } // Set player LEDs when Button B is pressed if ((gp->buttons & BUTTON_B) && d->report_parser.set_player_leds != NULL) { static uint8_t led_pattern = 0; led_pattern = (led_pattern + 1) & 0x0f; d->report_parser.set_player_leds(d, led_pattern); } // Set lightbar color based on stick position if ((gp->buttons & BUTTON_X) && d->report_parser.set_lightbar_color != NULL) { uint8_t r = (uint8_t)((gp->axis_x + 512) / 4); uint8_t g = (uint8_t)((gp->axis_y + 512) / 4); uint8_t b = (uint8_t)((gp->axis_rx + 512) / 4); d->report_parser.set_lightbar_color(d, r, g, b); } } ``` -------------------------------- ### Pico W and POSIX Library Creation (CMake) Source: https://github.com/ricardoquesada/bluepad32/blob/main/src/components/bluepad32/CMakeLists.txt Creates a static library named 'bluepad32' for Pico W and POSIX targets. It specifies public include directories for the library. This is used when not building for ESP-IDF. ```cmake elseif(PICO_SDK_VERSION_STRING OR BLUEPAD32_TARGET_POSIX) # Valid for Pico W and Linux add_library(bluepad32 ${srcs}) target_include_directories(bluepad32 PUBLIC ./include) ``` -------------------------------- ### Pair PS Move Motion Controller Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/pair_ds3.md Commands using the PS Move API to list connected devices and pair the motion controller to the host Bluetooth address. ```bash sudo psmove list sudo psmove pair CC:50:E3:AF:E2:96 ``` -------------------------------- ### Configure Bluetooth Allowlist in Arduino Source: https://github.com/ricardoquesada/bluepad32/blob/main/docs/FAQ.md Demonstrates how to programmatically add a Bluetooth address to the allowlist and enable the feature using the uni_bt_allowlist API. The settings are persisted in Non-Volatile Storage (NVS). ```c++ #include static const char * controller_addr_string = "00:11:22:33:44:55"; void setup() { bd_addr_t controller_addr; sscanf_bd_addr(controller_addr_string, controller_addr); uni_bt_allowlist_add_addr(controller_addr); uni_bt_allowlist_set_enabled(true); } ``` -------------------------------- ### Flash Bluepad32 Firmware to AirLift Source: https://github.com/ricardoquesada/bluepad32/blob/main/tools/fw/template-README-airlift.md Flushes the Bluepad32 firmware onto the AirLift module using esptool.py. This command requires specifying the correct serial port and the firmware file. Ensure the AirLift module is in 'boot' mode and has the 'Passthrough' firmware enabled. ```shell # Linux export ESPPORT=/dev/ttyACM0 # macOS export ESPPORT=/dev/cu.usbmodem14121301 # Windows export ESPPORT=COM?? #??? Try different ones esptool.py --port ${ESPPORT} --baud 115200 --before no_reset write_flash 0x0000 bluepad32-airlift-full.bin ``` -------------------------------- ### New Rumble API (C) Source: https://github.com/ricardoquesada/bluepad32/blob/main/CHANGELOG.md Introduces a new rumble API `play_dual_rumble` for more granular control over rumble effects, including delayed start, duration, and magnitude for weak and strong motors. The older `set_rumble` is deprecated in the raw API but remains in Arduino for backward compatibility. ```c play_dual_rumble(start_delayed_ms, duration_ms, weak_magnitude, strong_magnitude) ``` ```c // To convert your old code to the new one, do: play_dual_rumble(0, duration * 4, force, force); ```