3.3.7
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#include "USB.h"
|
||||
#include "USBHIDMouse.h"
|
||||
#include "USBHIDKeyboard.h"
|
||||
#include "USBHIDGamepad.h"
|
||||
#include "USBHIDConsumerControl.h"
|
||||
#include "USBHIDSystemControl.h"
|
||||
#include "USBHIDVendor.h"
|
||||
#include "FirmwareMSC.h"
|
||||
|
||||
#if !ARDUINO_USB_MSC_ON_BOOT
|
||||
FirmwareMSC MSC_Update;
|
||||
#endif
|
||||
|
||||
#if !ARDUINO_USB_CDC_ON_BOOT
|
||||
USBCDC USBSerial;
|
||||
#endif
|
||||
|
||||
USBHID HID;
|
||||
USBHIDKeyboard Keyboard;
|
||||
USBHIDMouse Mouse;
|
||||
USBHIDGamepad Gamepad;
|
||||
USBHIDConsumerControl ConsumerControl;
|
||||
USBHIDSystemControl SystemControl;
|
||||
USBHIDVendor Vendor;
|
||||
|
||||
const int buttonPin = 0;
|
||||
int previousButtonState = HIGH;
|
||||
|
||||
static void usbEventCallback(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
|
||||
if (event_base == ARDUINO_USB_EVENTS) {
|
||||
arduino_usb_event_data_t *data = (arduino_usb_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_USB_STARTED_EVENT: Serial.println("USB PLUGGED"); break;
|
||||
case ARDUINO_USB_STOPPED_EVENT: Serial.println("USB UNPLUGGED"); break;
|
||||
case ARDUINO_USB_SUSPEND_EVENT: Serial.printf("USB SUSPENDED: remote_wakeup_en: %u\n", data->suspend.remote_wakeup_en); break;
|
||||
case ARDUINO_USB_RESUME_EVENT: Serial.println("USB RESUMED"); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
} else if (event_base == ARDUINO_USB_CDC_EVENTS) {
|
||||
arduino_usb_cdc_event_data_t *data = (arduino_usb_cdc_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_USB_CDC_CONNECTED_EVENT: Serial.println("CDC CONNECTED"); break;
|
||||
case ARDUINO_USB_CDC_DISCONNECTED_EVENT: Serial.println("CDC DISCONNECTED"); break;
|
||||
case ARDUINO_USB_CDC_LINE_STATE_EVENT: Serial.printf("CDC LINE STATE: dtr: %u, rts: %u\n", data->line_state.dtr, data->line_state.rts); break;
|
||||
case ARDUINO_USB_CDC_LINE_CODING_EVENT:
|
||||
Serial.printf(
|
||||
"CDC LINE CODING: bit_rate: %lu, data_bits: %u, stop_bits: %u, parity: %u\n", data->line_coding.bit_rate, data->line_coding.data_bits,
|
||||
data->line_coding.stop_bits, data->line_coding.parity
|
||||
);
|
||||
break;
|
||||
case ARDUINO_USB_CDC_RX_EVENT:
|
||||
Serial.printf("CDC RX [%u]:", data->rx.len);
|
||||
{
|
||||
uint8_t buf[data->rx.len];
|
||||
size_t len = USBSerial.read(buf, data->rx.len);
|
||||
Serial.write(buf, len);
|
||||
}
|
||||
Serial.println();
|
||||
break;
|
||||
case ARDUINO_USB_CDC_RX_OVERFLOW_EVENT: Serial.printf("CDC RX Overflow of %d bytes", data->rx_overflow.dropped_bytes); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
} else if (event_base == ARDUINO_FIRMWARE_MSC_EVENTS) {
|
||||
arduino_firmware_msc_event_data_t *data = (arduino_firmware_msc_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_FIRMWARE_MSC_START_EVENT: Serial.println("MSC Update Start"); break;
|
||||
case ARDUINO_FIRMWARE_MSC_WRITE_EVENT:
|
||||
//Serial.printf("MSC Update Write %u bytes at offset %u\n", data->write.size, data->write.offset);
|
||||
Serial.print(".");
|
||||
break;
|
||||
case ARDUINO_FIRMWARE_MSC_END_EVENT: Serial.printf("\nMSC Update End: %u bytes\n", data->end.size); break;
|
||||
case ARDUINO_FIRMWARE_MSC_ERROR_EVENT: Serial.printf("MSC Update ERROR! Progress: %u bytes\n", data->error.size); break;
|
||||
case ARDUINO_FIRMWARE_MSC_POWER_EVENT:
|
||||
Serial.printf("MSC Update Power: power: %u, start: %u, eject: %u\n", data->power.power_condition, data->power.start, data->power.load_eject);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
} else if (event_base == ARDUINO_USB_HID_EVENTS) {
|
||||
arduino_usb_hid_event_data_t *data = (arduino_usb_hid_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_USB_HID_SET_PROTOCOL_EVENT: Serial.printf("HID SET PROTOCOL: %s\n", data->set_protocol.protocol ? "REPORT" : "BOOT"); break;
|
||||
case ARDUINO_USB_HID_SET_IDLE_EVENT: Serial.printf("HID SET IDLE: %u\n", data->set_idle.idle_rate); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
} else if (event_base == ARDUINO_USB_HID_KEYBOARD_EVENTS) {
|
||||
arduino_usb_hid_keyboard_event_data_t *data = (arduino_usb_hid_keyboard_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_USB_HID_KEYBOARD_LED_EVENT:
|
||||
Serial.printf("HID KEYBOARD LED: NumLock:%u, CapsLock:%u, ScrollLock:%u\n", data->numlock, data->capslock, data->scrolllock);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
} else if (event_base == ARDUINO_USB_HID_VENDOR_EVENTS) {
|
||||
arduino_usb_hid_vendor_event_data_t *data = (arduino_usb_hid_vendor_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_USB_HID_VENDOR_GET_FEATURE_EVENT:
|
||||
Serial.printf("HID VENDOR GET FEATURE: len:%u\n", data->len);
|
||||
for (uint16_t i = 0; i < data->len; i++) {
|
||||
Serial.write(data->buffer[i] ? data->buffer[i] : '.');
|
||||
}
|
||||
Serial.println();
|
||||
break;
|
||||
case ARDUINO_USB_HID_VENDOR_SET_FEATURE_EVENT:
|
||||
Serial.printf("HID VENDOR SET FEATURE: len:%u\n", data->len);
|
||||
for (uint16_t i = 0; i < data->len; i++) {
|
||||
Serial.write(data->buffer[i] ? data->buffer[i] : '.');
|
||||
}
|
||||
Serial.println();
|
||||
break;
|
||||
case ARDUINO_USB_HID_VENDOR_OUTPUT_EVENT:
|
||||
Serial.printf("HID VENDOR OUTPUT: len:%u\n", data->len);
|
||||
for (uint16_t i = 0; i < data->len; i++) {
|
||||
Serial.write(Vendor.read());
|
||||
}
|
||||
Serial.println();
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
|
||||
USB.onEvent(usbEventCallback);
|
||||
USBSerial.onEvent(usbEventCallback);
|
||||
MSC_Update.onEvent(usbEventCallback);
|
||||
HID.onEvent(usbEventCallback);
|
||||
Keyboard.onEvent(usbEventCallback);
|
||||
Vendor.onEvent(usbEventCallback);
|
||||
|
||||
USBSerial.begin();
|
||||
MSC_Update.begin();
|
||||
Vendor.begin();
|
||||
Mouse.begin();
|
||||
Keyboard.begin();
|
||||
Gamepad.begin();
|
||||
ConsumerControl.begin();
|
||||
SystemControl.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int buttonState = digitalRead(buttonPin);
|
||||
if (HID.ready() && buttonState != previousButtonState) {
|
||||
previousButtonState = buttonState;
|
||||
if (buttonState == LOW) {
|
||||
if (Serial != USBSerial) {
|
||||
Serial.println("Button Pressed");
|
||||
}
|
||||
USBSerial.println("Button Pressed");
|
||||
Vendor.println("Button Pressed");
|
||||
Mouse.move(10, 10);
|
||||
Keyboard.pressRaw(HID_KEY_CAPS_LOCK);
|
||||
Gamepad.leftStick(100, 100);
|
||||
ConsumerControl.press(CONSUMER_CONTROL_VOLUME_INCREMENT);
|
||||
//SystemControl.press(SYSTEM_CONTROL_POWER_OFF);
|
||||
} else {
|
||||
Keyboard.releaseRaw(HID_KEY_CAPS_LOCK);
|
||||
Gamepad.leftStick(0, 0);
|
||||
ConsumerControl.release();
|
||||
//SystemControl.release();
|
||||
Vendor.println("Button Released");
|
||||
USBSerial.println("Button Released");
|
||||
if (Serial != USBSerial) {
|
||||
Serial.println("Button Released");
|
||||
}
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
|
||||
while (Serial.available()) {
|
||||
size_t l = Serial.available();
|
||||
uint8_t b[l];
|
||||
l = Serial.read(b, l);
|
||||
USBSerial.write(b, l);
|
||||
if (HID.ready()) {
|
||||
Vendor.write(b, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#include "USB.h"
|
||||
#include "USBHIDConsumerControl.h"
|
||||
USBHIDConsumerControl ConsumerControl;
|
||||
|
||||
const int buttonPin = 0;
|
||||
int previousButtonState = HIGH;
|
||||
|
||||
void setup() {
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
ConsumerControl.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int buttonState = digitalRead(buttonPin);
|
||||
if ((buttonState != previousButtonState) && (buttonState == LOW)) {
|
||||
ConsumerControl.press(CONSUMER_CONTROL_VOLUME_INCREMENT);
|
||||
ConsumerControl.release();
|
||||
}
|
||||
previousButtonState = buttonState;
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,88 @@
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#include "USB.h"
|
||||
#include "USBHID.h"
|
||||
USBHID HID;
|
||||
|
||||
static const uint8_t report_descriptor[] = {
|
||||
// 8 axis
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x04, // Usage (Joystick)
|
||||
0xa1, 0x01, // Collection (Application)
|
||||
0xa1, 0x00, // Collection (Physical)
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
0x09, 0x32, // Usage (Z)
|
||||
0x09, 0x33, // Usage (Rx)
|
||||
0x09, 0x34, // Usage (Ry)
|
||||
0x09, 0x35, // Usage (Rz)
|
||||
0x09, 0x36, // Usage (Slider)
|
||||
0x09, 0x36, // Usage (Slider)
|
||||
0x15, 0x81, // Logical Minimum (-127)
|
||||
0x25, 0x7f, // Logical Maximum (127)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x08, // Report Count (8)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, // End Collection
|
||||
0xC0, // End Collection
|
||||
};
|
||||
|
||||
class CustomHIDDevice : public USBHIDDevice {
|
||||
public:
|
||||
CustomHIDDevice(void) {
|
||||
static bool initialized = false;
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
HID.addDevice(this, sizeof(report_descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
void begin(void) {
|
||||
HID.begin();
|
||||
}
|
||||
|
||||
uint16_t _onGetDescriptor(uint8_t *buffer) {
|
||||
memcpy(buffer, report_descriptor, sizeof(report_descriptor));
|
||||
return sizeof(report_descriptor);
|
||||
}
|
||||
|
||||
bool send(uint8_t *value) {
|
||||
return HID.SendReport(0, value, 8);
|
||||
}
|
||||
};
|
||||
|
||||
CustomHIDDevice Device;
|
||||
|
||||
const int buttonPin = 0;
|
||||
int previousButtonState = HIGH;
|
||||
uint8_t axis[8];
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
Device.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int buttonState = digitalRead(buttonPin);
|
||||
if (HID.ready() && buttonState != previousButtonState) {
|
||||
previousButtonState = buttonState;
|
||||
if (buttonState == LOW) {
|
||||
Serial.println("Button Pressed");
|
||||
axis[0] = random() & 0xFF;
|
||||
Device.send(axis);
|
||||
} else {
|
||||
Serial.println("Button Released");
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#include "USB.h"
|
||||
#include "FirmwareMSC.h"
|
||||
|
||||
#if !ARDUINO_USB_MSC_ON_BOOT
|
||||
FirmwareMSC MSC_Update;
|
||||
#endif
|
||||
|
||||
static void usbEventCallback(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
|
||||
if (event_base == ARDUINO_USB_EVENTS) {
|
||||
arduino_usb_event_data_t *data = (arduino_usb_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_USB_STARTED_EVENT: Serial.println("USB PLUGGED"); break;
|
||||
case ARDUINO_USB_STOPPED_EVENT: Serial.println("USB UNPLUGGED"); break;
|
||||
case ARDUINO_USB_SUSPEND_EVENT: Serial.printf("USB SUSPENDED: remote_wakeup_en: %u\n", data->suspend.remote_wakeup_en); break;
|
||||
case ARDUINO_USB_RESUME_EVENT: Serial.println("USB RESUMED"); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
} else if (event_base == ARDUINO_FIRMWARE_MSC_EVENTS) {
|
||||
arduino_firmware_msc_event_data_t *data = (arduino_firmware_msc_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_FIRMWARE_MSC_START_EVENT: Serial.println("MSC Update Start"); break;
|
||||
case ARDUINO_FIRMWARE_MSC_WRITE_EVENT:
|
||||
//Serial.printf("MSC Update Write %u bytes at offset %u\n", data->write.size, data->write.offset);
|
||||
Serial.print(".");
|
||||
break;
|
||||
case ARDUINO_FIRMWARE_MSC_END_EVENT: Serial.printf("\nMSC Update End: %u bytes\n", data->end.size); break;
|
||||
case ARDUINO_FIRMWARE_MSC_ERROR_EVENT: Serial.printf("MSC Update ERROR! Progress: %u bytes\n", data->error.size); break;
|
||||
case ARDUINO_FIRMWARE_MSC_POWER_EVENT:
|
||||
Serial.printf("MSC Update Power: power: %u, start: %u, eject: %u", data->power.power_condition, data->power.start, data->power.load_eject);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
|
||||
USB.onEvent(usbEventCallback);
|
||||
MSC_Update.onEvent(usbEventCallback);
|
||||
MSC_Update.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#include "USB.h"
|
||||
#include "USBHIDGamepad.h"
|
||||
USBHIDGamepad Gamepad;
|
||||
|
||||
const int buttonPin = 0;
|
||||
int previousButtonState = HIGH;
|
||||
|
||||
void setup() {
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
Gamepad.begin();
|
||||
USB.begin();
|
||||
Serial.begin(115200);
|
||||
Serial.println("\n==================\nUSB Gamepad Testing\n==================\n");
|
||||
Serial.println("Press BOOT Button to activate the USB gamepad.");
|
||||
Serial.println("Longer press will change the affected button and controls.");
|
||||
Serial.println("Shorter press/release just activates the button and controls.");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static uint8_t padID = 0;
|
||||
static long lastPress = 0;
|
||||
|
||||
int buttonState = digitalRead(buttonPin);
|
||||
if (buttonState != previousButtonState) {
|
||||
if (buttonState == LOW) { // BOOT Button pressed
|
||||
Gamepad.pressButton(padID); // Buttons 1 to 32
|
||||
Gamepad.leftStick(padID << 3, padID << 3); // X Axis, Y Axis
|
||||
Gamepad.rightStick(-(padID << 2), padID << 2); // Z Axis, Z Rotation
|
||||
Gamepad.leftTrigger(padID << 4); // X Rotation
|
||||
Gamepad.rightTrigger(-(padID << 4)); // Y Rotation
|
||||
Gamepad.hat((padID & 0x7) + 1); // Point of View Hat
|
||||
log_d("Pressed PadID [%d]", padID);
|
||||
lastPress = millis();
|
||||
} else {
|
||||
Gamepad.releaseButton(padID);
|
||||
Gamepad.leftStick(0, 0);
|
||||
Gamepad.rightStick(0, 0);
|
||||
Gamepad.leftTrigger(0);
|
||||
Gamepad.rightTrigger(0);
|
||||
Gamepad.hat(HAT_CENTER);
|
||||
log_d("Released PadID [%d]\n", padID);
|
||||
if (millis() - lastPress > 300) {
|
||||
padID = (padID + 1) & 0x1F;
|
||||
log_d("Changed padID to %d\n", padID);
|
||||
}
|
||||
}
|
||||
}
|
||||
previousButtonState = buttonState;
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#include "USB.h"
|
||||
#include "USBHIDVendor.h"
|
||||
USBHIDVendor Vendor;
|
||||
|
||||
const int buttonPin = 0;
|
||||
int previousButtonState = HIGH;
|
||||
|
||||
static void vendorEventCallback(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
|
||||
if (event_base == ARDUINO_USB_HID_VENDOR_EVENTS) {
|
||||
arduino_usb_hid_vendor_event_data_t *data = (arduino_usb_hid_vendor_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_USB_HID_VENDOR_GET_FEATURE_EVENT: Serial.printf("HID VENDOR GET FEATURE: len:%u\n", data->len); break;
|
||||
case ARDUINO_USB_HID_VENDOR_SET_FEATURE_EVENT:
|
||||
Serial.printf("HID VENDOR SET FEATURE: len:%u\n", data->len);
|
||||
for (uint16_t i = 0; i < data->len; i++) {
|
||||
Serial.printf("0x%02X ", *(data->buffer));
|
||||
}
|
||||
Serial.println();
|
||||
break;
|
||||
case ARDUINO_USB_HID_VENDOR_OUTPUT_EVENT:
|
||||
Serial.printf("HID VENDOR OUTPUT: len:%u\n", data->len);
|
||||
// for(uint16_t i=0; i<data->len; i++){
|
||||
// Serial.write(Vendor.read());
|
||||
// }
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
Serial.begin(115200);
|
||||
Vendor.onEvent(vendorEventCallback);
|
||||
Vendor.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int buttonState = digitalRead(buttonPin);
|
||||
if ((buttonState != previousButtonState) && (buttonState == LOW)) {
|
||||
Vendor.println("Hello World!");
|
||||
}
|
||||
previousButtonState = buttonState;
|
||||
while (Vendor.available()) {
|
||||
Serial.write(Vendor.read());
|
||||
}
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
Keyboard logout
|
||||
|
||||
This sketch demonstrates the Keyboard library.
|
||||
|
||||
When you connect pin 2 to ground, it performs a logout.
|
||||
It uses keyboard combinations to do this, as follows:
|
||||
|
||||
On Windows, CTRL-ALT-DEL followed by ALT-l
|
||||
On Ubuntu, CTRL-ALT-DEL, and ENTER
|
||||
On OSX, CMD-SHIFT-q
|
||||
|
||||
To wake: Spacebar.
|
||||
|
||||
Circuit:
|
||||
- Arduino Leonardo or Micro
|
||||
- wire to connect D2 to ground
|
||||
|
||||
created 6 Mar 2012
|
||||
modified 27 Mar 2012
|
||||
by Tom Igoe
|
||||
|
||||
This example is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/KeyboardLogout
|
||||
*/
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#define OSX 0
|
||||
#define WINDOWS 1
|
||||
#define UBUNTU 2
|
||||
|
||||
#include "USB.h"
|
||||
#include "USBHIDKeyboard.h"
|
||||
USBHIDKeyboard Keyboard;
|
||||
|
||||
// change this to match your platform:
|
||||
int platform = OSX;
|
||||
|
||||
const int buttonPin = 0; // input pin for pushbutton
|
||||
|
||||
void setup() {
|
||||
// make pin 0 an input and turn on the pull-up resistor so it goes high unless
|
||||
// connected to ground:
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
Keyboard.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
while (digitalRead(buttonPin) == HIGH) {
|
||||
// do nothing until pin 2 goes low
|
||||
delay(500);
|
||||
}
|
||||
delay(1000);
|
||||
|
||||
switch (platform) {
|
||||
case OSX:
|
||||
Keyboard.press(KEY_LEFT_GUI);
|
||||
// Shift-Q logs out:
|
||||
Keyboard.press(KEY_LEFT_SHIFT);
|
||||
Keyboard.press('Q');
|
||||
delay(100);
|
||||
Keyboard.releaseAll();
|
||||
// enter:
|
||||
Keyboard.write(KEY_RETURN);
|
||||
break;
|
||||
case WINDOWS:
|
||||
// CTRL-ALT-DEL:
|
||||
Keyboard.press(KEY_LEFT_CTRL);
|
||||
Keyboard.press(KEY_LEFT_ALT);
|
||||
Keyboard.press(KEY_DELETE);
|
||||
delay(100);
|
||||
Keyboard.releaseAll();
|
||||
// ALT-l:
|
||||
delay(2000);
|
||||
Keyboard.press(KEY_LEFT_ALT);
|
||||
Keyboard.press('l');
|
||||
Keyboard.releaseAll();
|
||||
break;
|
||||
case UBUNTU:
|
||||
// CTRL-ALT-DEL:
|
||||
Keyboard.press(KEY_LEFT_CTRL);
|
||||
Keyboard.press(KEY_LEFT_ALT);
|
||||
Keyboard.press(KEY_DELETE);
|
||||
delay(1000);
|
||||
Keyboard.releaseAll();
|
||||
// Enter to confirm logout:
|
||||
Keyboard.write(KEY_RETURN);
|
||||
break;
|
||||
}
|
||||
|
||||
// do nothing:
|
||||
while (true) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
Keyboard Message test
|
||||
|
||||
For the Arduino Leonardo and Micro.
|
||||
|
||||
Sends a text string when a button is pressed.
|
||||
|
||||
The circuit:
|
||||
- pushbutton attached from pin 0 to ground
|
||||
- 10 kilohm resistor attached from pin 0 to +5V
|
||||
|
||||
created 24 Oct 2011
|
||||
modified 27 Mar 2012
|
||||
by Tom Igoe
|
||||
modified 11 Nov 2013
|
||||
by Scott Fitzgerald
|
||||
|
||||
This example code is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/KeyboardMessage
|
||||
*/
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#include "USB.h"
|
||||
#include "USBHIDKeyboard.h"
|
||||
USBHIDKeyboard Keyboard;
|
||||
|
||||
const int buttonPin = 0; // input pin for pushbutton
|
||||
int previousButtonState = HIGH; // for checking the state of a pushButton
|
||||
int counter = 0; // button push counter
|
||||
|
||||
void setup() {
|
||||
// make the pushButton pin an input:
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
// initialize control over the keyboard:
|
||||
Keyboard.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// read the pushbutton:
|
||||
int buttonState = digitalRead(buttonPin);
|
||||
// if the button state has changed,
|
||||
if ((buttonState != previousButtonState)
|
||||
// and it's currently pressed:
|
||||
&& (buttonState == LOW)) {
|
||||
// increment the button counter
|
||||
counter++;
|
||||
// type out a message
|
||||
Keyboard.print("You pressed the button ");
|
||||
Keyboard.print(counter);
|
||||
Keyboard.println(" times.");
|
||||
}
|
||||
// save the current button state for comparison next time:
|
||||
previousButtonState = buttonState;
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
Arduino Programs Blink
|
||||
|
||||
This sketch demonstrates the Keyboard library.
|
||||
|
||||
For Leonardo and Due boards only.
|
||||
|
||||
When you connect pin 2 to ground, it creates a new window with a key
|
||||
combination (CTRL-N), then types in the Blink sketch, then auto-formats the
|
||||
text using another key combination (CTRL-T), then uploads the sketch to the
|
||||
currently selected Arduino using a final key combination (CTRL-U).
|
||||
|
||||
Circuit:
|
||||
- Arduino Leonardo, Micro, Due, LilyPad USB, or Yún
|
||||
- wire to connect D2 to ground
|
||||
|
||||
created 5 Mar 2012
|
||||
modified 29 Mar 2012
|
||||
by Tom Igoe
|
||||
modified 3 May 2014
|
||||
by Scott Fitzgerald
|
||||
|
||||
This example is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/KeyboardReprogram
|
||||
*/
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#include "USB.h"
|
||||
#include "USBHIDKeyboard.h"
|
||||
USBHIDKeyboard Keyboard;
|
||||
|
||||
const int buttonPin = 0; // input pin for pushbutton
|
||||
|
||||
// use this option for OSX.
|
||||
// Comment it out if using Windows or Linux:
|
||||
char ctrlKey = KEY_LEFT_GUI;
|
||||
// use this option for Windows and Linux.
|
||||
// leave commented out if using OSX:
|
||||
// char ctrlKey = KEY_LEFT_CTRL;
|
||||
|
||||
void setup() {
|
||||
// make pin 0 an input and turn on the pull-up resistor so it goes high unless
|
||||
// connected to ground:
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
// initialize control over the keyboard:
|
||||
Keyboard.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
while (digitalRead(buttonPin) == HIGH) {
|
||||
// do nothing until pin 0 goes low
|
||||
delay(500);
|
||||
}
|
||||
delay(1000);
|
||||
// new document:
|
||||
Keyboard.press(ctrlKey);
|
||||
Keyboard.press('n');
|
||||
delay(100);
|
||||
Keyboard.releaseAll();
|
||||
// wait for new window to open:
|
||||
delay(1000);
|
||||
|
||||
// versions of the Arduino IDE after 1.5 pre-populate new sketches with
|
||||
// setup() and loop() functions let's clear the window before typing anything new
|
||||
// select all
|
||||
Keyboard.press(ctrlKey);
|
||||
Keyboard.press('a');
|
||||
delay(500);
|
||||
Keyboard.releaseAll();
|
||||
// delete the selected text
|
||||
Keyboard.write(KEY_BACKSPACE);
|
||||
delay(500);
|
||||
|
||||
// Type out "blink":
|
||||
Keyboard.println("void setup() {");
|
||||
Keyboard.println("pinMode(13, OUTPUT);");
|
||||
Keyboard.println("}");
|
||||
Keyboard.println();
|
||||
Keyboard.println("void loop() {");
|
||||
Keyboard.println("digitalWrite(13, HIGH);");
|
||||
Keyboard.print("delay(3000);");
|
||||
// 3000 ms is too long. Delete it:
|
||||
for (int keystrokes = 0; keystrokes < 6; keystrokes++) {
|
||||
delay(500);
|
||||
Keyboard.write(KEY_BACKSPACE);
|
||||
}
|
||||
// make it 1000 instead:
|
||||
Keyboard.println("1000);");
|
||||
Keyboard.println("digitalWrite(13, LOW);");
|
||||
Keyboard.println("delay(1000);");
|
||||
Keyboard.println("}");
|
||||
// tidy up:
|
||||
Keyboard.press(ctrlKey);
|
||||
Keyboard.press('t');
|
||||
delay(100);
|
||||
Keyboard.releaseAll();
|
||||
delay(3000);
|
||||
// upload code:
|
||||
Keyboard.press(ctrlKey);
|
||||
Keyboard.press('u');
|
||||
delay(100);
|
||||
Keyboard.releaseAll();
|
||||
|
||||
// wait for the sweet oblivion of reprogramming:
|
||||
while (true) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Keyboard test
|
||||
|
||||
Reads a byte from the serial port, sends a keystroke back.
|
||||
The sent keystroke is one higher than what's received, e.g. if you send a,
|
||||
you get b, send A you get B, and so forth.
|
||||
|
||||
The circuit:
|
||||
- none
|
||||
|
||||
created 21 Oct 2011
|
||||
modified 27 Mar 2012
|
||||
by Tom Igoe
|
||||
|
||||
This example code is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/KeyboardSerial
|
||||
*/
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#include "USB.h"
|
||||
#include "USBHIDKeyboard.h"
|
||||
USBHIDKeyboard Keyboard;
|
||||
|
||||
void setup() {
|
||||
// open the serial port:
|
||||
Serial.begin(115200);
|
||||
// initialize control over the keyboard:
|
||||
Keyboard.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check for incoming serial data:
|
||||
if (Serial.available() > 0) {
|
||||
// read incoming serial data:
|
||||
char inChar = Serial.read();
|
||||
// Type the next ASCII value from what you received:
|
||||
Keyboard.write(inChar + 1);
|
||||
}
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
KeyboardAndMouseControl
|
||||
|
||||
Hardware:
|
||||
- five pushbuttons attached to D12, D13, D14, D15, D0
|
||||
|
||||
The mouse movement is always relative. This sketch reads four pushbuttons, and
|
||||
uses them to set the movement of the mouse.
|
||||
|
||||
WARNING: When you use the Mouse.move() command, the Arduino takes over your
|
||||
mouse! Make sure you have control before you use the mouse commands.
|
||||
|
||||
created 15 Mar 2012
|
||||
modified 27 Mar 2012
|
||||
by Tom Igoe
|
||||
|
||||
This example code is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/KeyboardAndMouseControl
|
||||
*/
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#include "USB.h"
|
||||
#include "USBHIDMouse.h"
|
||||
#include "USBHIDKeyboard.h"
|
||||
USBHIDMouse Mouse;
|
||||
USBHIDKeyboard Keyboard;
|
||||
|
||||
// set pin numbers for the five buttons:
|
||||
const int upButton = 12;
|
||||
const int downButton = 13;
|
||||
const int leftButton = 14;
|
||||
const int rightButton = 15;
|
||||
const int mouseButton = 0;
|
||||
|
||||
void setup() { // initialize the buttons' inputs:
|
||||
pinMode(upButton, INPUT_PULLUP);
|
||||
pinMode(downButton, INPUT_PULLUP);
|
||||
pinMode(leftButton, INPUT_PULLUP);
|
||||
pinMode(rightButton, INPUT_PULLUP);
|
||||
pinMode(mouseButton, INPUT_PULLUP);
|
||||
|
||||
Serial.begin(115200);
|
||||
// initialize mouse control:
|
||||
Mouse.begin();
|
||||
Keyboard.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// use serial input to control the mouse:
|
||||
if (Serial.available() > 0) {
|
||||
char inChar = Serial.read();
|
||||
|
||||
switch (inChar) {
|
||||
case 'u':
|
||||
// move mouse up
|
||||
Mouse.move(0, -40);
|
||||
break;
|
||||
case 'd':
|
||||
// move mouse down
|
||||
Mouse.move(0, 40);
|
||||
break;
|
||||
case 'l':
|
||||
// move mouse left
|
||||
Mouse.move(-40, 0);
|
||||
break;
|
||||
case 'r':
|
||||
// move mouse right
|
||||
Mouse.move(40, 0);
|
||||
break;
|
||||
case 'm':
|
||||
// perform mouse left click
|
||||
Mouse.click(MOUSE_LEFT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// use the pushbuttons to control the keyboard:
|
||||
if (digitalRead(upButton) == LOW) {
|
||||
Keyboard.write('u');
|
||||
}
|
||||
if (digitalRead(downButton) == LOW) {
|
||||
Keyboard.write('d');
|
||||
}
|
||||
if (digitalRead(leftButton) == LOW) {
|
||||
Keyboard.write('l');
|
||||
}
|
||||
if (digitalRead(rightButton) == LOW) {
|
||||
Keyboard.write('r');
|
||||
}
|
||||
if (digitalRead(mouseButton) == LOW) {
|
||||
Keyboard.write('m');
|
||||
}
|
||||
delay(5);
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
This is an example of a Simple MIDI Controller using an ESP32 with a native USB support stack (S2, S3,
|
||||
etc.).
|
||||
|
||||
For a hookup guide and more information on reading the ADC, please see:
|
||||
https://randomnerdtutorials.com/esp32-adc-analog-read-arduino-ide/ (Note: This sketch uses GPIO05)
|
||||
|
||||
For best results, it is recommended to add an extra offset resistor between VCC and the potentiometer.
|
||||
(For a standard 10kOhm potentiometer, 3kOhm - 4kOhm will do.)
|
||||
|
||||
View this sketch in action on YouTube: https://youtu.be/Y9TLXs_3w1M
|
||||
*/
|
||||
#if ARDUINO_USB_MODE
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "USB.h"
|
||||
#include "USBMIDI.h"
|
||||
// Creates the MIDI device with specific descriptor
|
||||
USBMIDI MIDI("ESP MIDI Device");
|
||||
|
||||
#define MIDI_NOTE_C4 60
|
||||
|
||||
#define MIDI_CC_CUTOFF 74
|
||||
|
||||
///// ADC & Controller Input Handling /////
|
||||
|
||||
#define CONTROLLER_PIN 5
|
||||
|
||||
// ESP32 ADC needs a ton of smoothing
|
||||
#define SMOOTHING_VALUE 1000
|
||||
static double controllerInputValue = 0;
|
||||
|
||||
void updateControllerInputValue() {
|
||||
controllerInputValue = (controllerInputValue * (SMOOTHING_VALUE - 1) + analogRead(CONTROLLER_PIN)) / SMOOTHING_VALUE;
|
||||
}
|
||||
|
||||
void primeControllerInputValue() {
|
||||
for (int i = 0; i < SMOOTHING_VALUE; i++) {
|
||||
updateControllerInputValue();
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t readControllerValue() {
|
||||
// Lower ADC input amplitude to get a stable value
|
||||
return round(controllerInputValue / 12);
|
||||
}
|
||||
|
||||
///// Button Handling /////
|
||||
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
// Simple button state transition function with debounce
|
||||
// (See also: https://tinyurl.com/simple-debounce)
|
||||
#define PRESSED 0xff00
|
||||
#define RELEASED 0xfe1f
|
||||
uint16_t getButtonEvent() {
|
||||
static uint16_t state = 0;
|
||||
state = (state << 1) | digitalRead(BUTTON_PIN) | 0xfe00;
|
||||
return state;
|
||||
}
|
||||
|
||||
///// Arduino Hooks /////
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
MIDI.begin();
|
||||
USB.begin();
|
||||
pinMode(BUTTON_PIN, INPUT_PULLUP);
|
||||
primeControllerInputValue();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
uint16_t newControllerValue = readControllerValue();
|
||||
static uint16_t lastControllerValue = 0;
|
||||
|
||||
// Auto-calibrate the controller range
|
||||
static uint16_t maxControllerValue = 0;
|
||||
static uint16_t minControllerValue = 0xFFFF;
|
||||
|
||||
if (newControllerValue < minControllerValue) {
|
||||
minControllerValue = newControllerValue;
|
||||
}
|
||||
if (newControllerValue > maxControllerValue) {
|
||||
maxControllerValue = newControllerValue;
|
||||
}
|
||||
|
||||
// Send update if the controller value has changed
|
||||
if (lastControllerValue != newControllerValue) {
|
||||
lastControllerValue = newControllerValue;
|
||||
|
||||
// Can't map if the range is zero
|
||||
if (minControllerValue != maxControllerValue) {
|
||||
MIDI.controlChange(MIDI_CC_CUTOFF, map(newControllerValue, minControllerValue, maxControllerValue, 0, 127));
|
||||
}
|
||||
}
|
||||
|
||||
updateControllerInputValue();
|
||||
|
||||
// Hook Button0 to a MIDI note so that we can observe
|
||||
// the CC effect without the need for a MIDI keyboard.
|
||||
switch (getButtonEvent()) {
|
||||
case PRESSED: MIDI.noteOn(MIDI_NOTE_C4, 64); break;
|
||||
case RELEASED: MIDI.noteOff(MIDI_NOTE_C4, 0); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
This is an example of using an ESP32 with a native USB support stack (S2, S3, etc.) as a Serial MIDI to
|
||||
USB MIDI bridge (AKA "A MIDI Interface").
|
||||
|
||||
View this sketch in action on YouTube: https://youtu.be/BXG5i55I9s0
|
||||
|
||||
Receiving and decoding USB MIDI 1.0 packets is a more advanced topic than sending MIDI over USB,
|
||||
please refer to the other examples in this library for a more basic example of sending MIDI over USB.
|
||||
|
||||
This example should still be self explanatory, please refer to the USB MIDI 1.0 specification (the spec)
|
||||
for a more in-depth explanation of the packet format.
|
||||
|
||||
For the spec please visit: https://www.midi.org/specifications-old/item/usb-midi-1-0-specification
|
||||
|
||||
Note: Because ESP32 works at VCC=3.3v normal schematics for Serial MIDI connections will not suffice,
|
||||
Please refer to the Updated MIDI 1.1 Electrical Specification [1] for information on how to hookup
|
||||
Serial MIDI for 3.3v devices.
|
||||
|
||||
[1] - https://www.midi.org/specifications/midi-transports-specifications/5-pin-din-electrical-specs
|
||||
*/
|
||||
#if ARDUINO_USB_MODE
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
// define a new USB MIDI device name using a macro
|
||||
SET_USB_MIDI_DEVICE_NAME("ESP MIDI Device")
|
||||
|
||||
#include "USB.h"
|
||||
#include "USBMIDI.h"
|
||||
// Creates the MIDI device with specific name defined with the SET_USB_MIDI_DEVICE_NAME() macro
|
||||
USBMIDI MIDI;
|
||||
|
||||
#define MIDI_RX 39
|
||||
#define MIDI_TX 40
|
||||
|
||||
void setup() {
|
||||
// USBCDC Serial
|
||||
Serial.begin(115200);
|
||||
|
||||
// HW UART Serial
|
||||
Serial1.begin(31250, SERIAL_8N1, MIDI_RX, MIDI_TX);
|
||||
|
||||
MIDI.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// MIDI Serial 1.0 to USB MIDI 1.0
|
||||
if (Serial1.available()) {
|
||||
byte data = Serial1.read();
|
||||
MIDI.write(data);
|
||||
}
|
||||
|
||||
// USB MIDI 1.0 to MIDI Serial 1.0
|
||||
midiEventPacket_t midi_packet_in = {0, 0, 0, 0};
|
||||
// See Chapter 4: USB-MIDI Event Packets (page 16) of the spec.
|
||||
int8_t cin_to_midix_size[16] = {-1, -1, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1};
|
||||
|
||||
if (MIDI.readPacket(&midi_packet_in)) {
|
||||
midi_code_index_number_t code_index_num = MIDI_EP_HEADER_CIN_GET(midi_packet_in.header);
|
||||
int8_t midix_size = cin_to_midix_size[code_index_num];
|
||||
|
||||
// We skip Misc and Cable Events for simplicity
|
||||
if (code_index_num >= 0x2) {
|
||||
for (int i = 0; i < midix_size; i++) {
|
||||
Serial1.write(((uint8_t *)&midi_packet_in)[i + 1]);
|
||||
}
|
||||
Serial1.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
This is an example of a MIDI Music Box using an ESP32 with a native USB support stack (S2, S3, etc.).
|
||||
|
||||
Every time the button on the ESP32 board (attached to pin 0) is pressed the next note of a melody is
|
||||
played. It is up to the user to get the timing of the button presses right.
|
||||
|
||||
One simple way of running this sketch is to download the Pianoteq evaluation version, because upon
|
||||
application start it automatically listens to the first MIDI Input on Channel 1, which is the case,
|
||||
if the ESP32 is the only MIDI device attached.
|
||||
|
||||
View this sketch in action on YouTube: https://youtu.be/JFrc-wSmcus
|
||||
*/
|
||||
#if ARDUINO_USB_MODE
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#include "USB.h"
|
||||
#include "USBMIDI.h"
|
||||
USBMIDI MIDI;
|
||||
|
||||
#define END_OF_SONG 255
|
||||
uint8_t notes[] = {END_OF_SONG, 71, 76, 79, 78, 76, 83, 81, 78, 76, 79, 78, 75, 77, 71};
|
||||
uint8_t noteIndex = 0; // From 0 to sizeof(notes)
|
||||
#define SONG_LENGTH (sizeof(notes) - 1) // END_OF_SONG does not attribute to the length.
|
||||
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
// Simple button press check with debounce
|
||||
// (See also: https://tinyurl.com/simple-debounce)
|
||||
bool isButtonPressed() {
|
||||
static uint16_t state = 0;
|
||||
state = (state << 1) | digitalRead(BUTTON_PIN) | 0xfe00;
|
||||
return (state == 0xff00);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
// Make the BUTTON_PIN an input:
|
||||
pinMode(BUTTON_PIN, INPUT_PULLUP);
|
||||
|
||||
MIDI.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (isButtonPressed()) {
|
||||
// Stop current note
|
||||
MIDI.noteOff(notes[noteIndex]);
|
||||
|
||||
// Play next note
|
||||
noteIndex = noteIndex < SONG_LENGTH ? noteIndex + 1 : 0;
|
||||
if (notes[noteIndex] != END_OF_SONG) {
|
||||
MIDI.noteOn(notes[noteIndex], 64);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
This is an example of receiving USB MIDI 1.0 messages using an ESP32 with a native USB support stack
|
||||
(S2, S3, etc.).
|
||||
|
||||
Receiving and decoding USB MIDI 1.0 packets is a more advanced topic than sending MIDI over USB,
|
||||
please refer to the other examples in this library for a more basic example of sending MIDI over USB.
|
||||
|
||||
This example should still be self explanatory, please refer to the USB MIDI 1.0 specification (the spec)
|
||||
for a more in-depth explanation of the packet format.
|
||||
|
||||
For the spec please visit: https://www.midi.org/specifications-old/item/usb-midi-1-0-specification
|
||||
*/
|
||||
#if ARDUINO_USB_MODE
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#include "USB.h"
|
||||
#include "USBMIDI.h"
|
||||
USBMIDI MIDI;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
MIDI.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
midiEventPacket_t midi_packet_in = {0, 0, 0, 0};
|
||||
|
||||
if (MIDI.readPacket(&midi_packet_in)) {
|
||||
printDetails(midi_packet_in);
|
||||
}
|
||||
}
|
||||
|
||||
void printDetails(midiEventPacket_t &midi_packet_in) {
|
||||
// See Chapter 4: USB-MIDI Event Packets (page 16) of the spec.
|
||||
uint8_t cable_num = MIDI_EP_HEADER_CN_GET(midi_packet_in.header);
|
||||
midi_code_index_number_t code_index_num = MIDI_EP_HEADER_CIN_GET(midi_packet_in.header);
|
||||
|
||||
Serial.println("Received a USB MIDI packet:");
|
||||
Serial.println(".----.-----.--------.--------.--------.");
|
||||
Serial.println("| CN | CIN | STATUS | DATA 0 | DATA 1 |");
|
||||
Serial.println("+----+-----+--------+--------+--------+");
|
||||
Serial.printf("| %d | %X | %X | %X | %X |\n", cable_num, code_index_num, midi_packet_in.byte1, midi_packet_in.byte2, midi_packet_in.byte3);
|
||||
Serial.println("'----'-----'--------.--------'--------'\n");
|
||||
Serial.print("Description: ");
|
||||
|
||||
switch (code_index_num) {
|
||||
case MIDI_CIN_MISC: Serial.println("This a Miscellaneous event"); break;
|
||||
case MIDI_CIN_CABLE_EVENT: Serial.println("This a Cable event"); break;
|
||||
case MIDI_CIN_SYSCOM_2BYTE: // 2 byte system common message e.g MTC, SongSelect
|
||||
case MIDI_CIN_SYSCOM_3BYTE: // 3 byte system common message e.g SPP
|
||||
Serial.println("This a System Common (SysCom) event");
|
||||
break;
|
||||
case MIDI_CIN_SYSEX_START: // SysEx starts or continue
|
||||
case MIDI_CIN_SYSEX_END_1BYTE: // SysEx ends with 1 data, or 1 byte system common message
|
||||
case MIDI_CIN_SYSEX_END_2BYTE: // SysEx ends with 2 data
|
||||
case MIDI_CIN_SYSEX_END_3BYTE: // SysEx ends with 3 data
|
||||
Serial.println("This a system exclusive (SysEx) event");
|
||||
break;
|
||||
case MIDI_CIN_NOTE_ON: Serial.printf("This a Note-On event of Note %d with a Velocity of %d\n", midi_packet_in.byte2, midi_packet_in.byte3); break;
|
||||
case MIDI_CIN_NOTE_OFF: Serial.printf("This a Note-Off event of Note %d with a Velocity of %d\n", midi_packet_in.byte2, midi_packet_in.byte3); break;
|
||||
case MIDI_CIN_POLY_KEYPRESS: Serial.printf("This a Poly Aftertouch event for Note %d and Value %d\n", midi_packet_in.byte2, midi_packet_in.byte3); break;
|
||||
case MIDI_CIN_CONTROL_CHANGE:
|
||||
Serial.printf(
|
||||
"This a Control Change/Continuous Controller (CC) event of Controller %d "
|
||||
"with a Value of %d\n",
|
||||
midi_packet_in.byte2, midi_packet_in.byte3
|
||||
);
|
||||
break;
|
||||
case MIDI_CIN_PROGRAM_CHANGE: Serial.printf("This a Program Change event with a Value of %d\n", midi_packet_in.byte2); break;
|
||||
case MIDI_CIN_CHANNEL_PRESSURE: Serial.printf("This a Channel Pressure event with a Value of %d\n", midi_packet_in.byte2); break;
|
||||
case MIDI_CIN_PITCH_BEND_CHANGE:
|
||||
Serial.printf("This a Pitch Bend Change event with a Value of %d\n", ((uint16_t)midi_packet_in.byte2) << 7 | midi_packet_in.byte3);
|
||||
break;
|
||||
case MIDI_CIN_1BYTE_DATA: Serial.printf("This an embedded Serial MIDI event byte with Value %X\n", midi_packet_in.byte1); break;
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
ButtonMouseControl
|
||||
|
||||
Controls the mouse from five pushbuttons on an Arduino Leonardo, Micro or Due.
|
||||
|
||||
Hardware:
|
||||
- five pushbuttons attached to D12, D13, D14, D15, D0
|
||||
|
||||
The mouse movement is always relative. This sketch reads four pushbuttons,
|
||||
and uses them to set the movement of the mouse.
|
||||
|
||||
WARNING: When you use the Mouse.move() command, the Arduino takes over your
|
||||
mouse! Make sure you have control before you use the mouse commands.
|
||||
|
||||
created 15 Mar 2012
|
||||
modified 27 Mar 2012
|
||||
by Tom Igoe
|
||||
|
||||
This example code is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/ButtonMouseControl
|
||||
*/
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#include "USB.h"
|
||||
#include "USBHIDMouse.h"
|
||||
USBHIDMouse Mouse;
|
||||
|
||||
// set pin numbers for the five buttons:
|
||||
const int upButton = 12;
|
||||
const int downButton = 13;
|
||||
const int leftButton = 14;
|
||||
const int rightButton = 15;
|
||||
const int mouseButton = 0;
|
||||
|
||||
int range = 5; // output range of X or Y movement; affects movement speed
|
||||
int responseDelay = 10; // response delay of the mouse, in ms
|
||||
|
||||
void setup() {
|
||||
// initialize the buttons' inputs:
|
||||
pinMode(upButton, INPUT_PULLUP);
|
||||
pinMode(downButton, INPUT_PULLUP);
|
||||
pinMode(leftButton, INPUT_PULLUP);
|
||||
pinMode(rightButton, INPUT_PULLUP);
|
||||
pinMode(mouseButton, INPUT_PULLUP);
|
||||
// initialize mouse control:
|
||||
Mouse.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// read the buttons:
|
||||
int upState = digitalRead(upButton);
|
||||
int downState = digitalRead(downButton);
|
||||
int rightState = digitalRead(rightButton);
|
||||
int leftState = digitalRead(leftButton);
|
||||
int clickState = digitalRead(mouseButton);
|
||||
|
||||
// calculate the movement distance based on the button states:
|
||||
int xDistance = (leftState - rightState) * range;
|
||||
int yDistance = (upState - downState) * range;
|
||||
|
||||
// if X or Y is non-zero, move:
|
||||
if ((xDistance != 0) || (yDistance != 0)) {
|
||||
Mouse.move(xDistance, yDistance, 0);
|
||||
}
|
||||
|
||||
// if the mouse button is pressed:
|
||||
if (clickState == LOW) {
|
||||
// if the mouse is not pressed, press it:
|
||||
if (!Mouse.isPressed(MOUSE_LEFT)) {
|
||||
Mouse.press(MOUSE_LEFT);
|
||||
}
|
||||
}
|
||||
// else the mouse button is not pressed:
|
||||
else {
|
||||
// if the mouse is pressed, release it:
|
||||
if (Mouse.isPressed(MOUSE_LEFT)) {
|
||||
Mouse.release(MOUSE_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
// a delay so the mouse doesn't move too fast:
|
||||
delay(responseDelay);
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#include "USB.h"
|
||||
#include "USBHIDSystemControl.h"
|
||||
USBHIDSystemControl SystemControl;
|
||||
|
||||
const int buttonPin = 0;
|
||||
int previousButtonState = HIGH;
|
||||
|
||||
void setup() {
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
SystemControl.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int buttonState = digitalRead(buttonPin);
|
||||
if ((buttonState != previousButtonState) && (buttonState == LOW)) {
|
||||
SystemControl.press(SYSTEM_CONTROL_POWER_OFF);
|
||||
SystemControl.release();
|
||||
}
|
||||
previousButtonState = buttonState;
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,166 @@
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#include "USB.h"
|
||||
#include "USBMSC.h"
|
||||
|
||||
USBMSC MSC;
|
||||
|
||||
#define FAT_U8(v) ((v) & 0xFF)
|
||||
#define FAT_U16(v) FAT_U8(v), FAT_U8((v) >> 8)
|
||||
#define FAT_U32(v) FAT_U8(v), FAT_U8((v) >> 8), FAT_U8((v) >> 16), FAT_U8((v) >> 24)
|
||||
#define FAT_MS2B(s, ms) FAT_U8(((((s) & 0x1) * 1000) + (ms)) / 10)
|
||||
#define FAT_HMS2B(h, m, s) FAT_U8(((s) >> 1) | (((m) & 0x7) << 5)), FAT_U8((((m) >> 3) & 0x7) | ((h) << 3))
|
||||
#define FAT_YMD2B(y, m, d) FAT_U8(((d) & 0x1F) | (((m) & 0x7) << 5)), FAT_U8((((m) >> 3) & 0x1) | ((((y) - 1980) & 0x7F) << 1))
|
||||
#define FAT_TBL2B(l, h) FAT_U8(l), FAT_U8(((l >> 8) & 0xF) | ((h << 4) & 0xF0)), FAT_U8(h >> 4)
|
||||
|
||||
#define README_CONTENTS \
|
||||
"This is tinyusb's MassStorage Class demo.\r\n\r\nIf you find any bugs or get any questions, feel free to file an\r\nissue at github.com/hathach/tinyusb"
|
||||
|
||||
static const uint32_t DISK_SECTOR_COUNT = 2 * 8; // 8KB is the smallest size that windows allow to mount
|
||||
static const uint16_t DISK_SECTOR_SIZE = 512; // Should be 512
|
||||
static const uint16_t DISC_SECTORS_PER_TABLE = 1; //each table sector can fit 170KB (340 sectors)
|
||||
|
||||
static uint8_t msc_disk[DISK_SECTOR_COUNT][DISK_SECTOR_SIZE] = {
|
||||
//------------- Block0: Boot Sector -------------//
|
||||
{ // Header (62 bytes)
|
||||
0xEB, 0x3C, 0x90, //jump_instruction
|
||||
'M', 'S', 'D', 'O', 'S', '5', '.', '0', //oem_name
|
||||
FAT_U16(DISK_SECTOR_SIZE), //bytes_per_sector
|
||||
FAT_U8(1), //sectors_per_cluster
|
||||
FAT_U16(1), //reserved_sectors_count
|
||||
FAT_U8(1), //file_alloc_tables_num
|
||||
FAT_U16(16), //max_root_dir_entries
|
||||
FAT_U16(DISK_SECTOR_COUNT), //fat12_sector_num
|
||||
0xF8, //media_descriptor
|
||||
FAT_U16(DISC_SECTORS_PER_TABLE), //sectors_per_alloc_table;//FAT12 and FAT16
|
||||
FAT_U16(1), //sectors_per_track;//A value of 0 may indicate LBA-only access
|
||||
FAT_U16(1), //num_heads
|
||||
FAT_U32(0), //hidden_sectors_count
|
||||
FAT_U32(0), //total_sectors_32
|
||||
0x00, //physical_drive_number;0x00 for (first) removable media, 0x80 for (first) fixed disk
|
||||
0x00, //reserved
|
||||
0x29, //extended_boot_signature;//should be 0x29
|
||||
FAT_U32(0x1234), //serial_number: 0x1234 => 1234
|
||||
'T', 'i', 'n', 'y', 'U', 'S', 'B', ' ', 'M', 'S', 'C', //volume_label padded with spaces (0x20)
|
||||
'F', 'A', 'T', '1', '2', ' ', ' ', ' ', //file_system_type padded with spaces (0x20)
|
||||
|
||||
// Zero up to 2 last bytes of FAT magic code (448 bytes)
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
//boot signature (2 bytes)
|
||||
0x55, 0xAA
|
||||
},
|
||||
|
||||
//------------- Block1: FAT12 Table -------------//
|
||||
{
|
||||
FAT_TBL2B(0xFF8, 0xFFF), FAT_TBL2B(0xFFF, 0x000) // first 2 entries must be 0xFF8 0xFFF, third entry is cluster end of readme file
|
||||
},
|
||||
|
||||
//------------- Block2: Root Directory -------------//
|
||||
{
|
||||
// first entry is volume label
|
||||
'E', 'S', 'P', '3', '2', 'S', '2', ' ', 'M', 'S', 'C',
|
||||
0x08, //FILE_ATTR_VOLUME_LABEL
|
||||
0x00, FAT_MS2B(0, 0), FAT_HMS2B(0, 0, 0), FAT_YMD2B(0, 0, 0), FAT_YMD2B(0, 0, 0), FAT_U16(0), FAT_HMS2B(13, 42, 30), //last_modified_hms
|
||||
FAT_YMD2B(2018, 11, 5), //last_modified_ymd
|
||||
FAT_U16(0), FAT_U32(0),
|
||||
|
||||
// second entry is readme file
|
||||
'R', 'E', 'A', 'D', 'M', 'E', ' ', ' ', //file_name[8]; padded with spaces (0x20)
|
||||
'T', 'X', 'T', //file_extension[3]; padded with spaces (0x20)
|
||||
0x20, //file attributes: FILE_ATTR_ARCHIVE
|
||||
0x00, //ignore
|
||||
FAT_MS2B(1, 980), //creation_time_10_ms (max 199x10 = 1s 990ms)
|
||||
FAT_HMS2B(13, 42, 36), //create_time_hms [5:6:5] => h:m:(s/2)
|
||||
FAT_YMD2B(2018, 11, 5), //create_time_ymd [7:4:5] => (y+1980):m:d
|
||||
FAT_YMD2B(2020, 11, 5), //last_access_ymd
|
||||
FAT_U16(0), //extended_attributes
|
||||
FAT_HMS2B(13, 44, 16), //last_modified_hms
|
||||
FAT_YMD2B(2019, 11, 5), //last_modified_ymd
|
||||
FAT_U16(2), //start of file in cluster
|
||||
FAT_U32(sizeof(README_CONTENTS) - 1) //file size
|
||||
},
|
||||
|
||||
//------------- Block3: Readme Content -------------//
|
||||
README_CONTENTS
|
||||
};
|
||||
|
||||
static int32_t onWrite(uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) {
|
||||
Serial.printf("MSC WRITE: lba: %lu, offset: %lu, bufsize: %lu\n", lba, offset, bufsize);
|
||||
memcpy(msc_disk[lba] + offset, buffer, bufsize);
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
static int32_t onRead(uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize) {
|
||||
Serial.printf("MSC READ: lba: %lu, offset: %lu, bufsize: %lu\n", lba, offset, bufsize);
|
||||
memcpy(buffer, msc_disk[lba] + offset, bufsize);
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
static bool onStartStop(uint8_t power_condition, bool start, bool load_eject) {
|
||||
Serial.printf("MSC START/STOP: power: %u, start: %u, eject: %u\n", power_condition, start, load_eject);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void usbEventCallback(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
|
||||
if (event_base == ARDUINO_USB_EVENTS) {
|
||||
arduino_usb_event_data_t *data = (arduino_usb_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_USB_STARTED_EVENT: Serial.println("USB PLUGGED"); break;
|
||||
case ARDUINO_USB_STOPPED_EVENT: Serial.println("USB UNPLUGGED"); break;
|
||||
case ARDUINO_USB_SUSPEND_EVENT: Serial.printf("USB SUSPENDED: remote_wakeup_en: %u\n", data->suspend.remote_wakeup_en); break;
|
||||
case ARDUINO_USB_RESUME_EVENT: Serial.println("USB RESUMED"); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
|
||||
USB.onEvent(usbEventCallback);
|
||||
MSC.vendorID("ESP32"); //max 8 chars
|
||||
MSC.productID("USB_MSC"); //max 16 chars
|
||||
MSC.productRevision("1.0"); //max 4 chars
|
||||
MSC.onStartStop(onStartStop);
|
||||
MSC.onRead(onRead);
|
||||
MSC.onWrite(onWrite);
|
||||
|
||||
MSC.mediaPresent(true);
|
||||
MSC.isWritable(true); // true if writable, false if read-only
|
||||
|
||||
MSC.begin(DISK_SECTOR_COUNT, DISK_SECTOR_SIZE);
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,72 @@
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#include "USB.h"
|
||||
|
||||
#if !ARDUINO_USB_CDC_ON_BOOT
|
||||
USBCDC USBSerial;
|
||||
#endif
|
||||
|
||||
static void usbEventCallback(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
|
||||
if (event_base == ARDUINO_USB_EVENTS) {
|
||||
arduino_usb_event_data_t *data = (arduino_usb_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_USB_STARTED_EVENT: Serial.println("USB PLUGGED"); break;
|
||||
case ARDUINO_USB_STOPPED_EVENT: Serial.println("USB UNPLUGGED"); break;
|
||||
case ARDUINO_USB_SUSPEND_EVENT: Serial.printf("USB SUSPENDED: remote_wakeup_en: %u\n", data->suspend.remote_wakeup_en); break;
|
||||
case ARDUINO_USB_RESUME_EVENT: Serial.println("USB RESUMED"); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
} else if (event_base == ARDUINO_USB_CDC_EVENTS) {
|
||||
arduino_usb_cdc_event_data_t *data = (arduino_usb_cdc_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_USB_CDC_CONNECTED_EVENT: Serial.println("CDC CONNECTED"); break;
|
||||
case ARDUINO_USB_CDC_DISCONNECTED_EVENT: Serial.println("CDC DISCONNECTED"); break;
|
||||
case ARDUINO_USB_CDC_LINE_STATE_EVENT: Serial.printf("CDC LINE STATE: dtr: %u, rts: %u\n", data->line_state.dtr, data->line_state.rts); break;
|
||||
case ARDUINO_USB_CDC_LINE_CODING_EVENT:
|
||||
Serial.printf(
|
||||
"CDC LINE CODING: bit_rate: %lu, data_bits: %u, stop_bits: %u, parity: %u\n", data->line_coding.bit_rate, data->line_coding.data_bits,
|
||||
data->line_coding.stop_bits, data->line_coding.parity
|
||||
);
|
||||
break;
|
||||
case ARDUINO_USB_CDC_RX_EVENT:
|
||||
Serial.printf("CDC RX [%u]:", data->rx.len);
|
||||
{
|
||||
uint8_t buf[data->rx.len];
|
||||
size_t len = USBSerial.read(buf, data->rx.len);
|
||||
Serial.write(buf, len);
|
||||
}
|
||||
Serial.println();
|
||||
break;
|
||||
case ARDUINO_USB_CDC_RX_OVERFLOW_EVENT: Serial.printf("CDC RX Overflow of %d bytes", data->rx_overflow.dropped_bytes); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
|
||||
USB.onEvent(usbEventCallback);
|
||||
USBSerial.onEvent(usbEventCallback);
|
||||
|
||||
USBSerial.begin();
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
while (Serial.available()) {
|
||||
size_t l = Serial.available();
|
||||
uint8_t b[l];
|
||||
l = Serial.read(b, l);
|
||||
USBSerial.write(b, l);
|
||||
}
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,186 @@
|
||||
#ifndef ARDUINO_USB_MODE
|
||||
#error This ESP32 SoC has no Native USB interface
|
||||
#elif ARDUINO_USB_MODE == 1
|
||||
#warning This sketch should be used when USB is in OTG mode
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#include "USB.h"
|
||||
#include "USBVendor.h"
|
||||
|
||||
USBVendor Vendor;
|
||||
const int buttonPin = 0;
|
||||
|
||||
//CDC Control Requests
|
||||
#define REQUEST_SET_LINE_CODING 0x20
|
||||
#define REQUEST_GET_LINE_CODING 0x21
|
||||
#define REQUEST_SET_CONTROL_LINE_STATE 0x22
|
||||
|
||||
//CDC Line Coding Control Request Structure
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t bit_rate;
|
||||
uint8_t stop_bits; //0: 1 stop bit, 1: 1.5 stop bits, 2: 2 stop bits
|
||||
uint8_t parity; //0: None, 1: Odd, 2: Even, 3: Mark, 4: Space
|
||||
uint8_t data_bits; //5, 6, 7, 8 or 16
|
||||
} request_line_coding_t;
|
||||
|
||||
static request_line_coding_t vendor_line_coding = {9600, 0, 0, 8};
|
||||
|
||||
// Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send)
|
||||
static uint8_t vendor_line_state = 0;
|
||||
|
||||
//USB and Vendor events
|
||||
static void usbEventCallback(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
|
||||
if (event_base == ARDUINO_USB_EVENTS) {
|
||||
arduino_usb_event_data_t *data = (arduino_usb_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_USB_STARTED_EVENT: Serial.println("USB PLUGGED"); break;
|
||||
case ARDUINO_USB_STOPPED_EVENT: Serial.println("USB UNPLUGGED"); break;
|
||||
case ARDUINO_USB_SUSPEND_EVENT: Serial.printf("USB SUSPENDED: remote_wakeup_en: %u\n", data->suspend.remote_wakeup_en); break;
|
||||
case ARDUINO_USB_RESUME_EVENT: Serial.println("USB RESUMED"); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
} else if (event_base == ARDUINO_USB_VENDOR_EVENTS) {
|
||||
arduino_usb_vendor_event_data_t *data = (arduino_usb_vendor_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case ARDUINO_USB_VENDOR_DATA_EVENT:
|
||||
Serial.printf("Vendor RX: len:%u\n", data->data.len);
|
||||
for (uint16_t i = 0; i < data->data.len; i++) {
|
||||
Serial.write(Vendor.read());
|
||||
}
|
||||
Serial.println();
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char *strRequestDirections[] = {"OUT", "IN"};
|
||||
static const char *strRequestTypes[] = {"STANDARD", "CLASS", "VENDOR", "INVALID"};
|
||||
static const char *strRequestRecipients[] = {"DEVICE", "INTERFACE", "ENDPOINT", "OTHER"};
|
||||
static const char *strRequestStages[] = {"SETUP", "DATA", "ACK"};
|
||||
|
||||
//Handle USB requests to the vendor interface
|
||||
bool vendorRequestCallback(uint8_t rhport, uint8_t requestStage, arduino_usb_control_request_t const *request) {
|
||||
Serial.printf(
|
||||
"Vendor Request: Stage: %5s, Direction: %3s, Type: %8s, Recipient: %9s, bRequest: 0x%02x, wValue: 0x%04x, wIndex: %u, wLength: %u\n",
|
||||
strRequestStages[requestStage], strRequestDirections[request->bmRequestDirection], strRequestTypes[request->bmRequestType],
|
||||
strRequestRecipients[request->bmRequestRecipient], request->bRequest, request->wValue, request->wIndex, request->wLength
|
||||
);
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (request->bmRequestDirection == REQUEST_DIRECTION_OUT && request->bmRequestType == REQUEST_TYPE_STANDARD
|
||||
&& request->bmRequestRecipient == REQUEST_RECIPIENT_INTERFACE && request->bRequest == 0x0b) {
|
||||
if (requestStage == REQUEST_STAGE_SETUP) {
|
||||
// response with status OK
|
||||
result = Vendor.sendResponse(rhport, request);
|
||||
} else {
|
||||
result = true;
|
||||
}
|
||||
} else
|
||||
//Implement CDC Control Requests
|
||||
if (request->bmRequestType == REQUEST_TYPE_CLASS && request->bmRequestRecipient == REQUEST_RECIPIENT_DEVICE) {
|
||||
switch (request->bRequest) {
|
||||
|
||||
case REQUEST_SET_LINE_CODING: //0x20
|
||||
// Accept only direction OUT with data size 7
|
||||
if (request->wLength != sizeof(request_line_coding_t) || request->bmRequestDirection != REQUEST_DIRECTION_OUT) {
|
||||
break;
|
||||
}
|
||||
if (requestStage == REQUEST_STAGE_SETUP) {
|
||||
//Send the response in setup stage (it will write the data to vendor_line_coding in the DATA stage)
|
||||
result = Vendor.sendResponse(rhport, request, (void *)&vendor_line_coding, sizeof(request_line_coding_t));
|
||||
} else if (requestStage == REQUEST_STAGE_ACK) {
|
||||
//In the ACK stage the response is complete
|
||||
Serial.printf(
|
||||
"Vendor Line Coding: bit_rate: %lu, data_bits: %u, stop_bits: %u, parity: %u\n", vendor_line_coding.bit_rate, vendor_line_coding.data_bits,
|
||||
vendor_line_coding.stop_bits, vendor_line_coding.parity
|
||||
);
|
||||
}
|
||||
result = true;
|
||||
break;
|
||||
|
||||
case REQUEST_GET_LINE_CODING: //0x21
|
||||
// Accept only direction IN with data size 7
|
||||
if (request->wLength != sizeof(request_line_coding_t) || request->bmRequestDirection != REQUEST_DIRECTION_IN) {
|
||||
break;
|
||||
}
|
||||
if (requestStage == REQUEST_STAGE_SETUP) {
|
||||
//Send the response in setup stage (it will write the data to vendor_line_coding in the DATA stage)
|
||||
result = Vendor.sendResponse(rhport, request, (void *)&vendor_line_coding, sizeof(request_line_coding_t));
|
||||
}
|
||||
result = true;
|
||||
break;
|
||||
|
||||
case REQUEST_SET_CONTROL_LINE_STATE: //0x22
|
||||
// Accept only direction OUT with data size 0
|
||||
if (request->wLength != 0 || request->bmRequestDirection != REQUEST_DIRECTION_OUT) {
|
||||
break;
|
||||
}
|
||||
if (requestStage == REQUEST_STAGE_SETUP) {
|
||||
//Send the response in setup stage
|
||||
vendor_line_state = request->wValue;
|
||||
result = Vendor.sendResponse(rhport, request);
|
||||
} else if (requestStage == REQUEST_STAGE_ACK) {
|
||||
//In the ACK stage the response is complete
|
||||
bool dtr = (vendor_line_state & 1) != 0;
|
||||
bool rts = (vendor_line_state & 2) != 0;
|
||||
Serial.printf("Vendor Line State: dtr: %u, rts: %u\n", dtr, rts);
|
||||
}
|
||||
result = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
// stall unknown request
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
|
||||
Vendor.onEvent(usbEventCallback);
|
||||
Vendor.onRequest(vendorRequestCallback);
|
||||
Vendor.begin();
|
||||
|
||||
USB.onEvent(usbEventCallback);
|
||||
USB.webUSB(true);
|
||||
// Set the URL for your WebUSB landing page
|
||||
USB.webUSBURL("https://docs.espressif.com/projects/arduino-esp32/en/latest/_static/webusb.html");
|
||||
USB.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static int previousButtonState = HIGH;
|
||||
int buttonState = digitalRead(buttonPin);
|
||||
if (buttonState != previousButtonState) {
|
||||
previousButtonState = buttonState;
|
||||
if (buttonState == LOW) {
|
||||
Serial.println("Button Pressed");
|
||||
Vendor.println("Button Pressed");
|
||||
Vendor.flush(); //Without flushing the data will only be sent when the buffer is full (64 bytes)
|
||||
} else {
|
||||
Serial.println("Button Released");
|
||||
Vendor.println("Button Released");
|
||||
Vendor.flush(); //Without flushing the data will only be sent when the buffer is full (64 bytes)
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
|
||||
while (Serial.available()) {
|
||||
size_t l = Serial.available();
|
||||
uint8_t b[l];
|
||||
l = Serial.read(b, l);
|
||||
Vendor.write(b, l);
|
||||
Vendor.flush(); //Without flushing the data will only be sent when the buffer is full (64 bytes)
|
||||
}
|
||||
}
|
||||
#endif /* ARDUINO_USB_MODE */
|
||||
@@ -0,0 +1,2 @@
|
||||
requires:
|
||||
- CONFIG_SOC_USB_OTG_SUPPORTED=y
|
||||
@@ -0,0 +1,133 @@
|
||||
<!-- Based on https://github.com/zephyrproject-rtos/zephyr/tree/main/samples/subsys/usb/webusb -->
|
||||
|
||||
<!--
|
||||
Example of WebUSB web page to communicate with a USB device.
|
||||
This can be used as a starting point for your self-hosted WebUSB landing page.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Espressif WebUSB Console Example</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
var serial = {};
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
serial.getPorts = function() {
|
||||
return navigator.usb.getDevices().then(devices => {
|
||||
return devices.map(device => new serial.Port(device));
|
||||
});
|
||||
};
|
||||
|
||||
serial.requestPort = function() {
|
||||
const filters = [
|
||||
{ 'vendorId': 0x10c4, 'productId': 0xea60 },
|
||||
{ 'vendorId': 0x303a, 'productId': 0x1001 },
|
||||
{ 'vendorId': 0x303a, 'productId': 0x0002 },
|
||||
];
|
||||
return navigator.usb.requestDevice({ 'filters': filters }).then(
|
||||
device => new serial.Port(device)
|
||||
);
|
||||
}
|
||||
|
||||
serial.Port = function(device) {
|
||||
this.device_ = device;
|
||||
};
|
||||
|
||||
serial.Port.prototype.connect = function() {
|
||||
let readLoop = () => {
|
||||
const {
|
||||
endpointNumber
|
||||
} = this.device_.configuration.interfaces[0].alternate.endpoints[0]
|
||||
this.device_.transferIn(endpointNumber, 64).then(result => {
|
||||
this.onReceive(result.data);
|
||||
readLoop();
|
||||
}, error => {
|
||||
this.onReceiveError(error);
|
||||
});
|
||||
};
|
||||
|
||||
return this.device_.open()
|
||||
.then(() => {
|
||||
if (this.device_.configuration === null) {
|
||||
return this.device_.selectConfiguration(1);
|
||||
}
|
||||
})
|
||||
.then(() => this.device_.claimInterface(0))
|
||||
.then(() => {
|
||||
readLoop();
|
||||
});
|
||||
};
|
||||
|
||||
serial.Port.prototype.disconnect = function() {
|
||||
return this.device_.close();
|
||||
};
|
||||
|
||||
serial.Port.prototype.send = function(data) {
|
||||
const {
|
||||
endpointNumber
|
||||
} = this.device_.configuration.interfaces[0].alternate.endpoints[1]
|
||||
return this.device_.transferOut(endpointNumber, data);
|
||||
};
|
||||
})();
|
||||
|
||||
let port;
|
||||
|
||||
function connect() {
|
||||
port.connect().then(() => {
|
||||
port.onReceive = data => {
|
||||
let textDecoder = new TextDecoder();
|
||||
console.log("Received:", textDecoder.decode(data));
|
||||
document.getElementById('output').value += textDecoder.decode(data);
|
||||
}
|
||||
port.onReceiveError = error => {
|
||||
console.error(error);
|
||||
document.querySelector("#connect").style = "visibility: initial";
|
||||
port.disconnect();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function send(string) {
|
||||
console.log("sending to serial:" + string.length);
|
||||
if (string.length === 0)
|
||||
return;
|
||||
console.log("sending to serial: [" + string +"]\n");
|
||||
|
||||
let view = new TextEncoder('utf-8').encode(string);
|
||||
console.log(view);
|
||||
if (port) {
|
||||
port.send(view);
|
||||
}
|
||||
};
|
||||
|
||||
window.onload = _ => {
|
||||
document.querySelector("#connect").onclick = function() {
|
||||
serial.requestPort().then(selectedPort => {
|
||||
port = selectedPort;
|
||||
this.style = "visibility: hidden";
|
||||
connect();
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelector("#submit").onclick = () => {
|
||||
let source = document.querySelector("#input").value;
|
||||
send(source);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<button id="connect" style="visibility: initial">Connect To ESP Device</button>
|
||||
<br><br><label for="input">Sender: </label> <br>
|
||||
<textarea id="input" rows="25" cols="80">Send to ESP Device</textarea>
|
||||
<br><button id="submit">Send</button>
|
||||
<br><br>
|
||||
<label for="output">Receiver: </label> <br>
|
||||
<textarea id="output" rows="25" cols="80"></textarea>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user