Compare commits

..

332 commits

Author SHA1 Message Date
Tyeth Gundry
737dfb2115
Update library.json - 3.7.1 2025-07-17 11:49:41 +01:00
Tyeth Gundry
766d8cca00
Update library.properties - 3.7.1 2025-07-17 11:49:27 +01:00
Ha Thach
d3cc12070a
Merge pull request #540 from adafruit/update-bug-template
Update bug_report.yml
2025-07-15 10:37:45 +07:00
Ha Thach
86dfc05234
Merge pull request #539 from valeros/patch-1
Remove redundant USE_TINYUSB macro from PlatformIO library manifest
2025-07-15 10:30:04 +07:00
Ha Thach
8f13cb8bca
Update bug_report.yml 2025-07-15 10:19:48 +07:00
Valerii Koval
fb9763423c
Remove redundant USE_TINYUSB macro 2025-07-14 16:36:00 +03:00
Tyeth Gundry
7b30ff9e14
Update library.properties - bump version to 3.7.0 2025-06-17 19:36:00 +01:00
Tyeth Gundry
0e054b598b
Update library.json - bump version to 3.7.0 2025-06-17 19:35:40 +01:00
Ha Thach
5ab76b7931
Merge pull request #536 from adafruit/update-example
Update example
2025-06-10 17:14:19 +07:00
hathach
028629e93e
add fruitjam sdfat pinout support 2025-06-10 16:18:49 +07:00
hathach
8c615b6519
update pio-usb host requirement to only multiple of 12Mhz (previously 120Mhz) 2025-06-10 16:18:16 +07:00
Tyeth Gundry
d4071f5abe
Update library.json - bump version to 3.6.1 2025-06-03 18:53:58 +01:00
Tyeth Gundry
4daede3744
Update library.properties - bump version to 3.6.1 2025-06-03 18:53:46 +01:00
Ha Thach
44053c45df
Merge pull request #533 from adafruit/fix-metro-rp2040-msc-sdfat-macos-conflict 2025-05-31 11:03:15 +07:00
hathach
eaa9bfdaa5
update msc_sdfat.ino and msc_external_flash_sdcard.ino to
- use SDIO (pio) for rp2040/rp2350
- remove printing flash/sdcard contents to Serial since it conflict with host, which can cause conflict in spi/sdio transport and/or correupt cache,sector
2025-05-30 19:59:27 +07:00
Tyeth Gundry
9806375c60
Update library.properties - bump version to 3.6.0 2025-05-28 15:40:58 +01:00
Tyeth Gundry
e896107698
Update library.json - bump version to 3.6.0 2025-05-28 15:40:44 +01:00
Ha Thach
805aa2d41a
Merge pull request #530 from adafruit/test-metro-rp2040-sd
update msc sdcad example to work with metro rp2040
2025-05-22 22:42:50 +07:00
hathach
fee8a5e6bc
update msc sdcad example to work with metro rp2040 2025-05-22 15:58:03 +07:00
Ha Thach
59d4393012
Merge pull request #529 from adafruit/add-set-maxpower
add setConfigurationMaxPower() and setConfigurationAttribute
2025-05-22 11:48:06 +07:00
hathach
60fb663caa
add Adafruit_USBD_Device::setConfigurationMaxPower() and setConfigurationAttribute 2025-05-22 11:07:31 +07:00
Ha Thach
cdc07c1d96
Merge pull request #505 from Props3D/master
USB Device Descriptor Max Power is not configurable #504
2025-05-22 11:02:59 +07:00
Ha Thach
794ac7f34b
bump up version to 3.5.0 2025-05-21 17:29:16 +07:00
Ha Thach
9496740134
Merge pull request #528 from adafruit/fix-esp32-max3421e
fix compiling hcd max3421e with arduino-esp32 and arduino-pico due to missing atomic_flag function
2025-05-21 17:25:39 +07:00
hathach
6fa11c4d5e
bump up tinyusb to commit e41a63c60dbebd9579698e6444bc62cfa518e15c 2025-05-21 17:03:01 +07:00
Tyeth Gundry
f05bd099c3
Update library.properties - bump version to 3.4.5 2025-05-09 21:57:55 +01:00
Tyeth Gundry
951dba38f6
Update library.json - bump version to 3.4.5 2025-05-09 21:57:43 +01:00
Ha Thach
5618d9c054
Merge pull request #525 from adafruit/fix-sigma-mouse
fix sigma mouse in adafruit store cause multiple attach connection
2025-05-06 21:43:30 +07:00
hathach
46d2c6cb49
update tinyusb to commit 809af3e74ca37495d6c385acd33a488c2984a093 2025-05-06 16:14:14 +07:00
hathach
23426ed3f6
fix sigma mouse in adafruit store cause multiple attach connection 2025-05-05 23:31:59 +07:00
Ha Thach
72cd81005b
Merge pull request #523 from adafruit/update-tinyusb-commit-1a783b357343d053eb861ae783922371ce9e1b17
update tinyusb to commit 1a783b357343d053eb861ae783922371ce9e1b17
2025-05-05 17:33:24 +07:00
hathach
fafc824f6b
update tinyusb to 1a783b3573 2025-05-05 10:00:12 +07:00
Tyeth Gundry
6b772c0ac4
Update library.properties - bump version to 3.4.4 2025-03-25 17:51:36 +00:00
Tyeth Gundry
560a21bdec
Update library.json - bump version to 3.4.4 2025-03-25 17:51:21 +00:00
Ha Thach
4b9a629a55
Merge pull request #510 from adafruit/fix-esp32-max3421e
Fix esp32 max3421e
2025-03-20 20:09:29 +07:00
hathach
55a0283b48
skip more examples 2025-03-20 10:28:09 +07:00
hathach
332b0c8e31
skip device example for feather_esp32_v2 2025-03-20 09:50:31 +07:00
hathach
f83e0ce0ff
only enable CFG_TUD_ENABLED with esp wgen CONFIG_USB_OTG_SUPPORTED = 1. Add feather_esp32_v2 to ci pool 2025-03-19 16:54:45 +07:00
Props3D - Craig
d522523fd1 USB Device Descriptor Max Power is not configurable #504
Replacing hardcoded value with define macro
2025-03-07 17:32:30 -08:00
Tyeth Gundry
76a551be81
Update library.json - bump version to 3.4.3 2025-03-07 19:18:47 +00:00
Tyeth Gundry
f4e8959828
Update library.properties - bump version to 3.4.3 2025-03-07 14:30:33 +00:00
Ha Thach
7b22bd0adf
Merge pull request #503 from adafruit/support-esp32p4
support esp32p4
2025-03-07 17:08:11 +07:00
hathach
36396f4f9e
fix esp32p4 build due to lack of LED_BUILTIN 2025-03-07 16:42:10 +07:00
hathach
cfe6da84d1
fix build with host native 2025-03-07 12:48:59 +07:00
hathach
7f7ac74899
support esp32p4 2025-03-07 12:20:53 +07:00
Ha Thach
8ef30202e5
Merge pull request #498 from adafruit/update-tinyusb-1cfc88dbcb8cff6f926aef02c5609880169ec94c
Update tinyusb to commit 334ac8072650e3b18278042c2c2b402db73c7359
2025-03-07 10:58:24 +07:00
hathach
3918606fbe
update to commit 334ac8072650e3b18278042c2c2b402db73c7359 2025-03-07 10:07:41 +07:00
hathach
1d3576a40a
enable CFG_TUH_MAX3421 and skip native host dwc2 for esp32 2025-03-06 22:42:57 +07:00
hathach
605d681c81
feat(esp32) resolve conflict with latest v3.1.3. better enforce tusb_config_esp32.h within tusb_option.h
also change CFG_TUD_MIDI_RX/TX_BUFSIZE for rp2040 to 64
2025-03-06 21:18:54 +07:00
hathach
41bde22a7c
change to "SdFat_Adafruit_Fork.h" and revert to build sdfat examples 2025-03-05 22:52:39 +07:00
hathach
411821714b
update tinyusb to commit 51cfae6e97b08e9c34a4551cfa45c85a2498a943 2025-03-04 17:30:48 +07:00
hathach
aba2328b00
skip example with SdFat for rp2040 due to conflict with builtin vs Adafruit's Fork of SdFat 2025-02-26 17:10:26 +07:00
hathach
f12e3f2886
add missing files 2025-02-26 16:04:17 +07:00
hathach
a17922159b
temp patch for rp2040 lacking atomic flags test/set 2025-02-26 15:58:14 +07:00
hathach
96ac318c19
implement tusb_time_millis_api() 2025-02-26 13:10:12 +07:00
hathach
8f2d3edd77
update tinyusb to upstream 1cfc88dbcb 2025-02-26 12:48:44 +07:00
Tyeth Gundry
c92b7fde16
Update library.properties - bump version to 3.4.2 2024-12-12 18:45:22 +00:00
Ha Thach
85476dcd8f
Merge pull request #475 from OrhanYigitDurmaz/master
Bring library.json up to date
2024-12-02 15:06:31 +07:00
Orhan Yiğit Durmaz
8077b62029 Update library.json 2024-12-01 10:45:40 -08:00
Orhan Yiğit Durmaz
c976061caa fix platformio issue 2024-12-01 10:35:18 -08:00
Tyeth Gundry
f5211f4226
Update library.properties - bump version to 3.4.1 2024-11-19 19:50:14 +00:00
Ha Thach
f8ac8130c5
Merge pull request #452 from westinpigott/patch-1
Enable multiple serial over usb for rp2040
2024-11-15 12:31:23 +07:00
Ha Thach
1798428b15
Update library.properties
bump library for release
2024-10-24 17:44:30 +07:00
Ha Thach
5920d15f73
Merge pull request #466 from adafruit/update-tinyusb-fix-esp32-build
update tinyusb to fix esp32 build with v3.0.7
2024-10-24 17:43:46 +07:00
hathach
71e2c4a4bd
fix undefined reference to `__atomic_test_and_set' with rp2040 with gcc 14.2. Temporarily modify to use native semaphore 2024-10-24 16:12:17 +07:00
hathach
f13b57a01a
update tinyusb to commit 8b1e40c3e2447de5b4a86bbcdcc0344946a4793d 2024-10-23 21:20:25 +07:00
Tyeth Gundry
a529a74e4f
Update library.properties - bump version to 3.3.4 2024-09-18 19:48:04 +01:00
Ha Thach
05686e7f97
Merge pull request #454 from adafruit/force-example-re_enum
force re-enumerate for all examples.
2024-09-05 17:33:54 +07:00
hathach
59a651cca0
force re-enumerate for all examples. For some fast chip such as esp32-s3, by the time we initialize class driver enumeration process is already done. 2024-09-05 16:15:34 +07:00
Ha Thach
2df6d2905e
Merge pull request #453 from adafruit/update-tinyusb-55951b71aea46c09f27afe1640454fe43c983eec
update tinyusb to commit 55951b71aea46c09f27afe1640454fe43c983eec
2024-09-05 15:42:50 +07:00
hathach
a7c9db3f62
update tinyusb to commit 55951b71aea46c09f27afe1640454fe43c983eec 2024-09-05 14:26:59 +07:00
Westin Pigott
0a9c3fe818
Enable multiple serial over usb for rp2040 2024-09-03 14:41:27 -04:00
Tyeth Gundry
446e0af7a9
Update library.properties - bump version to 3.3.3 2024-08-13 22:28:39 +01:00
Ha Thach
f752bc6e05
Merge pull request #448 from adafruit/more-ch32v203-update
update tinyusb to fix ch32v203 race with hub in setup
2024-08-13 20:28:35 +07:00
hathach
8587060a19
update tinyusb to fix ch32v203 race with hub in setup 2024-08-13 16:14:46 +07:00
Ha Thach
0061a40530
Merge pull request #443 from adafruit/update-tinyusb-fsdev
update tinyusb to improve fsdev driver for ch32v203
2024-08-08 22:43:54 +07:00
hathach
9aaf9b56bb
add back weak callback for tud_vendor_control_xfer_cb due to conflict with arduino esp32 2024-08-08 20:56:14 +07:00
hathach
7a32772d52
add back weak callback for tud_descriptor_bos_cb to prevent conflict issue with esp32 core 2024-08-08 18:23:07 +07:00
hathach
c748ad674a
forgot to add fsdev_type.h 2024-08-08 17:36:28 +07:00
hathach
4c6e9ce4e0
make webusb tud_vendor_control_xfer_cb() weak by default to be overwritable for user sketch 2024-08-08 16:30:31 +07:00
hathach
e92d597803
update tinyusb to https://github.com/hathach/tinyusb/pull/2750 to fix ch32v203 2024-08-08 15:46:07 +07:00
hathach
889a5d65ed
udpate tinyusb to c60934eedc 2024-07-31 21:51:26 +07:00
Tyeth Gundry
51a9de832e
Update library.properties - bump version to 3.3.2 2024-07-23 15:15:03 +01:00
Ha Thach
3bd0180973
Merge pull request #441 from adafruit/fix-feather52832-build
fix build with nrf52832
2024-07-18 17:42:41 +07:00
hathach
264556032f
fix build with nrf52832 2024-07-18 17:15:58 +07:00
Tyeth Gundry
e034538570
Update library.properties - bump version to 3.3.1 2024-06-25 16:33:46 +01:00
Ha Thach
c67266b094
Update library.properties 2024-06-20 22:03:20 +07:00
Ha Thach
c1cab3e41c
Update README.md 2024-06-20 22:02:05 +07:00
Ha Thach
1f9da4918f
bump up version to 3.3.0 2024-06-20 21:47:56 +07:00
Ha Thach
a56612b5a9
Merge pull request #429 from adafruit/ch32-core-support
Add Ch32 built-inn core support
2024-06-20 21:46:48 +07:00
Tyeth Gundry
6cc5113f35
Update library.properties - bump version to 3.2.0 2024-06-18 12:37:24 +01:00
hathach
8cb40327f1
update tinyusb core for better ch32v103 support, but not working with v103 just yet 2024-06-14 17:01:00 +07:00
hathach
468f72001e
update bulk to have 512 for highspeed usb, tested usbhs with v307 using 144mhz hse 2024-06-13 23:33:29 +07:00
hathach
1b9e433c75
update to work with ch32v307 usbfs 2024-06-13 22:59:49 +07:00
hathach
f5ad52fe7f
more update for ch32 2024-06-13 11:46:13 +07:00
hathach
d1708bc87f
move menu check to TinyUSB_API 2024-06-13 11:31:12 +07:00
hathach
f2168e439f
define Serial as SerialTinyUSB if USE_TINYUSB is defined 2024-06-13 10:31:28 +07:00
Ha Thach
69333be53d
Merge pull request #428 from adafruit/add-ch32v2-support
Add ch32v2 support
2024-06-11 17:54:57 +07:00
hathach
7ca12e3688
update build_all.py 2024-06-11 16:10:19 +07:00
hathach
efa33be67c
clean up 2024-06-11 14:17:02 +07:00
hathach
e7941194dc
skip more 2024-06-11 13:14:33 +07:00
hathach
6f0f7e6a05
skip non-compilable for ch32v2 2024-06-11 13:08:38 +07:00
hathach
1c1a65c834
add more .skip.txt 2024-06-11 12:53:32 +07:00
hathach
f2286b88a8
test skip.txt 2024-06-11 12:33:29 +07:00
hathach
4d5e4231e2
fix ci 2024-06-10 23:52:59 +07:00
hathach
ee005588d0
define SerialTinyUSB Serial for esp32 2024-06-10 17:53:13 +07:00
hathach
75fd754212
use arduino lib as escape string 2024-06-10 16:38:31 +07:00
hathach
6d6cd1788b
use env for ARDUINO_LIBS, try to build ch32 2024-06-10 16:22:38 +07:00
hathach
8f7fe509d1
- add CDC/serial_echo example using SerialTinyUSB
- call CDC flush in task() for core without tinyusb builtin support
2024-06-10 16:07:10 +07:00
hathach
2179aeb6d2
most example works with ch32: hid,msc,midi though mouse_ramdisk does not. 2024-06-07 21:04:53 +07:00
hathach
2e8f1b5c33
initial support for ch32 with usbd 2024-06-07 13:24:50 +07:00
hathach
c0e19ef533
add tinyusb driver for ch32: usbfs, stm32fsdev, usbhs 2024-06-07 12:21:01 +07:00
Tyeth Gundry
c953968c46
Update library.properties - bump version to 3.1.5 2024-06-04 17:15:23 +01:00
Ha Thach
10b35388a3
Merge pull request #423 from BadCD/patch-1 2024-05-31 18:18:34 +07:00
BadCD
28dd927214
Update cdc_multi.ino
fixed a typo
2024-05-31 10:57:21 +02:00
Ha Thach
e90e6be60f
Merge pull request #422 from adafruit/update-tinyusb-1fe86f654fdca8a4a555737f34215582a812b481
Update tinyusb to 1fe86f654fdca8a4a555737f34215582a812b481
2024-05-29 16:35:25 +07:00
hathach
f7e7028fd6
skip build test with esp32 v2 2024-05-29 16:22:25 +07:00
hathach
2682fe811b
correct esp32 v2 ci build 2024-05-29 15:07:07 +07:00
hathach
93f546aa19
specify v2.0.17 (last v2 version) 2024-05-29 12:53:05 +07:00
hathach
307e8dc52b
switch ci to ref: importable-build_platform 2024-05-29 11:23:24 +07:00
hathach
320903f0d8
update tinyusb to commit 1fe86f654fdca8a4a555737f34215582a812b481 2024-05-29 10:33:03 +07:00
Tyeth Gundry
c0ba78e110
Update library.properties - bump version to 3.1.4 2024-05-01 16:19:15 +01:00
Ha Thach
8cdf80ab42
Merge pull request #414 from adafruit/update-tinyusb-022de87
Update tinyusb 022de87
2024-04-26 15:14:11 +07:00
hathach
78f060b048
list core/lib in esp-stable 2024-04-26 14:50:57 +07:00
hathach
a3abd887a9
fix ci syntax 2024-04-26 13:49:52 +07:00
hathach
e6d15a2c3f
update ci to also build with arduino-esp32 stable 2024-04-26 13:48:06 +07:00
hathach
a8aae07ec5
update tinyusb to commit 022de87 2024-04-26 11:10:15 +07:00
Ha Thach
b1eb772117
Merge pull request #413 from adafruit/update-max3421e-sketch-for-c6
use correct pin D8, D7 for feather c6 in max3421e sketch
2024-04-26 00:36:14 +07:00
hathach
f5a27167f6
use correct pin D8, D7 for feather c6 in max3421e sketch 2024-04-26 00:27:44 +07:00
Tyeth Gundry
d629476752
Update library.properties - bump version to 3.1.3 2024-03-26 13:10:47 +00:00
Ha Thach
df1a09fe48
Merge pull request #408 from adafruit/update-tinyusb-pr2526
update tinyusb to include uvc hardfault fix
2024-03-22 21:25:31 +07:00
hathach
681746cc58
update tinyusb to include uvc hardfault fix 2024-03-21 16:29:21 +07:00
Ha Thach
040eb93e77
Merge pull request #404 from adafruit/update-tinyusb-15775727e7e29cf6b4d748f01d9457479f8f6899 2024-03-14 19:08:08 +07:00
hathach
ebe252cd5a
update tinyusb to 15775727e7 2024-03-14 16:24:28 +07:00
Ha Thach
631d192b10
Merge pull request #378 from tlyu/override-tud-cfg
allow override of TUD interface counts
2024-03-13 18:02:06 +07:00
Tyeth Gundry
f755225450
Update library.properties - bump version to 3.1.1 2024-03-11 15:45:06 +00:00
Ha Thach
1679e75595
Merge pull request #402 from earlephilhower/a123 2024-03-08 09:30:19 +07:00
Earle F. Philhower, III
2c6f60941e Remove GCC 12 warning in Vendor example 2024-03-07 11:15:32 -08:00
Ha Thach
2ebb6ab2bf
Merge pull request #393 from adafruit/hathach-bump-v3.1 2024-02-20 15:12:12 +07:00
Ha Thach
cc0babfe1b
fix typo 2024-02-20 14:29:20 +07:00
Ha Thach
c1d2eed330
Update README.md 2024-02-20 14:27:55 +07:00
Ha Thach
6dab54c855
Merge pull request #392 from adafruit/fix-config-typo
fix CFG_TUD_ENDPOINT0_SIZE typo
2024-02-20 14:17:38 +07:00
Ha Thach
2913c9cb2b
Merge pull request #391 from adafruit/update-ramdisk-with-start-stop
Update ramdisk with start stop
2024-02-20 14:13:17 +07:00
Ha Thach
16168f09dc
bump up version for 3.1 release 2024-02-20 14:09:13 +07:00
hathach
e12a2f80f8 fix CFG_TUD_ENDPOINT0_SIZE typo 2024-02-20 14:00:54 +07:00
hathach
dac1eee654 clean up 2024-02-20 13:58:52 +07:00
hathach
8bd4ee67b2 add star/stop callback to ramdisk example 2024-02-20 13:54:08 +07:00
Ha Thach
e39183c0da
Merge pull request #390 from adafruit/fix-384
Fix  undefined reference to `log_printf' when enable debug with native usb host
2024-02-20 12:51:48 +07:00
hathach
7be2c9a613 fix debug eanble with host native 2024-02-20 10:49:04 +07:00
hathach
1366ac5d50 skip all device example for native host 2024-02-19 18:17:35 +07:00
hathach
4fb7872555 skip some tests with native host 2024-02-19 18:02:51 +07:00
Ha Thach
9851a7d7b0
Merge pull request #382 from tlyu/hid-getprotocol
add Adafruit_USBD_HID::getProtocol
2024-02-19 17:44:37 +07:00
hathach
7b257c0f86 eanble ci for rp2040 tinyusb native host 2024-02-19 17:38:44 +07:00
Ha Thach
232be2f7ab
Merge pull request #388 from adafruit/fix-esp32-v2-build
fix build with esp32 v2
2024-02-19 16:57:53 +07:00
Ha Thach
e5ae023803
Merge pull request #386 from earlephilhower/gccwarn
Fix GCC 12.3 warning in USB Video core
2024-02-19 16:53:48 +07:00
hathach
fc0ecddc0d fix build with esp32 v2 2024-02-19 16:38:57 +07:00
Earle F. Philhower, III
8dc1275ede Fix GCC 12.3 warning in USB Video core
GCC 12 complains when a structure member is not initialized, so set a
sane default value.

Fixes #385
2024-02-13 10:47:29 -08:00
Taylor Yu
99736ac1ac add Adafruit_USBD_HID::getProtocol
Add a getProtocol method, allowing an application to query whether the
HID interface is currently set to Boot or Report Protocol.
2024-02-08 09:22:13 -06:00
Taylor Yu
8ee7989e42 allow override of TUD interface counts
This allows a board definition to override interface counts on the
compiler command line, instead of replacing the entire tusb_config.h
file.
2024-02-07 10:43:56 -06:00
Ha Thach
2e5fb959b5
fix typo 2024-02-06 13:26:58 +07:00
Ha Thach
756970144f
Update README.md 2024-02-06 13:24:47 +07:00
Ha Thach
56d4b611f2
Merge pull request #376 from adafruit/release-3.0
bump up release and API macros
2024-02-06 13:22:09 +07:00
hathach
29e0d60db6 bump up release and API macros 2024-02-06 13:06:56 +07:00
Ha Thach
5cd4063bb8
Merge pull request #372 from adafruit/rework-esp-config-desc-builder
Rework ESP32 configuration descriptor builder
2024-02-06 12:58:45 +07:00
hathach
1bae99a760 clean up 2024-02-06 12:45:18 +07:00
hathach
6c7624fcdc minor change config 2024-02-05 18:30:42 +07:00
hathach
2ff208bbe0 add dwc2 driver for esp32 2024-02-05 18:25:17 +07:00
hathach
55eebb98c0 more clean up, use log_pritnf for debugging tinyusb with esp32 2024-02-05 12:57:50 +07:00
hathach
9eae19b58a clean up midi 2024-02-05 12:05:03 +07:00
hathach
10e0c41466 fix clang 2024-02-05 11:44:06 +07:00
hathach
f0f92403f7 clean up webusb 2024-02-05 11:41:00 +07:00
hathach
15111810b0 clean up msc class 2024-02-05 11:30:12 +07:00
hathach
fe14079068 fix hid out endpoint generation, update all hids examples to use dynamic set instead of constructor 2024-02-02 19:42:20 +07:00
hathach
12a186b550 update HID to work with new esp32 config descriptor builder 2024-02-02 19:05:46 +07:00
hathach
6e77d5b4a5 rework esp32 configuration descriptor builder to manage our own descriptor 2024-02-02 18:17:31 +07:00
hathach
7dfc5ab324 clean up 2024-02-02 17:00:11 +07:00
Ha Thach
185692be69
bump up version 2.4.1 2024-02-01 16:10:44 +07:00
hathach
bd3fba42d4 sync tinyusb upstream 2024-02-01 13:22:55 +07:00
Ha Thach
27ae871a8b
Merge pull request #371 from adafruit/enhance-uvc
Enhance uvc
2024-02-01 13:00:23 +07:00
hathach
fb2bfc3e57 fix ci build 2024-01-31 23:18:34 +07:00
hathach
19814da37b rework video configuration builder 2024-01-31 19:40:58 +07:00
hathach
5564bbd997 update tinyusb to have lastest uvc upstream 2024-01-31 11:22:08 +07:00
Tyeth Gundry
a93bb80c6e
Update library.properties - bumlo 2024-01-30 22:37:51 +00:00
Ha Thach
766a14babd
Merge pull request #370 from adafruit/rework-config-descriptor-builder
Rework config descriptor builder
2024-01-31 01:13:05 +07:00
hathach
a9262b4c21 update to actions/setup-python@v5 2024-01-31 00:48:56 +07:00
hathach
cbfff996b3 fix warnings with esp32 2024-01-31 00:36:30 +07:00
hathach
d8e9044069 increase TINYUSB_API_VERSION to 20400 for new _strid and new configuration builder
add backward compatible with core including pre-2.4.0 version
2024-01-30 23:19:36 +07:00
hathach
b5fb020216 rename itfnum to itfnum_deprecated instead of dropping 2024-01-30 20:22:35 +07:00
hathach
9047e04cae Revert "drop itfnum in signature of Adafruit_USBD_Interface::getInterfaceDescriptor()"
This reverts commit 0df71c015f.
2024-01-30 19:33:39 +07:00
hathach
0df71c015f drop itfnum in signature of Adafruit_USBD_Interface::getInterfaceDescriptor() 2024-01-30 18:13:36 +07:00
hathach
52fca115ba rework configuration builder with new allocInterface(), allocEndpoint() 2024-01-30 18:02:52 +07:00
Ha Thach
7a926e8fb9
Merge pull request #367 from adafruit/fix-esp32-build
fix esp32 out of sync with esp core v2.0.14
2024-01-25 19:17:15 +07:00
hathach
fe5a155381 fix esp32 out of sync with esp core v2.0.14 2024-01-25 19:00:15 +07:00
Ha Thach
208f6c8e4c
Merge pull request #366 from adafruit/enable-uvc-rp2040
Add Video class support
2024-01-25 16:19:02 +07:00
hathach
70fd45a713 enable uvc for samd and nrf 2024-01-25 15:48:03 +07:00
hathach
536c8233b5 bump up frame rate to 30fps in example 2024-01-25 11:47:00 +07:00
hathach
9db1fdf435 adjust streaming interface number in VC Header, and endpoint address in VS input/output header 2024-01-25 11:36:11 +07:00
hathach
fb97586573 eanble video and video streaming, start adding usbd video class, update interface desc parsing to update IAD number 2024-01-24 17:31:51 +07:00
Tyeth Gundry
693f7d4bd5
Update library.properties - bump version to 2.3.3 2024-01-23 15:13:34 +00:00
Ha Thach
f36defbf26
Merge pull request #364 from adafruit/enable-ch340x-configure
enable CFG_TUH_CDC_CH34X config for all ports
2024-01-23 18:42:03 +07:00
hathach
8d996db507 enable CFG_TUH_CDC_CH34X config for all ports 2024-01-23 18:18:09 +07:00
Ha Thach
6481d697a7
Merge pull request #363 from adafruit/update-tinyusb-for-ch34x-host
update tinyusb for ch34x host support
2024-01-23 00:13:59 +07:00
hathach
5bbad8d1eb update tinyusb for ch34x host support 2024-01-22 23:20:14 +07:00
Tyeth Gundry
eb09bb48d7
Update library.properties - bump version to 2.3.2 2024-01-16 19:19:39 +00:00
Ha Thach
6de4a11a3b
Merge pull request #361 from adafruit/update-tinyusb-to-fix-357
update tinyusb to pr https://github.com/hathach/tinyusb/pull/2412
2024-01-12 16:22:35 +07:00
hathach
565619630e update tinyusb to pr https://github.com/hathach/tinyusb/pull/2412 2024-01-12 16:07:25 +07:00
Tyeth Gundry
ac087e4bd3
Update library.properties - bump version to 2.3.1 2023-12-27 15:34:10 +00:00
Ha Thach
541fc93a67
Merge pull request #356 from adafruit/correct-feather-esp32v2-pin
correct feather esp32 v2 with max3421e pin
2023-12-27 16:20:39 +07:00
hathach
e4e854ea2a correct feather esp32 v2 with max3421e pin 2023-12-27 15:56:22 +07:00
Ha Thach
de5353d0ca
Merge pull request #355 from adafruit/add-rp2040-max3421e-support
Add rp2040 max3421e support
2023-12-26 23:19:44 +07:00
hathach
31f1edc668 add specific example for max3421e: device_info_max3421e 2023-12-26 23:05:37 +07:00
hathach
6905192954 update tinyusb, config and add rp2040 driver for max3421e as host 2023-12-26 23:02:07 +07:00
Ha Thach
e291865233
Merge pull request #354 from adafruit/release-2.3.0
bump up version 2.3.0
2023-12-25 10:56:54 +07:00
Ha Thach
e7985fa52e
Update library.properties 2023-12-23 14:58:22 +07:00
Ha Thach
89ffd9dca5
Merge pull request #353 from adafruit/suport-pico-host-native
support rp2040 native usb host configuration
2023-12-23 14:57:15 +07:00
hathach
b276e9ec83 rename test only 2023-12-22 16:21:53 +07:00
hathach
c25ae4328c update tinyusb to support rp2040 native usb host configuration
add new example Host/Simple/host_device_info
2023-12-22 16:07:30 +07:00
Liz
58698b05b9
Update library.properties 2023-12-19 18:19:23 -05:00
Ha Thach
865f31b2d1
Merge pull request #351 from adafruit/update-tinyusb-0.16.0
update tinyusb to 0.16.0
2023-12-18 18:46:08 +07:00
hathach
7d72d0b1d8 missing a file 2023-12-18 16:42:53 +07:00
hathach
a34e2f29e0 update tinyusb to 0.16.0 2023-12-18 16:37:57 +07:00
Ha Thach
221ef2cca1
Merge pull request #350 from adafruit/update-featherwing-host-rev
update featherwing host to new revision
2023-12-15 12:36:04 +07:00
hathach
0ff42ce190 update featherwing host to new revision
- cs, int are pin 10, 9
- remove GPIO0 as vbus enable
2023-12-15 11:28:25 +07:00
Tyeth Gundry
ebbd30b571
Update library.properties 2023-11-22 15:27:29 +00:00
Ha Thach
2b0b8148db
Merge pull request #346 from adafruit/support-featherwing-max3421
Support featherwing max3421
2023-11-21 17:23:30 +07:00
hathach
2ca4b908bc fix build with esp32s2,s3 2023-11-21 16:58:54 +07:00
hathach
61e908e428 add support for running tinyusb + max3421 on no OTG MCU such as esp32 2023-11-21 16:33:26 +07:00
hathach
f3e0ff74cc add max3421_readRegister() max3421_readRegister(), max3421_writeIOPINS1(), max3421_writeIOPINS2() to usbhost with max3421
update examples to work with featherwing usb host max3421
2023-11-21 13:28:44 +07:00
Ha Thach
22f5dacfde
Merge pull request #345 from adafruit/update-tinyusb-41e2da79f4a86c242deb84e0c8fab8afb7e0e74e
update tinyusb to commit 41e2da79f4a86c242deb84e0c8fab8afb7e0e74e
2023-11-21 11:54:20 +07:00
hathach
08856552b0 update tinyusb to commit 41e2da79f4a86c242deb84e0c8fab8afb7e0e74e 2023-11-21 11:14:06 +07:00
Tyeth Gundry
997c1ec86e
Update library.properties - bump version to 2.2.6 2023-11-09 02:10:26 +00:00
Ha Thach
1c7f9c4d5e
Merge pull request #344 from adafruit/fix-usbh-enumeration-race
update tinyusb to fix race condition
2023-11-03 23:25:43 +07:00
hathach
6a87063a3b
update tinyusb to fix race condition https://github.com/hathach/tinyusb/pull/2310 2023-11-03 22:39:18 +07:00
Ha Thach
1708cffa55
Merge pull request #343 from adafruit/more-max3421-2
move SPI beginTransaction()/endTransaction() to tuh_max3421_spi_cs_api()
2023-11-02 18:43:09 +07:00
hathach
9d5e6a2ff8
house clean up 2023-11-02 15:27:34 +07:00
hathach
03bfda3196 call SPI beginTransaction()/endTransaction() in tuh_max3421_spi_cs_api()
this is correct implementation to share SPI with other peripherals.
Therefore hcd_init() should not call this, only when start/end a
transfer
2023-11-02 15:18:55 +07:00
Ha Thach
bf68b766f9
Merge pull request #341 from adafruit/more-max3421
change USBHost declaration with spi pin for esp32
2023-10-27 16:13:36 +07:00
hathach
2c80ef1f7d use tuh_task_ext() 2023-10-27 15:30:46 +07:00
hathach
9a83b0bda8 change USBHost declaration with spi pin for esp32 2023-10-26 16:29:00 +07:00
Tyeth Gundry
1c5cb1d07c
Update library.properties - bump to version 2.2.5 2023-10-10 23:45:27 +01:00
Ha Thach
9985421c95
Merge pull request #337 from adafruit/support-max3421-for-esp32
Support max3421 for esp32
2023-10-09 21:58:15 +07:00
hathach
c91d537c55 fix typo in previous commit 2023-10-09 18:51:06 +07:00
hathach
5deecfb0b7 fix esp32 printf() format 2023-10-09 17:50:49 +07:00
hathach
09c47035d9 fix esp32 build with examples 2023-10-09 17:02:37 +07:00
hathach
4d397111f1 remove all test only for dual roles since all port should work via max3421e 2023-10-09 16:16:28 +07:00
hathach
b12da3e01f fix building serial host with esp32, it runs but does not echo, probably due to inherit of HardwareSerial (fix/test later) 2023-10-09 16:15:03 +07:00
hathach
554cb09c6e remove .test.only 2023-10-09 11:54:44 +07:00
hathach
6b2a48199d enable ci build for esp32 for dual roles exmaples 2023-10-09 11:04:27 +07:00
hathach
b5ad457895
fix version typo check for 2.0.14 2023-10-09 10:26:50 +07:00
hathach
702d953871
typo, require at least 2.0.8 2023-10-06 17:55:19 +07:00
hathach
6f420fa0bc require esp32 core at least 2.0.7 2023-10-06 17:46:14 +07:00
hathach
ffc744ae87 fix build with other ports 2023-10-06 17:34:30 +07:00
hathach
4be0aed13e update all example configure to work with esp32 2023-10-06 16:50:46 +07:00
hathach
4d04364b68 update to work better with arduino-esp32 master and latest release 2.0.14 2023-10-06 16:40:07 +07:00
hathach
33c2a089e5 work rather well with esp32s2 2023-10-06 15:08:12 +07:00
hathach
ea80c18955 update tinyusb with latest tuh_max3421_spi_xfer_api() signature
tested with nrf52840, samd21, samd51
2023-10-05 18:29:01 +07:00
hathach
34c59499d0 fix build with other ports 2023-10-04 15:15:16 +07:00
hathach
a07f9fb2df compile with both esp32 master (idf 4.4.3) and platformio (idf 4.4.5) 2023-10-04 12:24:46 +07:00
hathach
788d47d533 compiled with platformio 2023-10-04 11:58:58 +07:00
hathach
2c8cb9e541 improve compatibility with esp32 2023-10-04 11:01:16 +07:00
Tyeth Gundry
31a23f3686
Update library.properties 2023-10-03 22:01:32 +01:00
hathach
4f811125fd fix compatible with pio on esp32 2023-10-03 10:30:11 +07:00
Ha Thach
5c650e84e3
Merge pull request #336 from CSC-Sendance/fix/platformio-compat
Add platformio compatibility
2023-10-03 10:11:05 +07:00
Clemens Schartmüller
02f1321a48 ADDed USE_TINYUSB flag in library.json
Based on discussions in https://github.com/adafruit/Adafruit_TinyUSB_Arduino/pull/336
2023-10-02 09:16:47 +02:00
CSC-Sendance
9f3059c200 ADD platformio library.json
This adds platformio compatibility, when this library is pulled as a gitsubmodule (e.g. in adafruit's nrf52 framework).
2023-09-29 14:48:42 +02:00
Ha Thach
f898ccab35
Merge pull request #335 from adafruit/update-tinyusb-b394ae1786911a89ea3437d7090cda477ca7df6c
update tinyusb to commit b394ae1786911a89ea3437d7090cda477ca7df6c
2023-09-29 13:56:38 +07:00
hathach
c038be85af update tinyusb to commit b394ae1786911a89ea3437d7090cda477ca7df6c 2023-09-29 13:10:03 +07:00
Tyeth Gundry
a465c3c73a
Update library.properties - bump version to 2.2.3 2023-09-19 11:48:39 +01:00
Ha Thach
d4c72bf143
Merge pull request #334 from adafruit/add-max3421e-support
Support max3421e (usb host shield) for nrf52 and samd21/samd51
2023-09-19 00:49:39 +07:00
hathach
2ab530d253 comment debug code 2023-09-18 22:27:12 +07:00
hathach
3861b59d15 fix msc host wait for io issue with freertos 2023-09-18 22:06:35 +07:00
hathach
fe9ae96122 update all dual examples to support max3421e tested with samd21 and nrf52840 2023-09-18 22:04:38 +07:00
hathach
1752f57cd6 update dual examples: serial_host_bridge, hid_device_report, msc_file_explorer to work with max3421e 2023-09-14 22:47:56 +07:00
hathach
6829820ac9 add max3421e port for nrf52840 2023-09-14 21:44:30 +07:00
hathach
1429b5cce8 samd 21 and 51 can only work reliably with SPI at 12Mhz 2023-09-14 18:37:03 +07:00
hathach
edd9c845a5 ported to samd51, work the same as samd21 2023-09-14 16:27:32 +07:00
hathach
898c62f9c7 device info works with samd21 + max3421e
not too reliable probably due to tinyusb stack core issue: USBH Defer
Attach until current enumeration complete
2023-09-14 16:04:42 +07:00
Ha Thach
3df90297f4
Merge pull request #331 from adafruit/update-tinyusb-46f7cf4da2959b96d3af6b7f23d0d02ff7187f2f
update tinyusb to commit 46f7cf4da2959b96d3af6b7f23d0d02ff7187f2f
2023-09-13 16:22:37 +07:00
hathach
70605b7ec2 starting max3421e support 2023-09-13 15:35:58 +07:00
hathach
336f2378e9 update tinyusb to commit 46f7cf4da2959b96d3af6b7f23d0d02ff7187f2f 2023-09-12 19:23:26 +07:00
Ha Thach
b16bbbf5bb
Merge pull request #329 from adafruit/update-tinyusb-7bf5923052e5861f54c9cb0581e328f8be26a0a9
update tinyusb to commit 7bf5923052e5861f54c9cb0581e328f8be26a0a9
2023-09-12 18:33:56 +07:00
hathach
d6f51faac0 more workaround for esp32 core, skip vendor_device.c entirely 2023-09-12 18:25:37 +07:00
hathach
102ff12a06 more ci fix 2023-09-06 16:55:55 +07:00
hathach
2c4b77b9e4 more esp32 sync issue 2023-09-06 16:39:29 +07:00
hathach
b79a383b8b fix sync issue with esp32 2023-09-06 13:28:00 +07:00
hathach
2849480b71 update tinyusb to commit 7bf5923052e5861f54c9cb0581e328f8be26a0a9 2023-09-05 17:32:23 +07:00
Eva Herrada
4a93c7d869
Bumped to 2.2.2 2023-07-18 15:38:34 -04:00
Ha Thach
138a336892
Merge pull request #319 from adafruit/add-multiple-deviceinfo
Add multiple deviceinfo
2023-07-10 16:11:37 +07:00
hathach
2b4f48d770
rename and move device_info_rp2040 to Simple/device_info 2023-07-10 15:08:57 +07:00
hathach
0a773af488
add better multiple devices for device info with lsusb 2023-07-10 15:06:09 +07:00
Ha Thach
ffaa85e9e7
Merge pull request #307 from lyusupov/master
make DualRole sketches applicable for Pico W
2023-06-12 23:43:49 +07:00
hathach
3a2ee4e480 add more note for pico-w 2023-06-12 23:29:06 +07:00
Linar Yusupov
feb3f158f3 make DualRole sketches applicable for Pico W 2023-06-08 07:54:35 +03:00
Eva Herrada
b17ab37a0e
Bumped to 2.2.1 2023-05-30 12:37:27 -04:00
Ha Thach
beff567b60
Update config.yml 2023-05-10 10:40:22 +07:00
Ha Thach
0c067f82d6
Merge pull request #301 from dglaude/patch-2
Update hid_mouse_tremor_filter.ino
2023-05-09 22:52:18 +07:00
Ha Thach
2e561bec9c
Merge pull request #300 from dglaude/patch-1
Update hid_mouse_log_filter.ino
2023-05-09 22:51:58 +07:00
David Glaude
6257be4f91
Update hid_mouse_tremor_filter.ino
Better describe what this example code does, removing unrelated keyboard remapping description and trying to explain what this code does to mouse report.
2023-05-06 23:18:03 +02:00
David Glaude
cd5f6edbc0
Update hid_mouse_log_filter.ino
Update the comment to contain a description of what this example really do.
The text is mostly a copy from description of the function log_filter at the end of the source file.
2023-05-06 22:55:05 +02:00
Ha Thach
5aeca208a5
Merge pull request #299 from adafruit/update-serial-host-example
Enhance Host CDC
2023-05-05 16:23:39 +07:00
hathach
2fc1e483da USBH CDC setBaudrate() do nothing if baud is already matched
begin() will also change baudrate if mounted()
2023-05-05 16:10:18 +07:00
hathach
9aaa6c9855 update serial host bridge example 2023-05-04 13:11:31 +07:00
Ha Thach
29a0342258
Update library.properties 2023-05-03 13:00:55 +07:00
Ha Thach
553127a253
Merge pull request #298 from adafruit/ifndef_update
Updating pin names for examples
2023-05-01 23:26:51 +07:00
Liz
5678d97fff Updating pin names for examples
hihi- just updating the ifndef pin names to match the board def names in some of the examples. looks like the updated pin names are not in the newest bsp release yet so also updating pin numbers to 16-18.
2023-05-01 10:23:31 -04:00
Ha Thach
2e0f267f60
Merge pull request #297 from adafruit/enhance-serial-host
Enhance serial host
2023-05-01 09:11:37 +07:00
hathach
5924834d75
add mount/umount setDtrRts(), setBaudrate(), baud() for Serila Host 2023-05-01 01:08:47 +07:00
hathach
2db0de209a
update tinyusb core to 1763eede4839d0131cda077e2dd9631f315ce115 2023-04-28 22:15:03 +07:00
hathach
f06eb748a4
update tinyusb to commit fb5fe3360f 2023-04-28 21:54:41 +07:00
Ha Thach
c58ed81a7e
Merge pull request #295 from adafruit/enable-host-ftdi-cp210x
enable CFG_TUH_CDC_FTDI and CFG_TUH_CDC_CP210X for rp2040 host
2023-04-28 12:33:47 +07:00
hathach
311f3a3940
forgot to add ftdi/cp210x header 2023-04-28 12:25:12 +07:00
hathach
64256d753d
enable CFG_TUH_CDC_FTDI and CFG_TUH_CDC_CP210X for rp2040 host 2023-04-28 12:13:01 +07:00
Ha Thach
ac6d4c51e6
Merge pull request #294 from adafruit/update-tinyusb-2afef458be5ddea97d286f5dd8d3925c4846ee6e
update tinyusb core for Serial Host driver for ftdi/cp210x/ch9102f
2023-04-28 12:06:13 +07:00
hathach
d62f7ef7d2 update tinyusb core to 2afef458be 2023-04-28 11:41:22 +07:00
Ha Thach
47fd7f190e
Merge pull request #291 from ATMakersBill/master
Add additional example for Tremors using a logarithm filter
2023-04-25 13:05:52 +07:00
ATMakers - Bill Binko
3bf82685f5 Create .feather_rp2040_tinyusb.test.only
Adding .only file
2023-04-25 01:33:36 -04:00
ATMakers - Bill Binko
71c70ea1c3 Create hid_mouse_log_filter.ino
This filter seems to compensate for Essential Tremors better than the other.  YMMV, but I think this is a good starting point
2023-04-25 01:13:55 -04:00
Ha Thach
761cfd3b49
Merge pull request #290 from adafruit/add-mouse-tremor
add mouse tremor with Butterworth filter
2023-04-24 16:18:18 +07:00
hathach
c2ffe2d537 ci with rp2040 only 2023-04-24 15:50:41 +07:00
hathach
6bbc3dbe9c add mouse tremor with Butterworth filter 2023-04-24 15:40:19 +07:00
Ha Thach
a2bcb19f6c
Merge pull request #288 from adafruit/hathach-patch-1
bump up release 2.1.0
2023-04-21 16:38:53 +07:00
Ha Thach
e7ad4fe2bc
bump up release 2.1.0 2023-04-21 16:10:55 +07:00
Ha Thach
b576368bec
Merge pull request #287 from adafruit/add-mul-hid-example
add multiple hid interfaces example
2023-04-21 16:10:23 +07:00
hathach
d6dffe11a4 add multiple hid examples 2023-04-21 15:32:20 +07:00
Ha Thach
008de7ff37
Merge pull request #286 from adafruit/update-tinyusb-0871238cacddb1802e5ce88a8e407d55a7fa34af
update tinyusb
2023-04-21 14:45:53 +07:00
hathach
c4d4a0a4d8 update tinyusb to commit 0871238cac 2023-04-21 14:32:40 +07:00
Ha Thach
6546b4c08c
Merge pull request #280 from adafruit/multiple-hid-instances
enable multiple HID instances support, change CFG_TUD_HID=2 for all ports
2023-04-13 00:18:42 +07:00
hathach
647f6b27ae use tud_hid_n() API 2023-04-13 00:07:53 +07:00
hathach
b75604f794 enable multiple HID instances support, change CFG_TUD_HID=2 for all ports except esp32sx 2023-04-12 22:37:04 +07:00
Eva Herrada
3c5a5bc727
Bump to 2.0.3 2023-04-06 14:36:59 -04:00
Ha Thach
34362e561e
Merge pull request #277 from adafruit/sync-tinyusb
sync tinyusb
2023-04-06 12:15:24 +07:00
Eva Herrada
409f909578
Bump to 2.0.2 2023-04-03 16:58:08 -04:00
251 changed files with 30213 additions and 12018 deletions

View file

@ -2,3 +2,5 @@ synopsys
sie sie
inout inout
busses busses
thre

View file

@ -46,7 +46,7 @@ body:
- type: input - type: input
attributes: attributes:
label: TinyUSB Library version label: TinyUSB Library version
placeholder: "Release version or github latest" placeholder: "Release version or commit SHA"
validations: validations:
required: true required: true
@ -100,3 +100,11 @@ body:
description: If applicable, add screenshots to help explain your problem. description: If applicable, add screenshots to help explain your problem.
validations: validations:
required: false 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,3 +3,6 @@ contact_links:
- name: Adafruit Support Forum - name: Adafruit Support Forum
url: https://forums.adafruit.com url: https://forums.adafruit.com
about: If you have other questions or need help, post it here. about: If you have other questions or need help, post it here.
- name: TinyUSB Arduino Discussion
url: https://github.com/adafruit/Adafruit_TinyUSB_Arduino/discussions
about: If you have other questions or need help, post it here.

View file

@ -3,26 +3,24 @@ name: Build
on: [pull_request, push, repository_dispatch] on: [pull_request, push, repository_dispatch]
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true 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: jobs:
pre-commit: pre-commit:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Checkout code - name: Checkout code
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Run pre-commit - name: Run pre-commit
uses: pre-commit/action@v3.0.0 uses: pre-commit/action@v3.0.1
- name: Checkout adafruit/ci-arduino - name: Checkout adafruit/ci-arduino
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
repository: adafruit/ci-arduino repository: adafruit/ci-arduino
path: ci path: ci
@ -39,6 +37,9 @@ jobs:
PRETTYNAME : "Adafruit TinyUSB Library" PRETTYNAME : "Adafruit TinyUSB Library"
run: bash ci/doxy_gen_and_deploy.sh run: bash ci/doxy_gen_and_deploy.sh
# ---------------------------------------
# build
# ---------------------------------------
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: pre-commit needs: pre-commit
@ -46,31 +47,28 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
arduino-platform: arduino-platform:
# ESP32S3 # ESP32 ci use dev json
- 'feather_esp32s3' - 'feather_esp32_v2'
# ESP32S2
- 'feather_esp32s2' - 'feather_esp32s2'
- 'feather_esp32s3'
- 'esp32p4'
# nRF52 # nRF52
- 'cpb' - 'cpb'
- 'nrf52840' - 'nrf52840'
# RP2040 # RP2040
- 'feather_rp2040_tinyusb' - 'feather_rp2040_tinyusb'
- 'pico_rp2040_tinyusb_host'
# SAMD # SAMD
- 'feather_m4_can_tinyusb'
- 'metro_m0_tinyusb' - 'metro_m0_tinyusb'
- 'metro_m4_tinyusb' - 'metro_m4_tinyusb'
# Ch32v2
- 'CH32V20x_EVT'
steps: steps:
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Checkout code - name: Checkout code
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Checkout adafruit/ci-arduino - name: Checkout adafruit/ci-arduino
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
repository: adafruit/ci-arduino repository: adafruit/ci-arduino
path: ci path: ci
@ -78,8 +76,10 @@ jobs:
- name: pre-install - name: pre-install
run: bash ci/actions_install.sh run: bash ci/actions_install.sh
- name: Install Libraries for building examples - name: Install Libraries
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" run: |
arduino-cli lib install ${{ env.ARDUINO_LIBS }}
arduino-cli lib list
- name: test platforms - name: test platforms
run: python3 ci/build_platform.py ${{ matrix.arduino-platform }} run: python3 ci/build_platform.py ${{ matrix.arduino-platform }}

3
.gitignore vendored
View file

@ -1,2 +1,5 @@
/examples/**/build/ /examples/**/build/
/.development /.development
.idea
platformio.ini
.pio/

View file

@ -15,15 +15,18 @@ Supported device class drivers are:
- Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ... - Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ...
- Mass Storage Class (MSC): with multiple LUNs - Mass Storage Class (MSC): with multiple LUNs
- Musical Instrument Digital Interface (MIDI) - Musical Instrument Digital Interface (MIDI)
- Video (UVC): work in progress
- WebUSB with vendor specific class - WebUSB with vendor specific class
### Host Stack ### Host Stack
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: 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:
- Communication (CDC) - Communication (CDC): including vendor usb2uart such as FTDI, CP210x, CH34x
- MassStorage class - MassStorage class
Note: Host stack is still work-in-progress
## Supported Cores ## 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. 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.
@ -35,9 +38,12 @@ 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/Adafruit_nRF52_Arduino](https://github.com/adafruit/Adafruit_nRF52_Arduino)
- [adafruit/ArduinoCore-samd](https://github.com/adafruit/ArduinoCore-samd) - [adafruit/ArduinoCore-samd](https://github.com/adafruit/ArduinoCore-samd)
- [earlephilhower/arduino-pico](https://github.com/earlephilhower/arduino-pico) - [earlephilhower/arduino-pico](https://github.com/earlephilhower/arduino-pico)
- [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) - [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)
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. 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.
### Cores without built-in support ### Cores without built-in support

View file

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

View file

@ -25,11 +25,9 @@
#include <Adafruit_TinyUSB.h> #include <Adafruit_TinyUSB.h>
#define LED LED_BUILTIN
// Create 2nd instance of CDC Ports. // Create 2nd instance of CDC Ports.
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
#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." #error "Currently multiple CDCs on ESP32 is not yet supported"
// for ESP32, we need to specify instance number when declaring object // for ESP32, we need to specify instance number when declaring object
Adafruit_USBD_CDC USBSer1(1); Adafruit_USBD_CDC USBSer1(1);
#else #else
@ -37,13 +35,17 @@
#endif #endif
void setup() { void setup() {
pinMode(LED, OUTPUT); #ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
#endif
Serial.begin(115200); Serial.begin(115200);
// check to see if multiple CDCs are enabled // check to see if multiple CDCs are enabled
if ( CFG_TUD_CDC < 2 ) { if ( CFG_TUD_CDC < 2 ) {
digitalWrite(LED, HIGH); // LED on for error indicator #ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, HIGH); // LED on for error indicator
#endif
while(1) { while(1) {
Serial.printf("CFG_TUD_CDC must be at least 2, current value is %u\n", CFG_TUD_CDC); Serial.printf("CFG_TUD_CDC must be at least 2, current value is %u\n", CFG_TUD_CDC);
@ -56,6 +58,13 @@ void setup() {
// initialize 2nd CDC interface // initialize 2nd CDC interface
USBSer1.begin(115200); 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) { while (!Serial || !USBSer1) {
if (Serial) { if (Serial) {
Serial.println("Waiting for other USB ports"); Serial.println("Waiting for other USB ports");
@ -89,7 +98,9 @@ void loop() {
if (delay_without_delaying(500)) { if (delay_without_delaying(500)) {
LEDstate = !LEDstate; LEDstate = !LEDstate;
digitalWrite(LED, LEDstate); #ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, LEDstate);
#endif
} }
} }

View file

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

View file

@ -18,19 +18,40 @@
* Note: this will cause device to loose the touch1200 and require * Note: this will cause device to loose the touch1200 and require
* user manual interaction to put device into bootloader/DFU mode. * 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);
}
int led = LED_BUILTIN; // clear configuration will remove all USB interfaces including CDC (Serial)
TinyUSBDevice.clearConfiguration();
void setup() // If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
{ if (TinyUSBDevice.mounted()) {
Serial.end(); TinyUSBDevice.detach();
pinMode(led, OUTPUT); delay(10);
TinyUSBDevice.attach();
}
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
#endif
} }
void loop() void loop() {
{ #ifdef TINYUSB_NEED_POLLING_TASK
digitalWrite(led, HIGH); // Manual call tud_task since it isn't called by Core's background
delay(1000); TinyUSBDevice.task();
digitalWrite(led, LOW); #endif
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
}
} }

View file

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

View file

@ -0,0 +1,41 @@
/*********************************************************************
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

@ -1,192 +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 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

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

View file

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

View file

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

View file

@ -9,154 +9,162 @@
any redistribution any redistribution
*********************************************************************/ *********************************************************************/
/* This example demonstrates use of both device and host, where
* - Device run on native usb controller (roothub port0)
* - Host depending on MCUs run on either:
* - rp2040: bit-banging 2 GPIOs with the help of Pico-PIO-USB library (roothub port1)
* - samd21/51, nrf52840, esp32: using MAX3421e controller (host shield)
*
* Requirements:
* - For rp2040:
* - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library
* - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1
* - Provide VBus (5v) and GND for peripheral
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed"
* - For samd21/51, nrf52840, esp32:
* - Additional MAX2341e USB Host shield or featherwing is required
* - SPI instance, CS pin, INT pin are correctly configured in usbh_helper.h
*/
/* This example demonstrates use of Host Serial (CDC). SerialHost (declared below) is /* This example demonstrates use of Host Serial (CDC). SerialHost (declared below) is
* an object to manage an CDC peripheral connected to our USB Host connector. This example * an object to manage an CDC peripheral connected to our USB Host connector. This example
* will forward all characters from Serial to SerialHost and vice versa. * will forward all characters from Serial to SerialHost and vice versa.
*
* Note:
* - Device run on native usb controller (controller0)
* - Host run on bit-banging 2 GPIOs with the help of Pico-PIO-USB library (controller1)
* Requirements:
* - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library
* - 2 consecutive GPIOs: D+ is defined by PIN_PIO_USB_HOST_DP, D- = D+ +1
* - Provide VBus (5v) and GND for peripheral
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed"
*/ */
// pio-usb is required for rp2040 host // nRF52 and ESP32 use freeRTOS, we may need to run USBhost.task() in its own rtos's thread.
#include "pio_usb.h" // Since USBHost.task() will put loop() into dormant state and prevent followed code from running
// until there is USB host event.
// TinyUSB lib #if defined(ARDUINO_NRF52_ADAFRUIT) || defined(ARDUINO_ARCH_ESP32)
#include "Adafruit_TinyUSB.h" #define USE_FREERTOS
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_PIO_USB_HOST_DP
#define PIN_PIO_USB_HOST_DP 20
#endif #endif
// Pin for enabling Host VBUS. comment out if not used // USBHost is defined in usbh_helper.h
#ifndef PIN_PIO_USB_HOST_VBUSEN #include "usbh_helper.h"
#define PIN_PIO_USB_HOST_VBUSEN 22
#endif
#ifndef PIN_PIO_USB_HOST_VBUSEN_STATE
#define PIN_PIO_USB_HOST_VBUSEN_STATE 1
#endif
// USB Host object
Adafruit_USBH_Host USBHost;
// CDC Host object // CDC Host object
Adafruit_USBH_CDC SerialHost; Adafruit_USBH_CDC SerialHost;
//--------------------------------------------------------------------+ // forward Seral <-> SerialHost
// Setup and Loop on Core0 void forward_serial(void) {
//--------------------------------------------------------------------+
void setup() {
Serial1.begin(115200);
Serial.begin(115200);
while ( !Serial ) delay(10); // wait for native usb
Serial.println("TinyUSB Host Serial Echo Example");
}
void loop()
{
uint8_t buf[64]; uint8_t buf[64];
// Serial -> SerialHost // Serial -> SerialHost
if (Serial.available()) { if (Serial.available()) {
size_t count = Serial.read(buf, sizeof(buf)); size_t count = Serial.read(buf, sizeof(buf));
if ( SerialHost && SerialHost.connected() ) { if (SerialHost && SerialHost.connected()) {
SerialHost.write(buf, count); SerialHost.write(buf, count);
SerialHost.flush(); SerialHost.flush();
} }
} }
// SerialHost -> Serial // SerialHost -> Serial
if ( SerialHost.connected() && SerialHost.available() ) { if (SerialHost.connected() && SerialHost.available()) {
size_t count = SerialHost.read(buf, sizeof(buf)); size_t count = SerialHost.read(buf, sizeof(buf));
Serial.write(buf, count); Serial.write(buf, count);
Serial.flush();
} }
} }
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Setup and Loop on Core1 // Using Host shield MAX3421E controller
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
void setup1() { #ifdef USE_FREERTOS
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 120Mhz for bit-banging USB #ifdef ARDUINO_ARCH_ESP32
uint32_t cpu_hz = clock_get_hz(clk_sys); #define USBH_STACK_SZ 2048
if ( cpu_hz != 120000000UL && cpu_hz != 240000000UL ) { #else
while ( !Serial ) { #define USBH_STACK_SZ 200
delay(10); // wait for native usb
}
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);
}
}
#ifdef PIN_PIO_USB_HOST_VBUSEN
pinMode(PIN_PIO_USB_HOST_VBUSEN, OUTPUT);
// power off first
digitalWrite(PIN_PIO_USB_HOST_VBUSEN, 1-PIN_PIO_USB_HOST_VBUSEN_STATE);
delay(1);
// power on
digitalWrite(PIN_PIO_USB_HOST_VBUSEN, PIN_PIO_USB_HOST_VBUSEN_STATE);
delay(10);
#endif #endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG; void usbhost_rtos_task(void *param) {
pio_cfg.pin_dp = PIN_PIO_USB_HOST_DP; (void) param;
USBHost.configure_pio_usb(1, &pio_cfg); while (1) {
USBHost.task();
}
}
#endif
void setup() {
Serial.begin(115200);
// init host stack on controller (rhport) 1
USBHost.begin(1);
// Initialize SerialHost
SerialHost.begin(115200);
#ifdef USE_FREERTOS
// Create a task to run USBHost.task() in background
xTaskCreate(usbhost_rtos_task, "usbh", USBH_STACK_SZ, NULL, 3, NULL);
#endif
// while ( !Serial ) delay(10); // wait for native usb
Serial.println("TinyUSB Host Serial Echo Example");
}
void loop() {
#ifndef USE_FREERTOS
USBHost.task();
#endif
forward_serial();
}
#elif defined(ARDUINO_ARCH_RP2040)
//--------------------------------------------------------------------+
// For RP2040 use both core0 for device stack, core1 for host stack
//--------------------------------------------------------------------+
//------------- Core0 -------------//
void setup() {
Serial.begin(115200);
// while ( !Serial ) delay(10); // wait for native usb
Serial.println("TinyUSB Host Serial Echo Example");
}
void loop() {
forward_serial();
}
//------------- Core1 -------------//
void setup1() {
// configure pio-usb: defined in usbh_helper.h
rp2040_configure_pio_usb();
// run host stack on controller (rhport) 1 // run host stack on controller (rhport) 1
// Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the // Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
// host bit-banging processing works done in core1 to free up core0 for other works // host bit-banging processing works done in core1 to free up core0 for other works
USBHost.begin(1); USBHost.begin(1);
// Initialize SerialHost
SerialHost.begin(115200);
} }
void loop1() void loop1() {
{
USBHost.task(); USBHost.task();
// periodically flush SerialHost if connected
if ( SerialHost && SerialHost.connected() ) {
SerialHost.flush();
}
} }
#endif
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// TinyUSB Host callbacks // TinyUSB Host callbacks
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
extern "C" {
// Invoked when a device with CDC interface is mounted // Invoked when a device with CDC interface is mounted
// idx is index of cdc interface in the internal pool. // idx is index of cdc interface in the internal pool.
void tuh_cdc_mount_cb(uint8_t idx) { void tuh_cdc_mount_cb(uint8_t idx) {
// bind SerialHost object to this interface index // bind SerialHost object to this interface index
SerialHost.setInterfaceIndex(idx); SerialHost.mount(idx);
SerialHost.begin(115200);
Serial.println("SerialHost is connected to a new CDC device"); Serial.println("SerialHost is connected to a new CDC device");
} }
// Invoked when a device with CDC interface is unmounted // Invoked when a device with CDC interface is unmounted
void tuh_cdc_umount_cb(uint8_t idx) { void tuh_cdc_umount_cb(uint8_t idx) {
if (idx == SerialHost.getInterfaceIndex()) { SerialHost.umount(idx);
// unbind SerialHost if this interface is unmounted Serial.println("SerialHost is disconnected");
SerialHost.end(); }
Serial.println("SerialHost is disconnected");
}
} }

View file

@ -0,0 +1,99 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
MIT license, check LICENSE for more information
Copyright (c) 2019 Ha Thach for Adafruit Industries
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/
#ifndef USBH_HELPER_H
#define USBH_HELPER_H
#ifdef ARDUINO_ARCH_RP2040
// pio-usb is required for rp2040 host
#include "pio_usb.h"
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_USB_HOST_DP
#define PIN_USB_HOST_DP 16
#endif
// Pin for enabling Host VBUS. comment out if not used
#ifndef PIN_5V_EN
#define PIN_5V_EN 18
#endif
#ifndef PIN_5V_EN_STATE
#define PIN_5V_EN_STATE 1
#endif
#endif // ARDUINO_ARCH_RP2040
#include "Adafruit_TinyUSB.h"
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// USB Host using MAX3421E: SPI, CS, INT
#include "SPI.h"
#if defined(ARDUINO_METRO_ESP32S2)
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
#endif
#else
// Native USB Host such as rp2040
Adafruit_USBH_Host USBHost;
#endif
//--------------------------------------------------------------------+
// Helper Functions
//--------------------------------------------------------------------+
#ifdef ARDUINO_ARCH_RP2040
static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
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");
while (1) {
delay(1);
}
}
#ifdef PIN_5V_EN
pinMode(PIN_5V_EN, OUTPUT);
digitalWrite(PIN_5V_EN, PIN_5V_EN_STATE);
#endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.pin_dp = PIN_USB_HOST_DP;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
// For pico-w, PIO is also used to communicate with cyw43
// Therefore we need to alternate the pio-usb configuration
// details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46
pio_cfg.sm_tx = 3;
pio_cfg.sm_rx = 2;
pio_cfg.sm_eop = 3;
pio_cfg.pio_rx_num = 0;
pio_cfg.pio_tx_num = 1;
pio_cfg.tx_ch = 9;
#endif
USBHost.configure_pio_usb(1, &pio_cfg);
}
#endif
#endif

View file

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

View file

@ -11,83 +11,64 @@
/* This example demonstrates use of both device and host, where /* This example demonstrates use of both device and host, where
* - Device run on native usb controller (controller0) * - Device run on native usb controller (roothub port0)
* - Host run on bit-banging 2 GPIOs with the help of Pico-PIO-USB library (controller1) * - Host depending on MCUs run on either:
* - rp2040: bit-banging 2 GPIOs with the help of Pico-PIO-USB library (roothub port1)
* - samd21/51, nrf52840, esp32: using MAX3421e controller (host shield)
* *
* Requirements: * Requirements:
* - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library * - For rp2040:
* - 2 consecutive GPIOs: D+ is defined by PIN_PIO_USB_HOST_DP, D- = D+ +1 * - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library
* - Provide VBus (5v) and GND for peripheral * - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed" * - Provide VBus (5v) and GND for peripheral
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed"
* - For samd21/51, nrf52840, esp32:
* - Additional MAX2341e USB Host shield or featherwing is required
* - SPI instance, CS pin, INT pin are correctly configured in usbh_helper.h
*/ */
// pio-usb is required for rp2040 host // USBHost is defined in usbh_helper.h
#include "pio_usb.h" #include "usbh_helper.h"
#include "Adafruit_TinyUSB.h"
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_PIO_USB_HOST_DP
#define PIN_PIO_USB_HOST_DP 20
#endif
// Pin for enabling Host VBUS. comment out if not used
#ifndef PIN_PIO_USB_HOST_VBUSEN
#define PIN_PIO_USB_HOST_VBUSEN 22
#endif
#ifndef PIN_PIO_USB_HOST_VBUSEN_STATE
#define PIN_PIO_USB_HOST_VBUSEN_STATE 1
#endif
// Language ID: English
#define LANGUAGE_ID 0x0409
// USB Host object
Adafruit_USBH_Host USBHost;
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Setup and Loop on Core0 // Using Host shield MAX3421E controller
//--------------------------------------------------------------------+
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: HID Device Report Example");
}
void loop() {
USBHost.task();
Serial.flush();
}
#elif defined(ARDUINO_ARCH_RP2040)
//--------------------------------------------------------------------+
// For RP2040 use both core0 for device stack, core1 for host stack
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
void setup() //------------- Core0 -------------//
{ void setup() {
Serial1.begin(115200);
Serial.begin(115200); Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb //while ( !Serial ) delay(10); // wait for native usb
Serial.println("TinyUSB Dual: HID Device Report Example");
Serial.println("TinyUSB Dual Device Info Example");
} }
void loop() void loop() {
{ Serial.flush();
} }
//--------------------------------------------------------------------+ //------------- Core1 -------------//
// Setup and Loop on Core1
//--------------------------------------------------------------------+
void setup1() { void setup1() {
//while ( !Serial ) delay(10); // wait for native usb // configure pio-usb: defined in usbh_helper.h
Serial.println("Core1 setup to run TinyUSB host with pio-usb"); rp2040_configure_pio_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 != 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 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);
}
#ifdef PIN_PIO_USB_HOST_VBUSEN
pinMode(PIN_PIO_USB_HOST_VBUSEN, OUTPUT);
digitalWrite(PIN_PIO_USB_HOST_VBUSEN, PIN_PIO_USB_HOST_VBUSEN_STATE);
#endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.pin_dp = PIN_PIO_USB_HOST_DP;
USBHost.configure_pio_usb(1, &pio_cfg);
// run host stack on controller (rhport) 1 // run host stack on controller (rhport) 1
// Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the // Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
@ -95,19 +76,22 @@ void setup1() {
USBHost.begin(1); USBHost.begin(1);
} }
void loop1() void loop1() {
{
USBHost.task(); USBHost.task();
} }
#endif
extern "C" {
// Invoked when device with hid interface is mounted // Invoked when device with hid interface is mounted
// Report descriptor is also available for use. // Report descriptor is also available for use.
// tuh_hid_parse_report_descriptor() can be used to parse common/simple enough // tuh_hid_parse_report_descriptor() can be used to parse common/simple enough
// descriptor. Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, // descriptor. Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE,
// it will be skipped therefore report_desc = NULL, desc_len = 0 // it will be skipped therefore report_desc = NULL, desc_len = 0
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) { void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) {
(void)desc_report; (void) desc_report;
(void)desc_len; (void) desc_len;
uint16_t vid, pid; uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid); tuh_vid_pid_get(dev_addr, &vid, &pid);
@ -135,3 +119,5 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
Serial.printf("Error: cannot request to receive report\r\n"); Serial.printf("Error: cannot request to receive report\r\n");
} }
} }
} // extern C

View file

@ -0,0 +1,99 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
MIT license, check LICENSE for more information
Copyright (c) 2019 Ha Thach for Adafruit Industries
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/
#ifndef USBH_HELPER_H
#define USBH_HELPER_H
#ifdef ARDUINO_ARCH_RP2040
// pio-usb is required for rp2040 host
#include "pio_usb.h"
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_USB_HOST_DP
#define PIN_USB_HOST_DP 16
#endif
// Pin for enabling Host VBUS. comment out if not used
#ifndef PIN_5V_EN
#define PIN_5V_EN 18
#endif
#ifndef PIN_5V_EN_STATE
#define PIN_5V_EN_STATE 1
#endif
#endif // ARDUINO_ARCH_RP2040
#include "Adafruit_TinyUSB.h"
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// USB Host using MAX3421E: SPI, CS, INT
#include "SPI.h"
#if defined(ARDUINO_METRO_ESP32S2)
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
#endif
#else
// Native USB Host such as rp2040
Adafruit_USBH_Host USBHost;
#endif
//--------------------------------------------------------------------+
// Helper Functions
//--------------------------------------------------------------------+
#ifdef ARDUINO_ARCH_RP2040
static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
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");
while (1) {
delay(1);
}
}
#ifdef PIN_5V_EN
pinMode(PIN_5V_EN, OUTPUT);
digitalWrite(PIN_5V_EN, PIN_5V_EN_STATE);
#endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.pin_dp = PIN_USB_HOST_DP;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
// For pico-w, PIO is also used to communicate with cyw43
// Therefore we need to alternate the pio-usb configuration
// details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46
pio_cfg.sm_tx = 3;
pio_cfg.sm_rx = 2;
pio_cfg.sm_eop = 3;
pio_cfg.pio_rx_num = 0;
pio_cfg.pio_tx_num = 1;
pio_cfg.tx_ch = 9;
#endif
USBHost.configure_pio_usb(1, &pio_cfg);
}
#endif
#endif

