f@1: /****************************************************************************** f@5: * Copyright (C) 2015 Ben Bengler (mail@benbengler.com) f@5: * Copyright (C) 2016 Queen Mary University of London f@5: * Authors: Ben Bengler, Fiore Martin f@1: * f@5: * This file is part of Collidoscope. f@5: * f@5: * Collidoscope is free software: you can redistribute it and/or modify f@5: * it under the terms of the GNU General Public License as published by f@5: * the Free Software Foundation, either version 3 of the License, or f@5: * (at your option) any later version. f@5: * f@5: * This program is distributed in the hope that it will be useful, f@5: * but WITHOUT ANY WARRANTY; without even the implied warranty of f@5: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the f@5: * GNU General Public License for more details. f@5: * f@5: * You should have received a copy of the GNU General Public License f@5: * along with this program. If not, see . f@1: * f@5: **************************************************************************** f@5: * f@1: * Teensy 2 ++ pinout: https://www.pjrc.com/teensy/card4b.pdf f@1: * f@1: * ANALOG INPUTS: f@1: * Wavejet -> F0 (38) [Horizontal rail 1] f@1: * Wavejet -> F1 (39) [Horizontal rail 2] f@5: * Filter 1 -> F2 (40) [Fader with moon/sun 1] f@5: * Filter 2 -> F4 (42) [Fader with moon/sun 2] f@5: * Duration 1-> F3 (41) [Fader with grains 1] f@5: * Duration 2-> F5 (43) [Fader with grains 2] f@1: * f@1: * DIGITAL INPUTS [INTERRUPTS]: f@1: * Sel. length 1 -> INT0/INT1 (0, 1) [Encoder 1] f@5: * Sel. length 2 -> INT2/INT3 (2, 3) [Encoder 2] f@1: * f@1: * DIGITAL INPUTS: f@1: * Play1 toggle -> B0 (20) f@1: * Record1 -> B1 (21) f@1: * Play2 toggle -> B3 (22) f@1: * Record2 -> B4 (24) f@1: * f@1: * DIGITAL OUTPUTS: f@1: * Record Button 1 Led -> D4 (4) f@1: * Record Button 2 Led -> D5 (5) f@5: * f@1: ******************************************************************************/ f@1: f@1: f@1: #include f@1: #include f@1: f@1: /////////////////////////////////////////////////// f@1: //MIDI settings f@1: const int midi_chan_inst1 = 1; // MIDI channel for Instrument 1 f@1: const int midi_chan_inst2 = 2; // MIDI channel for Instrument 2 f@1: f@1: const int cc_length = 1; // MIDI cc controlling selection length f@1: const int cc_duration = 2; // MIDI cc controlling duration f@1: const int cc_filter = 7; // MIDI cc controlling LP filter f@1: const int cc_play = 4; // MIDI cc controlling PLAY f@1: const int cc_record = 5; // MIDI cc controlling RECORD f@5: f@1: f@1: /////////////////////////////////////////////////// f@1: //Default Values: f@1: const int Enc_def = 64; //default selection length f@1: int MIDI_led_state = LOW; f@1: f@1: /////////////////////////////////////////////////// f@1: // Interface Inputs f@1: f@1: //Buttons: f@1: f@1: const int Pin_play1 = 20; //B0 f@1: const int Pin_record1 = 21; //B1 f@1: const int Pin_play2 = 23; //B3 f@1: const int Pin_record2 = 24; //B4 f@1: const int Pin_record1_led = 4; //D4 f@1: const int Pin_record2_led = 5; //D5 f@1: const int Pin_MIDIled = 6; f@1: f@1: Bounce button1 = Bounce(Pin_play1, 5); f@1: Bounce button2 = Bounce(Pin_record1, 5); f@1: Bounce button3 = Bounce(Pin_play2, 5); f@1: Bounce button4 = Bounce(Pin_record2, 5); f@1: f@1: f@1: //Encoder f@1: Encoder Enc1 (0, 1); //Encoder for section length on Wavejet 1 f@1: Encoder Enc2 (2, 3); //Encoder for section length on Wavejet 2 f@1: f@1: f@1: // Variables f@11: const int jitter_thresh = 10; // threshold value for analog INs to suppress sending MIDI due to input jitter f@1: f@1: void setup() { f@1: f@1: pinMode(Pin_play1, INPUT_PULLUP); f@1: pinMode(Pin_record1, INPUT_PULLUP); f@1: pinMode(Pin_play2, INPUT_PULLUP); f@1: pinMode(Pin_record2, INPUT_PULLUP); f@1: f@1: f@1: pinMode(Pin_MIDIled, OUTPUT); f@1: pinMode(Pin_record1_led, OUTPUT); f@1: pinMode(Pin_record2_led, OUTPUT); f@1: } f@1: f@1: //Store recent values to detect parameter change f@1: long Enc1_old = -999; f@1: long Enc2_old = -999; f@1: f@1: uint16_t Jet1_old = 0; f@1: int16_t Jet1_old_MIDI = -1; f@1: uint16_t Jet2_old = 0; f@1: int16_t Jet2_old_MIDI = -1; f@1: f@1: uint16_t filter1_old = 0; f@1: int16_t filter1_old_MIDI = -1; f@1: uint16_t filter2_old = 0; f@1: int16_t filter2_old_MIDI = -1; f@1: f@1: uint16_t dur1_old = 0; f@1: int16_t dur1_old_MIDI = -1; f@1: uint16_t dur2_old = 0; f@1: int16_t dur2_old_MIDI = -1; f@1: f@1: void loop() { f@1: f@1: digitalWrite(Pin_MIDIled, LOW); f@1: digitalWrite(Pin_record1_led, HIGH); f@1: digitalWrite(Pin_record2_led, HIGH); f@1: button1.update(); f@1: button2.update(); f@1: button3.update(); f@1: button4.update(); f@1: f@1: f@11: uint16_t Jet1_new = analogRead(0); //read Wavejet/Rail 1; ADJUST INPUT RANGE ACCORDING TO SENSOR f@11: uint16_t Jet2_new = analogRead(1); //read Wavejet/Rail 2; ADJUST INPUT RANGE ACCORDING TO SENSOR f@11: uint16_t filter1_new = analogRead(2); //read filter Instrument 1; f@11: uint16_t filter2_new = analogRead(4); //read filter Instrument 2; f@1: uint16_t dur1_new = analogRead(3); f@1: uint16_t dur2_new = analogRead(5); f@1: f@1: f@1: //Encoder 1 [Controls selection length of wave 1] f@1: long Enc1_new = Enc1.read(); f@1: Enc1_new = constrain(Enc1_new, 0, 127); //constrain to 7-bit MIDI range f@1: f@1: //Dynamic reset of counter to MIDI range f@1: if (Enc1_new <= 0){ f@1: Enc1.write(0); f@1: } f@1: else if (Enc1_new >= 127){ f@1: Enc1.write(127); f@1: } f@1: f@1: //Encoder 2 [Controls selection length of wave 2] f@1: long Enc2_new = Enc2.read(); f@1: Enc2_new = constrain(Enc2_new, 0, 127); //constrain to 7-bit MIDI range f@1: f@1: //Dynamic reset of counter to MIDI range f@1: if (Enc2_new <= 0){ f@1: Enc2.write(0); f@1: } f@1: else if (Enc2_new >= 127){ f@1: Enc2.write(127); f@1: } f@1: f@1: //Instrument 1 Controls////////////////////////////////////// f@1: f@1: //Loop/Keymode Switch Instrument 1 f@1: f@1: if (button1.risingEdge()) { f@1: usbMIDI.sendControlChange(cc_play, 1, midi_chan_inst1); f@1: } f@1: f@1: if (button1.fallingEdge()) { f@1: usbMIDI.sendControlChange(cc_play, 0, midi_chan_inst1); f@1: } f@1: f@1: f@1: //Record Instrument 1 f@1: if (button2.fallingEdge()) { f@1: usbMIDI.sendControlChange(cc_record, 1, midi_chan_inst1); f@1: } f@1: f@1: //send MIDI Wavejet 1 [Position Instrument 1] f@11: // f@1: if (Jet1_new > Jet1_old+jitter_thresh || Jet1_new < Jet1_old-jitter_thresh) { f@5: int16_t midiVal = constrain( map(Jet1_new, 18, 800, 0, 149), 0, 149 ); f@1: if( midiVal != Jet1_old_MIDI ){ f@1: Jet1_old_MIDI = midiVal; f@1: usbMIDI.sendPitchBend( midiVal, midi_chan_inst1 ); f@1: } f@1: f@1: Jet1_old = Jet1_new; f@1: digitalWrite(Pin_MIDIled, HIGH); f@1: } f@1: f@1: f@1: //send MIDI Filter 1 [Filter Instrument 1] f@5: if ( filter1_new != filter1_old ) { f@1: int16_t midiVal = constrain( map(filter1_new, 0, 1024, 0, 127), 0, 127 ); f@1: if( midiVal != filter1_old_MIDI){ f@1: //Serial.println( midiVal ); f@1: filter1_old_MIDI = midiVal; f@1: usbMIDI.sendControlChange(cc_filter, midiVal, midi_chan_inst1); f@1: } f@1: f@1: filter1_old = filter1_new; f@1: digitalWrite(Pin_MIDIled, HIGH); f@1: } f@1: f@5: if ( dur1_new != dur1_old ) { f@1: f@1: int16_t midiVal = constrain( map(dur1_new, 0, 1024, 0, 127), 0, 127 ); f@1: if( midiVal != dur1_old_MIDI){ f@1: dur1_old_MIDI = midiVal; f@1: usbMIDI.sendControlChange(cc_duration, midiVal, midi_chan_inst1); f@1: } f@1: f@1: dur1_old = dur1_new; f@1: digitalWrite(Pin_MIDIled, HIGH); f@1: } f@1: f@1: //send MIDI Encoder 1 [Selection length Instrument 1] f@1: if (Enc1_new != Enc1_old) { f@1: Enc1_old = Enc1_new; f@1: usbMIDI.sendControlChange(cc_length, Enc1_new, midi_chan_inst1); f@1: digitalWrite(Pin_MIDIled, HIGH); f@1: } f@1: f@1: f@1: f@1: //Instrument 2 Controls////////////////////////////////////// f@1: f@1: //Loop/Keymode Switch Instrument 2 f@1: f@1: if (button3.risingEdge()) { f@1: usbMIDI.sendControlChange(cc_play, 1, midi_chan_inst2); f@1: } f@1: f@1: if (button3.fallingEdge()) { f@1: usbMIDI.sendControlChange(cc_play, 0, midi_chan_inst2); f@1: } f@1: f@1: //Record Instrument 2 f@1: if (button4.fallingEdge()) { f@1: usbMIDI.sendControlChange(cc_record, 1, midi_chan_inst2); f@1: } f@1: f@1: //send MIDI Wavejet 2 [Position Instrument 2] f@11: // f@1: if (Jet2_new > Jet2_old+jitter_thresh || Jet2_new < Jet2_old-jitter_thresh) { f@5: int16_t midiVal = constrain( map( Jet2_new, 15, 780, 0, 149 ), 0, 149 ); f@1: if( midiVal != Jet2_old_MIDI ){ f@1: Jet2_old_MIDI = midiVal; f@1: usbMIDI.sendPitchBend( midiVal, midi_chan_inst2 ); f@1: } f@1: f@1: Jet2_old = Jet2_new; f@1: digitalWrite(Pin_MIDIled, HIGH); f@1: } f@1: f@5: if ( filter2_new != filter2_old ) { f@1: int16_t midiVal = constrain( map(filter2_new, 0, 1024, 0, 127), 0, 127 ); f@1: if( midiVal != filter2_old_MIDI){ f@1: //Serial.println( midiVal ); f@1: filter2_old_MIDI = midiVal; f@1: usbMIDI.sendControlChange(cc_filter, midiVal, midi_chan_inst2); f@1: } f@1: f@1: filter2_old = filter2_new; f@1: digitalWrite(Pin_MIDIled, HIGH); f@1: } f@1: f@5: if ( dur2_new != dur2_old ) { f@1: int16_t midiVal = constrain( map(dur2_new, 0, 1024, 0, 127), 0, 127 ); f@1: if( midiVal != dur2_old_MIDI){ f@1: //Serial.println( midiVal ); f@1: dur2_old_MIDI = midiVal; f@1: usbMIDI.sendControlChange(cc_duration, midiVal, midi_chan_inst2); f@1: } f@1: f@1: dur2_old = dur2_new; f@1: digitalWrite(Pin_MIDIled, HIGH); f@1: } f@1: f@1: f@1: //send MIDI Encoder 2 [Selection length Instrument 2] f@1: if (Enc2_new != Enc2_old) { f@1: Enc2_old = Enc2_new; f@1: usbMIDI.sendControlChange(cc_length, Enc2_new, midi_chan_inst2); f@1: digitalWrite(Pin_MIDIled, HIGH); f@1: } f@1: f@1: } f@1: