-
Notifications
You must be signed in to change notification settings - Fork 0
/
24-touch-midi-controller.ino
210 lines (176 loc) · 5.5 KB
/
24-touch-midi-controller.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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#include <Adafruit_MPR121.h>
#include <MIDIUSB.h>
#include <Adafruit_NeoPixel.h>
#include "Arduino.h"
#include "avdweb_Switch.h"
#define PIN 6
#define NUM_LEDS 2
#define THRESHOLD 2
#define RELEASE 1
#define BASE_NOTE_MIN 24 //C-1
#define BASE_NOTE_MAX 94 //C8
#define BASE_NOTE 36 //def note C1
#define MIDI_VELOCITY 0x7F //127 velocity
#define BRIGHTNESS 30
const byte downButtonPin = 5; // downButton
const byte upButtonPin = 4; // upButton
Switch downButton = Switch(downButtonPin);
Switch upButton = Switch(upButtonPin);
bool isMuted = false; // midi muted
Adafruit_MPR121 cap1 = Adafruit_MPR121(); //initialize first mpr121
Adafruit_MPR121 cap2 = Adafruit_MPR121(); //initialize second mpr121
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800); //initialize ws8212b
uint16_t last_touched[24] = {0};
long pixelHue = 0;
int baseNote = BASE_NOTE; // set base note
void setup() {
Serial.begin(9600);
cap1.begin(0x5B); // initialization MPR121 adress 0x5B
cap1.setThresholds(THRESHOLD, RELEASE); // set treshold MPR121 adress 0x5B
cap2.begin(0x5A); //initialization MPR121 adress 0x5A
cap2.setThresholds(THRESHOLD, RELEASE); // Uset treshold MPR121 adress 0x5A
strip.begin(); //initialization LED
strip.setBrightness(BRIGHTNESS); // set default brighthness
}
void loop() {
readTouchInputs(&cap1, 0); // waiting for touch first mpr121
readTouchInputs(&cap2, 12); // waiting for touch second mpr121
RGBFade(0); // fade effect on led 1
strip.show();
downButton.poll();
if(downButton.singleClick()) {
if (baseNote >= BASE_NOTE_MIN) {
baseNote -= 12;
Serial.println(baseNote);
blinkLed(1, getColor(baseNote));
if (isMuted) {
strip.setPixelColor(1, strip.Color(255, 0, 0));
strip.show();
}
}
}
if(downButton.longPress()) {
if (!isMuted) {
muteAllChannels();
strip.setPixelColor(1, strip.Color(255, 0, 0));
strip.show();
}
}
upButton.poll();
if(upButton.singleClick()) {
if (baseNote <= BASE_NOTE_MAX) {
baseNote += 12;
Serial.println(baseNote);
blinkLed(1, getColor(baseNote));
if (isMuted) {
strip.setPixelColor(1, strip.Color(255, 0, 0));
strip.show();
}
}
}
if(upButton.longPress() && isMuted) {
if (isMuted) {
strip.setPixelColor(1, strip.Color(0, 255, 0));
strip.show();
delay(400);
cap1.setThresholds(THRESHOLD, RELEASE);
cap2.setThresholds(THRESHOLD, RELEASE);
unmuteAllChannels();
}
}
}
void readTouchInputs(Adafruit_MPR121* cap, int offset) {
uint16_t current_touched = cap->touched();
for (uint8_t i=0; i<12; i++) {
if ((current_touched & _BV(i)) && !(last_touched[i + offset] & _BV(i))) {
handleTouchOn(i, offset);
}
else if (!(current_touched & _BV(i)) && (last_touched[i + offset] & _BV(i))) {
handleTouchOff(i, offset);
}
last_touched[i + offset] = current_touched;
}
}
void handleTouchOn(uint8_t i, int offset) {
if (!isMuted) {
noteOn(0x90, baseNote + i + offset, MIDI_VELOCITY);
MidiUSB.flush();
Serial.print("Wysłano noteOn z wartością ");
Serial.println(baseNote + i + offset);
strip.setPixelColor(1, strip.Color(255, 255, 246));
}
}
void handleTouchOff(uint8_t i, int offset) {
if (!isMuted) {
noteOff(0x80, baseNote + i + offset, 0);
MidiUSB.flush();
Serial.print("Wysłano noteOff z wartością ");
Serial.println(baseNote + i + offset);
strip.setPixelColor(1, strip.Color(0, 0, 0));
}
}
// rgb fade effect
void RGBFade(int pixel) {
strip.setPixelColor(pixel, strip.gamma32(strip.ColorHSV(pixelHue)));
pixelHue += 12;
if(pixelHue > 3*65536) {
pixelHue = 0;
}
}
// function noteOn
void noteOn(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOn);
}
// function noteOff
void noteOff(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOff = {0x08, channel, pitch, velocity};
MidiUSB.sendMIDI(noteOff);
}
// function CC change
void controlChange(byte channel, byte control, byte value) {
midiEventPacket_t controlChange = {0x0B, 0xB0 | channel, control, value};
MidiUSB.sendMIDI(controlChange);
}
// function mute all channels
void muteAllChannels() {
for (byte channel = 0; channel < 16; channel++) {
controlChange(channel, 120, 0);
}
isMuted = true;
}
// function unmute all channels
void unmuteAllChannels() {
for (byte channel = 0; channel < 16; channel++) {
controlChange(channel, 121, 0);
}
isMuted = false;
for (uint8_t i=0; i<24; i++) {
last_touched[i] = 0;
}
}
// change flash color when change octave
uint32_t getColor(int baseNote) {
switch (baseNote) {
case 12: return strip.Color(252, 3, 3); // red
case 24: return strip.Color(252, 136, 3); // orange
case 36: return strip.Color(252, 235, 3); // yellow
case 48: return strip.Color(132, 252, 3); // green
case 60: return strip.Color(3, 252, 219); // celeste
case 72: return strip.Color(3, 94, 252); // blue
case 84: return strip.Color(123, 3, 252); // violet
case 96: return strip.Color(252, 3, 235); // pink
default: return strip.Color(255, 255, 255); // white
}
}
// confirmation octave - led blinks
void blinkLed(int pixel, uint32_t color) {
for (int i = 0; i < 2; i++) {
strip.setPixelColor(pixel, color);
strip.show();
delay(100);
strip.setPixelColor(pixel, strip.Color(0, 0, 0));
strip.show();
delay(100);
}
}