View file

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

View file

@ -0,0 +1,184 @@
/*********************************************************************
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) 2023 Bill Binko for Adafruit Industries
Based on tremor_filter example by Thach Ha
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 depending on MCUs run on either:
* - rp2040: bit-banging 2 GPIOs with the help of Pico-PIO-USB library (roothub port1)
* - samd21/51, nrf52840, esp32: using MAX3421e controller (host shield)
*
* Requirements:
* - For rp2040:
* - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library
* - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1
* - Provide VBus (5v) and GND for peripheral
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed"
* - For samd21/51, nrf52840, esp32:
* - Additional MAX2341e USB Host shield or featherwing is required
* - SPI instance, CS pin, INT pin are correctly configured in usbh_helper.h
*/
/* Example sketch receive mouse report from host interface (from e.g consumer mouse)
* and reduce large motions due to tremors by applying the natural log function.
* It handles negative values and a dead zone where small values will not be adjusted.
* Adjusted mouse movement are send via device interface (to PC).
*/
// USBHost is defined in usbh_helper.h
#include "usbh_helper.h"
// 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: 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.
* Adjust for each user (would be ideal to have this adjustable w/o recompiling) */
#define PRESCALE 8.0 // Must be > 0, Higher numbers increase rate of attenuation
#define POSTSCALE 1.5 // Must be > 0, Higher numbers compensate for PRESCALE attenuation
#define DEADZONE 1.0 // Must be > 1, Movements < this magnitude will not be filtered
void setup() {
Serial.begin(115200);
usb_hid.begin();
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// init host stack on controller (rhport) 1
// For rp2040: this is called in core1's setup1()
USBHost.begin(1);
#endif
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("ATMakers Logarithm Tremor Filter Example");
}
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
//--------------------------------------------------------------------+
// Using Host shield MAX3421E controller
//--------------------------------------------------------------------+
void loop() {
USBHost.task();
Serial.flush();
}
#elif defined(ARDUINO_ARCH_RP2040)
//--------------------------------------------------------------------+
// For RP2040 use both core0 for device stack, core1 for host stack
//--------------------------------------------------------------------+
void loop() {
Serial.flush();
}
//------------- Core1 -------------//
void setup1() {
// configure pio-usb: defined in usbh_helper.h
rp2040_configure_pio_usb();
// run host stack on controller (rhport) 1
// Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
// host bit-banging processing works done in core1 to free up core0 for other works
USBHost.begin(1);
}
void loop1() {
USBHost.task();
}
#endif
//--------------------------------------------------------------------+
// TinyUSB Host callbacks
//--------------------------------------------------------------------+
extern "C"
{
// Invoked when device with hid interface is mounted
// Report descriptor is also available for use.
// tuh_hid_parse_report_descriptor() can be used to parse common/simple enough
// descriptor. Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE,
// it will be skipped therefore report_desc = NULL, desc_len = 0
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) {
(void) desc_report;
(void) desc_len;
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
Serial.printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
Serial.printf("VID = %04x, PID = %04x\r\n", vid, pid);
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
if (itf_protocol == HID_ITF_PROTOCOL_MOUSE) {
Serial.printf("HID Mouse\r\n");
if (!tuh_hid_receive_report(dev_addr, instance)) {
Serial.printf("Error: cannot request to receive report\r\n");
}
}
}
// Invoked when device with hid interface is un-mounted
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
Serial.printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
}
// Invoked when received report from device via interrupt endpoint
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
filter_report((hid_mouse_report_t const *) report);
// continue to request to receive report
if (!tuh_hid_receive_report(dev_addr, instance)) {
Serial.printf("Error: cannot request to receive report\r\n");
}
}
} // extern C
//--------------------------------------------------------------------+
// Low pass filter Functions
//--------------------------------------------------------------------+
/*
* log_filter: Reduce large motions due to tremors by applying the natural log function
* Handles negative values and a dead zone where small values will not be adjusted
*/
int8_t log_filter(int8_t val) {
if (val < -1 * DEADZONE) {
return (int8_t) (-1.0 * POSTSCALE * logf(-1.0 * PRESCALE * (float) val));
} else if (val > DEADZONE) {
return (int8_t) (POSTSCALE * logf(PRESCALE * (float) val));
} else {
return val;
}
}
/*
* Adjust HID report by applying log_filter
*/
void filter_report(hid_mouse_report_t const *report) {
int8_t old_x = report->x;
int8_t old_y = report->y;
hid_mouse_report_t filtered_report = *report;
filtered_report.x = log_filter(old_x);
filtered_report.y = log_filter(old_y);
//Serial.printf("%d,%d,%d,%d\n", old_x, filtered_report.x, old_y, filtered_report.y);
usb_hid.sendReport(0, &filtered_report, sizeof(filtered_report));
}

View file

@ -0,0 +1,99 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
MIT license, check LICENSE for more information
Copyright (c) 2019 Ha Thach for Adafruit Industries
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/
#ifndef USBH_HELPER_H
#define USBH_HELPER_H
#ifdef ARDUINO_ARCH_RP2040
// pio-usb is required for rp2040 host
#include "pio_usb.h"
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_USB_HOST_DP
#define PIN_USB_HOST_DP 16
#endif
// Pin for enabling Host VBUS. comment out if not used
#ifndef PIN_5V_EN
#define PIN_5V_EN 18
#endif
#ifndef PIN_5V_EN_STATE
#define PIN_5V_EN_STATE 1
#endif
#endif // ARDUINO_ARCH_RP2040
#include "Adafruit_TinyUSB.h"
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// USB Host using MAX3421E: SPI, CS, INT
#include "SPI.h"
#if defined(ARDUINO_METRO_ESP32S2)
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
#endif
#else
// Native USB Host such as rp2040
Adafruit_USBH_Host USBHost;
#endif
//--------------------------------------------------------------------+
// Helper Functions
//--------------------------------------------------------------------+
#ifdef ARDUINO_ARCH_RP2040
static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
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");
while (1) {
delay(1);
}
}
#ifdef PIN_5V_EN
pinMode(PIN_5V_EN, OUTPUT);
digitalWrite(PIN_5V_EN, PIN_5V_EN_STATE);
#endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.pin_dp = PIN_USB_HOST_DP;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
// For pico-w, PIO is also used to communicate with cyw43
// Therefore we need to alternate the pio-usb configuration
// details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46
pio_cfg.sm_tx = 3;
pio_cfg.sm_rx = 2;
pio_cfg.sm_eop = 3;
pio_cfg.pio_rx_num = 0;
pio_cfg.pio_tx_num = 1;
pio_cfg.tx_ch = 9;
#endif
USBHost.configure_pio_usb(1, &pio_cfg);
}
#endif
#endif

View file

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

View file

@ -0,0 +1,205 @@
/*********************************************************************
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 depending on MCUs run on either:
* - rp2040: bit-banging 2 GPIOs with the help of Pico-PIO-USB library (roothub port1)
* - samd21/51, nrf52840, esp32: using MAX3421e controller (host shield)
*
* Requirements:
* - For rp2040:
* - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library
* - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1
* - Provide VBus (5v) and GND for peripheral
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed"
* - For samd21/51, nrf52840, esp32:
* - Additional MAX2341e USB Host shield or featherwing is required
* - SPI instance, CS pin, INT pin are correctly configured in usbh_helper.h
*/
/* Example sketch receive mouse report from host interface (from e.g consumer mouse)
* and apply a butterworth low pass filter with a specific CUTOFF_FREQUENCY on hid mouse movement report.
* Filtered report are send via device interface (to PC) acting as a "Mouse Tremor Filter".
*/
// USBHost is defined in usbh_helper.h
#include "usbh_helper.h"
// 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: 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 -------------//
// Butterworth low-pass filter coefficients
typedef struct {
float b0, b1, b2, a1, a2;
} butterworth_coeffs_t;
#define SAMPLING_FREQUENCY 100.0 // Hz
#define CUTOFF_FREQUENCY 10.0 // Hz
// x, y
butterworth_coeffs_t coeffs[2];
butterworth_coeffs_t butterworth_lowpass(float cutoff_frequency, float sampling_frequency);
void filter_report(hid_mouse_report_t const *report);
void setup() {
Serial.begin(115200);
usb_hid.begin();
coeffs[0] = butterworth_lowpass(CUTOFF_FREQUENCY, SAMPLING_FREQUENCY);
coeffs[1] = butterworth_lowpass(CUTOFF_FREQUENCY, SAMPLING_FREQUENCY);
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// init host stack on controller (rhport) 1
// For rp2040: this is called in core1's setup1()
USBHost.begin(1);
#endif
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("TinyUSB Mouse Tremor Filter Example");
}
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
//--------------------------------------------------------------------+
// Using Host shield MAX3421E controller
//--------------------------------------------------------------------+
void loop() {
USBHost.task();
Serial.flush();
}
#elif defined(ARDUINO_ARCH_RP2040)
//--------------------------------------------------------------------+
// For RP2040 use both core0 for device stack, core1 for host stack
//--------------------------------------------------------------------+
void loop() {
Serial.flush();
}
//------------- Core1 -------------//
void setup1() {
// configure pio-usb: defined in usbh_helper.h
rp2040_configure_pio_usb();
// run host stack on controller (rhport) 1
// Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
// host bit-banging processing works done in core1 to free up core0 for other works
USBHost.begin(1);
}
void loop1() {
USBHost.task();
}
#endif
//--------------------------------------------------------------------+
// TinyUSB Host callbacks
//--------------------------------------------------------------------+
extern "C"
{
// Invoked when device with hid interface is mounted
// Report descriptor is also available for use.
// tuh_hid_parse_report_descriptor() can be used to parse common/simple enough
// descriptor. Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE,
// it will be skipped therefore report_desc = NULL, desc_len = 0
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) {
(void) desc_report;
(void) desc_len;
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
Serial.printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
Serial.printf("VID = %04x, PID = %04x\r\n", vid, pid);
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
if (itf_protocol == HID_ITF_PROTOCOL_MOUSE) {
Serial.printf("HID Mouse\r\n");
if (!tuh_hid_receive_report(dev_addr, instance)) {
Serial.printf("Error: cannot request to receive report\r\n");
}
}
}
// Invoked when device with hid interface is un-mounted
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
Serial.printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
}
// Invoked when received report from device via interrupt endpoint
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
filter_report((hid_mouse_report_t const *) report);
// continue to request to receive report
if (!tuh_hid_receive_report(dev_addr, instance)) {
Serial.printf("Error: cannot request to receive report\r\n");
}
}
} // extern C
//--------------------------------------------------------------------+
// Low pass filter Functions
//--------------------------------------------------------------------+
butterworth_coeffs_t butterworth_lowpass(float cutoff_frequency, float sampling_frequency) {
butterworth_coeffs_t coe;
float omega = 2.0 * PI * cutoff_frequency / sampling_frequency;
float s = sin(omega);
float t = tan(omega / 2.0);
float alpha = s / (2.0 * t);
coe.b0 = 1.0 / (1.0 + 2.0 * alpha + 2.0 * alpha * alpha);
coe.b1 = 2.0 * coe.b0;
coe.b2 = coe.b0;
coe.a1 = 2.0 * (alpha * alpha - 1.0) * coe.b0;
coe.a2 = (1.0 - 2.0 * alpha + 2.0 * alpha * alpha) * coe.b0;
return coe;
}
float butterworth_filter(float data, butterworth_coeffs_t *coeffs, float *filtered, float *prev1, float *prev2) {
float output = coeffs->b0 * data + coeffs->b1 * (*prev1) + coeffs->b2 * (*prev2) - coeffs->a1 * (*filtered) -
coeffs->a2 * (*prev1);
*prev2 = *prev1;
*prev1 = data;
*filtered = output;
return output;
}
void filter_report(hid_mouse_report_t const *report) {
static float filtered[2] = { 0.0, 0.0 };
static float prev1[2] = { 0.0, 0.0 };
static float prev2[2] = { 0.0, 0.0 };
butterworth_filter(report->x, &coeffs[0], &filtered[0], &prev1[0], &prev2[0]);
butterworth_filter(report->y, &coeffs[1], &filtered[1], &prev1[1], &prev2[1]);
hid_mouse_report_t filtered_report = *report;
filtered_report.x = (int8_t) filtered[0];
filtered_report.y = (int8_t) filtered[1];
usb_hid.sendReport(0, &filtered_report, sizeof(filtered_report));
}

View file

@ -0,0 +1,99 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
MIT license, check LICENSE for more information
Copyright (c) 2019 Ha Thach for Adafruit Industries
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/
#ifndef USBH_HELPER_H
#define USBH_HELPER_H
#ifdef ARDUINO_ARCH_RP2040
// pio-usb is required for rp2040 host
#include "pio_usb.h"
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_USB_HOST_DP
#define PIN_USB_HOST_DP 16
#endif
// Pin for enabling Host VBUS. comment out if not used
#ifndef PIN_5V_EN
#define PIN_5V_EN 18
#endif
#ifndef PIN_5V_EN_STATE
#define PIN_5V_EN_STATE 1
#endif
#endif // ARDUINO_ARCH_RP2040
#include "Adafruit_TinyUSB.h"
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// USB Host using MAX3421E: SPI, CS, INT
#include "SPI.h"
#if defined(ARDUINO_METRO_ESP32S2)
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
#endif
#else
// Native USB Host such as rp2040
Adafruit_USBH_Host USBHost;
#endif
//--------------------------------------------------------------------+
// Helper Functions
//--------------------------------------------------------------------+
#ifdef ARDUINO_ARCH_RP2040
static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
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");
while (1) {
delay(1);
}
}
#ifdef PIN_5V_EN
pinMode(PIN_5V_EN, OUTPUT);
digitalWrite(PIN_5V_EN, PIN_5V_EN_STATE);
#endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.pin_dp = PIN_USB_HOST_DP;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
// For pico-w, PIO is also used to communicate with cyw43
// Therefore we need to alternate the pio-usb configuration
// details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46
pio_cfg.sm_tx = 3;
pio_cfg.sm_rx = 2;
pio_cfg.sm_eop = 3;
pio_cfg.pio_rx_num = 0;
pio_cfg.pio_tx_num = 1;
pio_cfg.tx_ch = 9;
#endif
USBHost.configure_pio_usb(1, &pio_cfg);
}
#endif
#endif

View file

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

View file

