f@1:
f@1: /******************************************************************************
f@5: * Copyright (C) 2015 Ben Bengler (mail@benbengler.com)
f@5: * Copyright (C) 2016 Queen Mary University of London
f@13: * Authors: Ben Bengler, Fiore Martin, Christopher Paton (christopher.paton@gmail.com)
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@1: * Filter 1 -> F2 (40) [Vertical rail 1]
f@1: * Filter 2 -> F4 (42) [Vertical rail 2]
f@1: *
f@1: * DIGITAL INPUTS [INTERRUPTS]:
f@1: * Sel. length 1 -> INT0/INT1 (0, 1) [Encoder 1]
f@1: * Sel. length 2 -> INT2/INT3 (2, 3) [Encoder 2]
f@1: * Duration 1 -> INT4/INT5 (36, 37)[Encoder 3]
f@1: * Duration 2 -> INT6/INT7 (18, 19)[Encoder 4]
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: #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@15: const int cc_duration = 2; // MIDI cc controlling grain 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@1:
f@1: ///////////////////////////////////////////////////
f@1: // Interface Inputs
f@1:
f@13: //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@13: //Encoders
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@13: Encoder Enc3 (36, 37); //Encoder for duration of Wavejet 1 [granularisation effect]
f@13: Encoder Enc4 (18, 19); //Encoder for duration of Wavejet 2 [granularisation effect]
f@13:
f@1:
f@1: // Variables
f@13: const int jitter_thresh = 10; // threshold value for analog INs to make up for input jitter
f@1:
f@1: //Store recent values to detect parameter change
f@1: long Enc1_old = -999;
f@1: long Enc2_old = -999;
f@13:
f@14: long Enc3_old = -999;
f@14: long Enc4_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@13:
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@13: uint16_t dur1_old = 0;
f@13: int16_t dur1_old_MIDI = -1;
f@13: uint16_t dur2_old = 0;
f@13: int16_t dur2_old_MIDI = -1;
f@1:
f@13:
f@13: void setup()
f@13: {
f@13: pinMode(Pin_play1, INPUT_PULLUP);
f@13: pinMode(Pin_record1, INPUT_PULLUP);
f@13: pinMode(Pin_play2, INPUT_PULLUP);
f@13: pinMode(Pin_record2, INPUT_PULLUP);
f@13:
f@13:
f@13: pinMode(Pin_MIDIled, OUTPUT);
f@13: pinMode(Pin_record1_led, OUTPUT);
f@13: pinMode(Pin_record2_led, OUTPUT);
f@13: }
f@13:
f@13: void loop()
f@13: {
f@1: digitalWrite(Pin_MIDIled, LOW);
f@1: digitalWrite(Pin_record1_led, HIGH);
f@1: digitalWrite(Pin_record2_led, HIGH);
f@13:
f@1: button1.update();
f@1: button2.update();
f@1: button3.update();
f@1: button4.update();
f@1:
f@13: uint16_t Jet1_new = analogRead(0); //read Wavejet/Rail 1; ADJUST INPUT RANGE ACCORDING TO SENSOR
f@13: uint16_t Jet2_new = analogRead(1); //read Wavejet/Rail 2; ADJUST INPUT RANGE ACCORDING TO SENSOR
f@13: uint16_t filter1_new = analogRead(2); //read filter Instrument 1; ADJUST INPUT RANGE ACCORDING TO SENSOR
f@13: uint16_t filter2_new = analogRead(4); //read filter Instrument 2; ADJUST INPUT RANGE ACCORDING TO SENSOR
f@13: uint16_t dur1_new = analogRead(3);
f@13: uint16_t dur2_new = analogRead(5);
f@1:
f@13: //------ SEND INSTRUMENT 1 MIDI -----------
f@1:
f@13: // Play button instrument 1
f@13: if (button1.fallingEdge()){
f@13: usbMIDI.sendControlChange(cc_play, 1, midi_chan_inst1);
f@1: }
f@13:
f@13: if (button1.risingEdge()){
f@13: usbMIDI.sendControlChange(cc_play, 0, midi_chan_inst1);
f@1: }
f@1:
f@13:
f@13: // Record button instrument 1
f@13: if (button2.fallingEdge()){
f@13: usbMIDI.sendControlChange(cc_record, 1, midi_chan_inst1);
f@1: }
f@1:
f@13: // Selection start position instrument 1
f@13: //
f@13: if (Jet1_new > Jet1_old+jitter_thresh || Jet1_new < Jet1_old-jitter_thresh){
f@1:
f@13: int16_t midiVal = constrain( map(Jet1_new, 994, 121, 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@13: }
f@1:
f@13: //Filter instrument 1
f@13: //
f@13: if ( filter1_new != filter1_old ) {
f@1:
f@13: int16_t midiVal = constrain( map(filter1_new, 137, 734, 0, 127), 0, 127 );
f@1: if( midiVal != filter1_old_MIDI){
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@13:
f@13: //Selection length instrument 1
f@13: long Enc1_new = Enc1.read();
f@13: Enc1_new = constrain(Enc1_new, 0, 127); //constrain to 7-bit MIDI range
f@13:
f@13: if (Enc1_new <= 0){ //Dynamic reset of counter to MIDI range
f@13: Enc1.write(0);
f@13: }
f@13: else if (Enc1_new >= 127){
f@13: Enc1.write(127);
f@13: }
f@13:
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@13:
f@13: //Grain duration instrument 1
f@13: long Enc3_new = Enc3.read();
f@13: Enc3_new = constrain(Enc3_new, 0, 127); //constrain to 7-bit MIDI range
f@1:
f@13: if (Enc3_new <= 0){
f@13: Enc3.write(0);
f@13: }
f@13: else if (Enc3_new >= 127){
f@13: Enc3.write(127);
f@13: }
f@13:
f@1: if (Enc3_new != Enc3_old) {
f@1: Enc3_old = Enc3_new;
f@1: usbMIDI.sendControlChange(cc_duration, Enc3_new, midi_chan_inst1);
f@1: digitalWrite(Pin_MIDIled, HIGH);
f@1: }
f@13:
f@13: //------ SEND INSTRUMENT 2 MIDI -----------
f@1:
f@1:
f@13: //Play button instrument 2
f@13: if (button3.fallingEdge()) {
f@1: usbMIDI.sendControlChange(cc_play, 1, midi_chan_inst2);
f@1: }
f@1:
f@13: if (button3.risingEdge()) {
f@1: usbMIDI.sendControlChange(cc_play, 0, midi_chan_inst2);
f@1: }
f@1:
f@13: //Record button instrument 2
f@1: if (button4.fallingEdge()) {
f@1: usbMIDI.sendControlChange(cc_record, 1, midi_chan_inst2);
f@1: }
f@1:
f@13: // Selection start position instrument 2
f@13: //
f@1: if (Jet2_new > Jet2_old+jitter_thresh || Jet2_new < Jet2_old-jitter_thresh) {
f@13:
f@13: int16_t midiVal = constrain( map( Jet2_new, 103, 993, 149, 0 ), 0, 149 );
f@13:
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@13: //Filter instrument 2
f@13: //
f@13: if ( filter2_new != filter2_old ) {
f@13:
f@13: int16_t midiVal = constrain( map(filter2_new, 125, 684, 0, 127), 0, 127 );
f@1: if( midiVal != filter2_old_MIDI){
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@13: }
f@13:
f@13: //Selection length instrument 2
f@13: long Enc2_new = Enc2.read();
f@13: Enc2_new = constrain(Enc2_new, 0, 127); //constrain to 7-bit MIDI range
f@13:
f@13: if (Enc2_new <= 0){ //Dynamic reset of counter to MIDI range
f@13: Enc2.write(0);
f@1: }
f@13: else if (Enc2_new >= 127){
f@13: Enc2.write(127);
f@13: }
f@13:
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@13:
f@13: //Grain duration instrument 2
f@13: long Enc4_new = Enc4.read();
f@13: Enc4_new = constrain(Enc4_new, 0, 127); //constrain to 7-bit MIDI range
f@13:
f@13: if (Enc4_new <= 0){
f@13: Enc4.write(0);
f@13: }
f@13: else if (Enc4_new >= 127){
f@13: Enc4.write(127);
f@13: }
f@1:
f@1: if (Enc4_new != Enc4_old) {
f@1: Enc4_old = Enc4_new;
f@1: usbMIDI.sendControlChange(cc_duration, Enc4_new, midi_chan_inst2);
f@1: digitalWrite(Pin_MIDIled, HIGH);
f@1: }
f@1:
f@1: }
f@1: