Compare commits

..

No commits in common. "master" and "suport-pico-host-native" have entirely different histories.

228 changed files with 9809 additions and 24366 deletions

View file

@ -46,7 +46,7 @@ body:
- type: input
attributes:
label: TinyUSB Library version
placeholder: "Release version or commit SHA"
placeholder: "Release version or github latest"
validations:
required: true
@ -100,11 +100,3 @@ body:
description: If applicable, add screenshots to help explain your problem.
validations:
required: false
- type: checkboxes
attributes:
label: I have checked existing issues, pr, discussion and documentation
description: You agree to check all the resources above before opening a new issue.
options:
- label: I confirm I have checked existing issues, pr, discussion and documentation.
required: true

View file

@ -3,21 +3,23 @@ name: Build
on: [pull_request, push, repository_dispatch]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
env:
ARDUINO_LIBS: "\"Adafruit SPIFlash\" \"Adafruit seesaw Library\" \"Adafruit NeoPixel\" \"Adafruit Circuit Playground\" \"Adafruit InternalFlash\" \"SdFat - Adafruit Fork\" \"SD\" \"MIDI Library\" \"Pico PIO USB\""
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Checkout code
uses: actions/checkout@v4
- name: Run pre-commit
uses: pre-commit/action@v3.0.1
uses: pre-commit/action@v3.0.0
- name: Checkout adafruit/ci-arduino
uses: actions/checkout@v4
@ -37,9 +39,6 @@ jobs:
PRETTYNAME : "Adafruit TinyUSB Library"
run: bash ci/doxy_gen_and_deploy.sh
# ---------------------------------------
# build
# ---------------------------------------
build:
runs-on: ubuntu-latest
needs: pre-commit
@ -47,23 +46,24 @@ jobs:
fail-fast: false
matrix:
arduino-platform:
# ESP32 ci use dev json
- 'feather_esp32_v2'
# ESP32
- 'feather_esp32s2'
- 'feather_esp32s3'
- 'esp32p4'
# nRF52
- 'cpb'
- 'nrf52840'
# RP2040
- 'feather_rp2040_tinyusb'
- 'pico_rp2040_tinyusb_host'
# SAMD
- 'metro_m0_tinyusb'
- 'metro_m4_tinyusb'
# Ch32v2
- 'CH32V20x_EVT'
steps:
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Checkout code
uses: actions/checkout@v4
@ -76,10 +76,8 @@ jobs:
- name: pre-install
run: bash ci/actions_install.sh
- name: Install Libraries
run: |
arduino-cli lib install ${{ env.ARDUINO_LIBS }}
arduino-cli lib list
- name: Install Libraries for building examples
run: arduino-cli lib install "Adafruit SPIFlash" "MIDI Library" "Adafruit seesaw Library" "Adafruit NeoPixel" "SdFat - Adafruit Fork" "SD" "Adafruit Circuit Playground" "Adafruit InternalFlash" "Pico PIO USB"
- name: test platforms
run: python3 ci/build_platform.py ${{ matrix.arduino-platform }}

View file

@ -15,18 +15,15 @@ Supported device class drivers are:
- Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ...
- Mass Storage Class (MSC): with multiple LUNs
- Musical Instrument Digital Interface (MIDI)
- Video (UVC): work in progress
- WebUSB with vendor specific class
### Host Stack
Host stack is available with either addition of MAX3421E hardware (e.g [Host FeatherWing](https://www.adafruit.com/product/5858)) or rp2040 core (thanks to [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB)). Supported class driver are:
Host support is still work-in-progress but currently available with rp2040 core thanks to [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB). Supported class driver are:
- Communication (CDC): including vendor usb2uart such as FTDI, CP210x, CH34x
- Communication (CDC)
- MassStorage class
Note: Host stack is still work-in-progress
## Supported Cores
There are 2 type of supported cores: with and without built-in support for TinyUSB. Built-in support provide seamless integration but requires extra code added to core's source code. Unfortunately it is not always easy or possible to make those modification.
@ -38,12 +35,9 @@ Following core has TinyUSB as either the primary usb stack or selectable via men
- [adafruit/Adafruit_nRF52_Arduino](https://github.com/adafruit/Adafruit_nRF52_Arduino)
- [adafruit/ArduinoCore-samd](https://github.com/adafruit/ArduinoCore-samd)
- [earlephilhower/arduino-pico](https://github.com/earlephilhower/arduino-pico)
- [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) Host mode using MAX3421E controller should work with all chips. Device mode only support S2/S3/P4 and additional Tools menu are needed
- `USB Mode=USB-OTG (TinyUSB)` for S3 and P4
- `USB CDC On Boot=Enabled`, `USB Firmware MSC On Boot=Disabled`, `USB DFU On Boot=Disabled`
- [openwch/arduino_core_ch32](https://github.com/openwch/arduino_core_ch32)
- [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
Note: For ESP32 port, version before v3.0 requires all descriptors must be specified in usb objects declaration i.e constructors. Therefore all descriptor-related fields must be part of object declaration and descriptor-related API have no effect afterwards. This limitation is not the case for version from v3.0.
ESP32 port relies on Espressif's [esp32-hal-tinyusb.c](https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp32-hal-tinyusb.c) for building usb descriptors which requires all descriptors must be specified in usb objects declaration i.e constructors. Therefore all descriptor-related fields must be part of object declaration and descriptor-related API have no effect afterwards for this port.
### Cores without built-in support

View file

View file

@ -1,8 +0,0 @@
feather_esp32_v2
feather_esp32s2
feather_esp32s3
funhouse
magtag
metroesp32s2
esp32p4
pico_rp2040_tinyusb_host

View file

@ -25,9 +25,11 @@
#include <Adafruit_TinyUSB.h>
#define LED LED_BUILTIN
// Create 2nd instance of CDC Ports.
#ifdef ARDUINO_ARCH_ESP32
#error "Currently multiple CDCs on ESP32 is not yet supported"
#error "Currnetly multiple CDCs on ESP32-Sx is not yet supported. An PR to update core/esp32/USBCDC and/or pre-built libusb are needed."
// for ESP32, we need to specify instance number when declaring object
Adafruit_USBD_CDC USBSer1(1);
#else
@ -35,17 +37,13 @@
#endif
void setup() {
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
#endif
pinMode(LED, OUTPUT);
Serial.begin(115200);
// check to see if multiple CDCs are enabled
if ( CFG_TUD_CDC < 2 ) {
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, HIGH); // LED on for error indicator
#endif
digitalWrite(LED, HIGH); // LED on for error indicator
while(1) {
Serial.printf("CFG_TUD_CDC must be at least 2, current value is %u\n", CFG_TUD_CDC);
@ -58,13 +56,6 @@ void setup() {
// initialize 2nd CDC interface
USBSer1.begin(115200);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
while (!Serial || !USBSer1) {
if (Serial) {
Serial.println("Waiting for other USB ports");
@ -98,9 +89,7 @@ void loop() {
if (delay_without_delaying(500)) {
LEDstate = !LEDstate;
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, LEDstate);
#endif
digitalWrite(LED, LEDstate);
}
}

View file

@ -1,2 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -18,40 +18,19 @@
* Note: this will cause device to loose the touch1200 and require
* user manual interaction to put device into bootloader/DFU mode.
*/
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
// clear configuration will remove all USB interfaces including CDC (Serial)
TinyUSBDevice.clearConfiguration();
int led = LED_BUILTIN;
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
#endif
void setup()
{
Serial.end();
pinMode(led, OUTPUT);
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
// toggle LED
static uint32_t ms = 0;
static uint8_t led_state = 0;
if (millis() - ms > 1000) {
ms = millis();
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, 1-led_state);
#endif
}
void loop()
{
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(led, LOW);
delay(1000);
}

View file

@ -1,2 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -1,41 +0,0 @@
/*********************************************************************
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
*********************************************************************/
#include "Adafruit_TinyUSB.h"
/* This sketch demonstrates USB CDC Serial echo (convert to upper case) using SerialTinyUSB which
* is available for both core with built-in USB support and without.
* Note: on core with built-in support Serial is alias to SerialTinyUSB
*/
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
uint8_t buf[64];
uint32_t count = 0;
while (SerialTinyUSB.available()) {
buf[count++] = (uint8_t) toupper(SerialTinyUSB.read());
}
if (count) {
SerialTinyUSB.write(buf, count);
}
}

View file

@ -0,0 +1,192 @@
/*********************************************************************
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 sketch demonstrates USB Mass Storage and HID mouse (and CDC)
* - Enumerated as disk using on-board external flash
* - Press button pin will move mouse toward bottom right of monitor
*/
#include "SPI.h"
#include "SdFat.h"
#include "Adafruit_SPIFlash.h"
#include "Adafruit_TinyUSB.h"
//--------------------------------------------------------------------+
// MSC External Flash Config
//--------------------------------------------------------------------+
// Un-comment to run example with custom SPI SPI and SS e.g with FRAM breakout
// #define CUSTOM_CS A5
// #define CUSTOM_SPI SPI
#if defined(CUSTOM_CS) && defined(CUSTOM_SPI)
Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI);
#elif defined(ARDUINO_ARCH_ESP32)
// ESP32 use same flash device that store code.
// Therefore there is no need to specify the SPI and SS
Adafruit_FlashTransport_ESP32 flashTransport;
#elif defined(ARDUINO_ARCH_RP2040)
// RP2040 use same flash device that store code.
// Therefore there is no need to specify the SPI and SS
// Use default (no-args) constructor to be compatible with CircuitPython partition scheme
Adafruit_FlashTransport_RP2040 flashTransport;
// For generic usage:
// Adafruit_FlashTransport_RP2040 flashTransport(start_address, size)
// If start_address and size are both 0, value that match filesystem setting in
// 'Tools->Flash Size' menu selection will be used
#else
// On-board external flash (QSPI or SPI) macros should already
// defined in your board variant if supported
// - EXTERNAL_FLASH_USE_QSPI
// - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI
#if defined(EXTERNAL_FLASH_USE_QSPI)
Adafruit_FlashTransport_QSPI flashTransport;
#elif defined(EXTERNAL_FLASH_USE_SPI)
Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, EXTERNAL_FLASH_USE_SPI);
#else
#error No QSPI/SPI flash are defined on your board variant.h !
#endif
#endif
Adafruit_SPIFlash flash(&flashTransport);
Adafruit_USBD_MSC usb_msc;
//--------------------------------------------------------------------+
// HID Config
//--------------------------------------------------------------------+
// HID report descriptor using TinyUSB's template
// Single Report (no ID) descriptor
uint8_t const desc_hid_report[] =
{
TUD_HID_REPORT_DESC_MOUSE()
};
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, false);
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY)
const int pin = 4; // Left Button
bool activeState = true;
#elif defined(ARDUINO_FUNHOUSE_ESP32S2)
const int pin = BUTTON_DOWN;
bool activeState = true;
#elif defined PIN_BUTTON1
const int pin = PIN_BUTTON1;
bool activeState = false;
#else
const int pin = 12;
bool activeState = false;
#endif
// the setup function runs once when you press reset or power the board
void setup()
{
flash.begin();
pinMode(LED_BUILTIN, OUTPUT);
// Set disk vendor id, product id and revision with string up to 8, 16, 4 characters respectively
usb_msc.setID("Adafruit", "External Flash", "1.0");
// Set callback
usb_msc.setReadWriteCallback(msc_read_cb, msc_write_cb, msc_flush_cb);
// Set disk size, block size should be 512 regardless of spi flash page size
usb_msc.setCapacity(flash.size()/512, 512);
// MSC is ready for read/write
usb_msc.setUnitReady(true);
usb_msc.begin();
// Set up button
pinMode(pin, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
// Notes: following commented-out functions has no affect on ESP32
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.begin();
Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mouse + Mass Storage (external flash) example");
}
void loop()
{
// poll gpio once each 10 ms
delay(10);
// button is active low
uint32_t const btn = (digitalRead(pin) == activeState);
// Remote wakeup
if ( TinyUSBDevice.suspended() && btn )
{
// Wake up host if we are in suspend mode
// and REMOTE_WAKEUP feature is enabled by host
tud_remote_wakeup();
}
/*------------- Mouse -------------*/
if ( usb_hid.ready() )
{
if ( btn )
{
int8_t const delta = 5;
usb_hid.mouseMove(0, delta, delta); // no ID: right + down
// delay a bit before attempt to send keyboard report
delay(10);
}
}
}
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
// Note: SPIFLash Bock API: readBlocks/writeBlocks/syncBlocks
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
return flash.readBlocks(lba, (uint8_t*) buffer, bufsize/512) ? bufsize : -1;
}
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
// Note: SPIFLash Bock API: readBlocks/writeBlocks/syncBlocks
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
return flash.writeBlocks(lba, buffer, bufsize/512) ? bufsize : -1;
}
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void msc_flush_cb (void)
{
flash.syncBlocks();
}

View file

@ -1,2 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -23,7 +23,6 @@
// 8KB is the smallest size that windows allow to mount
#define DISK_BLOCK_NUM 16
#define DISK_BLOCK_SIZE 512
#include "ramdisk.h"
Adafruit_USBD_MSC usb_msc;
@ -34,51 +33,43 @@ Adafruit_USBD_MSC usb_msc;
// HID report descriptor using TinyUSB's template
// Single Report (no ID) descriptor
uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_MOUSE()
uint8_t const desc_hid_report[] =
{
TUD_HID_REPORT_DESC_MOUSE()
};
// USB HID object
Adafruit_USBD_HID usb_hid;
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, false);
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY)
const int pin = 4; // Left Button
bool activeState = true;
const int pin = 4; // Left Button
bool activeState = true;
#elif defined(ARDUINO_FUNHOUSE_ESP32S2)
const int pin = BUTTON_DOWN;
bool activeState = true;
const int pin = BUTTON_DOWN;
bool activeState = true;
#elif defined PIN_BUTTON1
const int pin = PIN_BUTTON1;
bool activeState = false;
#elif defined(ARDUINO_ARCH_ESP32)
const int pin = 0;
bool activeState = false;
#elif defined(ARDUINO_ARCH_RP2040)
const int pin = D0;
bool activeState = false;
const int pin = PIN_BUTTON1;
bool activeState = false;
#else
const int pin = A0;
bool activeState = false;
const int pin = 12;
bool activeState = false;
#endif
// the setup function runs once when you press reset or power the board
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
void setup()
{
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
TinyUSB_Device_Init(0);
#endif
// Set disk vendor id, product id and revision with string up to 8, 16, 4 characters respectively
usb_msc.setID("Adafruit", "Mass Storage", "1.0");
// Set disk size
usb_msc.setCapacity(DISK_BLOCK_NUM, DISK_BLOCK_SIZE);
@ -87,42 +78,44 @@ void setup() {
// Set Lun ready (RAM disk is always ready)
usb_msc.setUnitReady(true);
usb_msc.begin();
// Set up button
pinMode(pin, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
// Set up HID
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.setBootProtocol(HID_ITF_PROTOCOL_NONE);
usb_hid.setPollInterval(2);
// Notes: following commented-out functions has no affect on ESP32
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.begin(115200);
while( !TinyUSBDevice.mounted() ) delay(1); // wait for native usb
Serial.println("Adafruit TinyUSB Mouse + Mass Storage (ramdisk) example");
}
void process_hid() {
void loop()
{
// poll gpio once each 10 ms
delay(10);
// button is active low
uint32_t const btn = (digitalRead(pin) == activeState);
// Remote wakeup
if (TinyUSBDevice.suspended() && btn) {
if ( TinyUSBDevice.suspended() && btn )
{
// Wake up host if we are in suspend mode
// and REMOTE_WAKEUP feature is enabled by host
tud_remote_wakeup();
}
/*------------- Mouse -------------*/
if (usb_hid.ready()) {
if (btn) {
if ( usb_hid.ready() )
{
if ( btn )
{
int8_t const delta = 5;
usb_hid.mouseMove(0, delta, delta); // no ID: right + down
@ -132,29 +125,11 @@ void process_hid() {
}
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
// not enumerated()/mounted() yet: nothing to do
if (!TinyUSBDevice.mounted()) {
return;
}
// poll gpio once each 10 ms
static uint32_t ms = 0;
if (millis() - ms > 10) {
ms = millis();
process_hid();
}
}
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t msc_read_cb(uint32_t lba, void* buffer, uint32_t bufsize) {
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
uint8_t const* addr = msc_disk[lba];
memcpy(buffer, addr, bufsize);
@ -164,7 +139,8 @@ int32_t msc_read_cb(uint32_t lba, void* buffer, uint32_t bufsize) {
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t msc_write_cb(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
uint8_t* addr = msc_disk[lba];
memcpy(addr, buffer, bufsize);
@ -173,6 +149,7 @@ int32_t msc_write_cb(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void msc_flush_cb(void) {
void msc_flush_cb (void)
{
// nothing to do
}

View file

@ -1,2 +0,0 @@
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -40,7 +40,7 @@
#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);
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
@ -59,14 +59,14 @@ 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");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -1,2 +0,0 @@
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -40,7 +40,7 @@
#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);
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
@ -59,14 +59,14 @@ 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");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -1,3 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -42,7 +42,8 @@ uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_MOUSE()
};
// USB HID object: desc report, desc len, protocol, interval, use out endpoint
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_MOUSE, 2, false);
/* Adjustable parameters for the log_filter() method.

View file

@ -40,7 +40,7 @@
#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);
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
@ -59,14 +59,14 @@ 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");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -1,3 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -40,7 +40,8 @@ uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_MOUSE()
};
// USB HID object: desc report, desc len, protocol, interval, use out endpoint
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_MOUSE, 2, false);
//------------- Low pass filter with Butterworth -------------//

View file

@ -40,7 +40,7 @@
#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);
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
@ -59,14 +59,14 @@ 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");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -1,3 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -42,9 +42,11 @@ uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_KEYBOARD()
};
// USB HID object: desc report, desc len, protocol, interval, use out endpoint
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_KEYBOARD, 2, false);
void setup() {
Serial.begin(115200);
usb_hid.begin();

View file

@ -40,7 +40,7 @@
#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);
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
@ -59,14 +59,14 @@ 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");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -1,2 +0,0 @@
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -38,7 +38,7 @@
#endif
// SdFat is required for using Adafruit_USBH_MSC_SdFatDevice
#include "SdFat_Adafruit_Fork.h"
#include "SdFat.h"
// USBHost is defined in usbh_helper.h
#include "usbh_helper.h"
@ -73,9 +73,7 @@ void data_log(void) {
}
// Turn on LED when start writing
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, HIGH);
#endif
f_log = fatfs.open(LOG_FILE, O_WRITE | O_APPEND | O_CREAT);
@ -114,9 +112,7 @@ void usbhost_rtos_task(void *param) {
void setup() {
Serial.begin(115200);
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
#endif
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// init host stack on controller (rhport) 1
@ -176,12 +172,10 @@ bool write_complete_callback(uint8_t dev_addr, tuh_msc_complete_data_t const *cb
(void) dev_addr;
(void) cb_data;
#ifdef LED_BUILTIN
// turn off LED after write is complete
// Note this only marks the usb transfer is complete, device can take longer to actual
// write data to physical flash
digitalWrite(LED_BUILTIN, LOW);
#endif
return true;
}

View file

@ -40,7 +40,7 @@
#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);
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
@ -59,14 +59,14 @@ 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");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -1,2 +0,0 @@
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -27,7 +27,7 @@
*/
// SdFat is required for using Adafruit_USBH_MSC_SdFatDevice
#include "SdFat_Adafruit_Fork.h"
#include "SdFat.h"
// USBHost is defined in usbh_helper.h
#include "usbh_helper.h"

View file

@ -40,7 +40,7 @@
#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);
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
@ -59,14 +59,14 @@ 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");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -1 +0,0 @@
CH32V20x_EVT

View file

@ -40,7 +40,7 @@
#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);
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
@ -59,14 +59,14 @@ 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");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -1,2 +0,0 @@
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -1,241 +0,0 @@
/*********************************************************************
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 both device and host, where
* - Device run on native usb controller (roothub port0)
* - Host run on MAX3421E controller (roothub port1) tested with:
* - SAMD21, SAMD51, nRF52840, ESP32S2, ESP32S3, ESP32
* - RP2040: "pio_usb.h" must not be included, otherwise pio-usb will be used as host controller
*
* Requirements:
* - SPI instance, CS pin, INT pin are correctly configured
*/
/* Host example will get device descriptors of attached devices and print it out:
* Device 1: ID 046d:c52f
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 0200
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x046d
idProduct 0xc52f
bcdDevice 2200
iManufacturer 1 Logitech
iProduct 2 USB Receiver
iSerialNumber 0
bNumConfigurations 1
*
*/
#include "Adafruit_TinyUSB.h"
#include "SPI.h"
// USB Host using MAX3421E: SPI, CS, INT
#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);
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32C6)
Adafruit_USBH_Host USBHost(&SPI, 8, 7);
#elif defined(ARDUINO_ESP32C3_DEV)
Adafruit_USBH_Host USBHost(&SPI, 10, 7);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
#endif
// Language ID: English
#define LANGUAGE_ID 0x0409
typedef struct {
tusb_desc_device_t desc_device;
uint16_t manufacturer[32];
uint16_t product[48];
uint16_t serial[16];
bool mounted;
} dev_info_t;
// CFG_TUH_DEVICE_MAX is defined by tusb_config header
dev_info_t dev_info[CFG_TUH_DEVICE_MAX] = { 0 };
//--------------------------------------------------------------------+
// setup() & loop()
//--------------------------------------------------------------------+
void setup() {
Serial.begin(115200);
// init host stack on controller (rhport) 1
USBHost.begin(1);
// while ( !Serial ) delay(10); // wait for native usb
Serial.println("TinyUSB Dual: Device Info Example with MAX3421E");
}
void loop() {
USBHost.task();
Serial.flush();
}
//--------------------------------------------------------------------+
// TinyUSB Host callbacks
//--------------------------------------------------------------------+
void print_device_descriptor(tuh_xfer_t *xfer);
void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len);
void print_lsusb(void) {
bool no_device = true;
for (uint8_t daddr = 1; daddr < CFG_TUH_DEVICE_MAX + 1; daddr++) {
// TODO can use tuh_mounted(daddr), but tinyusb has an bug
// use local connected flag instead
dev_info_t *dev = &dev_info[daddr - 1];
if (dev->mounted) {
Serial.printf("Device %u: ID %04x:%04x %s %s\r\n", daddr,
dev->desc_device.idVendor, dev->desc_device.idProduct,
(char *) dev->manufacturer, (char *) dev->product);
no_device = false;
}
}
if (no_device) {
Serial.println("No device connected (except hub)");
}
}
// Invoked when device is mounted (configured)
void tuh_mount_cb(uint8_t daddr) {
Serial.printf("Device attached, address = %d\r\n", daddr);
dev_info_t *dev = &dev_info[daddr - 1];
dev->mounted = true;
// Get Device Descriptor
tuh_descriptor_get_device(daddr, &dev->desc_device, 18, print_device_descriptor, 0);
}
/// Invoked when device is unmounted (bus reset/unplugged)
void tuh_umount_cb(uint8_t daddr) {
Serial.printf("Device removed, address = %d\r\n", daddr);
dev_info_t *dev = &dev_info[daddr - 1];
dev->mounted = false;
// print device summary
print_lsusb();
}
void print_device_descriptor(tuh_xfer_t *xfer) {
if (XFER_RESULT_SUCCESS != xfer->result) {
Serial.printf("Failed to get device descriptor\r\n");
return;
}
uint8_t const daddr = xfer->daddr;
dev_info_t *dev = &dev_info[daddr - 1];
tusb_desc_device_t *desc = &dev->desc_device;
Serial.printf("Device %u: ID %04x:%04x\r\n", daddr, desc->idVendor, desc->idProduct);
Serial.printf("Device Descriptor:\r\n");
Serial.printf(" bLength %u\r\n" , desc->bLength);
Serial.printf(" bDescriptorType %u\r\n" , desc->bDescriptorType);
Serial.printf(" bcdUSB %04x\r\n" , desc->bcdUSB);
Serial.printf(" bDeviceClass %u\r\n" , desc->bDeviceClass);
Serial.printf(" bDeviceSubClass %u\r\n" , desc->bDeviceSubClass);
Serial.printf(" bDeviceProtocol %u\r\n" , desc->bDeviceProtocol);
Serial.printf(" bMaxPacketSize0 %u\r\n" , desc->bMaxPacketSize0);
Serial.printf(" idVendor 0x%04x\r\n" , desc->idVendor);
Serial.printf(" idProduct 0x%04x\r\n" , desc->idProduct);
Serial.printf(" bcdDevice %04x\r\n" , desc->bcdDevice);
// Get String descriptor using Sync API
Serial.printf(" iManufacturer %u ", desc->iManufacturer);
if (XFER_RESULT_SUCCESS ==
tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, dev->manufacturer, sizeof(dev->manufacturer))) {
utf16_to_utf8(dev->manufacturer, sizeof(dev->manufacturer));
Serial.printf((char *) dev->manufacturer);
}
Serial.printf("\r\n");
Serial.printf(" iProduct %u ", desc->iProduct);
if (XFER_RESULT_SUCCESS ==
tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, dev->product, sizeof(dev->product))) {
utf16_to_utf8(dev->product, sizeof(dev->product));
Serial.printf((char *) dev->product);
}
Serial.printf("\r\n");
Serial.printf(" iSerialNumber %u ", desc->iSerialNumber);
if (XFER_RESULT_SUCCESS ==
tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, dev->serial, sizeof(dev->serial))) {
utf16_to_utf8(dev->serial, sizeof(dev->serial));
Serial.printf((char *) dev->serial);
}
Serial.printf("\r\n");
Serial.printf(" bNumConfigurations %u\r\n", desc->bNumConfigurations);
// print device summary
print_lsusb();
}
//--------------------------------------------------------------------+
// String Descriptor Helper
//--------------------------------------------------------------------+
static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) {
// TODO: Check for runover.
(void) utf8_len;
// Get the UTF-16 length out of the data itself.
for (size_t i = 0; i < utf16_len; i++) {
uint16_t chr = utf16[i];
if (chr < 0x80) {
*utf8++ = chr & 0xff;
} else if (chr < 0x800) {
*utf8++ = (uint8_t) (0xC0 | (chr >> 6 & 0x1F));
*utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
} else {
// TODO: Verify surrogate.
*utf8++ = (uint8_t) (0xE0 | (chr >> 12 & 0x0F));
*utf8++ = (uint8_t) (0x80 | (chr >> 6 & 0x3F));
*utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
}
// TODO: Handle UTF-16 code points that take two entries.
}
}
// Count how many bytes a utf-16-le encoded string will take in utf-8.
static int _count_utf8_bytes(const uint16_t *buf, size_t len) {
size_t total_bytes = 0;
for (size_t i = 0; i < len; i++) {
uint16_t chr = buf[i];
if (chr < 0x80) {
total_bytes += 1;
} else if (chr < 0x800) {
total_bytes += 2;
} else {
total_bytes += 3;
}
// TODO: Handle UTF-16 code points that take two entries.
}
return total_bytes;
}
void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len) {
size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
size_t utf8_len = _count_utf8_bytes(temp_buf + 1, utf16_len);
_convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, buf_len);
((uint8_t *) temp_buf)[utf8_len] = '\0';
}

View file

@ -1,2 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -10,73 +10,93 @@
*********************************************************************/
#include "Adafruit_TinyUSB.h"
#include <Adafruit_NeoPixel.h>
/* This sketch demonstrates USB HID keyboard.
* - PIN A0-A3 is used to send digit '0' to '3' respectively
* - PIN A0-A5 is used to send digit '0' to '5' respectively
* (On the RP2040, pins D0-D5 used)
* - LED and/or Neopixels will be used as Capslock indicator
*/
// HID report descriptor using TinyUSB's template
// Single Report (no ID) descriptor
uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_KEYBOARD()
uint8_t const desc_hid_report[] =
{
TUD_HID_REPORT_DESC_KEYBOARD()
};
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid;
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_KEYBOARD, 2, false);
//------------- Input Pins -------------//
// Array of pins and its keycode.
// Notes: these pins can be replaced by PIN_BUTTONn if defined in setup()
#ifdef ARDUINO_ARCH_RP2040
uint8_t pins[] = { D0, D1, D2, D3 };
uint8_t pins[] = { D0, D1, D2, D3 };
#else
uint8_t pins[] = {A0, A1, A2, A3};
uint8_t pins[] = { A0, A1, A2, A3 };
#endif
// number of pins
uint8_t pincount = sizeof(pins) / sizeof(pins[0]);
uint8_t pincount = sizeof(pins)/sizeof(pins[0]);
// For keycode definition check out https://github.com/hathach/tinyusb/blob/master/src/class/hid/hid.h
uint8_t hidcode[] = {HID_KEY_0, HID_KEY_1, HID_KEY_2, HID_KEY_3};
uint8_t hidcode[] = { HID_KEY_ARROW_RIGHT, HID_KEY_ARROW_LEFT, HID_KEY_ARROW_DOWN, HID_KEY_ARROW_UP };
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY) || defined(ARDUINO_FUNHOUSE_ESP32S2)
bool activeState = true;
bool activeState = true;
#else
bool activeState = false;
bool activeState = false;
#endif
// the setup function runs once when you press reset or power the board
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
//------------- Neopixel -------------//
// #define PIN_NEOPIXEL 8
#ifdef PIN_NEOPIXEL
// Setup HID
usb_hid.setBootProtocol(HID_ITF_PROTOCOL_KEYBOARD);
usb_hid.setPollInterval(2);
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.setStringDescriptor("TinyUSB Keyboard");
// How many NeoPixels are attached to the Arduino?
// use on-board defined NEOPIXEL_NUM if existed
#ifndef NEOPIXEL_NUM
#define NEOPIXEL_NUM 10
#endif
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NEOPIXEL_NUM, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);
#endif
// the setup function runs once when you press reset or power the board
void setup()
{
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
TinyUSB_Device_Init(0);
#endif
// Notes: following commented-out functions has no affect on ESP32
// usb_hid.setBootProtocol(HID_ITF_PROTOCOL_KEYBOARD);
// usb_hid.setPollInterval(2);
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
// usb_hid.setStringDescriptor("TinyUSB Keyboard");
// Set up output report (on control endpoint) for Capslock indicator
usb_hid.setReportCallback(NULL, hid_report_callback);
usb_hid.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// led pin
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
// neopixel if existed
#ifdef PIN_NEOPIXEL
pixels.begin();
pixels.setBrightness(50);
#ifdef NEOPIXEL_POWER
pinMode(NEOPIXEL_POWER, OUTPUT);
digitalWrite(NEOPIXEL_POWER, NEOPIXEL_POWER_ON);
#endif
#endif
// overwrite input pin with PIN_BUTTONx
@ -97,21 +117,32 @@ void setup() {
#endif
// Set up pin as input
for (uint8_t i = 0; i < pincount; i++) {
for (uint8_t i=0; i<pincount; i++)
{
pinMode(pins[i], activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
}
// wait until device mounted
while( !TinyUSBDevice.mounted() ) delay(1);
}
void process_hid() {
void loop()
{
// poll gpio once each 2 ms
delay(2);
// used to avoid send multiple consecutive zero report for keyboard
static bool keyPressedPreviously = false;
uint8_t count = 0;
uint8_t keycode[6] = {0};
uint8_t count=0;
uint8_t keycode[6] = { 0 };
// scan normal key and send report
for (uint8_t i = 0; i < pincount; i++) {
if (activeState == digitalRead(pins[i])) {
for(uint8_t i=0; i < pincount; i++)
{
if ( activeState == digitalRead(pins[i]) )
{
// if pin is active (low), add its hid code to key report
keycode[count++] = hidcode[i];
@ -120,66 +151,55 @@ void process_hid() {
}
}
if (TinyUSBDevice.suspended() && count) {
if ( TinyUSBDevice.suspended() && count )
{
// Wake up host if we are in suspend mode
// and REMOTE_WAKEUP feature is enabled by host
TinyUSBDevice.remoteWakeup();
}
// skip if hid is not ready e.g still transferring previous report
if (!usb_hid.ready()) return;
if ( !usb_hid.ready() ) return;
if (count) {
if ( count )
{
// Send report if there is key pressed
uint8_t const report_id = 0;
uint8_t const modifier = 0;
keyPressedPreviously = true;
usb_hid.keyboardReport(report_id, modifier, keycode);
} else {
}else
{
// Send All-zero report to indicate there is no keys pressed
// Most of the time, it is, though we don't need to send zero report
// every loop(), only a key is pressed in previous loop()
if (keyPressedPreviously) {
if ( keyPressedPreviously )
{
keyPressedPreviously = false;
usb_hid.keyboardRelease(0);
}
}
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
// not enumerated()/mounted() yet: nothing to do
if (!TinyUSBDevice.mounted()) {
return;
}
// poll gpio once each 2 ms
static uint32_t ms = 0;
if (millis() - ms > 2) {
ms = millis();
process_hid();
}
}
// Output report callback for LED indicator such as Caplocks
void hid_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
void hid_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
{
(void) report_id;
(void) bufsize;
// LED indicator is output report with only 1 byte length
if (report_type != HID_REPORT_TYPE_OUTPUT) return;
if ( report_type != HID_REPORT_TYPE_OUTPUT ) return;
// The LED bit map is as follows: (also defined by KEYBOARD_LED_* )
// Kana (4) | Compose (3) | ScrollLock (2) | CapsLock (1) | Numlock (0)
uint8_t ledIndicator = buffer[0];
#ifdef LED_BUILTIN
// turn on LED if capslock is set
digitalWrite(LED_BUILTIN, ledIndicator & KEYBOARD_LED_CAPSLOCK);
#ifdef PIN_NEOPIXEL
pixels.fill(ledIndicator & KEYBOARD_LED_CAPSLOCK ? 0xff0000 : 0x000000);
pixels.show();
#endif
}

View file

@ -1,2 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -19,69 +19,66 @@
* and its active state (when pressed) are different
*/
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY)
const int pin = 4; // Left Button
bool activeState = true;
const int pin = 4; // Left Button
bool activeState = true;
#elif defined(ARDUINO_FUNHOUSE_ESP32S2)
const int pin = BUTTON_DOWN;
bool activeState = true;
const int pin = BUTTON_DOWN;
bool activeState = true;
#elif defined PIN_BUTTON1
const int pin = PIN_BUTTON1;
bool activeState = false;
const int pin = PIN_BUTTON1;
bool activeState = false;
#elif defined(ARDUINO_ARCH_ESP32)
const int pin = 0;
bool activeState = false;
#elif defined(ARDUINO_ARCH_RP2040)
const int pin = D0;
bool activeState = false;
#else
const int pin = A0;
bool activeState = false;
const int pin = 12;
bool activeState = false;
#endif
// HID report descriptor using TinyUSB's template
// Single Report (no ID) descriptor
uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_MOUSE()
uint8_t const desc_hid_report[] =
{
TUD_HID_REPORT_DESC_MOUSE()
};
// USB HID object
Adafruit_USBD_HID usb_hid;
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_MOUSE, 2, false);
// the setup function runs once when you press reset or power the board
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
void setup()
{
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
TinyUSB_Device_Init(0);
#endif
// Set up button, pullup opposite to active state
pinMode(pin, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
// Set up HID
usb_hid.setBootProtocol(HID_ITF_PROTOCOL_MOUSE);
usb_hid.setPollInterval(2);
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.setStringDescriptor("TinyUSB Mouse");
// Notes: following commented-out functions has no affect on ESP32
// usb_hid.setBootProtocol(HID_ITF_PROTOCOL_MOUSE);
// usb_hid.setPollInterval(2);
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
// usb_hid.setStringDescriptor("TinyUSB Mouse");
usb_hid.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.begin(115200);
// wait until device mounted
while( !TinyUSBDevice.mounted() ) delay(1);
Serial.println("Adafruit TinyUSB HID Mouse example");
}
void process_hid() {
void loop()
{
// poll gpio once each 10 ms
delay(10);
// Whether button is pressed
bool btn_pressed = (digitalRead(pin) == activeState);
@ -89,34 +86,17 @@ void process_hid() {
if (!btn_pressed) return;
// Remote wakeup
if (TinyUSBDevice.suspended()) {
if ( TinyUSBDevice.suspended() )
{
// Wake up host if we are in suspend mode
// and REMOTE_WAKEUP feature is enabled by host
TinyUSBDevice.remoteWakeup();
}
if (usb_hid.ready()) {
if ( usb_hid.ready() )
{
uint8_t const report_id = 0; // no ID
int8_t const delta = 5;
usb_hid.mouseMove(report_id, delta, delta); // right + down
}
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
// not enumerated()/mounted() yet: nothing to do
if (!TinyUSBDevice.mounted()) {
return;
}
// poll gpio once each 10 ms
static uint32_t ms = 0;
if (millis() - ms > 10) {
ms = millis();
process_hid();
}
}

View file

@ -1,2 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -20,90 +20,83 @@
* and its active state (when pressed) are different
*/
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY)
const int pin = 4; // Left Button
bool activeState = true;
const int pin = 4; // Left Button
bool activeState = true;
#elif defined(ARDUINO_FUNHOUSE_ESP32S2)
const int pin = BUTTON_DOWN;
bool activeState = true;
const int pin = BUTTON_DOWN;
bool activeState = true;
#elif defined PIN_BUTTON1
const int pin = PIN_BUTTON1;
bool activeState = false;
#elif defined(ARDUINO_ARCH_ESP32)
const int pin = 0;
bool activeState = false;
#elif defined(ARDUINO_ARCH_RP2040)
const int pin = D0;
bool activeState = false;
const int pin = PIN_BUTTON1;
bool activeState = false;
#else
const int pin = A0;
bool activeState = false;
const int pin = 12;
bool activeState = false;
#endif
// Report ID
enum {
enum
{
RID_KEYBOARD = 1,
RID_MOUSE,
RID_CONSUMER_CONTROL, // Media, volume etc ..
};
// HID report descriptor using TinyUSB's template
uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(RID_KEYBOARD)),
TUD_HID_REPORT_DESC_MOUSE (HID_REPORT_ID(RID_MOUSE)),
TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(RID_CONSUMER_CONTROL))
uint8_t const desc_hid_report[] =
{
TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(RID_KEYBOARD) ),
TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(RID_MOUSE) ),
TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(RID_CONSUMER_CONTROL) )
};
// USB HID object.
Adafruit_USBD_HID usb_hid;
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, false);
// the setup function runs once when you press reset or power the board
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
void setup()
{
// Notes: following commented-out functions has no affect on ESP32
// usb_hid.setPollInterval(2);
// usb_hid.setReportDescriptor();
// usb_hid.setStringDescriptor("TinyUSB HID Composite");
Serial.begin(115200);
// Set up HID
usb_hid.setPollInterval(2);
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.setStringDescriptor("TinyUSB HID Composite");
usb_hid.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// Set up button, pullup opposite to active state
pinMode(pin, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
Serial.begin(115200);
// wait until device mounted
while( !TinyUSBDevice.mounted() ) delay(1);
Serial.println("Adafruit TinyUSB HID Composite example");
}
void process_hid() {
void loop()
{
// poll gpio once each 10 ms
delay(10);
// Whether button is pressed
bool btn_pressed = (digitalRead(pin) == activeState);
// Remote wakeup
if (TinyUSBDevice.suspended() && btn_pressed) {
if ( TinyUSBDevice.suspended() && btn_pressed )
{
// Wake up host if we are in suspend mode
// and REMOTE_WAKEUP feature is enabled by host
TinyUSBDevice.remoteWakeup();
}
/*------------- Mouse -------------*/
if (usb_hid.ready() && btn_pressed) {
if ( usb_hid.ready() && btn_pressed )
{
int8_t const delta = 5;
usb_hid.mouseMove(RID_MOUSE, delta, delta); // right + down
@ -112,18 +105,21 @@ void process_hid() {
}
/*------------- Keyboard -------------*/
if (usb_hid.ready()) {
if ( usb_hid.ready() )
{
// use to send key release report
static bool has_key = false;
if (btn_pressed) {
uint8_t keycode[6] = {0};
if ( btn_pressed )
{
uint8_t keycode[6] = { 0 };
keycode[0] = HID_KEY_A;
usb_hid.keyboardReport(RID_KEYBOARD, 0, keycode);
has_key = true;
} else {
}else
{
// send empty key report if previously has key pressed
if (has_key) usb_hid.keyboardRelease(RID_KEYBOARD);
has_key = false;
@ -134,7 +130,8 @@ void process_hid() {
}
/*------------- Consumer Control -------------*/
if (usb_hid.ready()) {
if ( usb_hid.ready() )
{
// Consumer Control is used to control Media playback, Volume, Brightness etc ...
// Consumer report is 2-byte containing the control code of the key
// For list of control check out https://github.com/hathach/tinyusb/blob/master/src/class/hid/hid.h
@ -142,33 +139,16 @@ void process_hid() {
// use to send consumer release report
static bool has_consumer_key = false;
if (btn_pressed) {
if ( btn_pressed )
{
// send volume down (0x00EA)
usb_hid.sendReport16(RID_CONSUMER_CONTROL, HID_USAGE_CONSUMER_VOLUME_DECREMENT);
has_consumer_key = true;
} else {
}else
{
// release the consume key by sending zero (0x0000)
if (has_consumer_key) usb_hid.sendReport16(RID_CONSUMER_CONTROL, 0);
has_consumer_key = false;
}
}
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
// not enumerated()/mounted() yet: nothing to do
if (!TinyUSBDevice.mounted()) {
return;
}
// poll gpio once each 10 ms
static uint32_t ms = 0;
if (millis() - ms > 10) {
ms = millis();
process_hid();
}
}

View file

@ -1,3 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -33,15 +33,17 @@ uint32_t button_mask = (1 << BUTTON_A) | (1 << BUTTON_B) |
Adafruit_seesaw ss;
// Report ID
enum {
enum
{
RID_KEYBOARD = 1,
RID_MOUSE
};
// HID report descriptor using TinyUSB's template
uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(RID_KEYBOARD)),
TUD_HID_REPORT_DESC_MOUSE (HID_REPORT_ID(RID_MOUSE))
uint8_t const desc_hid_report[] =
{
TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(RID_KEYBOARD) ),
TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(RID_MOUSE) )
};
// USB HID object. For ESP32 these values cannot be changed after this declaration
@ -51,30 +53,20 @@ Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROT
int last_x, last_y;
// the setup function runs once when you press reset or power the board
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
void setup()
{
// Notes: following commented-out functions has no affect on ESP32
// usb_hid.setPollInterval(2);
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.begin(115200);
Serial.println("Adafruit TinyUSB HID Mouse with Joy FeatherWing example");
if (!ss.begin(0x49)) {
if(!ss.begin(0x49)){
Serial.println("ERROR! seesaw not found");
while (1) {}
while(1);
} else {
Serial.println("seesaw started");
Serial.print("version: ");
@ -85,9 +77,16 @@ void setup() {
last_y = ss.analogRead(2);
last_x = ss.analogRead(3);
// wait until device mounted
while( !TinyUSBDevice.mounted() ) delay(1);
}
void process_hid() {
void loop()
{
// poll gpio once each 10 ms
delay(10);
// If either analog stick or any buttons is pressed
bool has_action = false;
@ -99,10 +98,12 @@ void process_hid() {
int dx = (x - last_x) / 2;
int dy = (y - last_y) / 2;
if ((abs(dx) > 3) || (abs(dy) > 3)) {
if ( (abs(dx) > 3) || (abs(dy) > 3) )
{
has_action = true;
if (usb_hid.ready()) {
if ( usb_hid.ready() )
{
usb_hid.mouseMove(RID_MOUSE, dx, dy); // no ID: right + down
last_x = x;
@ -113,27 +114,31 @@ void process_hid() {
}
}
/*------------- Keyboard -------------*/
// button is active low, invert read value for convenience
uint32_t buttons = ~ss.digitalReadBulk(button_mask);
if (usb_hid.ready()) {
if ( usb_hid.ready() )
{
// use to prevent sending multiple consecutive zero report
static bool has_key = false;
if (buttons & button_mask) {
if ( buttons & button_mask )
{
has_action = true;
has_key = true;
uint8_t keycode[6] = {0};
if (buttons & (1 << BUTTON_A)) keycode[0] = HID_KEY_A;
if (buttons & (1 << BUTTON_B)) keycode[0] = HID_KEY_B;
if (buttons & (1 << BUTTON_X)) keycode[0] = HID_KEY_X;
if (buttons & (1 << BUTTON_Y)) keycode[0] = HID_KEY_Y;
uint8_t keycode[6] = { 0 };
if ( buttons & (1 << BUTTON_A) ) keycode[0] = HID_KEY_A;
if ( buttons & (1 << BUTTON_B) ) keycode[0] = HID_KEY_B;
if ( buttons & (1 << BUTTON_X) ) keycode[0] = HID_KEY_X;
if ( buttons & (1 << BUTTON_Y) ) keycode[0] = HID_KEY_Y;
usb_hid.keyboardReport(RID_KEYBOARD, 0, keycode);
} else {
}else
{
// send empty key report if previously has key pressed
if (has_key) usb_hid.keyboardRelease(RID_KEYBOARD);
has_key = false;
@ -142,28 +147,10 @@ void process_hid() {
/*------------- Remote Wakeup -------------*/
// Remote wakeup if PC is suspended and we has user interaction with joy feather wing
if (has_action && TinyUSBDevice.suspended()) {
if ( has_action && TinyUSBDevice.suspended() )
{
// Wake up only works if REMOTE_WAKEUP feature is enable by host
// Usually this is the case with Mouse/Keyboard device
TinyUSBDevice.remoteWakeup();
}
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
// not enumerated()/mounted() yet: nothing to do
if (!TinyUSBDevice.mounted()) {
return;
}
// poll gpio once each 10 ms
static uint32_t ms = 0;
if (millis() - ms > 10) {
ms = millis();
process_hid();
}
}

View file

@ -1,2 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -19,135 +19,105 @@
* and its active state (when pressed) are different
*/
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY)
const int pin = 4; // Left Button
bool activeState = true;
const int pin = 4; // Left Button
bool activeState = true;
#elif defined(ARDUINO_FUNHOUSE_ESP32S2)
const int pin = BUTTON_DOWN;
bool activeState = true;
const int pin = BUTTON_DOWN;
bool activeState = true;
#elif defined PIN_BUTTON1
const int pin = PIN_BUTTON1;
bool activeState = false;
const int pin = PIN_BUTTON1;
bool activeState = false;
#elif defined PIN_BUTTON
const int pin = PIN_BUTTON;
bool activeState = false;
const int pin = PIN_BUTTON;
bool activeState = false;
#elif defined(ARDUINO_ARCH_ESP32)
const int pin = 0;
bool activeState = false;
#elif defined(ARDUINO_ARCH_RP2040)
const int pin = D0;
bool activeState = false;
#else
const int pin = A0;
bool activeState = false;
const int pin = 12;
bool activeState = false;
#endif
// HID report descriptor using TinyUSB's template
uint8_t const desc_keyboard_report[] = {
TUD_HID_REPORT_DESC_KEYBOARD()
uint8_t const desc_keyboard_report[] =
{
TUD_HID_REPORT_DESC_KEYBOARD()
};
uint8_t const desc_mouse_report[] = {
TUD_HID_REPORT_DESC_MOUSE()
uint8_t const desc_mouse_report[] =
{
TUD_HID_REPORT_DESC_MOUSE()
};
// USB HID objects
Adafruit_USBD_HID usb_keyboard;
Adafruit_USBD_HID usb_mouse;
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_keyboard(desc_keyboard_report, sizeof(desc_keyboard_report), HID_ITF_PROTOCOL_KEYBOARD, 2, false);
Adafruit_USBD_HID usb_mouse(desc_mouse_report, sizeof(desc_mouse_report), HID_ITF_PROTOCOL_MOUSE, 2, false);
// the setup function runs once when you press reset or power the board
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
void setup()
{
// Notes: following commented-out functions has no affect on ESP32
// usb_keyboard.setPollInterval(2);
// usb_keyboard.setReportDescriptor();
// usb_keyboard.setStringDescriptor("TinyUSB HID Composite");
Serial.begin(115200);
// HID Keyboard
usb_keyboard.setPollInterval(2);
usb_keyboard.setBootProtocol(HID_ITF_PROTOCOL_KEYBOARD);
usb_keyboard.setReportDescriptor(desc_keyboard_report, sizeof(desc_keyboard_report));
usb_keyboard.setStringDescriptor("TinyUSB HID Keyboard");
usb_keyboard.begin();
// HID Mouse
usb_mouse.setPollInterval(2);
usb_mouse.setBootProtocol(HID_ITF_PROTOCOL_MOUSE);
usb_mouse.setReportDescriptor(desc_mouse_report, sizeof(desc_mouse_report));
usb_mouse.setStringDescriptor("TinyUSB HID Keyboard");
usb_mouse.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// Set up button, pullup opposite to active state
pinMode(pin, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
Serial.begin(115200);
// wait until device mounted
//while( !TinyUSBDevice.mounted() ) delay(1);
Serial.println("Adafruit TinyUSB HID Composite example");
}
void process_hid() {
void loop()
{
// poll gpio once each 10 ms
delay(10);
// Whether button is pressed
bool btn_pressed = (digitalRead(pin) == activeState);
// Remote wakeup
if (TinyUSBDevice.suspended() && btn_pressed) {
if ( TinyUSBDevice.suspended() && btn_pressed )
{
// Wake up host if we are in suspend mode
// and REMOTE_WAKEUP feature is enabled by host
TinyUSBDevice.remoteWakeup();
}
/*------------- Mouse -------------*/
if (usb_mouse.ready() && btn_pressed) {
if (usb_mouse.ready() && btn_pressed )
{
int8_t const delta = 5;
usb_mouse.mouseMove(0, delta, delta); // right + down
}
/*------------- Keyboard -------------*/
if (usb_keyboard.ready()) {
if ( usb_keyboard.ready() )
{
// use to send key release report
static bool has_key = false;
if (btn_pressed) {
uint8_t keycode[6] = {0};
if ( btn_pressed )
{
uint8_t keycode[6] = { 0 };
keycode[0] = HID_KEY_A;
usb_keyboard.keyboardReport(0, 0, keycode);
has_key = true;
} else {
}else
{
// send empty key report if previously has key pressed
if (has_key) usb_keyboard.keyboardRelease(0);
has_key = false;
}
}
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
// not enumerated()/mounted() yet: nothing to do
if (!TinyUSBDevice.mounted()) {
return;
}
// poll gpio once each 10 ms
static uint32_t ms = 0;
if (millis() - ms > 10) {
ms = millis();
process_hid();
}
}

View file

@ -1,2 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -22,52 +22,43 @@
// HID report descriptor using TinyUSB's template
// Single Report (no ID) descriptor
uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_GAMEPAD()
uint8_t const desc_hid_report[] =
{
TUD_HID_REPORT_DESC_GAMEPAD()
};
// USB HID object
Adafruit_USBD_HID usb_hid;
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, false);
// Report payload defined in src/class/hid/hid.h
// - For Gamepad Button Bit Mask see hid_gamepad_button_bm_t
// - For Gamepad Hat Bit Mask see hid_gamepad_hat_t
hid_gamepad_report_t gp;
hid_gamepad_report_t gp;
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
void setup()
{
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
TinyUSB_Device_Init(0);
#endif
Serial.begin(115200);
// Notes: following commented-out functions has no affect on ESP32
// usb_hid.setPollInterval(2);
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
// Setup HID
usb_hid.setPollInterval(2);
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// wait until device mounted
while( !TinyUSBDevice.mounted() ) delay(1);
Serial.println("Adafruit TinyUSB HID Gamepad example");
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
// not enumerated()/mounted() yet: nothing to do
if (!TinyUSBDevice.mounted()) {
return;
}
void loop()
{
// // Remote wakeup
// if ( TinyUSBDevice.suspended() && btn )
// {
@ -76,22 +67,22 @@ void loop() {
// TinyUSBDevice.remoteWakeup();
// }
if (!usb_hid.ready()) return;
if ( !usb_hid.ready() ) return;
// Reset buttons
Serial.println("No pressing buttons");
gp.x = 0;
gp.y = 0;
gp.z = 0;
gp.rz = 0;
gp.rx = 0;
gp.ry = 0;
gp.hat = 0;
gp.x = 0;
gp.y = 0;
gp.z = 0;
gp.rz = 0;
gp.rx = 0;
gp.ry = 0;
gp.hat = 0;
gp.buttons = 0;
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
// Hat/DPAD UP
Serial.println("Hat/DPAD UP");
gp.hat = 1; // GAMEPAD_HAT_UP;
@ -116,12 +107,12 @@ void loop() {
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
// Hat/DPAD DOWN
// Hat/DPAD DOWN
Serial.println("Hat/DPAD DOWN");
gp.hat = 5; // GAMEPAD_HAT_DOWN;
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
// Hat/DPAD DOWN LEFT
Serial.println("Hat/DPAD DOWN LEFT");
gp.hat = 6; // GAMEPAD_HAT_DOWN_LEFT;
@ -146,14 +137,14 @@ void loop() {
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
// Joystick 1 UP
Serial.println("Joystick 1 UP");
gp.x = 0;
gp.y = -127;
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
// Joystick 1 DOWN
Serial.println("Joystick 1 DOWN");
gp.x = 0;
@ -167,7 +158,7 @@ void loop() {
gp.y = 0;
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
// Joystick 1 LEFT
Serial.println("Joystick 1 LEFT");
gp.x = -127;
@ -185,35 +176,35 @@ void loop() {
// Joystick 2 UP
Serial.println("Joystick 2 UP");
gp.z = 0;
gp.z = 0;
gp.rz = 127;
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
// Joystick 2 DOWN
Serial.println("Joystick 2 DOWN");
gp.z = 0;
gp.z = 0;
gp.rz = -127;
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
// Joystick 2 RIGHT
Serial.println("Joystick 2 RIGHT");
gp.z = 127;
gp.z = 127;
gp.rz = 0;
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
// Joystick 2 LEFT
Serial.println("Joystick 2 LEFT");
gp.z = -127;
gp.z = -127;
gp.rz = 0;
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
// Joystick 2 CENTER
Serial.println("Joystick 2 CENTER");
gp.z = 0;
gp.z = 0;
gp.rz = 0;
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
@ -224,7 +215,7 @@ void loop() {
gp.rx = 127;
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
// Analog Trigger 1 DOWN
Serial.println("Analog Trigger 1 DOWN");
gp.rx = -127;
@ -243,7 +234,7 @@ void loop() {
gp.ry = 127;
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
// Analog Trigger 2 DOWN
Serial.println("Analog Trigger 2 DOWN");
gp.ry = -127;
@ -256,11 +247,11 @@ void loop() {
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);
// Test buttons (up to 32 buttons)
for (int i = 0; i < 32; ++i) {
Serial.print("Pressing button ");
Serial.println(i);
for (int i=0; i<32; ++i)
{
Serial.print("Pressing button "); Serial.println(i);
gp.buttons = (1U << i);
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(1000);
@ -269,13 +260,13 @@ void loop() {
// Random touch
Serial.println("Random touch");
gp.x = random(-127, 128);
gp.y = random(-127, 128);
gp.z = random(-127, 128);
gp.rz = random(-127, 128);
gp.rx = random(-127, 128);
gp.ry = random(-127, 128);
gp.hat = random(0, 9);
gp.x = random(-127, 128);
gp.y = random(-127, 128);
gp.z = random(-127, 128);
gp.rz = random(-127, 128);
gp.rx = random(-127, 128);
gp.ry = random(-127, 128);
gp.hat = random(0, 9);
gp.buttons = random(0, 0xffff);
usb_hid.sendReport(0, &gp, sizeof(gp));
delay(2000);

View file

@ -1,2 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -39,51 +39,50 @@
// HID report descriptor using TinyUSB's template
// Generic In Out with 64 bytes report (max)
uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_GENERIC_INOUT(64)
uint8_t const desc_hid_report[] =
{
TUD_HID_REPORT_DESC_GENERIC_INOUT(64)
};
// USB HID object
Adafruit_USBD_HID usb_hid;
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, true);
// the setup function runs once when you press reset or power the board
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
void setup()
{
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
TinyUSB_Device_Init(0);
#endif
// Notes: following commented-out functions has no affect on ESP32
usb_hid.enableOutEndpoint(true);
usb_hid.setPollInterval(2);
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.setStringDescriptor("TinyUSB HID Generic");
// usb_hid.enableOutEndpoint(true);
// usb_hid.setPollInterval(2);
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
// usb_hid.setStringDescriptor("TinyUSB HID Generic");
usb_hid.setReportCallback(get_report_callback, set_report_callback);
usb_hid.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.begin(115200);
// wait until device mounted
while( !TinyUSBDevice.mounted() ) delay(1);
Serial.println("Adafruit TinyUSB HID Generic In Out example");
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
void loop()
{
// nothing to do
}
// Invoked when received GET_REPORT control request
// Application must fill buffer report's content and return its length.
// Return zero will cause the stack to STALL request
uint16_t get_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
uint16_t get_report_callback (uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
{
// not used in this example
(void) report_id;
(void) report_type;
@ -94,7 +93,8 @@ uint16_t get_report_callback(uint8_t report_id, hid_report_type_t report_type, u
// Invoked when received SET_REPORT control request or
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
void set_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
void set_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
{
// This example doesn't use multiple report and report ID
(void) report_id;
(void) report_type;

View file

@ -55,9 +55,6 @@ dev_info_t dev_info[CFG_TUH_DEVICE_MAX] = { 0 };
Adafruit_USBH_Host USBHost;
//--------------------------------------------------------------------+
// setup() & loop()
//--------------------------------------------------------------------+
void setup() {
Serial1.begin(115200);
Serial1.println("TinyUSB Host: Device Info Example");
@ -66,6 +63,7 @@ void setup() {
USBHost.begin(0);
}
//------------- Core0 -------------//
void loop() {
USBHost.task();
Serial1.flush();

View file

@ -1,2 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -19,43 +19,28 @@
// USB MIDI object with 3 ports
Adafruit_USBD_MIDI usb_midi(3);
void setup() {
#ifdef LED_BUILTIN
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
#endif
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
TinyUSB_Device_Init(0);
#endif
// Set name for each cable, must be done before usb_midi.begin()
usb_midi.setCableName(1, "Keyboard");
usb_midi.setCableName(2, "Drum Pads");
usb_midi.setCableName(3, "Lights");
usb_midi.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
void loop()
{
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
// toggle LED
static uint32_t ms = 0;
static uint8_t led_state = 0;
if (millis() - ms > 1000) {
ms = millis();
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, 1-led_state);
#endif
}
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}

View file

@ -1,2 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -31,74 +31,65 @@ uint32_t position = 0;
// Store example melody as an array of note values
byte note_sequence[] = {
74, 78, 81, 86, 90, 93, 98, 102, 57, 61, 66, 69, 73, 78, 81, 85, 88, 92, 97, 100, 97, 92, 88, 85, 81, 78,
74, 69, 66, 62, 57, 62, 66, 69, 74, 78, 81, 86, 90, 93, 97, 102, 97, 93, 90, 85, 81, 78, 73, 68, 64, 61,
56, 61, 64, 68, 74, 78, 81, 86, 90, 93, 98, 102
74,78,81,86,90,93,98,102,57,61,66,69,73,78,81,85,88,92,97,100,97,92,88,85,81,78,
74,69,66,62,57,62,66,69,74,78,81,86,90,93,97,102,97,93,90,85,81,78,73,68,64,61,
56,61,64,68,74,78,81,86,90,93,98,102
};
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
void setup()
{
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
TinyUSB_Device_Init(0);
#endif
Serial.begin(115200);
usb_midi.setStringDescriptor("TinyUSB MIDI");
pinMode(LED_BUILTIN, OUTPUT);
//usb_midi.setStringDescriptor("TinyUSB MIDI");
// Initialize MIDI, and listen to all MIDI channels
// This will also call usb_midi's begin()
MIDI.begin(MIDI_CHANNEL_OMNI);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// Attach the handleNoteOn function to the MIDI Library. It will
// be called whenever the Bluefruit receives MIDI Note On messages.
MIDI.setHandleNoteOn(handleNoteOn);
// Do the same for MIDI Note Off messages.
MIDI.setHandleNoteOff(handleNoteOff);
Serial.begin(115200);
// wait until device mounted
while( !TinyUSBDevice.mounted() ) delay(1);
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
// not enumerated()/mounted() yet: nothing to do
if (!TinyUSBDevice.mounted()) {
return;
}
void loop()
{
static uint32_t start_ms = 0;
if (millis() - start_ms > 266) {
if ( millis() - start_ms > 266 )
{
start_ms += 266;
// Setup variables for the current and previous
// positions in the note sequence.
int previous = position - 1;
// If we currently are at position 0, set the
// previous position to the last note in the sequence.
if (previous < 0) {
previous = sizeof(note_sequence) - 1;
}
// Send Note On for current position at full velocity (127) on channel 1.
MIDI.sendNoteOn(note_sequence[position], 127, 1);
// Send Note Off for previous note.
MIDI.sendNoteOff(note_sequence[previous], 0, 1);
// Increment position
position++;
// If we are at the end of the sequence, start over.
if (position >= sizeof(note_sequence)) {
position = 0;
@ -106,10 +97,11 @@ void loop() {
}
// read any new MIDI messages
MIDI.read();
MIDI.read();
}
void handleNoteOn(byte channel, byte pitch, byte velocity) {
void handleNoteOn(byte channel, byte pitch, byte velocity)
{
// Log when a note is pressed.
Serial.print("Note on: channel = ");
Serial.print(channel);
@ -121,7 +113,8 @@ void handleNoteOn(byte channel, byte pitch, byte velocity) {
Serial.println(velocity);
}
void handleNoteOff(byte channel, byte pitch, byte velocity) {
void handleNoteOff(byte channel, byte pitch, byte velocity)
{
// Log when a note is released.
Serial.print("Note off: channel = ");
Serial.print(channel);

View file

@ -32,7 +32,7 @@
*/
#include "SPI.h"
#include "SdFat_Adafruit_Fork.h"
#include "SdFat.h"
#include "Adafruit_SPIFlash.h"
#include "Adafruit_TinyUSB.h"
@ -93,19 +93,14 @@ void setupMassStorage(void)
// MSC is ready for read/write
fs_changed = false;
usb_msc.setReadyCallback(0, msc_ready_callback);
usb_msc.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
usb_msc.begin();
// Init file system on the flash
fs_formatted = fatfs.begin(&flash);
if ( !fs_formatted ) {
if ( !fs_formatted )
{
DBG_SERIAL.println("Failed to init files system, flash may not be formatted");
}
}

View file

@ -1,3 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -23,7 +23,7 @@
*/
#include "SPI.h"
#include "SdFat_Adafruit_Fork.h"
#include "SdFat.h"
#include "Adafruit_SPIFlash.h"
#include "Adafruit_TinyUSB.h"
@ -48,12 +48,9 @@ bool fs_formatted = false;
bool fs_changed = true;;
// the setup function runs once when you press reset or power the board
void setup() {
#ifdef LED_BUILTIN
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
#endif
Serial.begin(115200);
flash.begin();
@ -71,16 +68,10 @@ void setup() {
usb_msc.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// Init file system on the flash
fs_formatted = fatfs.begin(&flash);
Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mass Storage External Flash example");
@ -88,12 +79,15 @@ void setup() {
Serial.print("Flash size: "); Serial.print(flash.size() / 1024); Serial.println(" KB");
}
void loop() {
void loop()
{
// check if formatted
if ( !fs_formatted ) {
if ( !fs_formatted )
{
fs_formatted = fatfs.begin(&flash);
if (!fs_formatted) {
if (!fs_formatted)
{
Serial.println("Failed to init files system, flash may not be formatted");
Serial.println("Please format it as FAT12 with your PC or using Adafruit_SPIFlash's SdFat_format example:");
Serial.println("- https://github.com/adafruit/Adafruit_SPIFlash/tree/master/examples/SdFat_format");
@ -104,12 +98,14 @@ void loop() {
}
}
if ( fs_changed ) {
if ( fs_changed )
{
fs_changed = false;
Serial.println("Opening root");
if ( !root.open("/") ) {
if ( !root.open("/") )
{
Serial.println("open root failed");
return;
}
@ -119,11 +115,13 @@ void loop() {
// Open next file in root.
// Warning, openNext starts at the current directory position
// so a rewind of the directory may be required.
while ( file.openNext(&root, O_RDONLY) ) {
while ( file.openNext(&root, O_RDONLY) )
{
file.printFileSize(&Serial);
Serial.write(' ');
file.printName(&Serial);
if ( file.isDir() ) {
if ( file.isDir() )
{
// Indicate a directory.
Serial.write('/');
}
@ -141,7 +139,8 @@ void loop() {
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) {
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
// Note: SPIFLash Block API: readBlocks/writeBlocks/syncBlocks
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
return flash.readBlocks(lba, (uint8_t*) buffer, bufsize/512) ? bufsize : -1;
@ -150,10 +149,9 @@ int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) {
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
#ifdef LED_BUILTIN
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
digitalWrite(LED_BUILTIN, HIGH);
#endif
// Note: SPIFLash Block API: readBlocks/writeBlocks/syncBlocks
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
@ -162,7 +160,8 @@ int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void msc_flush_cb (void) {
void msc_flush_cb (void)
{
// sync with flash
flash.syncBlocks();
@ -171,7 +170,5 @@ void msc_flush_cb (void) {
fs_changed = true;
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, LOW);
#endif
}

View file

@ -1,3 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -23,7 +23,7 @@
*/
#include "SPI.h"
#include "SdFat_Adafruit_Fork.h"
#include "SdFat.h"
#include "Adafruit_SPIFlash.h"
#include "Adafruit_TinyUSB.h"
@ -33,67 +33,42 @@
// for flashTransport definition
#include "flash_config.h"
Adafruit_SPIFlash flash(&flashTransport);
// External Flash File system
FatVolume fatfs;
//--------------------------------------------------------------------+
// SDCard Config
//--------------------------------------------------------------------+
#if defined(ARDUINO_PYPORTAL_M4) || defined(ARDUINO_PYPORTAL_M4_TITANO)
// PyPortal has on-board card reader
#define SDCARD_CS 32
#define SDCARD_DETECT 33
#define SDCARD_DETECT_ACTIVE HIGH
#elif defined(ARDUINO_ADAFRUIT_METRO_RP2040)
#define SDIO_CLK_PIN 18
#define SDIO_CMD_PIN 19 // MOSI
#define SDIO_DAT0_PIN 20 // DAT1: 21, DAT2: 22, DAT3: 23
#define SDCARD_DETECT 15
#define SDCARD_DETECT_ACTIVE LOW
#elif defined(ARDUINO_ADAFRUIT_METRO_RP2350)
// Note: not working yet (need troubleshoot later)
#define SDIO_CLK_PIN 34
#define SDIO_CMD_PIN 35 // MOSI
#define SDIO_DAT0_PIN 36 // DAT1: 37, DAT2: 38, DAT3: 39
#define SDCARD_DETECT 40
#define SDCARD_DETECT_ACTIVE LOW
#elif defined(ARDUINO_ADAFRUIT_FRUITJAM_RP2350)
#define SDIO_CLK_PIN 34
#define SDIO_CMD_PIN 35 // MOSI
#define SDIO_DAT0_PIN 36 // DAT1: 37, DAT2: 38, DAT3: 39
#define SDCARD_DETECT 33
#define SDCARD_DETECT_ACTIVE LOW
#define SDCARD_CS 32
#define SDCARD_DETECT 33
#else
// Use SPI, no detect
#define SDCARD_CS 10
// no detect
#endif
#if defined(SDIO_CLK_PIN) && defined(SDIO_CMD_PIN) && defined(SDIO_DAT0_PIN)
#define SD_CONFIG SdioConfig(SDIO_CLK_PIN, SDIO_CMD_PIN, SDIO_DAT0_PIN)
#else
#define SD_CONFIG SdSpiConfig(SDCARD_CS, SHARED_SPI, SD_SCK_MHZ(50))
#endif
// File system on SD Card
// SDCard File system
SdFat sd;
// USB Mass Storage object
Adafruit_USBD_MSC usb_msc;
// Set to true when PC write to flash
bool sd_changed = false;
bool sd_inited = false;
bool flash_formatted = false;
bool flash_changed = false;
// the setup function runs once when you press reset or power the board
void setup() {
#ifdef LED_BUILTIN
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
#endif
Serial.begin(115200);
// MSC with 2 Logical Units: LUN0: External Flash, LUN1: SDCard
@ -108,20 +83,16 @@ void setup() {
// LUN readiness will always be set later on
usb_msc.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
//------------- Lun 0 for external flash -------------//
flash.begin();
flash_formatted = fatfs.begin(&flash);
usb_msc.setCapacity(0, flash.size()/512, 512);
usb_msc.setReadWriteCallback(0, external_flash_read_cb, external_flash_write_cb, external_flash_flush_cb);
usb_msc.setUnitReady(0, true);
flash_changed = true; // to print contents initially
//------------- Lun 1 for SD card -------------//
#ifdef SDCARD_DETECT
// DETECT pin is available, detect card present on the fly with test unit ready
@ -134,44 +105,58 @@ void setup() {
usb_msc.setUnitReady(1, true);
#endif
// while ( !Serial ) delay(10); // wait for native usb
// while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mass Storage External Flash + SD Card example");
delay(1000);
}
bool init_sdcard(void) {
bool init_sdcard(void)
{
Serial.print("Init SDCard ... ");
if (!sd.begin(SD_CONFIG)) {
Serial.println("initialization failed. Things to check:");
Serial.println("- is a card inserted?");
Serial.println("- is your wiring correct?");
Serial.println("- did you change the SDCARD_CS or SDIO pin to match your shield or module?");
if ( !sd.begin(SDCARD_CS, SD_SCK_MHZ(50)) )
{
Serial.print("Failed ");
sd.errorPrint("sd.begin() failed");
return false;
}
uint32_t block_count = sd.card()->sectorCount();
uint32_t block_count;
#if SD_FAT_VERSION >= 20000
block_count = sd.card()->sectorCount();
#else
block_count = sd.card()->cardSize();
#endif
usb_msc.setCapacity(1, block_count, 512);
usb_msc.setReadWriteCallback(1, sdcard_read_cb, sdcard_write_cb, sdcard_flush_cb);
sd_changed = true; // to print contents initially
Serial.print("OK, Card size = ");
Serial.print((block_count / (1024 * 1024)) * 512);
Serial.print((block_count / (1024*1024)) * 512);
Serial.println(" MB");
return true;
}
void print_rootdir(File32* rdir) {
void print_rootdir(File32* rdir)
{
File32 file;
// Open next file in root.
// Warning, openNext starts at the current directory position
// so a rewind of the directory may be required.
while (file.openNext(rdir, O_RDONLY)) {
while ( file.openNext(rdir, O_RDONLY) )
{
file.printFileSize(&Serial);
Serial.write(' ');
file.printName(&Serial);
if (file.isDir()) {
if ( file.isDir() )
{
// Indicate a directory.
Serial.write('/');
}
@ -180,8 +165,46 @@ void print_rootdir(File32* rdir) {
}
}
void loop() {
// nothing to do
void loop()
{
if ( flash_changed )
{
if (!flash_formatted)
{
flash_formatted = fatfs.begin(&flash);
}
// skip if still not formatted
if (flash_formatted)
{
File32 root;
root = fatfs.open("/");
Serial.println("Flash contents:");
print_rootdir(&root);
Serial.println();
root.close();
}
flash_changed = false;
}
if ( sd_changed )
{
File32 root;
root = sd.open("/");
Serial.println("SD contents:");
print_rootdir(&root);
Serial.println();
root.close();
sd_changed = false;
}
delay(1000); // refresh every 1 second
}
@ -189,48 +212,76 @@ void loop() {
// SD Card callbacks
//--------------------------------------------------------------------+
int32_t sdcard_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) {
bool rc = sd.card()->readSectors(lba, (uint8_t*) buffer, bufsize/512);
int32_t sdcard_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
bool rc;
#if SD_FAT_VERSION >= 20000
rc = sd.card()->readSectors(lba, (uint8_t*) buffer, bufsize/512);
#else
rc = sd.card()->readBlocks(lba, (uint8_t*) buffer, bufsize/512);
#endif
return rc ? bufsize : -1;
}
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t sdcard_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
#ifdef LED_BUILTIN
int32_t sdcard_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
bool rc;
digitalWrite(LED_BUILTIN, HIGH);
#if SD_FAT_VERSION >= 20000
rc = sd.card()->writeSectors(lba, buffer, bufsize/512);
#else
rc = sd.card()->writeBlocks(lba, buffer, bufsize/512);
#endif
bool rc = sd.card()->writeSectors(lba, buffer, bufsize/512);
return rc ? bufsize : -1;
}
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void sdcard_flush_cb (void) {
void sdcard_flush_cb (void)
{
#if SD_FAT_VERSION >= 20000
sd.card()->syncDevice();
sd.cacheClear(); // clear file system's cache to force refresh
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, LOW);
#else
sd.card()->syncBlocks();
#endif
// clear file system's cache to force refresh
sd.cacheClear();
sd_changed = true;
digitalWrite(LED_BUILTIN, LOW);
}
#ifdef SDCARD_DETECT
// Invoked when received Test Unit Ready command.
// return true allowing host to read/write this LUN e.g SD card inserted
bool sdcard_ready_callback(void) {
bool sdcard_ready_callback(void)
{
// Card is inserted
if (digitalRead(SDCARD_DETECT) == SDCARD_DETECT_ACTIVE) {
if ( digitalRead(SDCARD_DETECT) == HIGH )
{
// init SD card if not already
if (!sd_inited) {
if ( !sd_inited )
{
sd_inited = init_sdcard();
}
} else {
}else
{
sd_inited = false;
usb_msc.setReadWriteCallback(1, NULL, NULL, NULL);
}
Serial.println(sd_inited);
return sd_inited;
}
#endif
@ -242,7 +293,8 @@ bool sdcard_ready_callback(void) {
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t external_flash_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) {
int32_t external_flash_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
// Note: SPIFLash Bock API: readBlocks/writeBlocks/syncBlocks
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
return flash.readBlocks(lba, (uint8_t*) buffer, bufsize/512) ? bufsize : -1;
@ -251,10 +303,9 @@ int32_t external_flash_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) {
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t external_flash_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
#ifdef LED_BUILTIN
int32_t external_flash_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
digitalWrite(LED_BUILTIN, HIGH);
#endif
// Note: SPIFLash Bock API: readBlocks/writeBlocks/syncBlocks
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
@ -263,9 +314,14 @@ int32_t external_flash_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void external_flash_flush_cb (void) {
void external_flash_flush_cb (void)
{
flash.syncBlocks();
#ifdef LED_BUILTIN
// clear file system's cache to force refresh
fatfs.cacheClear();
flash_changed = true;
digitalWrite(LED_BUILTIN, LOW);
#endif
}

View file

@ -10,7 +10,7 @@
*********************************************************************/
#include "SPI.h"
#include "SdFat_Adafruit_Fork.h"
#include "SdFat.h"
#include "Adafruit_InternalFlash.h"
#include "Adafruit_TinyUSB.h"
@ -35,9 +35,8 @@ Adafruit_USBD_MSC usb_msc;
bool fs_changed;
// the setup function runs once when you press reset or power the board
void setup() {
Serial.begin(115200);
void setup()
{
// Initialize internal flash
flash.begin();
@ -47,30 +46,32 @@ void setup() {
// Set callback
usb_msc.setReadWriteCallback(msc_read_callback, msc_write_callback, msc_flush_callback);
usb_msc.setWritableCallback(msc_writable_callback);
usb_msc.setCapacity(flash.size()/512, 512); // Set disk size, block size should be 512 regardless of flash page size
usb_msc.setUnitReady(true); // Set Lun ready
usb_msc.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// Set disk size, block size should be 512 regardless of flash page size
usb_msc.setCapacity(flash.size()/512, 512);
// Set Lun ready
usb_msc.setUnitReady(true);
usb_msc.begin();
// Init file system on the flash
fatfs.begin(&flash);
Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb
fs_changed = true; // to print contents initially
}
void loop() {
if ( fs_changed ) {
void loop()
{
if ( fs_changed )
{
fs_changed = false;
if ( !root.open("/") ) {
if ( !root.open("/") )
{
Serial.println("open root failed");
return;
}
@ -80,11 +81,13 @@ void loop() {
// Open next file in root.
// Warning, openNext starts at the current directory position
// so a rewind of the directory may be required.
while ( file.openNext(&root, O_RDONLY) ) {
while ( file.openNext(&root, O_RDONLY) )
{
file.printFileSize(&Serial);
Serial.write(' ');
file.printName(&Serial);
if ( file.isDir() ) {
if ( file.isDir() )
{
// Indicate a directory.
Serial.write('/');
}
@ -102,7 +105,8 @@ void loop() {
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t msc_read_callback (uint32_t lba, void* buffer, uint32_t bufsize) {
int32_t msc_read_callback (uint32_t lba, void* buffer, uint32_t bufsize)
{
// Note: InternalFlash Block API: readBlocks/writeBlocks/syncBlocks
// already include sector caching (if needed). We don't need to cache it, yahhhh!!
return flash.readBlocks(lba, (uint8_t*) buffer, bufsize/512) ? bufsize : -1;
@ -111,7 +115,8 @@ int32_t msc_read_callback (uint32_t lba, void* buffer, uint32_t bufsize) {
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t msc_write_callback (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
int32_t msc_write_callback (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
// Note: InternalFlash Block API: readBlocks/writeBlocks/syncBlocks
// already include sector caching (if needed). We don't need to cache it, yahhhh!!
return flash.writeBlocks(lba, buffer, bufsize/512) ? bufsize : -1;
@ -119,7 +124,8 @@ int32_t msc_write_callback (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void msc_flush_callback (void) {
void msc_flush_callback (void)
{
// sync with flash
flash.syncBlocks();
@ -131,7 +137,8 @@ void msc_flush_callback (void) {
// Invoked to check if device is writable as part of SCSI WRITE10
// Default mode is writable
bool msc_writable_callback(void) {
bool msc_writable_callback(void)
{
// true for writable, false for read-only
return true;
}

View file

@ -1,2 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -14,7 +14,6 @@
// 8KB is the smallest size that windows allow to mount
#define DISK_BLOCK_NUM 16
#define DISK_BLOCK_SIZE 512
#include "ramdisk.h"
Adafruit_USBD_MSC usb_msc;
@ -37,15 +36,10 @@ Adafruit_USBD_MSC usb_msc;
// the setup function runs once when you press reset or power the board
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
#ifdef BTN_EJECT
pinMode(BTN_EJECT, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
// Manual begin() is required on core without built-in support for TinyUSB such as
// - mbed rp2040
TinyUSB_Device_Init(0);
#endif
// Set disk vendor id, product id and revision with string up to 8, 16, 4 characters respectively
@ -56,35 +50,33 @@ void setup() {
// Set callback
usb_msc.setReadWriteCallback(msc_read_callback, msc_write_callback, msc_flush_callback);
usb_msc.setStartStopCallback(msc_start_stop_callback);
usb_msc.setReadyCallback(msc_ready_callback);
// Set Lun ready (RAM disk is always ready)
usb_msc.setUnitReady(true);
#ifdef BTN_EJECT
pinMode(BTN_EJECT, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
usb_msc.setReadyCallback(msc_ready_callback);
#endif
usb_msc.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb
// while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mass Storage RAM Disk example");
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
void loop()
{
// nothing to do
}
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t msc_read_callback(uint32_t lba, void* buffer, uint32_t bufsize) {
int32_t msc_read_callback (uint32_t lba, void* buffer, uint32_t bufsize)
{
uint8_t const* addr = msc_disk[lba];
memcpy(buffer, addr, bufsize);
@ -94,7 +86,8 @@ int32_t msc_read_callback(uint32_t lba, void* buffer, uint32_t bufsize) {
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t msc_write_callback(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
int32_t msc_write_callback (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
uint8_t* addr = msc_disk[lba];
memcpy(addr, buffer, bufsize);
@ -103,22 +96,18 @@ int32_t msc_write_callback(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void msc_flush_callback(void) {
void msc_flush_callback (void)
{
// nothing to do
}
bool msc_start_stop_callback(uint8_t power_condition, bool start, bool load_eject) {
Serial.printf("Start/Stop callback: power condition %u, start %u, load_eject %u\n", power_condition, start, load_eject);
return true;
}
#ifdef BTN_EJECT
// Invoked when received Test Unit Ready command.
// return true allowing host to read/write this LUN e.g SD card inserted
bool msc_ready_callback(void) {
#ifdef BTN_EJECT
bool msc_ready_callback(void)
{
// button not active --> medium ready
return digitalRead(BTN_EJECT) != activeState;
#else
return true;
#endif
}
#endif

View file

@ -1,3 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -14,22 +14,20 @@
// 8KB is the smallest size that windows allow to mount
#define DISK_BLOCK_NUM 16
#define DISK_BLOCK_SIZE 512
#include "ramdisk.h"
Adafruit_USBD_MSC usb_msc;
// the setup function runs once when you press reset or power the board
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
void setup()
{
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
TinyUSB_Device_Init(0);
#endif
usb_msc.setMaxLun(2);
// Set disk size and callback for Logical Unit 0 (LUN 0)
usb_msc.setID(0, "Adafruit", "Lun0", "1.0");
usb_msc.setCapacity(0, DISK_BLOCK_NUM, DISK_BLOCK_SIZE);
@ -41,25 +39,18 @@ void setup() {
usb_msc.setCapacity(1, DISK_BLOCK_NUM, DISK_BLOCK_SIZE);
usb_msc.setReadWriteCallback(1, ram1_read_cb, ram1_write_cb, ram1_flush_cb);
usb_msc.setUnitReady(1, true);
usb_msc.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mass Storage Dual RAM Disks example");
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
void loop()
{
// nothing to do
}
@ -70,7 +61,8 @@ void loop() {
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t ram0_read_cb(uint32_t lba, void* buffer, uint32_t bufsize) {
int32_t ram0_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
uint8_t const* addr = msc_disk0[lba];
memcpy(buffer, addr, bufsize);
@ -80,7 +72,8 @@ int32_t ram0_read_cb(uint32_t lba, void* buffer, uint32_t bufsize) {
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t ram0_write_cb(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
int32_t ram0_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
uint8_t* addr = msc_disk0[lba];
memcpy(addr, buffer, bufsize);
@ -89,7 +82,8 @@ int32_t ram0_write_cb(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void ram0_flush_cb(void) {
void ram0_flush_cb (void)
{
// nothing to do
}
@ -101,7 +95,8 @@ void ram0_flush_cb(void) {
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t ram1_read_cb(uint32_t lba, void* buffer, uint32_t bufsize) {
int32_t ram1_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
uint8_t const* addr = msc_disk1[lba];
memcpy(buffer, addr, bufsize);
@ -111,7 +106,8 @@ int32_t ram1_read_cb(uint32_t lba, void* buffer, uint32_t bufsize) {
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t ram1_write_cb(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
int32_t ram1_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
uint8_t* addr = msc_disk1[lba];
memcpy(addr, buffer, bufsize);
@ -120,6 +116,7 @@ int32_t ram1_write_cb(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void ram1_flush_cb(void) {
void ram1_flush_cb (void)
{
// nothing to do
}

View file

@ -1,10 +0,0 @@
feather_esp32_v2
feather_esp32s2
feather_esp32s3
funhouse
magtag
metroesp32s2
esp32p4
feather_rp2040_tinyusb
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -26,8 +26,6 @@ SdVolume volume;
// the setup function runs once when you press reset or power the board
void setup()
{
Serial.begin(115200);
// Set disk vendor id, product id and revision with string up to 8, 16, 4 characters respectively
usb_msc.setID("Adafruit", "SD Card", "1.0");
@ -39,18 +37,15 @@ void setup()
usb_msc.setUnitReady(false);
usb_msc.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mass Storage SD Card example");
Serial.println("\nInitializing SD card...");
if ( !card.init(SPI_HALF_SPEED, chipSelect) ) {
if ( !card.init(SPI_HALF_SPEED, chipSelect) )
{
Serial.println("initialization failed. Things to check:");
Serial.println("* is a card inserted?");
Serial.println("* is your wiring correct?");
@ -76,14 +71,16 @@ void setup()
usb_msc.setUnitReady(true);
}
void loop() {
void loop()
{
// nothing to do
}
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) {
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
(void) bufsize;
return card.readBlock(lba, (uint8_t*) buffer) ? 512 : -1;
}
@ -91,13 +88,15 @@ int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) {
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
(void) bufsize;
return card.writeBlock(lba, buffer) ? 512 : -1;
}
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void msc_flush_cb (void) {
void msc_flush_cb (void)
{
// nothing to do
}

View file

@ -1,2 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -10,69 +10,31 @@
*********************************************************************/
/* This example expose SD card as mass storage using
* - SdFat https://github.com/adafruit/SdFat
* SdFat Library
*/
#include "SPI.h"
#include "SdFat_Adafruit_Fork.h"
#include "SdFat.h"
#include "Adafruit_TinyUSB.h"
//--------------------------------------------------------------------+
// SDCard Config
//--------------------------------------------------------------------+
#if defined(ARDUINO_PYPORTAL_M4) || defined(ARDUINO_PYPORTAL_M4_TITANO)
// PyPortal has on-board card reader
#define SDCARD_CS 32
#define SDCARD_DETECT 33
#define SDCARD_DETECT_ACTIVE HIGH
#elif defined(ARDUINO_ADAFRUIT_METRO_RP2040)
#define SDIO_CLK_PIN 18
#define SDIO_CMD_PIN 19 // MOSI
#define SDIO_DAT0_PIN 20 // DAT1: 21, DAT2: 22, DAT3: 23
#define SDCARD_DETECT 15
#define SDCARD_DETECT_ACTIVE LOW
#elif defined(ARDUINO_ADAFRUIT_METRO_RP2350)
#define SDIO_CLK_PIN 34
#define SDIO_CMD_PIN 35 // MOSI
#define SDIO_DAT0_PIN 36 // DAT1: 37, DAT2: 38, DAT3: 39
#define SDCARD_DETECT 40
#define SDCARD_DETECT_ACTIVE LOW
#elif defined(ARDUINO_ADAFRUIT_FRUITJAM_RP2350)
#define SDIO_CLK_PIN 34
#define SDIO_CMD_PIN 35 // MOSI
#define SDIO_DAT0_PIN 36 // DAT1: 37, DAT2: 38, DAT3: 39
#define SDCARD_DETECT 33
#define SDCARD_DETECT_ACTIVE LOW
#else
// Use SPI, no detect
#define SDCARD_CS 10
#endif
#if defined(SDIO_CLK_PIN) && defined(SDIO_CMD_PIN) && defined(SDIO_DAT0_PIN)
#define SD_CONFIG SdioConfig(SDIO_CLK_PIN, SDIO_CMD_PIN, SDIO_DAT0_PIN)
#else
#define SD_CONFIG SdSpiConfig(SDCARD_CS, SHARED_SPI, SD_SCK_MHZ(50))
#endif
const int chipSelect = 10;
// File system on SD Card
SdFat sd;
SdFile root;
SdFile file;
// USB Mass Storage object
Adafruit_USBD_MSC usb_msc;
// Set to true when PC write to flash
bool fs_changed;
// the setup function runs once when you press reset or power the board
void setup() {
#ifdef LED_BUILTIN
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
#endif
Serial.begin(115200);
// Set disk vendor id, product id and revision with string up to 8, 16, 4 characters respectively
usb_msc.setID("Adafruit", "SD Card", "1.0");
@ -85,27 +47,30 @@ void setup() {
usb_msc.setUnitReady(false);
usb_msc.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mass Storage SD Card example");
Serial.print("\nInitializing SD card ... ");
if (!sd.begin(SD_CONFIG)) {
Serial.println("Adafruit TinyUSB Mass Storage SD Card example");
Serial.print("\nInitializing SD card ... ");
Serial.print("CS = "); Serial.println(chipSelect);
if ( !sd.begin(chipSelect, SD_SCK_MHZ(50)) )
{
Serial.println("initialization failed. Things to check:");
Serial.println("- is a card inserted?");
Serial.println("- is your wiring correct?");
Serial.println("- did you change the SDCARD_CS or SDIO pin to match your shield or module?");
Serial.println("* is a card inserted?");
Serial.println("* is your wiring correct?");
Serial.println("* did you change the chipSelect pin to match your shield or module?");
while (1) delay(1);
}
// Size in blocks (512 bytes)
#if SD_FAT_VERSION >= 20000
uint32_t block_count = sd.card()->sectorCount();
#else
uint32_t block_count = sd.card()->cardSize();
#endif
Serial.print("Volume size (MB): ");
Serial.println((block_count/2) / 1024);
@ -114,38 +79,91 @@ void setup() {
// MSC is ready for read/write
usb_msc.setUnitReady(true);
fs_changed = true; // to print contents initially
}
void loop() {
// noting to do
void loop()
{
if ( fs_changed )
{
root.open("/");
Serial.println("SD contents:");
// Open next file in root.
// Warning, openNext starts at the current directory position
// so a rewind of the directory may be required.
while ( file.openNext(&root, O_RDONLY) )
{
file.printFileSize(&Serial);
Serial.write(' ');
file.printName(&Serial);
if ( file.isDir() )
{
// Indicate a directory.
Serial.write('/');
}
Serial.println();
file.close();
}
root.close();
Serial.println();
fs_changed = false;
delay(1000); // refresh every 0.5 second
}
}
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) {
bool rc = sd.card()->readSectors(lba, (uint8_t*) buffer, bufsize/512);
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
bool rc;
#if SD_FAT_VERSION >= 20000
rc = sd.card()->readSectors(lba, (uint8_t*) buffer, bufsize/512);
#else
rc = sd.card()->readBlocks(lba, (uint8_t*) buffer, bufsize/512);
#endif
return rc ? bufsize : -1;
}
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
#ifdef LED_BUILTIN
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
bool rc;
digitalWrite(LED_BUILTIN, HIGH);
#if SD_FAT_VERSION >= 20000
rc = sd.card()->writeSectors(lba, buffer, bufsize/512);
#else
rc = sd.card()->writeBlocks(lba, buffer, bufsize/512);
#endif
bool rc = sd.card()->writeSectors(lba, buffer, bufsize/512);
return rc ? bufsize : -1;
}
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void msc_flush_cb (void) {
void msc_flush_cb (void)
{
#if SD_FAT_VERSION >= 20000
sd.card()->syncDevice();
sd.cacheClear(); // clear file system's cache to force refresh
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, LOW);
#else
sd.card()->syncBlocks();
#endif
// clear file system's cache to force refresh
sd.cacheClear();
fs_changed = true;
digitalWrite(LED_BUILTIN, LOW);
}

View file

@ -1,3 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -64,29 +64,15 @@ Adafruit_USBD_I2C::Adafruit_USBD_I2C(TwoWire* wire) {
setStringDescriptor("I2C Interface");
}
uint16_t Adafruit_USBD_I2C::getInterfaceDescriptor(uint8_t itfnum_deprecated, uint8_t* buf, uint16_t bufsize) {
uint8_t itfnum = 0;
uint8_t ep_in = 0;
uint8_t ep_out = 0;
(void) itfnum_deprecated;
// null buffer is used to get the length of descriptor only
if (buf) {
itfnum = TinyUSBDevice.allocInterface(1);
ep_in = TinyUSBDevice.allocEndpoint(TUSB_DIR_IN);
ep_out = TinyUSBDevice.allocEndpoint(TUSB_DIR_OUT);
}
uint8_t const desc[] = { TUD_VENDOR_DESCRIPTOR(itfnum, _strid, ep_out, ep_in, 64) };
uint16_t Adafruit_USBD_I2C::getInterfaceDescriptor(uint8_t itfnum, uint8_t* buf, uint16_t bufsize) {
uint8_t desc[] = { TUD_VENDOR_DESCRIPTOR(itfnum, 0, 0x00, 0x80, 64) };
uint16_t const len = sizeof(desc);
if (buf) {
if (bufsize < len) {
return 0;
}
memcpy(buf, desc, len);
}
return len;
}

View file

@ -88,13 +88,11 @@
class Adafruit_USBD_I2C : public Adafruit_USBD_Interface {
public:
Adafruit_USBD_I2C(TwoWire* wire);
uint16_t getInterfaceDescriptor(uint8_t itfnum, uint8_t* buf, uint16_t bufsize);
bool begin(uint8_t* buffer, size_t bufsize);
bool handleControlTransfer(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request);
// from Adafruit_USBD_Interface
virtual uint16_t getInterfaceDescriptor(uint8_t itfnum, uint8_t* buf, uint16_t bufsize);
private:
TwoWire* _wire;
uint8_t _state;

View file

@ -63,13 +63,6 @@ void setup() {
// init i2c usb with buffer and size
i2c_usb.begin(i2c_buf, sizeof(i2c_buf));
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
}
void loop() {

View file

@ -1,3 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -1,237 +0,0 @@
/*********************************************************************
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
*********************************************************************/
#include "Adafruit_TinyUSB.h"
//--------------------------------------------------------------------+
// Video descriptors
//--------------------------------------------------------------------+
/* Time stamp base clock. It is a deprecated parameter. */
#define FRAME_WIDTH 128
#define FRAME_HEIGHT 96
#define FRAME_RATE 30
/* video capture path
*
* | Camera Terminal (0x01) | ----> | Output Terminal (0x02 Streaming) |
* */
#define TERMID_CAMERA 0x01
#define TERMID_OUTPUT 0x02
tusb_desc_video_control_camera_terminal_t const desc_camera_terminal = {
.bLength = sizeof(tusb_desc_video_control_camera_terminal_t),
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
.bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL,
.bTerminalID = TERMID_CAMERA,
.wTerminalType = VIDEO_ITT_CAMERA,
.bAssocTerminal = 0,
.iTerminal = 0,
.wObjectiveFocalLengthMin = 0,
.wObjectiveFocalLengthMax = 0,
.wOcularFocalLength = 0,
.bControlSize = 3,
.bmControls = { 0, 0, 0 }
};
tusb_desc_video_control_output_terminal_t const desc_output_terminal = {
.bLength = sizeof(tusb_desc_video_control_output_terminal_t),
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
.bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL,
.bTerminalID = TERMID_OUTPUT,
.wTerminalType = VIDEO_TT_STREAMING,
.bAssocTerminal = 0,
.bSourceID = TERMID_CAMERA,
.iTerminal = 0
};
tusb_desc_video_format_uncompressed_t const desc_format = {
.bLength = sizeof(tusb_desc_video_format_uncompressed_t),
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
.bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED,
.bFormatIndex = 1, // 1-based index
.bNumFrameDescriptors = 1,
.guidFormat = { TUD_VIDEO_GUID_YUY2 },
.bBitsPerPixel = 16,
.bDefaultFrameIndex = 1,
.bAspectRatioX = 0,
.bAspectRatioY = 0,
.bmInterlaceFlags = 0,
.bCopyProtect = 0
};
tusb_desc_video_frame_uncompressed_continuous_t desc_frame = {
.bLength = sizeof(tusb_desc_video_frame_uncompressed_continuous_t),
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
.bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED,
.bFrameIndex = 1, // 1-based index
.bmCapabilities = 0,
.wWidth = FRAME_WIDTH,
.wHeight = FRAME_HEIGHT,
.dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1,
.dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE,
.dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8,
.dwDefaultFrameInterval = 10000000 / FRAME_RATE,
.bFrameIntervalType = 0, // continuous
.dwFrameInterval = {
10000000 / FRAME_RATE, // min
10000000, // max
10000000 / FRAME_RATE // step
}
};
tusb_desc_video_streaming_color_matching_t desc_color = {
.bLength = sizeof(tusb_desc_video_streaming_color_matching_t),
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
.bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT,
.bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709,
.bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709,
.bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M
};
//--------------------------------------------------------------------+
// Video and frame buffer
//--------------------------------------------------------------------+
Adafruit_USBD_Video usb_video;
// YUY2 frame buffer
static uint8_t frame_buffer[FRAME_WIDTH * FRAME_HEIGHT * 16 / 8];
static unsigned frame_num = 0;
static unsigned tx_busy = 0;
static unsigned interval_ms = 1000 / FRAME_RATE;
static unsigned start_ms = 0;
static unsigned already_sent = 0;
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+
static void fill_color_bar(uint8_t* buffer, unsigned start_position);
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
usb_video.addTerminal(&desc_camera_terminal);
usb_video.addTerminal(&desc_output_terminal);
usb_video.addFormat(&desc_format);
usb_video.addFrame(&desc_frame);
usb_video.addColorMatching(&desc_color);
usb_video.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
if (!tud_video_n_streaming(0, 0)) {
already_sent = 0;
frame_num = 0;
return;
}
if (!already_sent) {
already_sent = 1;
tx_busy = 1;
start_ms = millis();
fill_color_bar(frame_buffer, frame_num);
tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8);
}
unsigned cur = millis();
if (cur - start_ms < interval_ms) return; // not enough time
if (tx_busy) return;
start_ms += interval_ms;
tx_busy = 1;
fill_color_bar(frame_buffer, frame_num);
tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8);
}
//--------------------------------------------------------------------+
// TinyUSB Video Callbacks
//--------------------------------------------------------------------+
extern "C" {
void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) {
(void) ctl_idx;
(void) stm_idx;
tx_busy = 0;
/* flip buffer */
++frame_num;
}
int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx,
video_probe_and_commit_control_t const* parameters) {
(void) ctl_idx;
(void) stm_idx;
/* convert unit to ms from 100 ns */
interval_ms = parameters->dwFrameInterval / 10000;
return VIDEO_ERROR_NONE;
}
} // extern C
//------------- Helper -------------//
static void fill_color_bar(uint8_t* buffer, unsigned start_position) {
/* EBU color bars
* See also https://stackoverflow.com/questions/6939422 */
static uint8_t const bar_color[8][4] = {
/* Y, U, Y, V */
{ 235, 128, 235, 128}, /* 100% White */
{ 219, 16, 219, 138}, /* Yellow */
{ 188, 154, 188, 16}, /* Cyan */
{ 173, 42, 173, 26}, /* Green */
{ 78, 214, 78, 230}, /* Magenta */
{ 63, 102, 63, 240}, /* Red */
{ 32, 240, 32, 118}, /* Blue */
{ 16, 128, 16, 128}, /* Black */
};
uint8_t* p;
/* Generate the 1st line */
uint8_t* end = &buffer[FRAME_WIDTH * 2];
unsigned idx = (FRAME_WIDTH / 2 - 1) - (start_position % (FRAME_WIDTH / 2));
p = &buffer[idx * 4];
for (unsigned i = 0; i < 8; ++i) {
for (int j = 0; j < FRAME_WIDTH / (2 * 8); ++j) {
memcpy(p, &bar_color[i], 4);
p += 4;
if (end <= p) {
p = buffer;
}
}
}
/* Duplicate the 1st line to the others */
p = &buffer[FRAME_WIDTH * 2];
for (unsigned i = 1; i < FRAME_HEIGHT; ++i) {
memcpy(p, buffer, FRAME_WIDTH * 2);
p += FRAME_WIDTH * 2;
}
}

View file

@ -1,4 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT
# CH32V20x_EVT is not supported due to Adafruit_Neopixel

View file

@ -54,25 +54,18 @@ Adafruit_USBD_WebUSB usb_web;
WEBUSB_URL_DEF(landingPage, 1 /*https*/, "example.tinyusb.org/webusb-rgb/index.html");
// the setup function runs once when you press reset or power the board
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
void setup()
{
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
TinyUSB_Device_Init(0);
#endif
//usb_web.setStringDescriptor("TinyUSB WebUSB");
usb_web.setLandingPage(&landingPage);
usb_web.setLineStateCallback(line_state_callback);
usb_web.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.begin(115200);
// This initializes the NeoPixel with RED
#ifdef NEOPIXEL_POWER
@ -86,24 +79,21 @@ void setup() {
pixels.show();
// wait until device mounted
while (!TinyUSBDevice.mounted()) delay(1);
while( !TinyUSBDevice.mounted() ) delay(1);
Serial.println("TinyUSB WebUSB RGB example");
}
// convert a hex character to number
uint8_t char2num(char c) {
uint8_t char2num(char c)
{
if (c >= 'a') return c - 'a' + 10;
if (c >= 'A') return c - 'A' + 10;
return c - '0';
return c - '0';
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
void loop()
{
// Landing Page 7 characters as hex color '#RRGGBB'
if (usb_web.available() < 7) return;
@ -114,16 +104,17 @@ void loop() {
Serial.write(input, 7);
Serial.println();
uint8_t red = 16 * char2num(input[1]) + char2num(input[2]);
uint8_t green = 16 * char2num(input[3]) + char2num(input[4]);
uint8_t blue = 16 * char2num(input[5]) + char2num(input[6]);
uint8_t red = 16*char2num(input[1]) + char2num(input[2]);
uint8_t green = 16*char2num(input[3]) + char2num(input[4]);
uint8_t blue = 16*char2num(input[5]) + char2num(input[6]);
uint32_t color = (red << 16) | (green << 8) | blue;
pixels.fill(color);
pixels.show();
}
void line_state_callback(bool connected) {
void line_state_callback(bool connected)
{
// connected = green, disconnected = red
pixels.fill(connected ? 0x00ff00 : 0xff0000);
pixels.show();

View file

@ -1,4 +0,0 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT
# CH32V20x_EVT is not supported due to lacking of HardwareSerial::read(uint8_t [64], int)

View file

@ -34,81 +34,78 @@ Adafruit_USBD_WebUSB usb_web;
// Page source can be found at https://github.com/hathach/tinyusb-webusb-page/tree/main/webusb-serial
WEBUSB_URL_DEF(landingPage, 1 /*https*/, "example.tinyusb.org/webusb-serial/index.html");
// the setup function runs once when you press reset or power the board
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
int led_pin = LED_BUILTIN;
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
// the setup function runs once when you press reset or power the board
void setup()
{
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
TinyUSB_Device_Init(0);
#endif
pinMode(led_pin, OUTPUT);
digitalWrite(led_pin, LOW);
usb_web.setLandingPage(&landingPage);
usb_web.setLineStateCallback(line_state_callback);
//usb_web.setStringDescriptor("TinyUSB WebUSB");
usb_web.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.begin(115200);
// wait until device mounted
while (!TinyUSBDevice.mounted()) delay(1);
while( !TinyUSBDevice.mounted() ) delay(1);
Serial.println("TinyUSB WebUSB Serial example");
}
// function to echo to both Serial and WebUSB
void echo_all(uint8_t buf[], uint32_t count) {
if (usb_web.connected()) {
void echo_all(uint8_t buf[], uint32_t count)
{
if (usb_web.connected())
{
usb_web.write(buf, count);
usb_web.flush();
}
if (Serial) {
for (uint32_t i = 0; i < count; i++) {
if ( Serial )
{
for(uint32_t i=0; i<count; i++)
{
Serial.write(buf[i]);
if (buf[i] == '\r') Serial.write('\n');
if ( buf[i] == '\r' ) Serial.write('\n');
}
Serial.flush();
}
}
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
void loop()
{
uint8_t buf[64];
uint32_t count;
// From Serial to both Serial & webUSB
if (Serial.available()) {
if (Serial.available())
{
count = Serial.read(buf, 64);
echo_all(buf, count);
}
// from WebUSB to both Serial & webUSB
if (usb_web.available()) {
if (usb_web.available())
{
count = usb_web.read(buf, 64);
echo_all(buf, count);
}
}
void line_state_callback(bool connected) {
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, connected);
#endif
void line_state_callback(bool connected)
{
digitalWrite(led_pin, connected);
if (connected) {
if ( connected )
{
usb_web.println("WebUSB interface connected !!");
usb_web.flush();
}

View file

@ -1,22 +1,7 @@
{
"name": "Adafruit TinyUSB Library",
"keywords": "usb, arduino, tinyusb",
"description": "Arduino library for TinyUSB",
"version": "3.7.1",
"repository": {
"type": "git",
"url": "https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git"
},
"frameworks": "*",
"platforms": "*",
"build": {
"libArchive": false
},
"authors":
[
{
"name": "Adafruit",
"maintainer": true
}
]
"libArchive": false,
"flags": "-DUSE_TINYUSB"
}
}

View file

@ -1,9 +1,9 @@
name=Adafruit TinyUSB Library
version=3.7.1
version=2.2.8
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=TinyUSB library for Arduino
paragraph=Support nRF5x, SAMD21, SAMD51, RP2040, ESP32-S2/S3, CH32V
paragraph=Support nRF5x, SAMD21, SAMD51, RP2040, ESP32-S2/S3
category=Communication
url=https://github.com/adafruit/Adafruit_TinyUSB_Arduino
architectures=*

View file

@ -25,6 +25,18 @@
#ifndef ADAFRUIT_TINYUSB_H_
#define ADAFRUIT_TINYUSB_H_
// Error message for Core that must select TinyUSB via menu
#if !defined(USE_TINYUSB) && \
(defined(ARDUINO_ARCH_SAMD) || \
(defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED)))
#error TinyUSB is not selected, please select it in "Tools->Menu->USB Stack"
#endif
// ESP32 out-of-sync
#ifdef ARDUINO_ARCH_ESP32
#include "arduino/ports/esp32/tusb_config_esp32.h"
#endif
#include "tusb_option.h"
// Device
@ -52,10 +64,6 @@
#include "arduino/webusb/Adafruit_USBD_WebUSB.h"
#endif
#if CFG_TUD_VIDEO
#include "arduino/video/Adafruit_USBD_Video.h"
#endif
// Initialize device hardware, stack, also Serial as CDC
// Wrapper for TinyUSBDevice.begin(rhport)
void TinyUSB_Device_Init(uint8_t rhport);

View file

@ -24,19 +24,17 @@
#include "tusb_option.h"
#if CFG_TUD_ENABLED || CFG_TUH_ENABLED
// ESP32 will use the arduino-esp32 core initialization and Serial
#if CFG_TUD_ENABLED && !defined(ARDUINO_ARCH_ESP32)
#include "Adafruit_TinyUSB.h"
#include "Arduino.h"
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
extern "C" {
uint32_t tusb_time_millis_api(void) { return millis(); }
//--------------------------------------------------------------------+
// Device
//--------------------------------------------------------------------+
#if CFG_TUD_ENABLED
void TinyUSB_Device_Init(uint8_t rhport) {
// Init USB Device controller and stack
TinyUSBDevice.begin(rhport);
@ -50,24 +48,18 @@ void TinyUSB_Device_Task(void) {
}
#endif
#ifndef ARDUINO_ARCH_ESP32
void TinyUSB_Device_FlushCDC(void) {
uint8_t const cdc_instance = Adafruit_USBD_CDC::getInstanceCount();
for (uint8_t instance = 0; instance < cdc_instance; instance++) {
tud_cdc_n_write_flush(instance);
}
}
#endif
#endif // CFG_TUD_ENABLED
//------------- Debug log with Serial1 -------------//
#if CFG_TUSB_DEBUG && defined(CFG_TUSB_DEBUG_PRINTF) && \
!defined(ARDUINO_ARCH_ESP32)
// Debug log with Serial1
#if CFG_TUSB_DEBUG && defined(CFG_TUSB_DEBUG_PRINTF)
// #define USE_SEGGER_RTT
#ifndef SERIAL_TUSB_DEBUG
#define SERIAL_TUSB_DEBUG Serial1
#endif
#ifdef USE_SEGGER_RTT
#include "SEGGER_RTT/RTT/SEGGER_RTT.h"
@ -96,8 +88,8 @@ __attribute__((used)) int CFG_TUSB_DEBUG_PRINTF(const char *__restrict format,
va_end(ap);
return len;
}
#endif // CFG_TUSB_DEBUG
#endif
} // extern C
#endif // CFG_TUD_ENABLED || CFG_TUH_ENABLED
#endif

View file

@ -30,25 +30,7 @@
// API Version, need to be updated when there is changes for
// TinyUSB_API, USBD_CDC, USBD_Device, USBD_Interface,
#define TINYUSB_API_VERSION 30000
#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_NRF52_ADAFRUIT) || \
defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_CH32) || \
(defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED))
#define TINYUSB_HAS_BUITLTIN_CORE_SUPPORT
#endif
// Core that has built-in support: Adafruit SAMD, Adafruit nRF, rp2040, esp32
#if !defined(TINYUSB_HAS_BUITLTIN_CORE_SUPPORT)
#define TINYUSB_NEED_POLLING_TASK
#endif
// Error message for Core that must select TinyUSB via menu (built-in except
// esp32)
#if !defined(USE_TINYUSB) && (defined(TINYUSB_HAS_BUITLTIN_CORE_SUPPORT) && \
!defined(ARDUINO_ARCH_ESP32))
#error TinyUSB is not selected, please select it in "Tools->Menu->USB Stack"
#endif
#define TINYUSB_API_VERSION 20000
//--------------------------------------------------------------------+
// Core API

View file

@ -46,44 +46,21 @@ Adafruit_USBD_CDC::Adafruit_USBD_CDC(void) { _instance = INVALID_INSTANCE; }
#if CFG_TUD_ENABLED
uint16_t Adafruit_USBD_CDC::getInterfaceDescriptor(uint8_t itfnum_deprecated,
uint8_t *buf,
#define EPOUT 0x00
#define EPIN 0x80
uint16_t Adafruit_USBD_CDC::getInterfaceDescriptor(uint8_t itfnum, uint8_t *buf,
uint16_t bufsize) {
(void)itfnum_deprecated;
// CDC is mostly always existed for DFU
uint8_t itfnum = 0;
uint8_t ep_notif = 0;
uint8_t ep_in = 0;
uint8_t ep_out = 0;
if (buf) {
itfnum = TinyUSBDevice.allocInterface(2);
ep_notif = TinyUSBDevice.allocEndpoint(TUSB_DIR_IN);
ep_in = TinyUSBDevice.allocEndpoint(TUSB_DIR_IN);
ep_out = TinyUSBDevice.allocEndpoint(TUSB_DIR_OUT);
}
#if TINYUSB_API_VERSION < 20400
// backward compatible for core that include pre-2.4.0 TinyUSB
uint8_t _strid = 0;
#endif
uint16_t const mps =
(TUD_OPT_HIGH_SPEED ? 512 : 64); // TODO actual link speed
uint8_t const desc[] = {
TUD_CDC_DESCRIPTOR(itfnum, _strid, ep_notif, 8, ep_out, ep_in, mps)};
// usb core will automatically update endpoint number
uint8_t desc[] = {TUD_CDC_DESCRIPTOR(itfnum, 0, EPIN, 8, EPOUT, EPIN, 64)};
uint16_t const len = sizeof(desc);
// null buffer is used to get the length of descriptor only
if (buf) {
if (bufsize < len) {
return 0;
}
memcpy(buf, desc, len);
if (bufsize < len) {
return 0;
}
memcpy(buf, desc, len);
return len;
}
@ -289,12 +266,11 @@ void tud_cdc_line_state_cb(uint8_t instance, bool dtr, bool rts) {
#else
// Device stack is not enabled (probably in host mode)
#warning "TinyUSB Host selected. No output to Serial will occur!"
#warning "NO_USB selected. No output to Serial will occur!"
uint16_t Adafruit_USBD_CDC::getInterfaceDescriptor(uint8_t itfnum_deprecated,
uint8_t *buf,
uint16_t Adafruit_USBD_CDC::getInterfaceDescriptor(uint8_t itfnum, uint8_t *buf,
uint16_t bufsize) {
(void)itfnum_deprecated;
(void)itfnum;
(void)buf;
(void)bufsize;

View file

@ -33,7 +33,6 @@
// For ESP32 use USBCDC as it is compatible
#define Adafruit_USBD_CDC USBCDC
#define SerialTinyUSB Serial
#else
@ -46,6 +45,10 @@ public:
static uint8_t getInstanceCount(void) { return _instance_count; }
// from Adafruit_USBD_Interface
virtual uint16_t getInterfaceDescriptor(uint8_t itfnum, uint8_t *buf,
uint16_t bufsize);
void setPins(uint8_t pin_rx, uint8_t pin_tx) {
(void)pin_rx;
(void)pin_tx;
@ -80,10 +83,6 @@ public:
using Print::write; // pull in write(str) from Print
operator bool();
// from Adafruit_USBD_Interface
virtual uint16_t getInterfaceDescriptor(uint8_t itfnum_deprecated,
uint8_t *buf, uint16_t bufsize);
private:
enum { INVALID_INSTANCE = 0xffu };
static uint8_t _instance_count;
@ -93,15 +92,16 @@ private:
bool isValid(void) { return _instance != INVALID_INSTANCE; }
};
extern Adafruit_USBD_CDC SerialTinyUSB;
// Built-in support "Serial" is assigned to TinyUSB CDC
// CH32 defines Serial as alias in WSerial.h
#if defined(USE_TINYUSB) && !defined(ARDUINO_ARCH_CH32)
// "Serial" is used with TinyUSB CDC
#if defined(USE_TINYUSB)
extern Adafruit_USBD_CDC Serial;
#define SerialTinyUSB Serial
#endif
// Serial is probably used with HW Uart
#ifndef SerialTinyUSB
extern Adafruit_USBD_CDC SerialTinyUSB;
#endif
#endif // else of ESP32
#endif // __cplusplus

Some files were not shown because too many files have changed in this diff Show more