@ -9,103 +9,77 @@
any redistribution any redistribution
*********************************************************************/ *********************************************************************/
/* This example demonstrates use of both device and host, where /* This example demonstrates use of both device and host, where
* - Device run on native usb controller (controller0) * - Device run on native usb controller (roothub port0)
* - Host run on bit-banging 2 GPIOs with the help of Pico-PIO-USB library (controller1) * - Host depending on MCUs run on either:
* - rp2040: bit-banging 2 GPIOs with the help of Pico-PIO-USB library (roothub port1)
* - samd21/51, nrf52840, esp32: using MAX3421e controller (host shield)
* *
* Example sketch receive keyboard report from host interface (from e.g consumer keyboard) * Requirements:
* - For rp2040:
* - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library
* - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1
* - Provide VBus (5v) and GND for peripheral
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed"
* - For samd21/51, nrf52840, esp32:
* - Additional MAX2341e USB Host shield or featherwing is required
* - SPI instance, CS pin, INT pin are correctly configured in usbh_helper.h
*/
/* Example sketch receive keyboard report from host interface (from e.g consumer keyboard)
* and remap it to another key and send it via device interface (to PC). For simplicity, * and remap it to another key and send it via device interface (to PC). For simplicity,
* this example only toggle shift key to the report, effectively remap: * this example only toggle shift key to the report, effectively remap:
* - all character key <-> upper case * - all character key <-> upper case
* - number <-> its symbol (with shift) * - number <-> its symbol (with shift)
*
* Requirements:
* - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library
* - 2 consecutive GPIOs: D+ is defined by PIN_PIO_USB_HOST_DP, D- = D+ +1
* - Provide VBus (5v) and GND for peripheral
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed"
*/ */
// pio-usb is required for rp2040 host // USBHost is defined in usbh_helper.h
#include "pio_usb.h" #include "usbh_helper.h"
#include "Adafruit_TinyUSB.h"
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_PIO_USB_HOST_DP
#define PIN_PIO_USB_HOST_DP 20
#endif
// Pin for enabling Host VBUS. comment out if not used
#ifndef PIN_PIO_USB_HOST_VBUSEN
#define PIN_PIO_USB_HOST_VBUSEN 22
#endif
#ifndef PIN_PIO_USB_HOST_VBUSEN_STATE
#define PIN_PIO_USB_HOST_VBUSEN_STATE 1
#endif
// Language ID: English
#define LANGUAGE_ID 0x0409
// USB Host object
Adafruit_USBH_Host USBHost;
// HID report descriptor using TinyUSB's template // HID report descriptor using TinyUSB's template
// Single Report (no ID) descriptor // Single Report (no ID) descriptor
uint8_t const desc_hid_report[] = uint8_t const desc_hid_report[] = {
{ TUD_HID_REPORT_DESC_KEYBOARD()
TUD_HID_REPORT_DESC_KEYBOARD()
}; };
// USB HID object. For ESP32 these values cannot be changed after this declaration // USB HID object: desc report, desc len, protocol, interval, use out endpoint
// 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); Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_KEYBOARD, 2, false);
//--------------------------------------------------------------------+ void setup() {
// Setup and Loop on Core0
//--------------------------------------------------------------------+
void setup()
{
Serial.begin(115200); Serial.begin(115200);
usb_hid.begin(); usb_hid.begin();
//while ( !Serial ) delay(10); // wait for native usb #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// init host stack on controller (rhport) 1
// For rp2040: this is called in core1's setup1()
USBHost.begin(1);
#endif
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("TinyUSB Host HID Remap Example"); Serial.println("TinyUSB Host HID Remap Example");
} }
void loop() #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
{ //--------------------------------------------------------------------+
// Using Host shield MAX3421E controller
//--------------------------------------------------------------------+
void loop() {
USBHost.task();
} }
#elif defined(ARDUINO_ARCH_RP2040)
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Setup and Loop on Core1 // For RP2040 use both core0 for device stack, core1 for host stack
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
void loop() {
// nothing to do
}
//------------- Core1 -------------//
void setup1() { void setup1() {
//while ( !Serial ) delay(10); // wait for native usb // configure pio-usb: defined in usbh_helper.h
Serial.println("Core1 setup to run TinyUSB host with pio-usb"); rp2040_configure_pio_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 != 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 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);
}
#ifdef PIN_PIO_USB_HOST_VBUSEN
pinMode(PIN_PIO_USB_HOST_VBUSEN, OUTPUT);
digitalWrite(PIN_PIO_USB_HOST_VBUSEN, PIN_PIO_USB_HOST_VBUSEN_STATE);
#endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.pin_dp = PIN_PIO_USB_HOST_DP;
USBHost.configure_pio_usb(1, &pio_cfg);
// run host stack on controller (rhport) 1 // run host stack on controller (rhport) 1
// Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the // Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
@ -113,10 +87,16 @@ void setup1() {
USBHost.begin(1); USBHost.begin(1);
} }
void loop1() void loop1() {
{
USBHost.task(); USBHost.task();
} }
#endif
//--------------------------------------------------------------------+
// TinyUSB Host callbacks
//--------------------------------------------------------------------+
extern "C"
{
// Invoked when device with hid interface is mounted // Invoked when device with hid interface is mounted
// Report descriptor is also available for use. // Report descriptor is also available for use.
@ -124,8 +104,8 @@ void loop1()
// descriptor. Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, // descriptor. Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE,
// it will be skipped therefore report_desc = NULL, desc_len = 0 // it will be skipped therefore report_desc = NULL, desc_len = 0
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) { void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) {
(void)desc_report; (void) desc_report;
(void)desc_len; (void) desc_len;
uint16_t vid, pid; uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid); tuh_vid_pid_get(dev_addr, &vid, &pid);
@ -134,7 +114,7 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_re
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
if (itf_protocol == HID_ITF_PROTOCOL_KEYBOARD) { if (itf_protocol == HID_ITF_PROTOCOL_KEYBOARD) {
Serial.printf("HID Keyboard\r\n", vid, pid); Serial.printf("HID Keyboard\r\n");
if (!tuh_hid_receive_report(dev_addr, instance)) { if (!tuh_hid_receive_report(dev_addr, instance)) {
Serial.printf("Error: cannot request to receive report\r\n"); Serial.printf("Error: cannot request to receive report\r\n");
} }
@ -146,12 +126,11 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
Serial.printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); Serial.printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
} }
void remap_key(hid_keyboard_report_t const* original_report, hid_keyboard_report_t* remapped_report) void remap_key(hid_keyboard_report_t const *original_report, hid_keyboard_report_t *remapped_report) {
{
memcpy(remapped_report, original_report, sizeof(hid_keyboard_report_t)); memcpy(remapped_report, original_report, sizeof(hid_keyboard_report_t));
// only remap if not empty report i.e key released // only remap if not empty report i.e key released
for(uint8_t i=0; i<6; i++) { for (uint8_t i = 0; i < 6; i++) {
if (remapped_report->keycode[i] != 0) { if (remapped_report->keycode[i] != 0) {
// Note: we ignore right shift here // Note: we ignore right shift here
remapped_report->modifier ^= KEYBOARD_MODIFIER_LEFTSHIFT; remapped_report->modifier ^= KEYBOARD_MODIFIER_LEFTSHIFT;
@ -162,16 +141,16 @@ void remap_key(hid_keyboard_report_t const* original_report, hid_keyboard_report
// Invoked when received report from device via interrupt endpoint // Invoked when received report from device via interrupt endpoint
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
if ( len != 8 ) { if (len != 8) {
Serial.printf("report len = %u NOT 8, probably something wrong !!\r\n", len); Serial.printf("report len = %u NOT 8, probably something wrong !!\r\n", len);
}else { } else {
hid_keyboard_report_t remapped_report; hid_keyboard_report_t remapped_report;
remap_key((hid_keyboard_report_t const*) report, &remapped_report); remap_key((hid_keyboard_report_t const *) report, &remapped_report);
// send remapped report to PC // send remapped report to PC
// NOTE: for better performance you should save/queue remapped report instead of // NOTE: for better performance you should save/queue remapped report instead of
// blocking wait for usb_hid ready here // blocking wait for usb_hid ready here
while ( !usb_hid.ready() ) { while (!usb_hid.ready()) {
yield(); yield();
} }
@ -183,3 +162,5 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
Serial.printf("Error: cannot request to receive report\r\n"); Serial.printf("Error: cannot request to receive report\r\n");
} }
} }
}

View file

@ -0,0 +1,99 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
MIT license, check LICENSE for more information
Copyright (c) 2019 Ha Thach for Adafruit Industries
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/
#ifndef USBH_HELPER_H
#define USBH_HELPER_H
#ifdef ARDUINO_ARCH_RP2040
// pio-usb is required for rp2040 host
#include "pio_usb.h"
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_USB_HOST_DP
#define PIN_USB_HOST_DP 16
#endif
// Pin for enabling Host VBUS. comment out if not used
#ifndef PIN_5V_EN
#define PIN_5V_EN 18
#endif
#ifndef PIN_5V_EN_STATE
#define PIN_5V_EN_STATE 1
#endif
#endif // ARDUINO_ARCH_RP2040
#include "Adafruit_TinyUSB.h"
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// USB Host using MAX3421E: SPI, CS, INT
#include "SPI.h"
#if defined(ARDUINO_METRO_ESP32S2)
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
#endif
#else
// Native USB Host such as rp2040
Adafruit_USBH_Host USBHost;
#endif
//--------------------------------------------------------------------+
// Helper Functions
//--------------------------------------------------------------------+
#ifdef ARDUINO_ARCH_RP2040
static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
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");
while (1) {
delay(1);
}
}
#ifdef PIN_5V_EN
pinMode(PIN_5V_EN, OUTPUT);
digitalWrite(PIN_5V_EN, PIN_5V_EN_STATE);
#endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.pin_dp = PIN_USB_HOST_DP;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
// For pico-w, PIO is also used to communicate with cyw43
// Therefore we need to alternate the pio-usb configuration
// details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46
pio_cfg.sm_tx = 3;
pio_cfg.sm_rx = 2;
pio_cfg.sm_eop = 3;
pio_cfg.pio_rx_num = 0;
pio_cfg.pio_tx_num = 1;
pio_cfg.tx_ch = 9;
#endif
USBHost.configure_pio_usb(1, &pio_cfg);
}
#endif
#endif

View file

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

View file

@ -11,47 +11,43 @@
/* This example demonstrates use of both device and host, where /* This example demonstrates use of both device and host, where
* - Device run on native usb controller (controller0) * - Device run on native usb controller (roothub port0)
* - Host run on bit-banging 2 GPIOs with the help of Pico-PIO-USB library (controller1) * - Host depending on MCUs run on either:
* * - rp2040: bit-banging 2 GPIOs with the help of Pico-PIO-USB library (roothub port1)
* Example will log CPU temperature periodically (ms,value) to USB thumbdrive * - samd21/51, nrf52840, esp32: using MAX3421e controller (host shield)
* *
* Requirements: * Requirements:
* - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library * - For rp2040:
* - 2 consecutive GPIOs: D+ is defined by PIN_PIO_USB_HOST_DP, D- = D+ +1 * - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library
* - Provide VBus (5v) and GND for peripheral * - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed" * - Provide VBus (5v) and GND for peripheral
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed"
* - For samd21/51, nrf52840, esp32:
* - Additional MAX2341e USB Host shield or featherwing is required
* - SPI instance, CS pin, INT pin are correctly configured in usbh_helper.h
*/ */
// pio-usb is required for rp2040 host /* Example sketch read analog pin (default A0) and log it to LOG_FILE on the msc device
#include "pio_usb.h" * every LOG_INTERVAL ms. */
// nRF52 and ESP32 use freeRTOS, we may need to run USBhost.task() in its own rtos's thread.
// Since USBHost.task() will put loop() into dormant state and prevent followed code from running
// until there is USB host event.
#if defined(ARDUINO_NRF52_ADAFRUIT) || defined(ARDUINO_ARCH_ESP32)
#define USE_FREERTOS
#endif
// SdFat is required for using Adafruit_USBH_MSC_SdFatDevice // SdFat is required for using Adafruit_USBH_MSC_SdFatDevice
#include "SdFat.h" #include "SdFat_Adafruit_Fork.h"
// TinyUSB lib
#include "Adafruit_TinyUSB.h"
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_PIO_USB_HOST_DP
#define PIN_PIO_USB_HOST_DP 20
#endif
// Pin for enabling Host VBUS. comment out if not used
#ifndef PIN_PIO_USB_HOST_VBUSEN
#define PIN_PIO_USB_HOST_VBUSEN 22
#endif
#ifndef PIN_PIO_USB_HOST_VBUSEN_STATE
#define PIN_PIO_USB_HOST_VBUSEN_STATE 1
#endif
// USBHost is defined in usbh_helper.h
#include "usbh_helper.h"
#define LOG_FILE "cpu_temp.csv" #define LOG_FILE "cpu_temp.csv"
#define LOG_INTERVAL 5000 #define LOG_INTERVAL 5000
// USB Host object // Analog pin for reading
Adafruit_USBH_Host USBHost; const int analogPin = A0;
// USB Host MSC Block Device object which implemented API for use with SdFat // USB Host MSC Block Device object which implemented API for use with SdFat
Adafruit_USBH_MSC_BlockDevice msc_block_dev; Adafruit_USBH_MSC_BlockDevice msc_block_dev;
@ -63,77 +59,103 @@ File32 f_log;
// if file system is successfully mounted on usb block device // if file system is successfully mounted on usb block device
volatile bool is_mounted = false; volatile bool is_mounted = false;
//--------------------------------------------------------------------+ void data_log(void) {
// Setup and Loop on Core0
//--------------------------------------------------------------------+
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("TinyUSB Host MassStorage Data Logger Example");
}
void loop()
{
if (!is_mounted) { if (!is_mounted) {
// nothing to do // nothing to do
delay(1000); return;
}
static unsigned long last_ms = 0;
unsigned long ms = millis();
if ( ms - last_ms < LOG_INTERVAL ) {
return; return;
} }
// Turn on LED when start writing // Turn on LED when start writing
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, HIGH); digitalWrite(LED_BUILTIN, HIGH);
#endif
f_log = fatfs.open(LOG_FILE, O_WRITE | O_APPEND | O_CREAT); f_log = fatfs.open(LOG_FILE, O_WRITE | O_APPEND | O_CREAT);
if (!f_log) { if (!f_log) {
Serial.println("Cannot create file: " LOG_FILE); Serial.println("Cannot create file: " LOG_FILE);
}else { } else {
float cpu_temp = analogReadTemp(); int value = analogRead(analogPin);
uint32_t ms = millis();
Serial.printf("%u,%.02f\r\n", millis(), cpu_temp); Serial.printf("%lu,%d\r\n", ms, value);
f_log.printf("%u,%.02f\r\n", millis(), cpu_temp); f_log.printf("%lu,%d\r\n", ms, value);
f_log.close(); f_log.close();
} }
delay(LOG_INTERVAL); last_ms = ms;
Serial.flush();
} }
//--------------------------------------------------------------------+ #ifdef USE_FREERTOS
// Setup and Loop on Core1
//--------------------------------------------------------------------+
void setup1() { #ifdef ARDUINO_ARCH_ESP32
//while ( !Serial ) delay(10); // wait for native usb #define USBH_STACK_SZ 2048
Serial.println("Core1 setup to run TinyUSB host with pio-usb"); #else
#define USBH_STACK_SZ 200
// 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 != 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 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);
}
}
#ifdef PIN_PIO_USB_HOST_VBUSEN
pinMode(PIN_PIO_USB_HOST_VBUSEN, OUTPUT);
digitalWrite(PIN_PIO_USB_HOST_VBUSEN, PIN_PIO_USB_HOST_VBUSEN_STATE);
#endif #endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG; void usbhost_rtos_task(void *param) {
pio_cfg.pin_dp = PIN_PIO_USB_HOST_DP; (void) param;
USBHost.configure_pio_usb(1, &pio_cfg); while (1) {
USBHost.task();
}
}
#endif
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
// For rp2040: this is called in core1's setup1()
USBHost.begin(1);
#endif
#ifdef USE_FREERTOS
// Create a task to run USBHost.task() in background
xTaskCreate(usbhost_rtos_task, "usbh", USBH_STACK_SZ, NULL, 3, NULL);
#endif
// while ( !Serial ) delay(10); // wait for native usb
Serial.println("TinyUSB Host MassStorage Data Logger Example");
}
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
//--------------------------------------------------------------------+
// Using Host shield MAX3421E controller
//--------------------------------------------------------------------+
void loop() {
#ifndef USE_FREERTOS
USBHost.task();
#endif
data_log();
}
#elif defined(ARDUINO_ARCH_RP2040)
//--------------------------------------------------------------------+
// For RP2040 use both core0 for device stack, core1 for host stack
//--------------------------------------------------------------------+
void loop() {
data_log();
}
//------------- Core1 -------------//
void setup1() {
// configure pio-usb: defined in usbh_helper.h
rp2040_configure_pio_usb();
// run host stack on controller (rhport) 1 // run host stack on controller (rhport) 1
// Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the // Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
@ -141,51 +163,61 @@ void setup1() {
USBHost.begin(1); USBHost.begin(1);
} }
void loop1() void loop1() {
{
USBHost.task(); USBHost.task();
Serial.flush();
} }
#endif
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// TinyUSB Host callbacks // TinyUSB Host callbacks
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
bool write_complete_callback(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data) {
(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;
}
extern "C"
{
// Invoked when device is mounted (configured) // Invoked when device is mounted (configured)
void tuh_mount_cb (uint8_t daddr) void tuh_mount_cb(uint8_t daddr) {
{
(void) daddr; (void) daddr;
} }
/// Invoked when device is unmounted (bus reset/unplugged) /// Invoked when device is unmounted (bus reset/unplugged)
void tuh_umount_cb(uint8_t daddr) void tuh_umount_cb(uint8_t daddr) {
{
(void) daddr; (void) daddr;
} }
// Invoked when a device with MassStorage interface is mounted // Invoked when a device with MassStorage interface is mounted
void tuh_msc_mount_cb(uint8_t dev_addr) void tuh_msc_mount_cb(uint8_t dev_addr) {
{
// Initialize block device with MSC device address // Initialize block device with MSC device address
msc_block_dev.begin(dev_addr); msc_block_dev.begin(dev_addr);
// For simplicity this example only support LUN 0 // For simplicity this example only support LUN 0
msc_block_dev.setActiveLUN(0); msc_block_dev.setActiveLUN(0);
msc_block_dev.setWriteCompleteCallback(write_complete_callback); msc_block_dev.setWriteCompleteCallback(write_complete_callback);
is_mounted = fatfs.begin(&msc_block_dev); is_mounted = fatfs.begin(&msc_block_dev);
if (is_mounted) { if (is_mounted) {
fatfs.ls(&Serial, LS_SIZE); fatfs.ls(&Serial, LS_SIZE);
}else { } else {
Serial.println("Failed to mount mass storage device. Make sure it is formatted as FAT"); Serial.println("Failed to mount mass storage device. Make sure it is formatted as FAT");
} }
} }
// Invoked when a device with MassStorage interface is unmounted // Invoked when a device with MassStorage interface is unmounted
void tuh_msc_umount_cb(uint8_t dev_addr) void tuh_msc_umount_cb(uint8_t dev_addr) {
{
(void) dev_addr; (void) dev_addr;
// unmount file system // unmount file system
@ -196,17 +228,4 @@ void tuh_msc_umount_cb(uint8_t dev_addr)
msc_block_dev.end(); msc_block_dev.end();
} }
bool write_complete_callback(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data)
{
(void) dev_addr;
(void) cb_data;
// 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);
return true;
} }

View file

@ -0,0 +1,99 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
MIT license, check LICENSE for more information
Copyright (c) 2019 Ha Thach for Adafruit Industries
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/
#ifndef USBH_HELPER_H
#define USBH_HELPER_H
#ifdef ARDUINO_ARCH_RP2040
// pio-usb is required for rp2040 host
#include "pio_usb.h"
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_USB_HOST_DP
#define PIN_USB_HOST_DP 16
#endif
// Pin for enabling Host VBUS. comment out if not used
#ifndef PIN_5V_EN
#define PIN_5V_EN 18
#endif
#ifndef PIN_5V_EN_STATE
#define PIN_5V_EN_STATE 1
#endif
#endif // ARDUINO_ARCH_RP2040
#include "Adafruit_TinyUSB.h"
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// USB Host using MAX3421E: SPI, CS, INT
#include "SPI.h"
#if defined(ARDUINO_METRO_ESP32S2)
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
#endif
#else
// Native USB Host such as rp2040
Adafruit_USBH_Host USBHost;
#endif
//--------------------------------------------------------------------+
// Helper Functions
//--------------------------------------------------------------------+
#ifdef ARDUINO_ARCH_RP2040
static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
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");
while (1) {
delay(1);
}
}
#ifdef PIN_5V_EN
pinMode(PIN_5V_EN, OUTPUT);
digitalWrite(PIN_5V_EN, PIN_5V_EN_STATE);
#endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.pin_dp = PIN_USB_HOST_DP;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
// For pico-w, PIO is also used to communicate with cyw43
// Therefore we need to alternate the pio-usb configuration
// details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46
pio_cfg.sm_tx = 3;
pio_cfg.sm_rx = 2;
pio_cfg.sm_eop = 3;
pio_cfg.pio_rx_num = 0;
pio_cfg.pio_tx_num = 1;
pio_cfg.tx_ch = 9;
#endif
USBHost.configure_pio_usb(1, &pio_cfg);
}
#endif
#endif

View file

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

View file

