You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

267 lines
10 KiB

//=============================================================================
// Simple USBHost USBSerial test
// This sketch is very much like the main teensy example: USBtoSerial.ino
// but instead of going to hardware serial port it forwards the data
// between the USB Serial and a USB Serial device connected to the USB Host
// port.
//
// This example is in the public domain
//=============================================================================
#include <USBHost_t36.h>
//=============================================================================
// Options
//=============================================================================
// uncomment the line below to output debug information
//#define DEBUG_OUTPUT
// Uncomment the line below to print out information about the USB devices that attach.
#define PRINT_DEVICE_INFO
#define USBBAUD 1000000 //115200
uint32_t baud = USBBAUD;
uint32_t format = USBHOST_SERIAL_8N1;
USBHost myusb;
//=============================================================================
// USB Objects
//=============================================================================
// Optional if you use are possibly going to plug your USB Serial device
// into a USB Hub, you should include one or more USB Hub objects.
// How many? depends as some HUB chips support lets say 4 ports, so if the HUB
// actuall has more than this, than internally it may be made up using multiple
// HUBs and you may need one of the hub objects for each one of these.
USBHub hub1(myusb);
//USBHub hub2(myusb);
//USBHub hub3(myusb);
// There is now two versions of the USBSerial class, that are both derived from a common Base class
// The difference is on how large of transfers that it can handle. This is controlled by
// the device descriptor, where up to now we handled those up to 64 byte USB transfers.
// But there are now new devices that support larger transfer like 512 bytes. This for example
// includes the Teensy 4.x boards. For these we need the big buffer version.
// uncomment one of the following defines for userial
//USBSerial userial(myusb); // works only for those Serial devices who transfer <=64 bytes (like T3.x, FTDI...)
USBSerial_BigBuffer userial(myusb, 1); // Handles anything up to 512 bytes
//USBSerial_BigBuffer userial(myusb); // Handles up to 512 but by default only for those > 64 bytesUSBHost myusb;
// We also now have an optional set of parameters for the constructor that allows you to pass in a Vendor ID,
// product ID, what it maps to and the like, to handle USB objects which have underlying USB to serial converters,
// that are known, but not in our list.
//USBSerial_BigBuffer userial(myusb, 1, 0x10c4, 0xea60, USBSerialBase::CP210X, 0); // Handles anything up to 512 bytes
//
// Although not the Serial class, this sketch can also handle forwarding of the Teensy Serial Emulation object (SEREMU)
// may need multpile HID Parser objects depending on what other USB types the object supports.
//#define USERIAL_IS_SEREMU // SEREMU is not a top level device, so we need to update device tables for this
#ifdef USERIAL_IS_SEREMU
USBHIDParser hid1(myusb);
USBHIDParser hid2(myusb);
USBSerialEmu userial(myusb);
#endif
// Define the buffer to use to copy between the two devices
// I am using 512 bytes as that is the largest one that can happen between two T4.x
// if other type devices could easily reduce to something like 64 bytes
char buffer[512];
uint32_t led_on_time=0;
//=============================================================================
// optional debug stuff
//=============================================================================
#ifdef DEBUG_OUTPUT
#define DBGPrintf Serial.printf
#else
// not debug have it do nothing
inline void DBGPrintf(...) {
}
#endif
// This sketch can optionally print out when some of these devices are inserted and removed.
#ifdef PRINT_DEVICE_INFO
// If you add devices you may want to extend these structures to include them as well.
#ifndef USERIAL_IS_SEREMU
USBDriver *drivers[] = {&userial, &hub1};
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0]))
const char * driver_names[CNT_DEVICES] = {"USERIAL", "Hub1"};
bool driver_active[CNT_DEVICES] = {false, false};
#else
// For SEREMU
USBDriver *drivers[] = {&hid1, &hid2, &hub1};
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0]))
const char * driver_names[CNT_DEVICES] = {"HID1", "HID2", "Hub1"};
bool driver_active[CNT_DEVICES] = {false, false, false};
// Lets also look at HID Input devices
USBHIDInput *hiddrivers[] = {&userial };
#define CNT_HIDDEVICES (sizeof(hiddrivers) / sizeof(hiddrivers[0]))
const char *hid_driver_names[CNT_DEVICES] = { "USERIAL" };
bool hid_driver_active[CNT_DEVICES] = { false };
#endif // USERIAL_IS_SEREMU
#endif
//=============================================================================
// Setup - only runs once
//=============================================================================
void setup() {
myusb.begin();
// pre-Configure the USB Host Serial adapter at startup time
// Note: versions up till now, this needed to be done after the device connects
// and at that time the connecton defaulted to 115200
// In both of these begins below, the actual baud rate specified does not impact the USB communications.
// it is simply a hint to the devices that allow them to configure other parts of their device. Example
// USB to serial devices use this to figure their hardware USART or UART.
userial.begin(USBBAUD);
Serial.begin(USBBAUD);
pinMode(LED_BUILTIN, OUTPUT);
}
//=============================================================================
// loop: continuously called.
//=============================================================================
void loop() {
myusb.Task();
uint16_t rd, wr, n;
// check if any data has arrived on the USB virtual serial port
rd = Serial.available();
if (rd > 0) {
// check if the USB Host serial port is ready to transmit
wr = userial.availableForWrite();
if (wr > 0) {
// compute how much data to move, the smallest
// of rd, wr and the buffer size
if (rd > wr) rd = wr;
if (rd > sizeof(buffer)) rd = sizeof(buffer);
// read data from the USB port
n = Serial.readBytes((char *)buffer, rd);
// write it to the USB Host serial port
DBGPrintf("S-U(%u %u)\n", rd, n);
userial.write(buffer, n);
// turn on the LED to indicate activity
digitalWrite(LED_BUILTIN, HIGH);
led_on_time = millis();
}
}
// check if any data has arrived on the USBHost serial port
rd = userial.available();
if (rd > 0) {
// check if the USB virtual serial port is ready to transmit
wr = Serial.availableForWrite();
if (wr > 0) {
// compute how much data to move, the smallest
// of rd, wr and the buffer size
if (rd > wr) rd = wr;
if (rd > 80) rd = 80;
// read data from the USB host serial port
n = userial.readBytes((char *)buffer, rd);
// write it to the USB port
DBGPrintf("U-S(%u %u):", rd, n);
Serial.write(buffer, n);
// turn on the LED to indicate activity
digitalWrite(LED_BUILTIN, HIGH);
led_on_time = millis();
}
}
// if the LED has been left on without more activity, turn it off
if (led_on_time && (millis() - led_on_time > 3)) {
digitalWrite(LED_BUILTIN, LOW);
led_on_time = 0;
}
// check if the USB virtual serial wants a new baud rate
// ignore if 0 as current Serial monitor of Arduino sets to 0..
uint32_t cur_usb_baud = Serial.baud();
if (cur_usb_baud && (cur_usb_baud != baud)) {
baud = cur_usb_baud;
DBGPrintf("DEBUG: baud change: %u\n", baud);
if (baud == 57600) {
// This ugly hack is necessary for talking
// to the arduino bootloader, which actually
// communicates at 58824 baud (+2.1% error).
// Teensyduino will configure the UART for
// the closest baud rate, which is 57143
// baud (-0.8% error). Serial communication
// can tolerate about 2.5% error, so the
// combined error is too large. Simply
// setting the baud rate to the same as
// arduino's actual baud rate works.
userial.begin(58824);
} else {
userial.begin(baud);
}
}
// Optional check for defice changes
#ifdef PRINT_DEVICE_INFO
check_for_usbhost_device_changes();
#endif
}
// Optional check for defice changes
#ifdef PRINT_DEVICE_INFO
void check_for_usbhost_device_changes() {
// Print out information about different devices.
for (uint8_t i = 0; i < CNT_DEVICES; i++) {
if (*drivers[i] != driver_active[i]) {
if (driver_active[i]) {
Serial.printf("*** Device %s - disconnected ***\n", driver_names[i]);
driver_active[i] = false;
} else {
Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct());
driver_active[i] = true;
const uint8_t *psz = drivers[i]->manufacturer();
if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz);
psz = drivers[i]->product();
if (psz && *psz) Serial.printf(" product: %s\n", psz);
psz = drivers[i]->serialNumber();
if (psz && *psz) Serial.printf(" Serial: %s\n", psz);
#ifndef USERIAL_IS_SEREMU
if (drivers[i] == &userial) {
userial.begin(baud);
}
#endif
}
}
}
#ifdef USERIAL_IS_SEREMU
for (uint8_t i = 0; i < CNT_HIDDEVICES; i++) {
if (*hiddrivers[i] != hid_driver_active[i]) {
if (hid_driver_active[i]) {
Serial.printf("*** HID Device %s - disconnected ***\n", hid_driver_names[i]);
hid_driver_active[i] = false;
} else {
Serial.printf("*** HID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct());
hid_driver_active[i] = true;
const uint8_t *psz = hiddrivers[i]->manufacturer();
if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz);
psz = hiddrivers[i]->product();
if (psz && *psz) Serial.printf(" product: %s\n", psz);
psz = hiddrivers[i]->serialNumber();
if (psz && *psz) Serial.printf(" Serial: %s\n", psz);
// if (hiddrivers[i] == &seremu) {
// Serial.printf(" RX Size:%u TX Size:%u\n", seremu.rxSize(), seremu.txSize());
// }
// if (hiddrivers[i] == &rawhid1) {
// Serial.printf(" RX Size:%u TX Size:%u\n", rawhid1.rxSize(), rawhid1.txSize());
// }
}
}
}
#endif
}
#endif