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