@ -9,43 +9,28 @@
any redistribution any redistribution
*********************************************************************/ *********************************************************************/
/* This example demonstrates use of both device and host, where /* This example demonstrates use of both device and host, where
* - Device run on native usb controller (controller0) * - Device run on native usb controller (roothub port0)
* - Host run on bit-banging 2 GPIOs with the help of Pico-PIO-USB library (controller1) * - Host depending on MCUs run on either:
* - rp2040: bit-banging 2 GPIOs with the help of Pico-PIO-USB library (roothub port1)
* - samd21/51, nrf52840, esp32: using MAX3421e controller (host shield)
* *
* Requirements: * Requirements:
* - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library * - For rp2040:
* - 2 consecutive GPIOs: D+ is defined by PIN_PIO_USB_HOST_DP, D- = D+ +1 * - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library
* - Provide VBus (5v) and GND for peripheral * - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed" * - Provide VBus (5v) and GND for peripheral
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed"
* - For samd21/51, nrf52840, esp32:
* - Additional MAX2341e USB Host shield or featherwing is required
* - SPI instance, CS pin, INT pin are correctly configured in usbh_helper.h
*/ */
// pio-usb is required for rp2040 host
#include "pio_usb.h"
// SdFat is required for using Adafruit_USBH_MSC_SdFatDevice // SdFat is required for using Adafruit_USBH_MSC_SdFatDevice
#include "SdFat.h" #include "SdFat_Adafruit_Fork.h"
// TinyUSB lib // USBHost is defined in usbh_helper.h
#include "Adafruit_TinyUSB.h" #include "usbh_helper.h"
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_PIO_USB_HOST_DP
#define PIN_PIO_USB_HOST_DP 20
#endif
// Pin for enabling Host VBUS. comment out if not used
#ifndef PIN_PIO_USB_HOST_VBUSEN
#define PIN_PIO_USB_HOST_VBUSEN 22
#endif
#ifndef PIN_PIO_USB_HOST_VBUSEN_STATE
#define PIN_PIO_USB_HOST_VBUSEN_STATE 1
#endif
// USB Host object
Adafruit_USBH_Host USBHost;
// USB Host MSC Block Device object which implemented API for use with SdFat // USB Host MSC Block Device object which implemented API for use with SdFat
Adafruit_USBH_MSC_BlockDevice msc_block_dev; Adafruit_USBH_MSC_BlockDevice msc_block_dev;
@ -56,51 +41,40 @@ FatVolume fatfs;
// if file system is successfully mounted on usb block device // if file system is successfully mounted on usb block device
bool is_mounted = false; bool is_mounted = false;
//--------------------------------------------------------------------+ void setup() {
// Setup and Loop on Core0
//--------------------------------------------------------------------+
void setup()
{
Serial.begin(115200); Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// init host stack on controller (rhport) 1
// For rp2040: this is called in core1's setup1()
USBHost.begin(1);
#endif
// while ( !Serial ) delay(10); // wait for native usb
Serial.println("TinyUSB Host Mass Storage File Explorer Example"); Serial.println("TinyUSB Host Mass Storage File Explorer Example");
} }
void loop()
{ #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
//--------------------------------------------------------------------+
// Using Host shield MAX3421E controller
//--------------------------------------------------------------------+
void loop() {
USBHost.task();
Serial.flush();
} }
#elif defined(ARDUINO_ARCH_RP2040)
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Setup and Loop on Core1 // For RP2040 use both core0 for device stack, core1 for host stack
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
void loop() {
}
//------------- Core1 -------------//
void setup1() { void setup1() {
//while ( !Serial ) delay(10); // wait for native usb // configure pio-usb: defined in usbh_helper.h
Serial.println("Core1 setup to run TinyUSB host with pio-usb"); rp2040_configure_pio_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 != 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 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);
}
}
#ifdef PIN_PIO_USB_HOST_VBUSEN
pinMode(PIN_PIO_USB_HOST_VBUSEN, OUTPUT);
digitalWrite(PIN_PIO_USB_HOST_VBUSEN, PIN_PIO_USB_HOST_VBUSEN_STATE);
#endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.pin_dp = PIN_PIO_USB_HOST_DP;
USBHost.configure_pio_usb(1, &pio_cfg);
// run host stack on controller (rhport) 1 // run host stack on controller (rhport) 1
// Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the // Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
@ -108,30 +82,32 @@ void setup1() {
USBHost.begin(1); USBHost.begin(1);
} }
void loop1() void loop1() {
{
USBHost.task(); USBHost.task();
} }
#endif
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// TinyUSB Host callbacks // TinyUSB Host callbacks
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
extern "C"
{
// Invoked when device is mounted (configured) // Invoked when device is mounted (configured)
void tuh_mount_cb (uint8_t daddr) void tuh_mount_cb(uint8_t daddr) {
{
(void) daddr; (void) daddr;
} }
/// Invoked when device is unmounted (bus reset/unplugged) /// Invoked when device is unmounted (bus reset/unplugged)
void tuh_umount_cb(uint8_t daddr) void tuh_umount_cb(uint8_t daddr) {
{
(void) daddr; (void) daddr;
} }
// Invoked when a device with MassStorage interface is mounted // Invoked when a device with MassStorage interface is mounted
void tuh_msc_mount_cb(uint8_t dev_addr) void tuh_msc_mount_cb(uint8_t dev_addr) {
{ Serial.printf("Device attached, address = %d\r\n", dev_addr);
// Initialize block device with MSC device address // Initialize block device with MSC device address
msc_block_dev.begin(dev_addr); msc_block_dev.begin(dev_addr);
@ -146,9 +122,8 @@ void tuh_msc_mount_cb(uint8_t dev_addr)
} }
// Invoked when a device with MassStorage interface is unmounted // Invoked when a device with MassStorage interface is unmounted
void tuh_msc_umount_cb(uint8_t dev_addr) void tuh_msc_umount_cb(uint8_t dev_addr) {
{ Serial.printf("Device removed, address = %d\r\n", dev_addr);
(void) dev_addr;
// unmount file system // unmount file system
is_mounted = false; is_mounted = false;
@ -158,3 +133,4 @@ void tuh_msc_umount_cb(uint8_t dev_addr)
msc_block_dev.end(); msc_block_dev.end();
} }
}

View file

@ -0,0 +1,99 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
MIT license, check LICENSE for more information
Copyright (c) 2019 Ha Thach for Adafruit Industries
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/
#ifndef USBH_HELPER_H
#define USBH_HELPER_H
#ifdef ARDUINO_ARCH_RP2040
// pio-usb is required for rp2040 host
#include "pio_usb.h"
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_USB_HOST_DP
#define PIN_USB_HOST_DP 16
#endif
// Pin for enabling Host VBUS. comment out if not used
#ifndef PIN_5V_EN
#define PIN_5V_EN 18
#endif
#ifndef PIN_5V_EN_STATE
#define PIN_5V_EN_STATE 1
#endif
#endif // ARDUINO_ARCH_RP2040
#include "Adafruit_TinyUSB.h"
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// USB Host using MAX3421E: SPI, CS, INT
#include "SPI.h"
#if defined(ARDUINO_METRO_ESP32S2)
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
#endif
#else
// Native USB Host such as rp2040
Adafruit_USBH_Host USBHost;
#endif
//--------------------------------------------------------------------+
// Helper Functions
//--------------------------------------------------------------------+
#ifdef ARDUINO_ARCH_RP2040
static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
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");
while (1) {
delay(1);
}
}
#ifdef PIN_5V_EN
pinMode(PIN_5V_EN, OUTPUT);
digitalWrite(PIN_5V_EN, PIN_5V_EN_STATE);
#endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.pin_dp = PIN_USB_HOST_DP;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
// For pico-w, PIO is also used to communicate with cyw43
// Therefore we need to alternate the pio-usb configuration
// details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46
pio_cfg.sm_tx = 3;
pio_cfg.sm_rx = 2;
pio_cfg.sm_eop = 3;
pio_cfg.pio_rx_num = 0;
pio_cfg.pio_tx_num = 1;
pio_cfg.tx_ch = 9;
#endif
USBHost.configure_pio_usb(1, &pio_cfg);
}
#endif
#endif

View file

@ -0,0 +1 @@
CH32V20x_EVT

View file

@ -0,0 +1,268 @@
/*********************************************************************
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 depending on MCUs run on either:
* - rp2040: bit-banging 2 GPIOs with the help of Pico-PIO-USB library (roothub port1)
* - samd21/51, nrf52840, esp32: using MAX3421e controller (host shield)
*
* Requirements:
* - For rp2040:
* - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library
* - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1
* - Provide VBus (5v) and GND for peripheral
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed"
* - For samd21/51, nrf52840, esp32:
* - Additional MAX2341e USB Host shield or featherwing is required
* - SPI instance, CS pin, INT pin are correctly configured in usbh_helper.h
*/
/* Host example will get device descriptors of attached devices and print it out via
* device cdc (Serial) as follows:
* 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
*
*/
// USBHost is defined in usbh_helper.h
#include "usbh_helper.h"
// 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 };
void setup() {
Serial.begin(115200);
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// init host stack on controller (rhport) 1
// For rp2040: this is called in core1's setup1()
USBHost.begin(1);
#endif
// while ( !Serial ) delay(10); // wait for native usb
Serial.println("TinyUSB Dual Device Info Example");
}
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
//--------------------------------------------------------------------+
// Using Host shield MAX3421E controller
//--------------------------------------------------------------------+
void loop() {
USBHost.task();
Serial.flush();
}
#elif defined(ARDUINO_ARCH_RP2040)
//--------------------------------------------------------------------+
// For RP2040 use both core0 for device stack, core1 for host stack
//--------------------------------------------------------------------+
//------------- Core0 -------------//
void loop() {
}
//------------- Core1 -------------//
void setup1() {
//while ( !Serial ) delay(10); // wait for native usb
// configure pio-usb: defined in usbh_helper.h
rp2040_configure_pio_usb();
// run host stack on controller (rhport) 1
// Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
// host bit-banging processing works done in core1 to free up core0 for other works
USBHost.begin(1);
}
void loop1() {
USBHost.task();
Serial.flush();
}
#endif
//--------------------------------------------------------------------+
// 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

@ -0,0 +1,99 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
MIT license, check LICENSE for more information
Copyright (c) 2019 Ha Thach for Adafruit Industries
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/
#ifndef USBH_HELPER_H
#define USBH_HELPER_H
#ifdef ARDUINO_ARCH_RP2040
// pio-usb is required for rp2040 host
#include "pio_usb.h"
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_USB_HOST_DP
#define PIN_USB_HOST_DP 16
#endif
// Pin for enabling Host VBUS. comment out if not used
#ifndef PIN_5V_EN
#define PIN_5V_EN 18
#endif
#ifndef PIN_5V_EN_STATE
#define PIN_5V_EN_STATE 1
#endif
#endif // ARDUINO_ARCH_RP2040
#include "Adafruit_TinyUSB.h"
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// USB Host using MAX3421E: SPI, CS, INT
#include "SPI.h"
#if defined(ARDUINO_METRO_ESP32S2)
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
#else
// Default CS and INT are pin 10, 9
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
#endif
#else
// Native USB Host such as rp2040
Adafruit_USBH_Host USBHost;
#endif
//--------------------------------------------------------------------+
// Helper Functions
//--------------------------------------------------------------------+
#ifdef ARDUINO_ARCH_RP2040
static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
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");
while (1) {
delay(1);
}
}
#ifdef PIN_5V_EN
pinMode(PIN_5V_EN, OUTPUT);
digitalWrite(PIN_5V_EN, PIN_5V_EN_STATE);
#endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.pin_dp = PIN_USB_HOST_DP;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
// For pico-w, PIO is also used to communicate with cyw43
// Therefore we need to alternate the pio-usb configuration
// details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46
pio_cfg.sm_tx = 3;
pio_cfg.sm_rx = 2;
pio_cfg.sm_eop = 3;
pio_cfg.pio_rx_num = 0;
pio_cfg.pio_tx_num = 1;
pio_cfg.tx_ch = 9;
#endif
USBHost.configure_pio_usb(1, &pio_cfg);
}
#endif
#endif

View file

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

View file

@ -0,0 +1,241 @@
/*********************************************************************
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,252 +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 (controller0)
* - Host run on bit-banging 2 GPIOs with the help of Pico-PIO-USB library (controller1)
*
* Requirements:
* - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library
* - 2 consecutive GPIOs: D+ is defined by PIN_PIO_USB_HOST_DP, D- = D+ +1
* - Provide VBus (5v) and GND for peripheral
* - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed"
*
* RP2040 host stack will get device descriptors of attached devices and print it out via
* device cdc (Serial) as follows:
* 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
*
*/
// pio-usb is required for rp2040 host
#include "pio_usb.h"
#include "Adafruit_TinyUSB.h"
// Pin D+ for host, D- = D+ + 1
#ifndef PIN_PIO_USB_HOST_DP
#define PIN_PIO_USB_HOST_DP 20
#endif
// Pin for enabling Host VBUS. comment out if not used
#ifndef PIN_PIO_USB_HOST_VBUSEN
#define PIN_PIO_USB_HOST_VBUSEN 22
#endif
#ifndef PIN_PIO_USB_HOST_VBUSEN_STATE
#define PIN_PIO_USB_HOST_VBUSEN_STATE 1
#endif
// Language ID: English
#define LANGUAGE_ID 0x0409
// USB Host object
Adafruit_USBH_Host USBHost;
// holding device descriptor
tusb_desc_device_t desc_device;
//--------------------------------------------------------------------+
// Setup and Loop on Core0
//--------------------------------------------------------------------+
// the setup function runs once when you press reset or power the board
void setup()
{
Serial1.begin(115200);
Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("TinyUSB Dual Device Info Example");
}
void loop()
{
}
//--------------------------------------------------------------------+
// Setup and Loop on Core1
//--------------------------------------------------------------------+
void setup1() {
//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 120Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
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 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);
}
}
#ifdef PIN_PIO_USB_HOST_VBUSEN
pinMode(PIN_PIO_USB_HOST_VBUSEN, OUTPUT);
digitalWrite(PIN_PIO_USB_HOST_VBUSEN, PIN_PIO_USB_HOST_VBUSEN_STATE);
#endif
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.pin_dp = PIN_PIO_USB_HOST_DP;
USBHost.configure_pio_usb(1, &pio_cfg);
// run host stack on controller (rhport) 1
// Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
// host bit-banging processing works done in core1 to free up core0 for other works
USBHost.begin(1);
}
void loop1()
{
USBHost.task();
}
//--------------------------------------------------------------------+
// TinyUSB Host callbacks
//--------------------------------------------------------------------+
// Invoked when device is mounted (configured)
void tuh_mount_cb (uint8_t daddr)
{
Serial.printf("Device attached, address = %d\r\n", daddr);
// Get Device Descriptor
tuh_descriptor_get_device(daddr, &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);
}
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;
Serial.printf("Device %u: ID %04x:%04x\r\n", daddr, desc_device.idVendor, desc_device.idProduct);
Serial.printf("Device Descriptor:\r\n");
Serial.printf(" bLength %u\r\n" , desc_device.bLength);
Serial.printf(" bDescriptorType %u\r\n" , desc_device.bDescriptorType);
Serial.printf(" bcdUSB %04x\r\n" , desc_device.bcdUSB);
Serial.printf(" bDeviceClass %u\r\n" , desc_device.bDeviceClass);
Serial.printf(" bDeviceSubClass %u\r\n" , desc_device.bDeviceSubClass);
Serial.printf(" bDeviceProtocol %u\r\n" , desc_device.bDeviceProtocol);
Serial.printf(" bMaxPacketSize0 %u\r\n" , desc_device.bMaxPacketSize0);
Serial.printf(" idVendor 0x%04x\r\n" , desc_device.idVendor);
Serial.printf(" idProduct 0x%04x\r\n" , desc_device.idProduct);
Serial.printf(" bcdDevice %04x\r\n" , desc_device.bcdDevice);
// Get String descriptor using Sync API
uint16_t temp_buf[128];
Serial.printf(" iManufacturer %u " , desc_device.iManufacturer);
if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf)) )
{
print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf));
}
Serial.printf("\r\n");
Serial.printf(" iProduct %u " , desc_device.iProduct);
if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf)))
{
print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf));
}
Serial.printf("\r\n");
Serial.printf(" iSerialNumber %u " , desc_device.iSerialNumber);
if (XFER_RESULT_SUCCESS == tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf)))
{
print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf));
}
Serial.printf("\r\n");
Serial.printf(" bNumConfigurations %u\r\n" , desc_device.bNumConfigurations);
}
//--------------------------------------------------------------------+
// 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;
}
static void print_utf16(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, sizeof(uint16_t) * buf_len);
((uint8_t*) temp_buf)[utf8_len] = '\0';
Serial.printf((char*)temp_buf);
}

View file

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

View file

