-
Notifications
You must be signed in to change notification settings - Fork 7.5k
/
Copy pathMidiController.ino
111 lines (86 loc) · 2.96 KB
/
MidiController.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
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"
USBMIDI MIDI;
#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 */