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