@ -10,93 +10,73 @@
*********************************************************************/ *********************************************************************/
#include "Adafruit_TinyUSB.h" #include "Adafruit_TinyUSB.h"
#include <Adafruit_NeoPixel.h>
/* This sketch demonstrates USB HID keyboard. /* This sketch demonstrates USB HID keyboard.
* - PIN A0-A5 is used to send digit '0' to '5' respectively * - PIN A0-A3 is used to send digit '0' to '3' respectively
* (On the RP2040, pins D0-D5 used) * (On the RP2040, pins D0-D5 used)
* - LED and/or Neopixels will be used as Capslock indicator * - LED and/or Neopixels will be used as Capslock indicator
*/ */
// HID report descriptor using TinyUSB's template // HID report descriptor using TinyUSB's template
// Single Report (no ID) descriptor // Single Report (no ID) descriptor
uint8_t const desc_hid_report[] = uint8_t const desc_hid_report[] = {
{ TUD_HID_REPORT_DESC_KEYBOARD()
TUD_HID_REPORT_DESC_KEYBOARD()
}; };
// USB HID object. For ESP32 these values cannot be changed after this declaration // USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint // 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); Adafruit_USBD_HID usb_hid;
//------------- Input Pins -------------// //------------- Input Pins -------------//
// Array of pins and its keycode. // Array of pins and its keycode.
// Notes: these pins can be replaced by PIN_BUTTONn if defined in setup() // Notes: these pins can be replaced by PIN_BUTTONn if defined in setup()
#ifdef ARDUINO_ARCH_RP2040 #ifdef ARDUINO_ARCH_RP2040
uint8_t pins[] = { D0, D1, D2, D3 }; uint8_t pins[] = { D0, D1, D2, D3 };
#else #else
uint8_t pins[] = { A0, A1, A2, A3 }; uint8_t pins[] = {A0, A1, A2, A3};
#endif #endif
// number of pins // 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 // For keycode definition check out https://github.com/hathach/tinyusb/blob/master/src/class/hid/hid.h
uint8_t hidcode[] = { HID_KEY_ARROW_RIGHT, HID_KEY_ARROW_LEFT, HID_KEY_ARROW_DOWN, HID_KEY_ARROW_UP }; uint8_t hidcode[] = {HID_KEY_0, HID_KEY_1, HID_KEY_2, HID_KEY_3};
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY) || defined(ARDUINO_FUNHOUSE_ESP32S2) #if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY) || defined(ARDUINO_FUNHOUSE_ESP32S2)
bool activeState = true; bool activeState = true;
#else #else
bool activeState = false; bool activeState = false;
#endif #endif
//------------- Neopixel -------------//
// #define PIN_NEOPIXEL 8
#ifdef PIN_NEOPIXEL
// 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 // the setup function runs once when you press reset or power the board
void setup() void setup() {
{ // Manual begin() is required on core without built-in support e.g. mbed rp2040
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040) if (!TinyUSBDevice.isInitialized()) {
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040 TinyUSBDevice.begin(0);
TinyUSB_Device_Init(0); }
#endif
// Notes: following commented-out functions has no affect on ESP32 // Setup HID
// usb_hid.setBootProtocol(HID_ITF_PROTOCOL_KEYBOARD); usb_hid.setBootProtocol(HID_ITF_PROTOCOL_KEYBOARD);
// usb_hid.setPollInterval(2); usb_hid.setPollInterval(2);
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report)); usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
// usb_hid.setStringDescriptor("TinyUSB Keyboard"); usb_hid.setStringDescriptor("TinyUSB Keyboard");
// Set up output report (on control endpoint) for Capslock indicator // Set up output report (on control endpoint) for Capslock indicator
usb_hid.setReportCallback(NULL, hid_report_callback); usb_hid.setReportCallback(NULL, hid_report_callback);
usb_hid.begin(); 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 // led pin
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT); pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW); 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 #endif
// overwrite input pin with PIN_BUTTONx // overwrite input pin with PIN_BUTTONx
@ -117,32 +97,21 @@ void setup()
#endif #endif
// Set up pin as input // 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); 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 // used to avoid send multiple consecutive zero report for keyboard
static bool keyPressedPreviously = false; static bool keyPressedPreviously = false;
uint8_t count=0; uint8_t count = 0;
uint8_t keycode[6] = { 0 }; uint8_t keycode[6] = {0};
// scan normal key and send report // scan normal key and send report
for(uint8_t i=0; i < pincount; i++) for (uint8_t i = 0; i < pincount; i++) {
{ if (activeState == digitalRead(pins[i])) {
if ( activeState == digitalRead(pins[i]) )
{
// if pin is active (low), add its hid code to key report // if pin is active (low), add its hid code to key report
keycode[count++] = hidcode[i]; keycode[count++] = hidcode[i];
@ -151,55 +120,66 @@ void loop()
} }
} }
if ( TinyUSBDevice.suspended() && count ) if (TinyUSBDevice.suspended() && count) {
{
// Wake up host if we are in suspend mode // Wake up host if we are in suspend mode
// and REMOTE_WAKEUP feature is enabled by host // and REMOTE_WAKEUP feature is enabled by host
TinyUSBDevice.remoteWakeup(); TinyUSBDevice.remoteWakeup();
} }
// skip if hid is not ready e.g still transferring previous report // 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 // Send report if there is key pressed
uint8_t const report_id = 0; uint8_t const report_id = 0;
uint8_t const modifier = 0; uint8_t const modifier = 0;
keyPressedPreviously = true; keyPressedPreviously = true;
usb_hid.keyboardReport(report_id, modifier, keycode); usb_hid.keyboardReport(report_id, modifier, keycode);
}else } else {
{
// Send All-zero report to indicate there is no keys pressed // 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 // 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() // every loop(), only a key is pressed in previous loop()
if ( keyPressedPreviously ) if (keyPressedPreviously) {
{
keyPressedPreviously = false; keyPressedPreviously = false;
usb_hid.keyboardRelease(0); 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 // 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) report_id;
(void) bufsize; (void) bufsize;
// LED indicator is output report with only 1 byte length // 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_* ) // The LED bit map is as follows: (also defined by KEYBOARD_LED_* )
// Kana (4) | Compose (3) | ScrollLock (2) | CapsLock (1) | Numlock (0) // Kana (4) | Compose (3) | ScrollLock (2) | CapsLock (1) | Numlock (0)
uint8_t ledIndicator = buffer[0]; uint8_t ledIndicator = buffer[0];
#ifdef LED_BUILTIN
// turn on LED if capslock is set // turn on LED if capslock is set
digitalWrite(LED_BUILTIN, ledIndicator & KEYBOARD_LED_CAPSLOCK); digitalWrite(LED_BUILTIN, ledIndicator & KEYBOARD_LED_CAPSLOCK);
#ifdef PIN_NEOPIXEL
pixels.fill(ledIndicator & KEYBOARD_LED_CAPSLOCK ? 0xff0000 : 0x000000);
pixels.show();
#endif #endif
} }

View file

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

View file

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

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

View file

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

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

View file

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

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

View file

@ -0,0 +1,153 @@
/*********************************************************************
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 multiple USB HID interfaces. Pressing the button will
* - mouse toward bottom right of monitor
* - send 'a' key
*
* Depending on the board, the button pin
* 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;
#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;
#elif defined PIN_BUTTON
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;
#endif
// HID report descriptor using TinyUSB's template
uint8_t const desc_keyboard_report[] = {
TUD_HID_REPORT_DESC_KEYBOARD()
};
uint8_t const desc_mouse_report[] = {
TUD_HID_REPORT_DESC_MOUSE()
};
// USB HID objects
Adafruit_USBD_HID usb_keyboard;
Adafruit_USBD_HID usb_mouse;
// 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);
// 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.println("Adafruit TinyUSB HID Composite example");
}
void process_hid() {
// Whether button is pressed
bool btn_pressed = (digitalRead(pin) == activeState);
// Remote wakeup
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) {
int8_t const delta = 5;
usb_mouse.mouseMove(0, delta, delta); // right + down
}
/*------------- Keyboard -------------*/
if (usb_keyboard.ready()) {
// use to send key release report
static bool has_key = false;
if (btn_pressed) {
uint8_t keycode[6] = {0};
keycode[0] = HID_KEY_A;
usb_keyboard.keyboardReport(0, 0, keycode);
has_key = true;
} 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

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,225 @@
/*********************************************************************
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 native controller as host (TinyUSB Host)
* Note:
* - For most mcu with only 1 native usb, Serial is not available. We will use Serial1 instead
*
* Host example will get device descriptors of attached devices and print it out as follows:
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"
#ifndef USE_TINYUSB_HOST
#error This example requires usb stack configured as host in "Tools -> USB Stack -> Adafruit TinyUSB Host"
#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 };
Adafruit_USBH_Host USBHost;
//--------------------------------------------------------------------+
// setup() & loop()
//--------------------------------------------------------------------+
void setup() {
Serial1.begin(115200);
Serial1.println("TinyUSB Host: Device Info Example");
// Init USB Host on native controller roothub port0
USBHost.begin(0);
}
void loop() {
USBHost.task();
Serial1.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) {
Serial1.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) {
Serial1.println("No device connected (except hub)");
}
}
// Invoked when device is mounted (configured)
void tuh_mount_cb(uint8_t daddr) {
Serial1.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) {
Serial1.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) {
Serial1.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;
Serial1.printf("Device %u: ID %04x:%04x\r\n", daddr, desc->idVendor, desc->idProduct);
Serial1.printf("Device Descriptor:\r\n");
Serial1.printf(" bLength %u\r\n" , desc->bLength);
Serial1.printf(" bDescriptorType %u\r\n" , desc->bDescriptorType);
Serial1.printf(" bcdUSB %04x\r\n" , desc->bcdUSB);
Serial1.printf(" bDeviceClass %u\r\n" , desc->bDeviceClass);
Serial1.printf(" bDeviceSubClass %u\r\n" , desc->bDeviceSubClass);
Serial1.printf(" bDeviceProtocol %u\r\n" , desc->bDeviceProtocol);
Serial1.printf(" bMaxPacketSize0 %u\r\n" , desc->bMaxPacketSize0);
Serial1.printf(" idVendor 0x%04x\r\n" , desc->idVendor);
Serial1.printf(" idProduct 0x%04x\r\n" , desc->idProduct);
Serial1.printf(" bcdDevice %04x\r\n" , desc->bcdDevice);
// Get String descriptor using Sync API
Serial1.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));
Serial1.printf((char *) dev->manufacturer);
}
Serial1.printf("\r\n");
Serial1.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));
Serial1.printf((char *) dev->product);
}
Serial1.printf("\r\n");
Serial1.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));
Serial1.printf((char *) dev->serial);
}
Serial1.printf("\r\n");
Serial1.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

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

View file

@ -19,28 +19,43 @@
// USB MIDI object with 3 ports // USB MIDI object with 3 ports
Adafruit_USBD_MIDI usb_midi(3); Adafruit_USBD_MIDI usb_midi(3);
void setup() void setup() {
{ #ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT); pinMode(LED_BUILTIN, OUTPUT);
#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 #endif
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
// Set name for each cable, must be done before usb_midi.begin() // Set name for each cable, must be done before usb_midi.begin()
usb_midi.setCableName(1, "Keyboard"); usb_midi.setCableName(1, "Keyboard");
usb_midi.setCableName(2, "Drum Pads"); usb_midi.setCableName(2, "Drum Pads");
usb_midi.setCableName(3, "Lights"); usb_midi.setCableName(3, "Lights");
usb_midi.begin(); 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() void loop() {
{ #ifdef TINYUSB_NEED_POLLING_TASK
digitalWrite(LED_BUILTIN, HIGH); // Manual call tud_task since it isn't called by Core's background
delay(1000); TinyUSBDevice.task();
#endif
digitalWrite(LED_BUILTIN, LOW); // toggle LED
delay(1000); 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
}
} }

View file

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

View file

@ -31,65 +31,74 @@ uint32_t position = 0;
// Store example melody as an array of note values // Store example melody as an array of note values
byte note_sequence[] = { 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, 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, 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 56, 61, 64, 68, 74, 78, 81, 86, 90, 93, 98, 102
}; };
void setup() void setup() {
{ // Manual begin() is required on core without built-in support e.g. mbed rp2040
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040) if (!TinyUSBDevice.isInitialized()) {
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040 TinyUSBDevice.begin(0);
TinyUSB_Device_Init(0); }
#endif
pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200);
//usb_midi.setStringDescriptor("TinyUSB MIDI"); usb_midi.setStringDescriptor("TinyUSB MIDI");
// Initialize MIDI, and listen to all MIDI channels // Initialize MIDI, and listen to all MIDI channels
// This will also call usb_midi's begin() // This will also call usb_midi's begin()
MIDI.begin(MIDI_CHANNEL_OMNI); 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 // Attach the handleNoteOn function to the MIDI Library. It will
// be called whenever the Bluefruit receives MIDI Note On messages. // be called whenever the Bluefruit receives MIDI Note On messages.
MIDI.setHandleNoteOn(handleNoteOn); MIDI.setHandleNoteOn(handleNoteOn);
// Do the same for MIDI Note Off messages. // Do the same for MIDI Note Off messages.
MIDI.setHandleNoteOff(handleNoteOff); MIDI.setHandleNoteOff(handleNoteOff);
Serial.begin(115200);
// wait until device mounted
while( !TinyUSBDevice.mounted() ) delay(1);
} }
void loop() 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;
}
static uint32_t start_ms = 0; static uint32_t start_ms = 0;
if ( millis() - start_ms > 266 ) if (millis() - start_ms > 266) {
{
start_ms += 266; start_ms += 266;
// Setup variables for the current and previous // Setup variables for the current and previous
// positions in the note sequence. // positions in the note sequence.
int previous = position - 1; int previous = position - 1;
// If we currently are at position 0, set the // If we currently are at position 0, set the
// previous position to the last note in the sequence. // previous position to the last note in the sequence.
if (previous < 0) { if (previous < 0) {
previous = sizeof(note_sequence) - 1; previous = sizeof(note_sequence) - 1;
} }
// Send Note On for current position at full velocity (127) on channel 1. // Send Note On for current position at full velocity (127) on channel 1.
MIDI.sendNoteOn(note_sequence[position], 127, 1); MIDI.sendNoteOn(note_sequence[position], 127, 1);
// Send Note Off for previous note. // Send Note Off for previous note.
MIDI.sendNoteOff(note_sequence[previous], 0, 1); MIDI.sendNoteOff(note_sequence[previous], 0, 1);
// Increment position // Increment position
position++; position++;
// If we are at the end of the sequence, start over. // If we are at the end of the sequence, start over.
if (position >= sizeof(note_sequence)) { if (position >= sizeof(note_sequence)) {
position = 0; position = 0;
@ -97,11 +106,10 @@ void loop()
} }
// read any new MIDI messages // 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. // Log when a note is pressed.
Serial.print("Note on: channel = "); Serial.print("Note on: channel = ");
Serial.print(channel); Serial.print(channel);
@ -113,8 +121,7 @@ void handleNoteOn(byte channel, byte pitch, byte velocity)
Serial.println(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. // Log when a note is released.
Serial.print("Note off: channel = "); Serial.print("Note off: channel = ");
Serial.print(channel); Serial.print(channel);

View file

@ -32,7 +32,7 @@
*/ */
#include "SPI.h" #include "SPI.h"
#include "SdFat.h" #include "SdFat_Adafruit_Fork.h"
#include "Adafruit_SPIFlash.h" #include "Adafruit_SPIFlash.h"
#include "Adafruit_TinyUSB.h" #include "Adafruit_TinyUSB.h"
@ -93,14 +93,19 @@ void setupMassStorage(void)
// MSC is ready for read/write // MSC is ready for read/write
fs_changed = false; fs_changed = false;
usb_msc.setReadyCallback(0, msc_ready_callback); usb_msc.setReadyCallback(0, msc_ready_callback);
usb_msc.begin(); 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 // Init file system on the flash
fs_formatted = fatfs.begin(&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"); DBG_SERIAL.println("Failed to init files system, flash may not be formatted");
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -10,31 +10,69 @@
*********************************************************************/ *********************************************************************/
/* This example expose SD card as mass storage using /* This example expose SD card as mass storage using
* SdFat Library * - SdFat https://github.com/adafruit/SdFat
*/ */
#include "SPI.h" #include "SPI.h"
#include "SdFat.h" #include "SdFat_Adafruit_Fork.h"
#include "Adafruit_TinyUSB.h" #include "Adafruit_TinyUSB.h"
const int chipSelect = 10; //--------------------------------------------------------------------+
// 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
// File system on SD Card // File system on SD Card
SdFat sd; SdFat sd;
SdFile root;
SdFile file;
// USB Mass Storage object // USB Mass Storage object
Adafruit_USBD_MSC usb_msc; 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 // the setup function runs once when you press reset or power the board
void setup() void setup() {
{ #ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT); 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 // 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"); usb_msc.setID("Adafruit", "SD Card", "1.0");
@ -47,30 +85,27 @@ void setup()
usb_msc.setUnitReady(false); usb_msc.setUnitReady(false);
usb_msc.begin(); usb_msc.begin();
Serial.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 ) delay(10); // wait for native usb //while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mass Storage SD Card example"); Serial.println("Adafruit TinyUSB Mass Storage SD Card example");
Serial.print("\nInitializing SD card ... "); Serial.print("\nInitializing SD card ... ");
Serial.print("CS = "); Serial.println(chipSelect);
if ( !sd.begin(chipSelect, SD_SCK_MHZ(50)) ) if (!sd.begin(SD_CONFIG)) {
{
Serial.println("initialization failed. Things to check:"); Serial.println("initialization failed. Things to check:");
Serial.println("* is a card inserted?"); Serial.println("- is a card inserted?");
Serial.println("* is your wiring correct?"); Serial.println("- is your wiring correct?");
Serial.println("* did you change the chipSelect pin to match your shield or module?"); Serial.println("- did you change the SDCARD_CS or SDIO pin to match your shield or module?");
while (1) delay(1); while (1) delay(1);
} }
// Size in blocks (512 bytes) // Size in blocks (512 bytes)
#if SD_FAT_VERSION >= 20000
uint32_t block_count = sd.card()->sectorCount(); uint32_t block_count = sd.card()->sectorCount();
#else
uint32_t block_count = sd.card()->cardSize();
#endif
Serial.print("Volume size (MB): "); Serial.print("Volume size (MB): ");
Serial.println((block_count/2) / 1024); Serial.println((block_count/2) / 1024);
@ -79,91 +114,38 @@ void setup()
// MSC is ready for read/write // MSC is ready for read/write
usb_msc.setUnitReady(true); usb_msc.setUnitReady(true);
fs_changed = true; // to print contents initially
} }
void loop() void loop() {
{ // noting to do
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. // Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and // Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size) // 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) {
{ bool rc = sd.card()->readSectors(lba, (uint8_t*) buffer, bufsize/512);
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; return rc ? bufsize : -1;
} }
// Callback invoked when received WRITE10 command. // Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and // Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size) // 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) {
{ #ifdef LED_BUILTIN
bool rc;
digitalWrite(LED_BUILTIN, HIGH); 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 #endif
bool rc = sd.card()->writeSectors(lba, buffer, bufsize/512);
return rc ? bufsize : -1; return rc ? bufsize : -1;
} }
// Callback invoked when WRITE10 command is completed (status received and accepted by host). // Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache. // 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.card()->syncDevice();
#else sd.cacheClear(); // clear file system's cache to force refresh
sd.card()->syncBlocks();
#endif
// clear file system's cache to force refresh
sd.cacheClear();
fs_changed = true;
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, LOW); digitalWrite(LED_BUILTIN, LOW);
#endif
} }

View file

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

View file

@ -64,15 +64,29 @@ Adafruit_USBD_I2C::Adafruit_USBD_I2C(TwoWire* wire) {
setStringDescriptor("I2C Interface"); setStringDescriptor("I2C Interface");
} }
uint16_t Adafruit_USBD_I2C::getInterfaceDescriptor(uint8_t itfnum, uint8_t* buf, uint16_t bufsize) { uint16_t Adafruit_USBD_I2C::getInterfaceDescriptor(uint8_t itfnum_deprecated, uint8_t* buf, uint16_t bufsize) {
uint8_t desc[] = { TUD_VENDOR_DESCRIPTOR(itfnum, 0, 0x00, 0x80, 64) }; 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 const len = sizeof(desc); uint16_t const len = sizeof(desc);
if (buf) { if (buf) {
if (bufsize < len) { if (bufsize < len) {
return 0; return 0;
} }
memcpy(buf, desc, len); memcpy(buf, desc, len);
} }
return len; return len;
} }

View file

@ -88,11 +88,13 @@
class Adafruit_USBD_I2C : public Adafruit_USBD_Interface { class Adafruit_USBD_I2C : public Adafruit_USBD_Interface {
public: public:
Adafruit_USBD_I2C(TwoWire* wire); 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 begin(uint8_t* buffer, size_t bufsize);
bool handleControlTransfer(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request); 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: private:
TwoWire* _wire; TwoWire* _wire;
uint8_t _state; uint8_t _state;

View file

@ -63,6 +63,13 @@ void setup() {
// init i2c usb with buffer and size // init i2c usb with buffer and size
i2c_usb.begin(i2c_buf, sizeof(i2c_buf)); 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() { void loop() {

View file

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

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