Skip to content

Commit 1a7a893

Browse files
EleotleCramme-no-devlucasssvazP-R-O-C-H-Y
authored
Add USB MIDI support to libraries/USB (#8166)
* Added USBMIDI support to libraries/USB * Added MIDI examples to libraries/USB * Added missing newline at end of file to MidiController.ino * Added USBMIDI.cpp to CMake file * Fix narrowing conversion warning in USBMIDI.cpp * Fix incomplete initializers warning in USBMIDI.cpp * Apply suggestions from code review Co-authored-by: Lucas Saavedra Vaz <lucassvaz@yahoo.com.br> * add skip files for C6+H2 * remove already patched workaroud for bug * move #define to top of file --------- Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com> Co-authored-by: Lucas Saavedra Vaz <lucas.vaz@espressif.com> Co-authored-by: Jan Procházka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Co-authored-by: Lucas Saavedra Vaz <lucassvaz@yahoo.com.br>
1 parent 374280c commit 1a7a893

23 files changed

+555
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ set(LIBRARY_SRCS
115115
libraries/Update/src/Updater.cpp
116116
libraries/Update/src/HttpsOTAUpdate.cpp
117117
libraries/USB/src/USBHID.cpp
118+
libraries/USB/src/USBMIDI.cpp
118119
libraries/USB/src/USBHIDMouse.cpp
119120
libraries/USB/src/USBHIDKeyboard.cpp
120121
libraries/USB/src/USBHIDGamepad.cpp

libraries/USB/examples/MIDI/MidiController/.skip.esp32

Whitespace-only changes.

libraries/USB/examples/MIDI/MidiController/.skip.esp32c3

Whitespace-only changes.

libraries/USB/examples/MIDI/MidiController/.skip.esp32c6

Whitespace-only changes.

libraries/USB/examples/MIDI/MidiController/.skip.esp32h2

Whitespace-only changes.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
This is an example of a Simple MIDI Controller using an ESP32 with a native USB support stack (S2, S3,
3+
etc.).
4+
5+
For a hookup guide and more information on reading the ADC, please see:
6+
https://randomnerdtutorials.com/esp32-adc-analog-read-arduino-ide/ (Note: This sketch uses GPIO05)
7+
8+
For best results, it is recommended to add an extra offset resistor between VCC and the potentiometer.
9+
(For a standard 10kOhm potentiometer, 3kOhm - 4kOhm will do.)
10+
11+
View this sketch in action on YouTube: https://youtu.be/Y9TLXs_3w1M
12+
*/
13+
#if ARDUINO_USB_MODE
14+
#warning This sketch should be used when USB is in OTG mode
15+
void setup() {}
16+
void loop() {}
17+
#else
18+
19+
#include <math.h>
20+
21+
#include "USB.h"
22+
#include "USBMIDI.h"
23+
USBMIDI MIDI;
24+
25+
#define MIDI_NOTE_C4 64
26+
27+
#define MIDI_CC_CUTOFF 74
28+
29+
///// ADC & Controller Input Handling /////
30+
31+
#define CONTROLLER_PIN 5
32+
33+
// ESP32 ADC needs a ton of smoothing
34+
#define SMOOTHING_VALUE 1000
35+
static double controllerInputValue = 0;
36+
37+
void updateControllerInputValue() {
38+
controllerInputValue =
39+
(controllerInputValue * (SMOOTHING_VALUE - 1) + analogRead(CONTROLLER_PIN)) / SMOOTHING_VALUE;
40+
}
41+
42+
void primeControllerInputValue() {
43+
for (int i = 0; i < SMOOTHING_VALUE; i++) {
44+
updateControllerInputValue();
45+
}
46+
}
47+
48+
uint16_t readControllerValue() {
49+
// Lower ADC input amplitude to get a stable value
50+
return round(controllerInputValue / 12);
51+
}
52+
53+
///// Button Handling /////
54+
55+
#define BUTTON_PIN 0
56+
57+
// Simple button state transition function with debounce
58+
// (See also: https://tinyurl.com/simple-debounce)
59+
#define PRESSED 0xff00
60+
#define RELEASED 0xfe1f
61+
uint16_t getButtonEvent() {
62+
static uint16_t state = 0;
63+
state = (state << 1) | digitalRead(BUTTON_PIN) | 0xfe00;
64+
return state;
65+
}
66+
67+
///// Arduino Hooks /////
68+
69+
void setup() {
70+
Serial.begin(115200);
71+
MIDI.begin();
72+
USB.begin();
73+
74+
primeControllerInputValue();
75+
}
76+
77+
void loop() {
78+
uint16_t newControllerValue = readControllerValue();
79+
static uint16_t lastControllerValue = 0;
80+
81+
// Auto-calibrate the controller range
82+
static uint16_t maxControllerValue = 0;
83+
static uint16_t minControllerValue = 0xFFFF;
84+
85+
if (newControllerValue < minControllerValue) {
86+
minControllerValue = newControllerValue;
87+
}
88+
if (newControllerValue > maxControllerValue) {
89+
maxControllerValue = newControllerValue;
90+
}
91+
92+
// Send update if the controller value has changed
93+
if (lastControllerValue != newControllerValue) {
94+
lastControllerValue = newControllerValue;
95+
96+
// Can't map if the range is zero
97+
if (minControllerValue != maxControllerValue) {
98+
MIDI.controlChange(MIDI_CC_CUTOFF,
99+
map(newControllerValue, minControllerValue, maxControllerValue, 0, 127));
100+
}
101+
}
102+
103+
updateControllerInputValue();
104+
105+
// Hook Button0 to a MIDI note so that we can observe
106+
// the CC effect without the need for a MIDI keyboard.
107+
switch (getButtonEvent()) {
108+
case PRESSED:
109+
MIDI.noteOn(MIDI_NOTE_C4, 64);
110+
break;
111+
case RELEASED:
112+
MIDI.noteOff(MIDI_NOTE_C4, 0);
113+
break;
114+
default:
115+
break;
116+
}
117+
}
118+
#endif /* ARDUINO_USB_MODE */

libraries/USB/examples/MIDI/MidiInterface/.skip.esp32

Whitespace-only changes.

libraries/USB/examples/MIDI/MidiInterface/.skip.esp32c3

Whitespace-only changes.

libraries/USB/examples/MIDI/MidiInterface/.skip.esp32c6

Whitespace-only changes.

libraries/USB/examples/MIDI/MidiInterface/.skip.esp32h2

Whitespace-only changes.

0 commit comments

Comments
 (0)