-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmidi_c4_preset.ino
171 lines (131 loc) · 3.37 KB
/
midi_c4_preset.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <TM1637Display.h> // https://github.com/avishorp/TM1637
#include <usbh_midi.h> // https://github.com/gdsports/USB_Host_Library_SAMD
#ifdef ADAFRUIT_TRINKET_M0
// setup Dotstar LED on Trinket M0
#include <Adafruit_DotStar.h> // https://github.com/adafruit/Adafruit_DotStar
#define DATAPIN 7
#define CLOCKPIN 8
Adafruit_DotStar strip = Adafruit_DotStar(1, DATAPIN, CLOCKPIN, DOTSTAR_BRG);
#endif
USBHost usb;
USBH_MIDI Midi(&usb);
const int BUTTON_UP = 0;
const int BUTTON_DOWN = 1;
const int BUTTON_DEBOUNCE = 140; // Any shorter and we get double-presses. Any longer it's sluggish feeling...
const int CHANNEL_DEBOUNCE = 1200; // Show "ch00" on the screen for 1200ms
volatile int channel = 0; // MIDI channel is 0/1 by default
// volatile int commandCode = 103; // Bypass
volatile int commandCode = 104; // Engaged
volatile int preset = 0; // Initial preset value
volatile long buttonTime = 0;
volatile long displayTime = 0;
// instantiate display
const int LCD_DIO = 2;
const int LCD_CLK = 3;
TM1637Display display(LCD_CLK, LCD_DIO);
void changePreset(int value) {
preset = value; // Set globally for display
uint8_t buf[3] = {
0xB0 | (channel & 0xf),
commandCode & 0x7f,
value & 0x7f
};
Midi.SendData(buf);
}
int getNewValue(bool up, int max, int value) {
volatile int newValue = value;
if (up) {
newValue += 1;
if (newValue > max) {
return 0;
}
return newValue;
}
// else down
newValue -= 1;
if (newValue < 0) {
return max;
}
return newValue;
}
int getNewPreset(bool up) {
int max = 127;
return getNewValue(up, max, preset);
}
int getNewChannel() {
int max = 15;
return getNewValue(true, max, channel);
}
bool getValue(int pin) {
return digitalRead(pin) == LOW;
}
void showChannel() {
volatile int tens = 0;
volatile int ones = channel;
if (channel >= 10) {
tens = 1;
ones = channel - 10;
}
uint8_t channelSeg[] = {
SEG_D | SEG_E | SEG_G, // "c"
SEG_C | SEG_E | SEG_F | SEG_G, // "h"
display.encodeDigit(tens),
display.encodeDigit(ones)
};
display.setSegments(channelSeg);
delay(CHANNEL_DEBOUNCE);
}
void readButtons() {
if ((millis() - buttonTime) < BUTTON_DEBOUNCE) {
return;
}
int prevPreset = preset;
volatile int newPreset = preset;
bool upPressed = getValue(BUTTON_UP);
bool downPressed = getValue(BUTTON_DOWN);
if (upPressed && downPressed) {
// channel = getNewChannel(); // Uncomment this if we ever desire to change channel?
showChannel();
} else {
if (upPressed) {
newPreset = getNewPreset(true);
}
if (downPressed) {
newPreset = getNewPreset(false);
}
if ((upPressed || downPressed) && prevPreset != newPreset) {
changePreset(newPreset);
}
}
buttonTime = millis();
}
void updateDisplay() {
if ((millis() - displayTime) < (BUTTON_DEBOUNCE * 2)) {
return;
}
display.showNumberDec(preset);
displayTime = millis();
}
void setup() {
// Turn off built-in RED LED
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
#ifdef ADAFRUIT_TRINKET_M0
// Turn off built-in Dotstar RGB LED
strip.begin();
strip.clear();
strip.show();
#endif
usb.Init();
pinMode(BUTTON_UP, INPUT_PULLUP);
pinMode(BUTTON_DOWN, INPUT_PULLUP);
display.clear();
display.setBrightness(3);
showChannel();
delay(200);
}
void loop() {
usb.Task();
readButtons();
updateDisplay();
}