f@1
|
1 /******************************************************************************
|
f@5
|
2 * Copyright (C) 2015 Ben Bengler (mail@benbengler.com)
|
f@5
|
3 * Copyright (C) 2016 Queen Mary University of London
|
f@5
|
4 * Authors: Ben Bengler, Fiore Martin
|
f@1
|
5 *
|
f@5
|
6 * This file is part of Collidoscope.
|
f@5
|
7 *
|
f@5
|
8 * Collidoscope is free software: you can redistribute it and/or modify
|
f@5
|
9 * it under the terms of the GNU General Public License as published by
|
f@5
|
10 * the Free Software Foundation, either version 3 of the License, or
|
f@5
|
11 * (at your option) any later version.
|
f@5
|
12 *
|
f@5
|
13 * This program is distributed in the hope that it will be useful,
|
f@5
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
f@5
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
f@5
|
16 * GNU General Public License for more details.
|
f@5
|
17 *
|
f@5
|
18 * You should have received a copy of the GNU General Public License
|
f@5
|
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
f@1
|
20 *
|
f@5
|
21 ****************************************************************************
|
f@5
|
22 *
|
f@1
|
23 * Teensy 2 ++ pinout: https://www.pjrc.com/teensy/card4b.pdf
|
f@1
|
24 *
|
f@1
|
25 * ANALOG INPUTS:
|
f@1
|
26 * Wavejet -> F0 (38) [Horizontal rail 1]
|
f@1
|
27 * Wavejet -> F1 (39) [Horizontal rail 2]
|
f@5
|
28 * Filter 1 -> F2 (40) [Fader with moon/sun 1]
|
f@5
|
29 * Filter 2 -> F4 (42) [Fader with moon/sun 2]
|
f@5
|
30 * Duration 1-> F3 (41) [Fader with grains 1]
|
f@5
|
31 * Duration 2-> F5 (43) [Fader with grains 2]
|
f@1
|
32 *
|
f@1
|
33 * DIGITAL INPUTS [INTERRUPTS]:
|
f@1
|
34 * Sel. length 1 -> INT0/INT1 (0, 1) [Encoder 1]
|
f@5
|
35 * Sel. length 2 -> INT2/INT3 (2, 3) [Encoder 2]
|
f@1
|
36 *
|
f@1
|
37 * DIGITAL INPUTS:
|
f@1
|
38 * Play1 toggle -> B0 (20)
|
f@1
|
39 * Record1 -> B1 (21)
|
f@1
|
40 * Play2 toggle -> B3 (22)
|
f@1
|
41 * Record2 -> B4 (24)
|
f@1
|
42 *
|
f@1
|
43 * DIGITAL OUTPUTS:
|
f@1
|
44 * Record Button 1 Led -> D4 (4)
|
f@1
|
45 * Record Button 2 Led -> D5 (5)
|
f@5
|
46 *
|
f@1
|
47 ******************************************************************************/
|
f@1
|
48
|
f@1
|
49
|
f@1
|
50 #include <Encoder.h>
|
f@1
|
51 #include <Bounce.h>
|
f@1
|
52
|
f@1
|
53 ///////////////////////////////////////////////////
|
f@1
|
54 //MIDI settings
|
f@1
|
55 const int midi_chan_inst1 = 1; // MIDI channel for Instrument 1
|
f@1
|
56 const int midi_chan_inst2 = 2; // MIDI channel for Instrument 2
|
f@1
|
57
|
f@1
|
58 const int cc_length = 1; // MIDI cc controlling selection length
|
f@1
|
59 const int cc_duration = 2; // MIDI cc controlling duration
|
f@1
|
60 const int cc_filter = 7; // MIDI cc controlling LP filter
|
f@1
|
61 const int cc_play = 4; // MIDI cc controlling PLAY
|
f@1
|
62 const int cc_record = 5; // MIDI cc controlling RECORD
|
f@5
|
63
|
f@1
|
64
|
f@1
|
65 ///////////////////////////////////////////////////
|
f@1
|
66 //Default Values:
|
f@1
|
67 const int Enc_def = 64; //default selection length
|
f@1
|
68 int MIDI_led_state = LOW;
|
f@1
|
69
|
f@1
|
70 ///////////////////////////////////////////////////
|
f@1
|
71 // Interface Inputs
|
f@1
|
72
|
f@1
|
73 //Buttons:
|
f@1
|
74
|
f@1
|
75 const int Pin_play1 = 20; //B0
|
f@1
|
76 const int Pin_record1 = 21; //B1
|
f@1
|
77 const int Pin_play2 = 23; //B3
|
f@1
|
78 const int Pin_record2 = 24; //B4
|
f@1
|
79 const int Pin_record1_led = 4; //D4
|
f@1
|
80 const int Pin_record2_led = 5; //D5
|
f@1
|
81 const int Pin_MIDIled = 6;
|
f@1
|
82
|
f@1
|
83 Bounce button1 = Bounce(Pin_play1, 5);
|
f@1
|
84 Bounce button2 = Bounce(Pin_record1, 5);
|
f@1
|
85 Bounce button3 = Bounce(Pin_play2, 5);
|
f@1
|
86 Bounce button4 = Bounce(Pin_record2, 5);
|
f@1
|
87
|
f@1
|
88
|
f@1
|
89 //Encoder
|
f@1
|
90 Encoder Enc1 (0, 1); //Encoder for section length on Wavejet 1
|
f@1
|
91 Encoder Enc2 (2, 3); //Encoder for section length on Wavejet 2
|
f@1
|
92
|
f@1
|
93
|
f@1
|
94 // Variables
|
f@11
|
95 const int jitter_thresh = 10; // threshold value for analog INs to suppress sending MIDI due to input jitter
|
f@1
|
96
|
f@1
|
97 void setup() {
|
f@1
|
98
|
f@1
|
99 pinMode(Pin_play1, INPUT_PULLUP);
|
f@1
|
100 pinMode(Pin_record1, INPUT_PULLUP);
|
f@1
|
101 pinMode(Pin_play2, INPUT_PULLUP);
|
f@1
|
102 pinMode(Pin_record2, INPUT_PULLUP);
|
f@1
|
103
|
f@1
|
104
|
f@1
|
105 pinMode(Pin_MIDIled, OUTPUT);
|
f@1
|
106 pinMode(Pin_record1_led, OUTPUT);
|
f@1
|
107 pinMode(Pin_record2_led, OUTPUT);
|
f@1
|
108 }
|
f@1
|
109
|
f@1
|
110 //Store recent values to detect parameter change
|
f@1
|
111 long Enc1_old = -999;
|
f@1
|
112 long Enc2_old = -999;
|
f@1
|
113
|
f@1
|
114 uint16_t Jet1_old = 0;
|
f@1
|
115 int16_t Jet1_old_MIDI = -1;
|
f@1
|
116 uint16_t Jet2_old = 0;
|
f@1
|
117 int16_t Jet2_old_MIDI = -1;
|
f@1
|
118
|
f@1
|
119 uint16_t filter1_old = 0;
|
f@1
|
120 int16_t filter1_old_MIDI = -1;
|
f@1
|
121 uint16_t filter2_old = 0;
|
f@1
|
122 int16_t filter2_old_MIDI = -1;
|
f@1
|
123
|
f@1
|
124 uint16_t dur1_old = 0;
|
f@1
|
125 int16_t dur1_old_MIDI = -1;
|
f@1
|
126 uint16_t dur2_old = 0;
|
f@1
|
127 int16_t dur2_old_MIDI = -1;
|
f@1
|
128
|
f@1
|
129 void loop() {
|
f@1
|
130
|
f@1
|
131 digitalWrite(Pin_MIDIled, LOW);
|
f@1
|
132 digitalWrite(Pin_record1_led, HIGH);
|
f@1
|
133 digitalWrite(Pin_record2_led, HIGH);
|
f@1
|
134 button1.update();
|
f@1
|
135 button2.update();
|
f@1
|
136 button3.update();
|
f@1
|
137 button4.update();
|
f@1
|
138
|
f@1
|
139
|
f@11
|
140 uint16_t Jet1_new = analogRead(0); //read Wavejet/Rail 1; ADJUST INPUT RANGE ACCORDING TO SENSOR
|
f@11
|
141 uint16_t Jet2_new = analogRead(1); //read Wavejet/Rail 2; ADJUST INPUT RANGE ACCORDING TO SENSOR
|
f@11
|
142 uint16_t filter1_new = analogRead(2); //read filter Instrument 1;
|
f@11
|
143 uint16_t filter2_new = analogRead(4); //read filter Instrument 2;
|
f@1
|
144 uint16_t dur1_new = analogRead(3);
|
f@1
|
145 uint16_t dur2_new = analogRead(5);
|
f@1
|
146
|
f@1
|
147
|
f@1
|
148 //Encoder 1 [Controls selection length of wave 1]
|
f@1
|
149 long Enc1_new = Enc1.read();
|
f@1
|
150 Enc1_new = constrain(Enc1_new, 0, 127); //constrain to 7-bit MIDI range
|
f@1
|
151
|
f@1
|
152 //Dynamic reset of counter to MIDI range
|
f@1
|
153 if (Enc1_new <= 0){
|
f@1
|
154 Enc1.write(0);
|
f@1
|
155 }
|
f@1
|
156 else if (Enc1_new >= 127){
|
f@1
|
157 Enc1.write(127);
|
f@1
|
158 }
|
f@1
|
159
|
f@1
|
160 //Encoder 2 [Controls selection length of wave 2]
|
f@1
|
161 long Enc2_new = Enc2.read();
|
f@1
|
162 Enc2_new = constrain(Enc2_new, 0, 127); //constrain to 7-bit MIDI range
|
f@1
|
163
|
f@1
|
164 //Dynamic reset of counter to MIDI range
|
f@1
|
165 if (Enc2_new <= 0){
|
f@1
|
166 Enc2.write(0);
|
f@1
|
167 }
|
f@1
|
168 else if (Enc2_new >= 127){
|
f@1
|
169 Enc2.write(127);
|
f@1
|
170 }
|
f@1
|
171
|
f@1
|
172 //Instrument 1 Controls//////////////////////////////////////
|
f@1
|
173
|
f@1
|
174 //Loop/Keymode Switch Instrument 1
|
f@1
|
175
|
f@1
|
176 if (button1.risingEdge()) {
|
f@1
|
177 usbMIDI.sendControlChange(cc_play, 1, midi_chan_inst1);
|
f@1
|
178 }
|
f@1
|
179
|
f@1
|
180 if (button1.fallingEdge()) {
|
f@1
|
181 usbMIDI.sendControlChange(cc_play, 0, midi_chan_inst1);
|
f@1
|
182 }
|
f@1
|
183
|
f@1
|
184
|
f@1
|
185 //Record Instrument 1
|
f@1
|
186 if (button2.fallingEdge()) {
|
f@1
|
187 usbMIDI.sendControlChange(cc_record, 1, midi_chan_inst1);
|
f@1
|
188 }
|
f@1
|
189
|
f@1
|
190 //send MIDI Wavejet 1 [Position Instrument 1]
|
f@11
|
191 //<calibrate>
|
f@1
|
192 if (Jet1_new > Jet1_old+jitter_thresh || Jet1_new < Jet1_old-jitter_thresh) {
|
f@5
|
193 int16_t midiVal = constrain( map(Jet1_new, 18, 800, 0, 149), 0, 149 );
|
f@1
|
194 if( midiVal != Jet1_old_MIDI ){
|
f@1
|
195 Jet1_old_MIDI = midiVal;
|
f@1
|
196 usbMIDI.sendPitchBend( midiVal, midi_chan_inst1 );
|
f@1
|
197 }
|
f@1
|
198
|
f@1
|
199 Jet1_old = Jet1_new;
|
f@1
|
200 digitalWrite(Pin_MIDIled, HIGH);
|
f@1
|
201 }
|
f@1
|
202
|
f@1
|
203
|
f@1
|
204 //send MIDI Filter 1 [Filter Instrument 1]
|
f@5
|
205 if ( filter1_new != filter1_old ) {
|
f@1
|
206 int16_t midiVal = constrain( map(filter1_new, 0, 1024, 0, 127), 0, 127 );
|
f@1
|
207 if( midiVal != filter1_old_MIDI){
|
f@1
|
208 //Serial.println( midiVal );
|
f@1
|
209 filter1_old_MIDI = midiVal;
|
f@1
|
210 usbMIDI.sendControlChange(cc_filter, midiVal, midi_chan_inst1);
|
f@1
|
211 }
|
f@1
|
212
|
f@1
|
213 filter1_old = filter1_new;
|
f@1
|
214 digitalWrite(Pin_MIDIled, HIGH);
|
f@1
|
215 }
|
f@1
|
216
|
f@5
|
217 if ( dur1_new != dur1_old ) {
|
f@1
|
218
|
f@1
|
219 int16_t midiVal = constrain( map(dur1_new, 0, 1024, 0, 127), 0, 127 );
|
f@1
|
220 if( midiVal != dur1_old_MIDI){
|
f@1
|
221 dur1_old_MIDI = midiVal;
|
f@1
|
222 usbMIDI.sendControlChange(cc_duration, midiVal, midi_chan_inst1);
|
f@1
|
223 }
|
f@1
|
224
|
f@1
|
225 dur1_old = dur1_new;
|
f@1
|
226 digitalWrite(Pin_MIDIled, HIGH);
|
f@1
|
227 }
|
f@1
|
228
|
f@1
|
229 //send MIDI Encoder 1 [Selection length Instrument 1]
|
f@1
|
230 if (Enc1_new != Enc1_old) {
|
f@1
|
231 Enc1_old = Enc1_new;
|
f@1
|
232 usbMIDI.sendControlChange(cc_length, Enc1_new, midi_chan_inst1);
|
f@1
|
233 digitalWrite(Pin_MIDIled, HIGH);
|
f@1
|
234 }
|
f@1
|
235
|
f@1
|
236
|
f@1
|
237
|
f@1
|
238 //Instrument 2 Controls//////////////////////////////////////
|
f@1
|
239
|
f@1
|
240 //Loop/Keymode Switch Instrument 2
|
f@1
|
241
|
f@1
|
242 if (button3.risingEdge()) {
|
f@1
|
243 usbMIDI.sendControlChange(cc_play, 1, midi_chan_inst2);
|
f@1
|
244 }
|
f@1
|
245
|
f@1
|
246 if (button3.fallingEdge()) {
|
f@1
|
247 usbMIDI.sendControlChange(cc_play, 0, midi_chan_inst2);
|
f@1
|
248 }
|
f@1
|
249
|
f@1
|
250 //Record Instrument 2
|
f@1
|
251 if (button4.fallingEdge()) {
|
f@1
|
252 usbMIDI.sendControlChange(cc_record, 1, midi_chan_inst2);
|
f@1
|
253 }
|
f@1
|
254
|
f@1
|
255 //send MIDI Wavejet 2 [Position Instrument 2]
|
f@11
|
256 //<calibrate>
|
f@1
|
257 if (Jet2_new > Jet2_old+jitter_thresh || Jet2_new < Jet2_old-jitter_thresh) {
|
f@5
|
258 int16_t midiVal = constrain( map( Jet2_new, 15, 780, 0, 149 ), 0, 149 );
|
f@1
|
259 if( midiVal != Jet2_old_MIDI ){
|
f@1
|
260 Jet2_old_MIDI = midiVal;
|
f@1
|
261 usbMIDI.sendPitchBend( midiVal, midi_chan_inst2 );
|
f@1
|
262 }
|
f@1
|
263
|
f@1
|
264 Jet2_old = Jet2_new;
|
f@1
|
265 digitalWrite(Pin_MIDIled, HIGH);
|
f@1
|
266 }
|
f@1
|
267
|
f@5
|
268 if ( filter2_new != filter2_old ) {
|
f@1
|
269 int16_t midiVal = constrain( map(filter2_new, 0, 1024, 0, 127), 0, 127 );
|
f@1
|
270 if( midiVal != filter2_old_MIDI){
|
f@1
|
271 //Serial.println( midiVal );
|
f@1
|
272 filter2_old_MIDI = midiVal;
|
f@1
|
273 usbMIDI.sendControlChange(cc_filter, midiVal, midi_chan_inst2);
|
f@1
|
274 }
|
f@1
|
275
|
f@1
|
276 filter2_old = filter2_new;
|
f@1
|
277 digitalWrite(Pin_MIDIled, HIGH);
|
f@1
|
278 }
|
f@1
|
279
|
f@5
|
280 if ( dur2_new != dur2_old ) {
|
f@1
|
281 int16_t midiVal = constrain( map(dur2_new, 0, 1024, 0, 127), 0, 127 );
|
f@1
|
282 if( midiVal != dur2_old_MIDI){
|
f@1
|
283 //Serial.println( midiVal );
|
f@1
|
284 dur2_old_MIDI = midiVal;
|
f@1
|
285 usbMIDI.sendControlChange(cc_duration, midiVal, midi_chan_inst2);
|
f@1
|
286 }
|
f@1
|
287
|
f@1
|
288 dur2_old = dur2_new;
|
f@1
|
289 digitalWrite(Pin_MIDIled, HIGH);
|
f@1
|
290 }
|
f@1
|
291
|
f@1
|
292
|
f@1
|
293 //send MIDI Encoder 2 [Selection length Instrument 2]
|
f@1
|
294 if (Enc2_new != Enc2_old) {
|
f@1
|
295 Enc2_old = Enc2_new;
|
f@1
|
296 usbMIDI.sendControlChange(cc_length, Enc2_new, midi_chan_inst2);
|
f@1
|
297 digitalWrite(Pin_MIDIled, HIGH);
|
f@1
|
298 }
|
f@1
|
299
|
f@1
|
300 }
|
f@1
|
301
|