arduino usb host mouse examples
This commit is contained in:
parent
b666b57c4a
commit
fb4eee8158
8 changed files with 492 additions and 0 deletions
|
|
@ -0,0 +1,15 @@
|
|||
// SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// HID reports for standard boot mouse
|
||||
|
||||
// Byte indices for the gamepad report
|
||||
#define BYTE_BUTTONS 0 // Left, right, middle click buttons
|
||||
#define BYTE_DELTA_X 1 // Mouse movement horizontal
|
||||
#define BYTE_DELTA_Y 2 // Mouse movement vertical
|
||||
|
||||
#define BUTTON_NEUTRAL 0x00
|
||||
#define BUTTON_LEFT 0x01
|
||||
#define BUTTON_RIGHT 0x02
|
||||
#define BUTTON_MIDDLE 0x04
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
// SPDX-FileCopyrightText: 2024 Ha Thach for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*********************************************************************
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
MIT license, check LICENSE for more information
|
||||
Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||
All text above, and the splash screen below must be included in
|
||||
any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef USBH_HELPER_H
|
||||
#define USBH_HELPER_H
|
||||
|
||||
#ifdef ARDUINO_ARCH_RP2040
|
||||
// pio-usb is required for rp2040 host
|
||||
#include "pio_usb.h"
|
||||
|
||||
// Pin D+ for host, D- = D+ + 1
|
||||
#ifndef PIN_USB_HOST_DP
|
||||
#define PIN_USB_HOST_DP 16
|
||||
#endif
|
||||
|
||||
// Pin for enabling Host VBUS. comment out if not used
|
||||
#ifndef PIN_5V_EN
|
||||
#define PIN_5V_EN 18
|
||||
#endif
|
||||
|
||||
#ifndef PIN_5V_EN_STATE
|
||||
#define PIN_5V_EN_STATE 1
|
||||
#endif
|
||||
#endif // ARDUINO_ARCH_RP2040
|
||||
|
||||
#ifdef ARDUINO_ARCH_RP2350
|
||||
|
||||
// pio-usb is required for rp2040 host
|
||||
#include "pio_usb.h"
|
||||
|
||||
// Pin D+ for host, D- = D+ + 1
|
||||
#ifndef PIN_USB_HOST_DP
|
||||
#define PIN_USB_HOST_DP 32
|
||||
#endif
|
||||
|
||||
// Pin for enabling Host VBUS. comment out if not used
|
||||
#ifndef PIN_5V_EN
|
||||
#define PIN_5V_EN 29
|
||||
#endif
|
||||
|
||||
#ifndef PIN_5V_EN_STATE
|
||||
#define PIN_5V_EN_STATE 1
|
||||
#endif
|
||||
#endif // ARDUINO_ARCH_RP2350
|
||||
|
||||
#include "Adafruit_TinyUSB.h"
|
||||
|
||||
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
|
||||
// USB Host using MAX3421E: SPI, CS, INT
|
||||
#include "SPI.h"
|
||||
|
||||
#if defined(ARDUINO_METRO_ESP32S2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
|
||||
#else
|
||||
// Default CS and INT are pin 10, 9
|
||||
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
|
||||
#endif
|
||||
#else
|
||||
// Native USB Host such as rp2040
|
||||
Adafruit_USBH_Host USBHost;
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Helper Functions
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#ifdef ARDUINO_ARCH_RP2040
|
||||
static void rp2040_configure_pio_usb(void) {
|
||||
//while ( !Serial ) delay(10); // wait for native usb
|
||||
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
|
||||
|
||||
#ifdef PIN_5V_EN
|
||||
pinMode(PIN_5V_EN, OUTPUT);
|
||||
digitalWrite(PIN_5V_EN, PIN_5V_EN_STATE);
|
||||
#endif
|
||||
|
||||
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
|
||||
pio_cfg.pin_dp = PIN_USB_HOST_DP;
|
||||
|
||||
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
|
||||
// For pico-w, PIO is also used to communicate with cyw43
|
||||
// Therefore we need to alternate the pio-usb configuration
|
||||
// details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46
|
||||
pio_cfg.sm_tx = 3;
|
||||
pio_cfg.sm_rx = 2;
|
||||
pio_cfg.sm_eop = 3;
|
||||
pio_cfg.pio_rx_num = 0;
|
||||
pio_cfg.pio_tx_num = 1;
|
||||
pio_cfg.tx_ch = 9;
|
||||
#endif
|
||||
|
||||
USBHost.configure_pio_usb(1, &pio_cfg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
// SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*********************************************************************
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
MIT license, check LICENSE for more information
|
||||
Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||
All text above, and the splash screen below must be included in
|
||||
any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
/* This example demonstrates use of usb host with a standard HID boot mouse.
|
||||
* - Host depends on MCU:
|
||||
* - rp2040: bit-banging 2 GPIOs with Pico-PIO-USB library (roothub port1)
|
||||
*
|
||||
* Requirements:
|
||||
* - For rp2040:
|
||||
* - Pico-PIO-USB library
|
||||
* - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1
|
||||
* - Provide VBus (5v) and GND for peripheral
|
||||
*/
|
||||
|
||||
// USBHost is defined in usbh_helper.h
|
||||
#include "usbh_helper.h"
|
||||
#include "tusb.h"
|
||||
#include "Adafruit_TinyUSB.h"
|
||||
#include "hid_mouse_reports.h"
|
||||
|
||||
|
||||
bool printed_blank = false;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// configure pio-usb: defined in usbh_helper.h
|
||||
rp2040_configure_pio_usb();
|
||||
|
||||
// run host stack on controller (rhport) 1
|
||||
// Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
|
||||
// host bit-banging processing works done in core1 to free up core0 for other works
|
||||
USBHost.begin(1);
|
||||
delay(3000);
|
||||
Serial.print("USB D+ Pin:");
|
||||
Serial.println(PIN_USB_HOST_DP);
|
||||
Serial.print("USB 5V Pin:");
|
||||
Serial.println(PIN_5V_EN);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
USBHost.task();
|
||||
Serial.flush();
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// HID Host Callback Functions
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
|
||||
{
|
||||
Serial.printf("HID device mounted (address %d, instance %d)\n", dev_addr, instance);
|
||||
|
||||
// Start receiving HID reports
|
||||
if (!tuh_hid_receive_report(dev_addr, instance))
|
||||
{
|
||||
Serial.printf("Error: cannot request to receive report\n");
|
||||
}
|
||||
}
|
||||
|
||||
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
|
||||
{
|
||||
Serial.printf("HID device unmounted (address %d, instance %d)\n", dev_addr, instance);
|
||||
}
|
||||
|
||||
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) {
|
||||
|
||||
if (len > 0){
|
||||
|
||||
//debug print report data
|
||||
// Serial.print("Report data: ");
|
||||
// for (int i = 0; i < len; i++) {
|
||||
// if (i == 0 || i == 3){
|
||||
// Serial.print(report[i], HEX);
|
||||
// Serial.print(" ");
|
||||
// }else { // i==1 or i==2
|
||||
// Serial.print((int8_t)report[i]);
|
||||
// Serial.print(" ");
|
||||
// }
|
||||
// }
|
||||
// Serial.println();
|
||||
|
||||
Serial.print("X: ");
|
||||
Serial.print((int8_t)report[1]);
|
||||
Serial.print(" ");
|
||||
Serial.print("Y: ");
|
||||
Serial.print((int8_t)report[2]);
|
||||
Serial.print(" ");
|
||||
|
||||
if (report[BYTE_BUTTONS] != BUTTON_NEUTRAL){
|
||||
if ((report[BYTE_BUTTONS] & BUTTON_LEFT) == BUTTON_LEFT){
|
||||
Serial.print("Left ");
|
||||
}
|
||||
if ((report[BYTE_BUTTONS] & BUTTON_RIGHT) == BUTTON_RIGHT){
|
||||
Serial.print("Right ");
|
||||
}
|
||||
if ((report[BYTE_BUTTONS] & BUTTON_MIDDLE) == BUTTON_MIDDLE){
|
||||
Serial.print("Middle ");
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// Continue to receive the next report
|
||||
if (!tuh_hid_receive_report(dev_addr, instance)) {
|
||||
Serial.println("Error: cannot request to receive report");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// HID reports for standard boot mouse
|
||||
|
||||
// Byte indices for the gamepad report
|
||||
#define BYTE_BUTTONS 0 // Left, right, middle click buttons
|
||||
#define BYTE_DELTA_X 1 // Mouse movement horizontal
|
||||
#define BYTE_DELTA_Y 2 // Mouse movement vertical
|
||||
|
||||
#define BUTTON_NEUTRAL 0x00
|
||||
#define BUTTON_LEFT 0x01
|
||||
#define BUTTON_RIGHT 0x02
|
||||
#define BUTTON_MIDDLE 0x04
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
// SPDX-FileCopyrightText: 2024 Ha Thach for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*********************************************************************
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
MIT license, check LICENSE for more information
|
||||
Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||
All text above, and the splash screen below must be included in
|
||||
any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef USBH_HELPER_H
|
||||
#define USBH_HELPER_H
|
||||
|
||||
#ifdef ARDUINO_ARCH_RP2040
|
||||
// pio-usb is required for rp2040 host
|
||||
#include "pio_usb.h"
|
||||
|
||||
// Pin D+ for host, D- = D+ + 1
|
||||
#ifndef PIN_USB_HOST_DP
|
||||
#define PIN_USB_HOST_DP 16
|
||||
#endif
|
||||
|
||||
// Pin for enabling Host VBUS. comment out if not used
|
||||
#ifndef PIN_5V_EN
|
||||
#define PIN_5V_EN 18
|
||||
#endif
|
||||
|
||||
#ifndef PIN_5V_EN_STATE
|
||||
#define PIN_5V_EN_STATE 1
|
||||
#endif
|
||||
#endif // ARDUINO_ARCH_RP2040
|
||||
|
||||
#ifdef ARDUINO_ARCH_RP2350
|
||||
|
||||
// pio-usb is required for rp2040 host
|
||||
#include "pio_usb.h"
|
||||
|
||||
// Pin D+ for host, D- = D+ + 1
|
||||
#ifndef PIN_USB_HOST_DP
|
||||
#define PIN_USB_HOST_DP 32
|
||||
#endif
|
||||
|
||||
// Pin for enabling Host VBUS. comment out if not used
|
||||
#ifndef PIN_5V_EN
|
||||
#define PIN_5V_EN 29
|
||||
#endif
|
||||
|
||||
#ifndef PIN_5V_EN_STATE
|
||||
#define PIN_5V_EN_STATE 1
|
||||
#endif
|
||||
#endif // ARDUINO_ARCH_RP2350
|
||||
|
||||
#include "Adafruit_TinyUSB.h"
|
||||
|
||||
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
|
||||
// USB Host using MAX3421E: SPI, CS, INT
|
||||
#include "SPI.h"
|
||||
|
||||
#if defined(ARDUINO_METRO_ESP32S2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
|
||||
#else
|
||||
// Default CS and INT are pin 10, 9
|
||||
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
|
||||
#endif
|
||||
#else
|
||||
// Native USB Host such as rp2040
|
||||
Adafruit_USBH_Host USBHost;
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Helper Functions
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#ifdef ARDUINO_ARCH_RP2040
|
||||
static void rp2040_configure_pio_usb(void) {
|
||||
//while ( !Serial ) delay(10); // wait for native usb
|
||||
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
|
||||
|
||||
#ifdef PIN_5V_EN
|
||||
pinMode(PIN_5V_EN, OUTPUT);
|
||||
digitalWrite(PIN_5V_EN, PIN_5V_EN_STATE);
|
||||
#endif
|
||||
|
||||
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
|
||||
pio_cfg.pin_dp = PIN_USB_HOST_DP;
|
||||
|
||||
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
|
||||
// For pico-w, PIO is also used to communicate with cyw43
|
||||
// Therefore we need to alternate the pio-usb configuration
|
||||
// details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46
|
||||
pio_cfg.sm_tx = 3;
|
||||
pio_cfg.sm_rx = 2;
|
||||
pio_cfg.sm_eop = 3;
|
||||
pio_cfg.pio_rx_num = 0;
|
||||
pio_cfg.pio_tx_num = 1;
|
||||
pio_cfg.tx_ch = 9;
|
||||
#endif
|
||||
|
||||
USBHost.configure_pio_usb(1, &pio_cfg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
// SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*********************************************************************
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
MIT license, check LICENSE for more information
|
||||
Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||
All text above, and the splash screen below must be included in
|
||||
any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
/* This example demonstrates use of usb host with a standard HID boot mouse.
|
||||
* - Host depends on MCU:
|
||||
* - rp2040: bit-banging 2 GPIOs with Pico-PIO-USB library (roothub port1)
|
||||
*
|
||||
* Requirements:
|
||||
* - For rp2040:
|
||||
* - Pico-PIO-USB library
|
||||
* - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1
|
||||
* - Provide VBus (5v) and GND for peripheral
|
||||
*/
|
||||
|
||||
// USBHost is defined in usbh_helper.h
|
||||
#include "usbh_helper.h"
|
||||
#include "tusb.h"
|
||||
#include "Adafruit_TinyUSB.h"
|
||||
#include "hid_mouse_reports.h"
|
||||
|
||||
|
||||
bool printed_blank = false;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// configure pio-usb: defined in usbh_helper.h
|
||||
rp2040_configure_pio_usb();
|
||||
|
||||
// run host stack on controller (rhport) 1
|
||||
// Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
|
||||
// host bit-banging processing works done in core1 to free up core0 for other works
|
||||
USBHost.begin(1);
|
||||
delay(3000);
|
||||
Serial.print("USB D+ Pin:");
|
||||
Serial.println(PIN_USB_HOST_DP);
|
||||
Serial.print("USB 5V Pin:");
|
||||
Serial.println(PIN_5V_EN);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
USBHost.task();
|
||||
Serial.flush();
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// HID Host Callback Functions
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
|
||||
{
|
||||
Serial.printf("HID device mounted (address %d, instance %d)\n", dev_addr, instance);
|
||||
|
||||
// Start receiving HID reports
|
||||
if (!tuh_hid_receive_report(dev_addr, instance))
|
||||
{
|
||||
Serial.printf("Error: cannot request to receive report\n");
|
||||
}
|
||||
}
|
||||
|
||||
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
|
||||
{
|
||||
Serial.printf("HID device unmounted (address %d, instance %d)\n", dev_addr, instance);
|
||||
}
|
||||
|
||||
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) {
|
||||
|
||||
if (len > 0){
|
||||
|
||||
//debug print report data
|
||||
// Serial.print("Report data: ");
|
||||
// for (int i = 0; i < len; i++) {
|
||||
// if (i == 0 || i == 3){
|
||||
// Serial.print(report[i], HEX);
|
||||
// Serial.print(" ");
|
||||
// }else { // i==1 or i==2
|
||||
// Serial.print((int8_t)report[i]);
|
||||
// Serial.print(" ");
|
||||
// }
|
||||
// }
|
||||
// Serial.println();
|
||||
|
||||
Serial.print("X: ");
|
||||
Serial.print((int8_t)report[1]);
|
||||
Serial.print(" ");
|
||||
Serial.print("Y: ");
|
||||
Serial.print((int8_t)report[2]);
|
||||
Serial.print(" ");
|
||||
|
||||
if (report[BYTE_BUTTONS] != BUTTON_NEUTRAL){
|
||||
if ((report[BYTE_BUTTONS] & BUTTON_LEFT) == BUTTON_LEFT){
|
||||
Serial.print("Left ");
|
||||
}
|
||||
if ((report[BYTE_BUTTONS] & BUTTON_RIGHT) == BUTTON_RIGHT){
|
||||
Serial.print("Right ");
|
||||
}
|
||||
if ((report[BYTE_BUTTONS] & BUTTON_MIDDLE) == BUTTON_MIDDLE){
|
||||
Serial.print("Middle ");
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// Continue to receive the next report
|
||||
if (!tuh_hid_receive_report(dev_addr, instance)) {
|
||||
Serial.println("Error: cannot request to receive report");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue