Breath reading changed from 10 bit to 12 bit. Added hi res midi on cc#1 (mod) and an option to compile with breath CV output on DAC pin. Special key functions implemented (slur sustain, parallel chord, sub octave double). Cursor blinking disabled during note on to prevent glitching when testing changes in menus.
This commit is contained in:
parent
7598f62986
commit
5542a840c6
1 changed files with 257 additions and 80 deletions
321
NuEVI.ino
321
NuEVI.ino
|
|
@ -19,6 +19,58 @@ PROGRAMME FUNCTION: EVI Wind Controller using the Freescale MP3V5004GP breath
|
||||||
|
|
||||||
//_______________________________________________________________________________________________ DECLARATIONS
|
//_______________________________________________________________________________________________ DECLARATIONS
|
||||||
|
|
||||||
|
// Compile options, comment/uncomment to change
|
||||||
|
|
||||||
|
//#define BREATHCVOUTA14 // enables breath CV out on pin A14/DAC for Teensy 3.2
|
||||||
|
//#define BREATHCVOUTA12 // enables breath CV out on pin A12/DAC for Teensy LC
|
||||||
|
|
||||||
|
|
||||||
|
// Pin definitions
|
||||||
|
|
||||||
|
// Teensy pins
|
||||||
|
|
||||||
|
#define specialKeyPin 0 // 0
|
||||||
|
#define halfPitchBendKeyPin 1 // 1
|
||||||
|
|
||||||
|
#define bitePin 17
|
||||||
|
#define extraPin 16
|
||||||
|
#define pbUpPin 23
|
||||||
|
#define pbDnPin 22
|
||||||
|
#define vibratoPin 15
|
||||||
|
|
||||||
|
#define dPin 3
|
||||||
|
#define ePin 4
|
||||||
|
#define uPin 5
|
||||||
|
#define mPin 6
|
||||||
|
|
||||||
|
#define bLedPin 10
|
||||||
|
#define pLedPin 9
|
||||||
|
|
||||||
|
// MPR121 pins
|
||||||
|
|
||||||
|
#define R1Pin 10
|
||||||
|
#define R2Pin 11
|
||||||
|
#define R3Pin 8
|
||||||
|
#define R4Pin 9
|
||||||
|
#define R5Pin 6
|
||||||
|
|
||||||
|
#define K4Pin 7
|
||||||
|
#define K1Pin 4
|
||||||
|
#define K2Pin 5
|
||||||
|
#define K3Pin 2
|
||||||
|
#define K5Pin 3
|
||||||
|
#define K6Pin 0
|
||||||
|
#define K7Pin 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PINOUT ON PCB vs PINS ON MPR121
|
||||||
|
*
|
||||||
|
* (R2) (R4) (K4) (K2) (K5) (K7) <-> (11) (09) (07) (05) (03) (01)
|
||||||
|
*
|
||||||
|
* (R1) (R3/6) (R5) (K1) (K3) (K6) <-> (10) (08) (06) (04) (02) (00)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define ON_Delay 20 // Set Delay after ON threshold before velocity is checked (wait for tounging peak)
|
#define ON_Delay 20 // Set Delay after ON threshold before velocity is checked (wait for tounging peak)
|
||||||
#define touch_Thr 1200 // sensitivity for Teensy touch sensors
|
#define touch_Thr 1200 // sensitivity for Teensy touch sensors
|
||||||
|
|
@ -94,9 +146,9 @@ PROGRAMME FUNCTION: EVI Wind Controller using the Freescale MP3V5004GP breath
|
||||||
#define CTOUCH_THR_ADDR 42
|
#define CTOUCH_THR_ADDR 42
|
||||||
|
|
||||||
//"factory" values for settings
|
//"factory" values for settings
|
||||||
#define VERSION 15
|
#define VERSION 16
|
||||||
#define BREATH_THR_FACTORY 350
|
#define BREATH_THR_FACTORY 1400
|
||||||
#define BREATH_MAX_FACTORY 1000
|
#define BREATH_MAX_FACTORY 4000
|
||||||
#define PORTAM_THR_FACTORY 1730
|
#define PORTAM_THR_FACTORY 1730
|
||||||
#define PORTAM_MAX_FACTORY 3300
|
#define PORTAM_MAX_FACTORY 3300
|
||||||
#define PITCHB_THR_FACTORY 1300
|
#define PITCHB_THR_FACTORY 1300
|
||||||
|
|
@ -222,7 +274,7 @@ unsigned short octave; //
|
||||||
|
|
||||||
|
|
||||||
int breathLoLimit = 0;
|
int breathLoLimit = 0;
|
||||||
int breathHiLimit = 1023;
|
int breathHiLimit = 4095;
|
||||||
int portamLoLimit = 1000;
|
int portamLoLimit = 1000;
|
||||||
int portamHiLimit = 5000;
|
int portamHiLimit = 5000;
|
||||||
int pitchbLoLimit = 500;
|
int pitchbLoLimit = 500;
|
||||||
|
|
@ -240,11 +292,6 @@ int ctouchStep;
|
||||||
|
|
||||||
int minOffset = 50;
|
int minOffset = 50;
|
||||||
|
|
||||||
byte dPin = 3;
|
|
||||||
byte ePin = 4;
|
|
||||||
byte uPin = 5;
|
|
||||||
byte mPin = 6;
|
|
||||||
|
|
||||||
int deumButtons = 0;
|
int deumButtons = 0;
|
||||||
int lastDeumButtons = 0;
|
int lastDeumButtons = 0;
|
||||||
int deumButtonState = 0;
|
int deumButtonState = 0;
|
||||||
|
|
@ -269,7 +316,8 @@ byte subExtra = 0;
|
||||||
byte subVibrato = 0;
|
byte subVibrato = 0;
|
||||||
byte subDeglitch = 0;
|
byte subDeglitch = 0;
|
||||||
|
|
||||||
byte ccList[4] = {0,2,7,11}; // OFF, Breath, Volume, Expression
|
byte ccList[5] = {0,1,2,7,11}; // OFF, Modulation (Hi-res), Breath, Volume, Expression
|
||||||
|
|
||||||
int pbDepthList[13] = {0,8192,4096,2731,2048,1638,1365,1170,1024,910,819,744,683};
|
int pbDepthList[13] = {0,8192,4096,2731,2048,1638,1365,1170,1024,910,819,744,683};
|
||||||
|
|
||||||
byte cursorNow;
|
byte cursorNow;
|
||||||
|
|
@ -309,6 +357,7 @@ byte doPatchUpdate=1;
|
||||||
|
|
||||||
int breathLevel=0; // breath level (smoothed) not mapped to CC value
|
int breathLevel=0; // breath level (smoothed) not mapped to CC value
|
||||||
int oldbreath=0;
|
int oldbreath=0;
|
||||||
|
unsigned int oldbreathhires=0;
|
||||||
|
|
||||||
int pressureSensor; // pressure data from breath sensor, for midi breath cc and breath threshold checks
|
int pressureSensor; // pressure data from breath sensor, for midi breath cc and breath threshold checks
|
||||||
int lastPressure;
|
int lastPressure;
|
||||||
|
|
@ -340,9 +389,29 @@ byte dirUp=0; // direction of first vibrato wave
|
||||||
int fingeredNote; // note calculated from fingering (switches), transpose and octave settings
|
int fingeredNote; // note calculated from fingering (switches), transpose and octave settings
|
||||||
byte activeNote; // note playing
|
byte activeNote; // note playing
|
||||||
byte startNote=36; // set startNote to C (change this value in steps of 12 to start in other octaves)
|
byte startNote=36; // set startNote to C (change this value in steps of 12 to start in other octaves)
|
||||||
|
int slurBase; // first note in slur sustain chord
|
||||||
|
|
||||||
|
int slurInterval[9] = {-5,0,0,0,0,0,0,0,0};
|
||||||
|
byte addedIntervals = 1;
|
||||||
|
|
||||||
|
// Key variables, TRUE (1) for pressed, FALSE (0) for not pressed
|
||||||
|
byte K1; // Valve 1 (pitch change -2)
|
||||||
|
byte K2; // Valve 2 (pitch change -1)
|
||||||
|
byte K3; // Valve 3 (pitch change -3)
|
||||||
|
byte K4; // Left Hand index finger (pitch change -5)
|
||||||
|
byte K5; // Trill key 1 (pitch change +2)
|
||||||
|
byte K6; // Trill key 2 (pitch change +1)
|
||||||
|
byte K7; // Trill key 3 (pitch change +4)
|
||||||
|
|
||||||
|
byte octaveR = 0;
|
||||||
|
|
||||||
byte halfPitchBendKey;
|
byte halfPitchBendKey;
|
||||||
byte specialKey;
|
byte specialKey;
|
||||||
|
byte lastSpecialKey = 0;
|
||||||
|
|
||||||
|
byte slurSustain = 0;
|
||||||
|
byte parallelChord = 0;
|
||||||
|
byte subOctaveDouble = 0;
|
||||||
|
|
||||||
byte breathLedBrightness = 100; // up to 255, PWM
|
byte breathLedBrightness = 100; // up to 255, PWM
|
||||||
byte portamLedBrightness = 100; // up to 255, PWM
|
byte portamLedBrightness = 100; // up to 255, PWM
|
||||||
|
|
@ -407,13 +476,15 @@ void setup() {
|
||||||
extracStep = (extracHiLimit - extracLoLimit)/92;
|
extracStep = (extracHiLimit - extracLoLimit)/92;
|
||||||
ctouchStep = (ctouchHiLimit - ctouchLoLimit)/92;
|
ctouchStep = (ctouchHiLimit - ctouchLoLimit)/92;
|
||||||
|
|
||||||
|
analogReadResolution(12); // todo: adapt code for this first, then uncomment
|
||||||
|
|
||||||
pinMode(dPin, INPUT_PULLUP);
|
pinMode(dPin, INPUT_PULLUP);
|
||||||
pinMode(ePin, INPUT_PULLUP);
|
pinMode(ePin, INPUT_PULLUP);
|
||||||
pinMode(uPin, INPUT_PULLUP);
|
pinMode(uPin, INPUT_PULLUP);
|
||||||
pinMode(mPin, INPUT_PULLUP);
|
pinMode(mPin, INPUT_PULLUP);
|
||||||
|
|
||||||
pinMode(10, OUTPUT); // breath indicator LED
|
pinMode(bLedPin, OUTPUT); // breath indicator LED
|
||||||
pinMode(9, OUTPUT); // portam indicator LED
|
pinMode(pLedPin, OUTPUT); // portam indicator LED
|
||||||
|
|
||||||
if (!touchSensor.begin(0x5A)) {
|
if (!touchSensor.begin(0x5A)) {
|
||||||
while (1); // Touch sensor initialization failed - stop doing stuff
|
while (1); // Touch sensor initialization failed - stop doing stuff
|
||||||
|
|
@ -463,6 +534,9 @@ void loop() {
|
||||||
usbMIDI.sendProgramChange(activePatch-1,activeMIDIchannel);
|
usbMIDI.sendProgramChange(activePatch-1,activeMIDIchannel);
|
||||||
dinMIDIsendProgramChange(activePatch-1,activeMIDIchannel-1);
|
dinMIDIsendProgramChange(activePatch-1,activeMIDIchannel-1);
|
||||||
if (readSetting(PATCH_ADDR) != activePatch) writeSetting(PATCH_ADDR,activePatch);
|
if (readSetting(PATCH_ADDR) != activePatch) writeSetting(PATCH_ADDR,activePatch);
|
||||||
|
slurSustain = 0;
|
||||||
|
parallelChord = 0;
|
||||||
|
subOctaveDouble = 0;
|
||||||
doPatchUpdate = 0;
|
doPatchUpdate = 0;
|
||||||
}
|
}
|
||||||
if (pressureSensor > breathThrVal) {
|
if (pressureSensor > breathThrVal) {
|
||||||
|
|
@ -472,6 +546,27 @@ void loop() {
|
||||||
initial_breath_value = pressureSensor;
|
initial_breath_value = pressureSensor;
|
||||||
mainState = RISE_WAIT; // Go to next state
|
mainState = RISE_WAIT; // Go to next state
|
||||||
}
|
}
|
||||||
|
specialKey=(touchRead(specialKeyPin) > touch_Thr); //S2 on pcb
|
||||||
|
if (lastSpecialKey != specialKey){
|
||||||
|
if (specialKey){
|
||||||
|
// special key just pressed, check other keys
|
||||||
|
readSwitches();
|
||||||
|
if (K4) {
|
||||||
|
if (!slurSustain) {
|
||||||
|
slurSustain = 1;
|
||||||
|
parallelChord = 0;
|
||||||
|
} else slurSustain = 0;
|
||||||
|
}
|
||||||
|
if (K5) {
|
||||||
|
if (!parallelChord) {
|
||||||
|
parallelChord = 1;
|
||||||
|
slurSustain = 0;
|
||||||
|
} else parallelChord = 0;
|
||||||
|
}
|
||||||
|
if (K1) subOctaveDouble = !subOctaveDouble;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastSpecialKey = specialKey;
|
||||||
} else if (mainState == RISE_WAIT) {
|
} else if (mainState == RISE_WAIT) {
|
||||||
if (pressureSensor > breathThrVal) {
|
if (pressureSensor > breathThrVal) {
|
||||||
// Has enough time passed for us to collect our second
|
// Has enough time passed for us to collect our second
|
||||||
|
|
@ -479,7 +574,6 @@ void loop() {
|
||||||
if (millis() - breath_on_time > ON_Delay) {
|
if (millis() - breath_on_time > ON_Delay) {
|
||||||
// Yes, so calculate MIDI note and velocity, then send a note on event
|
// Yes, so calculate MIDI note and velocity, then send a note on event
|
||||||
readSwitches();
|
readSwitches();
|
||||||
//fingeredNote = startNote + 24;
|
|
||||||
// We should be at tonguing peak, so set velocity based on current pressureSensor value unless fixed velocity is set
|
// We should be at tonguing peak, so set velocity based on current pressureSensor value unless fixed velocity is set
|
||||||
// If initial value is greater than value after delay, go with initial value, constrain input to keep mapped output within 1 to 127
|
// If initial value is greater than value after delay, go with initial value, constrain input to keep mapped output within 1 to 127
|
||||||
if (!velocity) {
|
if (!velocity) {
|
||||||
|
|
@ -488,9 +582,29 @@ void loop() {
|
||||||
breathLevel=constrain(max(pressureSensor,initial_breath_value),breathThrVal,breathMaxVal);
|
breathLevel=constrain(max(pressureSensor,initial_breath_value),breathThrVal,breathMaxVal);
|
||||||
breath(); // send breath data
|
breath(); // send breath data
|
||||||
fingeredNote=noteValueCheck(fingeredNote);
|
fingeredNote=noteValueCheck(fingeredNote);
|
||||||
if ((fingeredNote >= 0) and (fingeredNote <= 127)){ // don't send midi out of range
|
|
||||||
usbMIDI.sendNoteOn(fingeredNote, velocitySend, activeMIDIchannel); // send Note On message for new note
|
usbMIDI.sendNoteOn(fingeredNote, velocitySend, activeMIDIchannel); // send Note On message for new note
|
||||||
dinMIDIsendNoteOn(fingeredNote, velocitySend, activeMIDIchannel - 1);
|
dinMIDIsendNoteOn(fingeredNote, velocitySend, activeMIDIchannel - 1);
|
||||||
|
if (parallelChord){
|
||||||
|
for (int i=0; i < addedIntervals; i++){
|
||||||
|
usbMIDI.sendNoteOn(noteValueCheck(fingeredNote+slurInterval[i]), velocitySend, activeMIDIchannel); // send Note On message for new note
|
||||||
|
dinMIDIsendNoteOn(noteValueCheck(fingeredNote+slurInterval[i]), velocitySend, activeMIDIchannel - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (slurSustain){
|
||||||
|
usbMIDI.sendControlChange(64,127, activeMIDIchannel);
|
||||||
|
dinMIDIsendControlChange(64,127, activeMIDIchannel - 1);
|
||||||
|
slurBase = fingeredNote;
|
||||||
|
addedIntervals = 0;
|
||||||
|
}
|
||||||
|
if (subOctaveDouble){
|
||||||
|
usbMIDI.sendNoteOn(noteValueCheck(fingeredNote-12), velocitySend, activeMIDIchannel);
|
||||||
|
dinMIDIsendNoteOn(noteValueCheck(fingeredNote-12), velocitySend, activeMIDIchannel - 1);
|
||||||
|
if (parallelChord){
|
||||||
|
for (int i=0; i < addedIntervals; i++){
|
||||||
|
usbMIDI.sendNoteOn(noteValueCheck(fingeredNote+slurInterval[i]-12), velocitySend, activeMIDIchannel); // send Note On message for new note
|
||||||
|
dinMIDIsendNoteOn(noteValueCheck(fingeredNote+slurInterval[i]-12), velocitySend, activeMIDIchannel - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
activeNote=fingeredNote;
|
activeNote=fingeredNote;
|
||||||
mainState = NOTE_ON;
|
mainState = NOTE_ON;
|
||||||
|
|
@ -501,18 +615,36 @@ void loop() {
|
||||||
mainState = NOTE_OFF;
|
mainState = NOTE_OFF;
|
||||||
}
|
}
|
||||||
} else if (mainState == NOTE_ON) {
|
} else if (mainState == NOTE_ON) {
|
||||||
|
cursorBlinkTime = millis(); // keep display from updating with cursor blinking if note on
|
||||||
if (pressureSensor < breathThrVal) {
|
if (pressureSensor < breathThrVal) {
|
||||||
// Value has fallen below threshold - turn the note off
|
// Value has fallen below threshold - turn the note off
|
||||||
activeNote=noteValueCheck(activeNote);
|
activeNote=noteValueCheck(activeNote);
|
||||||
if ((activeNote >= 0) and (activeNote <= 127)){ // don't send midi out of range
|
|
||||||
usbMIDI.sendNoteOff(activeNote, velocitySend, activeMIDIchannel); // send Note Off message
|
usbMIDI.sendNoteOff(activeNote, velocitySend, activeMIDIchannel); // send Note Off message
|
||||||
dinMIDIsendNoteOff(activeNote, velocitySend, activeMIDIchannel - 1);
|
dinMIDIsendNoteOff(activeNote, velocitySend, activeMIDIchannel - 1);
|
||||||
|
if (parallelChord){
|
||||||
|
for (int i=0; i < addedIntervals; i++){
|
||||||
|
usbMIDI.sendNoteOff(noteValueCheck(activeNote+slurInterval[i]), velocitySend, activeMIDIchannel); // send Note On message for new note
|
||||||
|
dinMIDIsendNoteOff(noteValueCheck(activeNote+slurInterval[i]), velocitySend, activeMIDIchannel - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (subOctaveDouble){
|
||||||
|
usbMIDI.sendNoteOff(noteValueCheck(activeNote-12), velocitySend, activeMIDIchannel);
|
||||||
|
dinMIDIsendNoteOff(noteValueCheck(activeNote-12), velocitySend, activeMIDIchannel - 1);
|
||||||
|
if (parallelChord){
|
||||||
|
for (int i=0; i < addedIntervals; i++){
|
||||||
|
usbMIDI.sendNoteOff(noteValueCheck(activeNote+slurInterval[i]-12), velocitySend, activeMIDIchannel); // send Note On message for new note
|
||||||
|
dinMIDIsendNoteOff(noteValueCheck(activeNote+slurInterval[i]-12), velocitySend, activeMIDIchannel - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (slurSustain){
|
||||||
|
usbMIDI.sendControlChange(64,0, activeMIDIchannel);
|
||||||
|
dinMIDIsendControlChange(64,0, activeMIDIchannel - 1);
|
||||||
}
|
}
|
||||||
breathLevel=0;
|
breathLevel=0;
|
||||||
mainState = NOTE_OFF;
|
mainState = NOTE_OFF;
|
||||||
} else {
|
} else {
|
||||||
readSwitches();
|
readSwitches();
|
||||||
//fingeredNote = startNote + 24;
|
|
||||||
if (fingeredNote != lastFingering){ //
|
if (fingeredNote != lastFingering){ //
|
||||||
// reset the debouncing timer
|
// reset the debouncing timer
|
||||||
lastDeglitchTime = millis();
|
lastDeglitchTime = millis();
|
||||||
|
|
@ -525,15 +657,58 @@ void loop() {
|
||||||
// Send a note off for the current note and a note on for
|
// Send a note off for the current note and a note on for
|
||||||
// the new note.
|
// the new note.
|
||||||
velocity = map(constrain(pressureSensor,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,7,127); // set new velocity value based on current pressure sensor level
|
velocity = map(constrain(pressureSensor,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,7,127); // set new velocity value based on current pressure sensor level
|
||||||
|
|
||||||
|
activeNote=noteValueCheck(activeNote);
|
||||||
|
if (parallelChord || subOctaveDouble){ // poly playing, send old note off before new note on
|
||||||
|
usbMIDI.sendNoteOff(activeNote, velocitySend, activeMIDIchannel); // send Note Off message for old note
|
||||||
|
dinMIDIsendNoteOff(activeNote, velocitySend, activeMIDIchannel - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parallelChord){
|
||||||
|
for (int i=0; i < addedIntervals; i++){
|
||||||
|
usbMIDI.sendNoteOff(noteValueCheck(activeNote+slurInterval[i]), velocitySend, activeMIDIchannel); // send Note Off message for old note
|
||||||
|
dinMIDIsendNoteOff(noteValueCheck(activeNote+slurInterval[i]), velocitySend, activeMIDIchannel - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (subOctaveDouble){
|
||||||
|
usbMIDI.sendNoteOff(noteValueCheck(activeNote-12), velocitySend, activeMIDIchannel); // send Note Off message for old note
|
||||||
|
dinMIDIsendNoteOff(noteValueCheck(activeNote-12), velocitySend, activeMIDIchannel - 1);
|
||||||
|
if (parallelChord){
|
||||||
|
for (int i=0; i < addedIntervals; i++){
|
||||||
|
usbMIDI.sendNoteOff(noteValueCheck(activeNote+slurInterval[i]-12), velocitySend, activeMIDIchannel); // send Note Off message for old note
|
||||||
|
dinMIDIsendNoteOff(noteValueCheck(activeNote+slurInterval[i]-12), velocitySend, activeMIDIchannel - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fingeredNote=noteValueCheck(fingeredNote);
|
fingeredNote=noteValueCheck(fingeredNote);
|
||||||
if ((fingeredNote >= 0) and (fingeredNote <= 127)){ // don't send midi out of range
|
|
||||||
usbMIDI.sendNoteOn(fingeredNote, velocitySend, activeMIDIchannel); // send Note On message for new note
|
usbMIDI.sendNoteOn(fingeredNote, velocitySend, activeMIDIchannel); // send Note On message for new note
|
||||||
dinMIDIsendNoteOn(fingeredNote, velocitySend, activeMIDIchannel - 1);
|
dinMIDIsendNoteOn(fingeredNote, velocitySend, activeMIDIchannel - 1);
|
||||||
|
if (parallelChord){
|
||||||
|
for (int i=0; i < addedIntervals; i++){
|
||||||
|
usbMIDI.sendNoteOn(noteValueCheck(fingeredNote+slurInterval[i]), velocitySend, activeMIDIchannel); // send Note On message for new note
|
||||||
|
dinMIDIsendNoteOn(noteValueCheck(fingeredNote+slurInterval[i]), velocitySend, activeMIDIchannel - 1);
|
||||||
}
|
}
|
||||||
activeNote=noteValueCheck(activeNote);
|
}
|
||||||
if ((activeNote >= 0) and (activeNote <= 127)){ // don't send midi out of range
|
if (subOctaveDouble){
|
||||||
usbMIDI.sendNoteOff(activeNote, 0, activeMIDIchannel); // send Note Off message for previous note (legato)
|
usbMIDI.sendNoteOn(noteValueCheck(fingeredNote-12), velocitySend, activeMIDIchannel); // send Note On message for new note
|
||||||
dinMIDIsendNoteOff(activeNote, 0, activeMIDIchannel - 1);
|
dinMIDIsendNoteOn(noteValueCheck(fingeredNote-12), velocitySend, activeMIDIchannel - 1);
|
||||||
|
if (parallelChord){
|
||||||
|
for (int i=0; i < addedIntervals; i++){
|
||||||
|
usbMIDI.sendNoteOn(noteValueCheck(fingeredNote+slurInterval[i]-12), velocitySend, activeMIDIchannel); // send Note On message for new note
|
||||||
|
dinMIDIsendNoteOn(noteValueCheck(fingeredNote+slurInterval[i]-12), velocitySend, activeMIDIchannel - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parallelChord && !subOctaveDouble){ // mono playing, send old note off after new note on
|
||||||
|
usbMIDI.sendNoteOff(activeNote, velocitySend, activeMIDIchannel); // send Note Off message
|
||||||
|
dinMIDIsendNoteOff(activeNote, velocitySend, activeMIDIchannel - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slurSustain){
|
||||||
|
addedIntervals++;
|
||||||
|
slurInterval[addedIntervals] = fingeredNote - slurBase;
|
||||||
}
|
}
|
||||||
activeNote=fingeredNote;
|
activeNote=fingeredNote;
|
||||||
}
|
}
|
||||||
|
|
@ -542,10 +717,7 @@ void loop() {
|
||||||
}
|
}
|
||||||
// Is it time to send more CC data?
|
// Is it time to send more CC data?
|
||||||
if (millis() - ccSendTime > CC_INTERVAL) {
|
if (millis() - ccSendTime > CC_INTERVAL) {
|
||||||
// Read touch pads (Teensy built in) and put value in variables
|
// deal with Breath, Pitch Bend, Modulation, etc.
|
||||||
specialKey=(touchRead(0) > touch_Thr); //S2 - not yet used
|
|
||||||
halfPitchBendKey=(touchRead(1) > touch_Thr); //S1 - hold for 1/2 pitchbend value
|
|
||||||
// deal with Breath, Pitch Bend and Modulation
|
|
||||||
breath();
|
breath();
|
||||||
pitch_bend();
|
pitch_bend();
|
||||||
portamento_();
|
portamento_();
|
||||||
|
|
@ -563,6 +735,7 @@ void loop() {
|
||||||
//do menu stuff
|
//do menu stuff
|
||||||
menu();
|
menu();
|
||||||
}
|
}
|
||||||
|
|
||||||
//_______________________________________________________________________________________________ FUNCTIONS
|
//_______________________________________________________________________________________________ FUNCTIONS
|
||||||
|
|
||||||
// MIDI note value check with out of range octave repeat
|
// MIDI note value check with out of range octave repeat
|
||||||
|
|
@ -575,6 +748,9 @@ int noteValueCheck(int note){
|
||||||
return note;
|
return note;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//**************************************************************
|
||||||
|
|
||||||
// Send a three byte din midi message
|
// Send a three byte din midi message
|
||||||
void midiSend3B(byte midistatus, byte data1, byte data2) {
|
void midiSend3B(byte midistatus, byte data1, byte data2) {
|
||||||
Serial3.write(midistatus);
|
Serial3.write(midistatus);
|
||||||
|
|
@ -638,14 +814,14 @@ void dinMIDIsendProgramChange(byte value, byte ch) {
|
||||||
|
|
||||||
void statusLEDs() {
|
void statusLEDs() {
|
||||||
if (breathLevel > breathThrVal){ // breath indicator LED, labeled "B" on PCB
|
if (breathLevel > breathThrVal){ // breath indicator LED, labeled "B" on PCB
|
||||||
analogWrite(10, breathLedBrightness);
|
analogWrite(bLedPin, breathLedBrightness);
|
||||||
} else {
|
} else {
|
||||||
analogWrite(10, 0);
|
analogWrite(bLedPin, 0);
|
||||||
}
|
}
|
||||||
if (biteSensor > portamThrVal){ // portamento indicator LED, labeled "P" on PCB
|
if (biteSensor > portamThrVal){ // portamento indicator LED, labeled "P" on PCB
|
||||||
analogWrite(9, portamLedBrightness);
|
analogWrite(pLedPin, portamLedBrightness);
|
||||||
} else {
|
} else {
|
||||||
analogWrite(9, 0);
|
analogWrite(pLedPin, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -653,10 +829,12 @@ void statusLEDs() {
|
||||||
|
|
||||||
void breath(){
|
void breath(){
|
||||||
int breathCCval;
|
int breathCCval;
|
||||||
|
unsigned int breathCCvalHires;
|
||||||
breathLevel = breathLevel*0.8+pressureSensor*0.2; // smoothing of breathLevel value
|
breathLevel = breathLevel*0.8+pressureSensor*0.2; // smoothing of breathLevel value
|
||||||
breathCCval = map(constrain(breathLevel,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,127);
|
breathCCval = map(constrain(breathLevel,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,127);
|
||||||
|
breathCCvalHires = map(constrain(breathLevel,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,16383);
|
||||||
if (breathCCval != oldbreath){ // only send midi data if breath has changed from previous value
|
if (breathCCval != oldbreath){ // only send midi data if breath has changed from previous value
|
||||||
if (breathCCval){
|
if (ccList[breathCC] > 1){
|
||||||
// send midi cc
|
// send midi cc
|
||||||
usbMIDI.sendControlChange(ccList[breathCC], breathCCval, activeMIDIchannel);
|
usbMIDI.sendControlChange(ccList[breathCC], breathCCval, activeMIDIchannel);
|
||||||
dinMIDIsendControlChange(ccList[breathCC], breathCCval, activeMIDIchannel - 1);
|
dinMIDIsendControlChange(ccList[breathCC], breathCCval, activeMIDIchannel - 1);
|
||||||
|
|
@ -664,10 +842,27 @@ void breath(){
|
||||||
if (breathAT){
|
if (breathAT){
|
||||||
// send aftertouch
|
// send aftertouch
|
||||||
usbMIDI.sendAfterTouch(breathCCval, activeMIDIchannel);
|
usbMIDI.sendAfterTouch(breathCCval, activeMIDIchannel);
|
||||||
dinMIDIsendAfterTouch(breathCCval, activeMIDIchannel);
|
dinMIDIsendAfterTouch(breathCCval, activeMIDIchannel - 1);
|
||||||
}
|
}
|
||||||
oldbreath = breathCCval;
|
oldbreath = breathCCval;
|
||||||
}
|
}
|
||||||
|
if (breathCCvalHires != oldbreathhires){
|
||||||
|
#if defined(BREATHCVOUTA14)
|
||||||
|
analogWrite(A14,breathCCvalHires); // Breath CV out at A14 on Teensy 3.2
|
||||||
|
#endif
|
||||||
|
#if defined(BREATHCVOUTA12)
|
||||||
|
analogWrite(A12,breathCCvalHires); // Breath CV out at A12 on Teensy LC
|
||||||
|
#endif
|
||||||
|
if (ccList[breathCC] == 1){ // if modulation cc is used, send high resolution midi
|
||||||
|
int fine = breathCCvalHires & 0x007F;
|
||||||
|
int coarse = (breathCCvalHires >>7) & 0x007F;
|
||||||
|
usbMIDI.sendControlChange(ccList[breathCC], coarse, activeMIDIchannel);
|
||||||
|
dinMIDIsendControlChange(ccList[breathCC], coarse, activeMIDIchannel - 1);
|
||||||
|
usbMIDI.sendControlChange(ccList[breathCC]+32, fine, activeMIDIchannel);
|
||||||
|
dinMIDIsendControlChange(ccList[breathCC]+32, fine, activeMIDIchannel - 1);
|
||||||
|
}
|
||||||
|
oldbreathhires = breathCCvalHires;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//**************************************************************
|
//**************************************************************
|
||||||
|
|
@ -678,9 +873,10 @@ void pitch_bend(){
|
||||||
float nudge;
|
float nudge;
|
||||||
int calculatedPBdepth;
|
int calculatedPBdepth;
|
||||||
byte vibratoMoved = 0;
|
byte vibratoMoved = 0;
|
||||||
pbUp = touchRead(23); // SENSOR PIN 23 - PCB PIN "Pu"
|
pbUp = touchRead(pbUpPin); // SENSOR PIN 23 - PCB PIN "Pu"
|
||||||
pbDn = touchRead(22); // SENSOR PIN 22 - PCB PIN "Pd"
|
pbDn = touchRead(pbDnPin); // SENSOR PIN 22 - PCB PIN "Pd"
|
||||||
int vibRead = touchRead(15); // SENSOR PIN 15 - built in var cap
|
halfPitchBendKey=(touchRead(halfPitchBendKeyPin) > touch_Thr); // SENSOR PIN 1 - PCB PIN "S1" - hold for 1/2 pitchbend value
|
||||||
|
int vibRead = touchRead(vibratoPin); // SENSOR PIN 15 - built in var cap
|
||||||
if ((vibRead < vibThr)&&(vibRead > oldvibRead)){
|
if ((vibRead < vibThr)&&(vibRead > oldvibRead)){
|
||||||
nudge = 0.01*constrain(abs(vibRead - oldvibRead),0,100);
|
nudge = 0.01*constrain(abs(vibRead - oldvibRead),0,100);
|
||||||
if (!dirUp){
|
if (!dirUp){
|
||||||
|
|
@ -731,7 +927,7 @@ void pitch_bend(){
|
||||||
|
|
||||||
void extraController(){
|
void extraController(){
|
||||||
// Extra Controller is the lip touch sensor (proportional) in front of the mouthpiece
|
// Extra Controller is the lip touch sensor (proportional) in front of the mouthpiece
|
||||||
exSensor=exSensor*0.6+0.4*touchRead(16); // get sensor data, do some smoothing - SENSOR PIN 16 - PCB PIN "EC" (marked K4 on some prototype boards)
|
exSensor=exSensor*0.6+0.4*touchRead(extraPin); // get sensor data, do some smoothing - SENSOR PIN 16 - PCB PIN "EC" (marked K4 on some prototype boards)
|
||||||
if (extraCT && (exSensor >= extracThrVal)) { // if we are enabled and over the threshold, send data
|
if (extraCT && (exSensor >= extracThrVal)) { // if we are enabled and over the threshold, send data
|
||||||
if (!extracIsOn) {
|
if (!extracIsOn) {
|
||||||
extracIsOn=1;
|
extracIsOn=1;
|
||||||
|
|
@ -764,9 +960,10 @@ void extraController(){
|
||||||
}
|
}
|
||||||
|
|
||||||
//***********************************************************
|
//***********************************************************
|
||||||
|
|
||||||
void portamento_(){
|
void portamento_(){
|
||||||
// Portamento is controlled with the bite sensor (variable capacitor) in the mouthpiece
|
// Portamento is controlled with the bite sensor (variable capacitor) in the mouthpiece
|
||||||
biteSensor=biteSensor*0.6+0.4*touchRead(17); // get sensor data, do some smoothing - SENSOR PIN 17 - PCB PINS LABELED "BITE" (GND left, sensor pin right)
|
biteSensor=biteSensor*0.6+0.4*touchRead(bitePin); // get sensor data, do some smoothing - SENSOR PIN 17 - PCB PINS LABELED "BITE" (GND left, sensor pin right)
|
||||||
if (portamento && (biteSensor >= portamThrVal)) { // if we are enabled and over the threshold, send portamento
|
if (portamento && (biteSensor >= portamThrVal)) { // if we are enabled and over the threshold, send portamento
|
||||||
if (!portIsOn) {
|
if (!portIsOn) {
|
||||||
portOn();
|
portOn();
|
||||||
|
|
@ -816,17 +1013,6 @@ void portOff(){
|
||||||
|
|
||||||
void readSwitches(){
|
void readSwitches(){
|
||||||
|
|
||||||
// Key variables, TRUE (1) for pressed, FALSE (0) for not pressed
|
|
||||||
byte K1; // Valve 1 (pitch change -2)
|
|
||||||
byte K2; // Valve 2 (pitch change -1)
|
|
||||||
byte K3; // Valve 3 (pitch change -3)
|
|
||||||
byte K4; // Left Hand index finger (pitch change -5)
|
|
||||||
byte K5; // Trill key 1 (pitch change +2)
|
|
||||||
byte K6; // Trill key 2 (pitch change +1)
|
|
||||||
byte K7; // Trill key 3 (pitch change +4)
|
|
||||||
|
|
||||||
byte octaveR = 0;
|
|
||||||
|
|
||||||
// Read touch pads (MPR121) and put value in variables
|
// Read touch pads (MPR121) and put value in variables
|
||||||
int touchValue[12];
|
int touchValue[12];
|
||||||
for (byte i=0; i<12; i++){
|
for (byte i=0; i<12; i++){
|
||||||
|
|
@ -834,31 +1020,22 @@ void readSwitches(){
|
||||||
}
|
}
|
||||||
|
|
||||||
// Octave rollers
|
// Octave rollers
|
||||||
if ((touchValue[6] < ctouchThrVal) && (touchValue[8] < ctouchThrVal)) octaveR = 6; //R6 = R5 && R3
|
octaveR = 0;
|
||||||
else if (touchValue[6] < ctouchThrVal) octaveR = 5; //R5
|
if ((touchValue[R5Pin] < ctouchThrVal) && (touchValue[R3Pin] < ctouchThrVal)) octaveR = 6; //R6 = R5 && R3
|
||||||
else if (touchValue[9] < ctouchThrVal) octaveR = 4; //R4
|
else if (touchValue[R5Pin] < ctouchThrVal) octaveR = 5; //R5
|
||||||
else if (touchValue[8] < ctouchThrVal) octaveR = 3; //R3
|
else if (touchValue[R4Pin] < ctouchThrVal) octaveR = 4; //R4
|
||||||
else if (touchValue[11] < ctouchThrVal) octaveR = 2; //R2
|
else if (touchValue[R3Pin] < ctouchThrVal) octaveR = 3; //R3
|
||||||
else if (touchValue[10] < ctouchThrVal) octaveR = 1; //R1
|
else if (touchValue[R2Pin] < ctouchThrVal) octaveR = 2; //R2
|
||||||
|
else if (touchValue[R1Pin] < ctouchThrVal) octaveR = 1; //R1
|
||||||
|
|
||||||
// Valves and trill keys
|
// Valves and trill keys
|
||||||
K4=(touchValue[7] < ctouchThrVal);
|
K4=(touchValue[K4Pin] < ctouchThrVal);
|
||||||
K1=(touchValue[4] < ctouchThrVal);
|
K1=(touchValue[K1Pin] < ctouchThrVal);
|
||||||
K2=(touchValue[5] < ctouchThrVal);
|
K2=(touchValue[K2Pin] < ctouchThrVal);
|
||||||
K3=(touchValue[2] < ctouchThrVal);
|
K3=(touchValue[K3Pin] < ctouchThrVal);
|
||||||
K5=(touchValue[3] < ctouchThrVal);
|
K5=(touchValue[K5Pin] < ctouchThrVal);
|
||||||
K6=(touchValue[0] < ctouchThrVal);
|
K6=(touchValue[K6Pin] < ctouchThrVal);
|
||||||
K7=(touchValue[1] < ctouchThrVal);
|
K7=(touchValue[K7Pin] < ctouchThrVal);
|
||||||
|
|
||||||
/*
|
|
||||||
* PINOUT ON PCB vs PINS ON MPR121
|
|
||||||
*
|
|
||||||
* (R2) (R4) (K4) (K2) (K5) (K7) <-> (11) (09) (07) (05) (03) (01)
|
|
||||||
*
|
|
||||||
* (R1) (R3/6) (R5) (K1) (K3) (K6) <-> (10) (08) (06) (04) (02) (00)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Calculate midi note number from pressed keys
|
// Calculate midi note number from pressed keys
|
||||||
fingeredNote=startNote-2*K1-K2-3*K3-5*K4+2*K5+K6+4*K7+octaveR*12+(octave-3)*12+transpose-12;
|
fingeredNote=startNote-2*K1-K2-3*K3-5*K4+2*K5+K6+4*K7+octaveR*12+(octave-3)*12+transpose-12;
|
||||||
|
|
@ -924,7 +1101,7 @@ void menu() {
|
||||||
// save the reading. Next time through the loop, it'll be the lastButtonState:
|
// save the reading. Next time through the loop, it'll be the lastButtonState:
|
||||||
lastDeumButtons = deumButtons;
|
lastDeumButtons = deumButtons;
|
||||||
|
|
||||||
if (state && ((millis() - menuTime) > menuTimeUp)) { // shut off menu system if not used for a while
|
if (state && ((millis() - menuTime) > menuTimeUp)) { // shut off menu system if not used for a while (changes not stored by exiting a setting manually will not be stored in EEPROM)
|
||||||
state = DISPLAYOFF_IDL;
|
state = DISPLAYOFF_IDL;
|
||||||
stateFirstRun = 1;
|
stateFirstRun = 1;
|
||||||
subTranspose = 0;
|
subTranspose = 0;
|
||||||
|
|
@ -1899,7 +2076,7 @@ void menu() {
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
// up
|
// up
|
||||||
if (breathCC < 3){
|
if (breathCC < 4){
|
||||||
plotBreathCC(BLACK);
|
plotBreathCC(BLACK);
|
||||||
breathCC++;
|
breathCC++;
|
||||||
plotBreathCC(WHITE);
|
plotBreathCC(WHITE);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue