New and improved vibrato. Added vibrato menu for setting depth, sensitivity and zero return speed. Added Gate Hold function. Added negative pressure trig for legacy instant settings functionality. Bug fix for vibrato not working properly when pb was disabled. Removed controller resets that messed things up on certain synths. Added extra redundancy check at zero value for portamento (bite) and extra controller (lip). Removed unwanted slew on bite sensor. Bug fix for reset of some menus after timeout. Did a change to the patch selection so the values are send immediately.

This commit is contained in:
Johan Berglund 2018-08-27 10:14:23 +02:00
parent 69e582cd47
commit b3d3b9dd6f
3 changed files with 483 additions and 125 deletions

BIN
NuEVI user guide 122.doc Normal file

Binary file not shown.

608
NuEVI.ino
View file

@ -156,6 +156,7 @@ PROGRAMME FUNCTION: EVI Wind Controller using the Freescale MP3V5004GP breath
#define SETUP_BR_MENU 80 #define SETUP_BR_MENU 80
#define SETUP_CT_MENU 90 #define SETUP_CT_MENU 90
#define ROTATOR_MENU 100 #define ROTATOR_MENU 100
#define VIBRATO_MENU 110
// EEPROM addresses for settings // EEPROM addresses for settings
#define VERSION_ADDR 0 #define VERSION_ADDR 0
@ -198,9 +199,11 @@ PROGRAMME FUNCTION: EVI Wind Controller using the Freescale MP3V5004GP breath
#define ROTN3_ADDR 74 #define ROTN3_ADDR 74
#define ROTN4_ADDR 76 #define ROTN4_ADDR 76
#define PRIO_ADDR 78 #define PRIO_ADDR 78
#define VIB_SENS_ADDR 80
#define VIB_RETN_ADDR 82
//"factory" values for settings //"factory" values for settings
#define VERSION 28 #define VERSION 29
#define BREATH_THR_FACTORY 1400 #define BREATH_THR_FACTORY 1400
#define BREATH_MAX_FACTORY 4000 #define BREATH_MAX_FACTORY 4000
#define PORTAM_THR_FACTORY 2600 #define PORTAM_THR_FACTORY 2600
@ -233,6 +236,8 @@ PROGRAMME FUNCTION: EVI Wind Controller using the Freescale MP3V5004GP breath
#define ROTN3_FACTORY 17 // -7 (+24) Rotation 3 #define ROTN3_FACTORY 17 // -7 (+24) Rotation 3
#define ROTN4_FACTORY 10 // -14 (+24) Rotation 4 #define ROTN4_FACTORY 10 // -14 (+24) Rotation 4
#define PRIO_FACTORY 0 // Mono priority 0 - BAS(e note), 1 - ROT(ating note) #define PRIO_FACTORY 0 // Mono priority 0 - BAS(e note), 1 - ROT(ating note)
#define VIB_SENS_FACTORY 2 // 1 least sensitive, higher more sensitive
#define VIB_RETN_FACTORY 2 // 1 fast return, higher slower return
#define OLED_RESET 4 #define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET); Adafruit_SSD1306 display(OLED_RESET);
@ -343,6 +348,9 @@ unsigned short pinkySetting; // 0 - 11 (QuickTranspose -12 to -1), 12 (pb/2), 13
unsigned short dipSwBits; // virtual dip switch settings for special modes (work in progress) unsigned short dipSwBits; // virtual dip switch settings for special modes (work in progress)
unsigned short priority; // mono priority for rotator chords unsigned short priority; // mono priority for rotator chords
unsigned short vibSens = 2; // vibrato sensitivity
unsigned short vibRetn = 1; // vibrato return speed
unsigned short fastPatch[7] = {0,0,0,0,0,0,0}; unsigned short fastPatch[7] = {0,0,0,0,0,0,0};
byte rotatorOn = 0; byte rotatorOn = 0;
@ -350,6 +358,8 @@ byte currentRotation = 0;
int rotations[4] = { -5, -10, -7, -14 }; // semitones { -5, -10, -7, -14 }; int rotations[4] = { -5, -10, -7, -14 }; // semitones { -5, -10, -7, -14 };
int parallel = 7; // semitones int parallel = 7; // semitones
byte gateOpen = 0; // setting for gate always open, note on sent for every time fingering changes, no matter the breath status
int breathLoLimit = 0; int breathLoLimit = 0;
int breathHiLimit = 4095; int breathHiLimit = 4095;
int portamLoLimit = 1000; int portamLoLimit = 1000;
@ -383,6 +393,7 @@ byte mainMenuCursor = 1;
byte setupBrMenuCursor = 1; byte setupBrMenuCursor = 1;
byte setupCtMenuCursor = 1; byte setupCtMenuCursor = 1;
byte rotatorMenuCursor = 1; byte rotatorMenuCursor = 1;
byte vibratoMenuCursor = 1;
byte state = 0; byte state = 0;
byte stateFirstRun = 1; byte stateFirstRun = 1;
@ -405,10 +416,12 @@ byte subVelBias = 0;
byte subParallel = 0; byte subParallel = 0;
byte subRotator = 0; byte subRotator = 0;
byte subPriority = 0; byte subPriority = 0;
byte subVibSens = 0;
byte subVibRetn = 0;
byte ccList[10] = {0,1,2,7,11,1,2,7,11,74}; // OFF, Modulation, Breath, Volume, Expression (then same sent in hires) byte ccList[10] = {0,1,2,7,11,1,2,7,11,74}; // OFF, Modulation, Breath, Volume, Expression (then same sent in hires)
int pbDepthList[13] = {0,8192,4096,2731,2048,1638,1365,1170,1024,910,819,744,683}; int pbDepthList[13] = {8192,8192,4096,2731,2048,1638,1365,1170,1024,910,819,744,683};
byte cursorNow; byte cursorNow;
byte forcePix = 0; byte forcePix = 0;
@ -448,6 +461,7 @@ byte activePatch=0;
byte doPatchUpdate=0; byte doPatchUpdate=0;
byte legacy = 0; byte legacy = 0;
byte legacyBrAct = 0;
byte FPD = 0; byte FPD = 0;
@ -461,6 +475,8 @@ float smoothedVal;
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;
byte velocitySend; // remapped midi velocity from breath sensor (or set to static value if selected) byte velocitySend; // remapped midi velocity from breath sensor (or set to static value if selected)
int breathCalZero;
int biteSensor=0; // capacitance data from bite sensor, for midi cc and threshold checks int biteSensor=0; // capacitance data from bite sensor, for midi cc and threshold checks
byte portIsOn=0; // keep track and make sure we send CC with 0 value when off threshold byte portIsOn=0; // keep track and make sure we send CC with 0 value when off threshold
@ -474,6 +490,7 @@ int lastEx=0;
int pitchBend=8192; int pitchBend=8192;
int oldpb=8192; int oldpb=8192;
int vibSignal=0;
int pbUp=0; int pbUp=0;
int pbDn=0; int pbDn=0;
int lastPbUp=0; int lastPbUp=0;
@ -502,7 +519,7 @@ unsigned int curveZ2[] = {0,2000,3200,3800,4096,4800,5100,5900,6650,7700,8800,99
int vibThr; // this gets auto calibrated in setup int vibThr; // this gets auto calibrated in setup
int vibThrLo; int vibThrLo;
int oldvibRead=0; int vibZero;
byte dirUp=0; // direction of first vibrato wave 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
@ -604,6 +621,8 @@ void setup() {
writeSetting(ROTN3_ADDR,ROTN3_FACTORY); writeSetting(ROTN3_ADDR,ROTN3_FACTORY);
writeSetting(ROTN4_ADDR,ROTN4_FACTORY); writeSetting(ROTN4_ADDR,ROTN4_FACTORY);
writeSetting(PRIO_ADDR,PRIO_FACTORY); writeSetting(PRIO_ADDR,PRIO_FACTORY);
writeSetting(VIB_SENS_ADDR,VIB_SENS_FACTORY);
writeSetting(VIB_RETN_ADDR,VIB_RETN_FACTORY);
} }
// read settings from EEPROM // read settings from EEPROM
breathThrVal = readSetting(BREATH_THR_ADDR); breathThrVal = readSetting(BREATH_THR_ADDR);
@ -645,8 +664,11 @@ void setup() {
rotations[2] = readSetting(ROTN3_ADDR)-24; rotations[2] = readSetting(ROTN3_ADDR)-24;
rotations[3] = readSetting(ROTN4_ADDR)-24; rotations[3] = readSetting(ROTN4_ADDR)-24;
priority = readSetting(PRIO_ADDR); priority = readSetting(PRIO_ADDR);
vibSens = readSetting(VIB_SENS_ADDR);
vibRetn = readSetting(VIB_RETN_ADDR);
legacy = dipSwBits & (1<<1); legacy = dipSwBits & (1<<1);
legacyBrAct = dipSwBits & (1<<2);
activePatch = patch; activePatch = patch;
breathStep = (breathHiLimit - breathLoLimit)/92; // 92 is the number of pixels in the settings bar breathStep = (breathHiLimit - breathLoLimit)/92; // 92 is the number of pixels in the settings bar
@ -676,18 +698,22 @@ void setup() {
//auto-calibrate the vibrato threshold while showing splash screen //auto-calibrate the vibrato threshold while showing splash screen
int cv1=touchRead(15); int cv1=touchRead(15);
int bc1=analogRead(A0);
digitalWrite(13,HIGH); digitalWrite(13,HIGH);
delay(250); delay(250);
int cv2=touchRead(15); int cv2=touchRead(15);
int bc2=analogRead(A0);
digitalWrite(13,LOW); digitalWrite(13,LOW);
delay(250); delay(250);
int cv3=touchRead(15); int cv3=touchRead(15);
int bc3=analogRead(A0);
digitalWrite(13,HIGH); digitalWrite(13,HIGH);
delay(250); delay(250);
digitalWrite(13,LOW); digitalWrite(13,LOW);
int cv4=touchRead(15); int cv4=touchRead(15);
vibThr=(cv1+cv2+cv3+cv4)/4-30; int bc4=analogRead(A0);
vibThrLo=(cv1+cv2+cv3+cv4)/4+30; vibZero=(cv1+cv2+cv3+cv4)/4;
breathCalZero=(bc1+bc2+bc3+bc4)/4;
delay(250); delay(250);
digitalWrite(13,HIGH); digitalWrite(13,HIGH);
delay(250); delay(250);
@ -695,10 +721,10 @@ void setup() {
display.setTextColor(WHITE); display.setTextColor(WHITE);
display.setTextSize(1); display.setTextSize(1);
display.setCursor(85,52); display.setCursor(85,52);
display.println("v.1.1.7"); // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<< display.println("v.1.2.2"); // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<<
display.display(); display.display();
delay(2000); delay(1500);
state = DISPLAYOFF_IDL; state = DISPLAYOFF_IDL;
mainState = NOTE_OFF; // initialize main state machine mainState = NOTE_OFF; // initialize main state machine
@ -712,8 +738,6 @@ void setup() {
Serial3.flush(); Serial3.flush();
digitalWrite(13,HIGH); // Switch on the onboard LED to indicate power on/ready digitalWrite(13,HIGH); // Switch on the onboard LED to indicate power on/ready
midiReset();
} }
@ -736,25 +760,24 @@ void mainLoop() {
activePatch = patch; activePatch = patch;
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);
slurSustain = 0; slurSustain = 0;
parallelChord = 0; parallelChord = 0;
subOctaveDouble = 0; subOctaveDouble = 0;
doPatchUpdate = 0; doPatchUpdate = 0;
} }
if (pressureSensor > breathThrVal) { if ((pressureSensor > breathThrVal) || gateOpen) {
// Value has risen above threshold. Move to the RISE_WAIT // Value has risen above threshold. Move to the RISE_WAIT
// state. Record time and initial breath value. // state. Record time and initial breath value.
breath_on_time = millis(); breath_on_time = millis();
initial_breath_value = pressureSensor; initial_breath_value = pressureSensor;
mainState = RISE_WAIT; // Go to next state mainState = RISE_WAIT; // Go to next state
} }
if (legacy){ if (legacy || legacyBrAct){
if ((pbUp > ((pitchbMaxVal + pitchbThrVal)/2)) && (pbDn > ((pitchbMaxVal + pitchbThrVal)/2))){ // both pb pads touched if (((pbUp > ((pitchbMaxVal + pitchbThrVal)/2)) && (pbDn > ((pitchbMaxVal + pitchbThrVal)/2)) && legacy) || ((analogRead(0) < (breathCalZero - 500)) && legacyBrAct)){ // both pb pads touched
readSwitches(); readSwitches();
fingeredNoteUntransposed=patchLimit(fingeredNoteUntransposed+1); fingeredNoteUntransposed=patchLimit(fingeredNoteUntransposed+1);
if (exSensor >= ((extracThrVal+extracMaxVal)/2)){ // instant midi setting if (exSensor >= ((extracThrVal+extracMaxVal)/2)){ // instant midi setting
if ((fingeredNoteUntransposed >= 72) && (fingeredNoteUntransposed <= 88)) { if ((fingeredNoteUntransposed >= 73) && (fingeredNoteUntransposed <= 88)) {
MIDIchannel = fingeredNoteUntransposed - 72; // Mid C and up MIDIchannel = fingeredNoteUntransposed - 72; // Mid C and up
digitalWrite(13,LOW); digitalWrite(13,LOW);
delay(150); delay(150);
@ -834,7 +857,7 @@ void mainLoop() {
} }
lastSpecialKey = specialKey; lastSpecialKey = specialKey;
} else if (mainState == RISE_WAIT) { } else if (mainState == RISE_WAIT) {
if (pressureSensor > breathThrVal) { if ((pressureSensor > breathThrVal) || gateOpen) {
// Has enough time passed for us to collect our second // Has enough time passed for us to collect our second
// sample? // sample?
if ((millis() - breath_on_time > velSmpDl) || (0 == velSmpDl)) { if ((millis() - breath_on_time > velSmpDl) || (0 == velSmpDl)) {
@ -896,8 +919,7 @@ void mainLoop() {
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) && !gateOpen) {
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 (priority){ if (priority){
@ -1036,6 +1058,7 @@ void mainLoop() {
} }
} }
} }
if (pressureSensor > breathThrVal) cursorBlinkTime = millis(); // keep display from updating with cursor blinking if breath is over thr
} }
// 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) {
@ -1045,6 +1068,7 @@ void mainLoop() {
portamento_(); portamento_();
extraController(); extraController();
statusLEDs(); statusLEDs();
doorKnobCheck();
ccSendTime = millis(); ccSendTime = millis();
} }
if (millis() - pixelUpdateTime > pixelUpdateInterval){ if (millis() - pixelUpdateTime > pixelUpdateInterval){
@ -1185,9 +1209,7 @@ void midiPanic(){ // all notes off
//************************************************************** //**************************************************************
void midiReset(){ // reset all controllers void midiReset(){ // reset controllers
usbMIDI.sendControlChange(121, 0, activeMIDIchannel);
dinMIDIsendControlChange(121, 0, activeMIDIchannel - 1);
usbMIDI.sendControlChange(7, 100, activeMIDIchannel); usbMIDI.sendControlChange(7, 100, activeMIDIchannel);
dinMIDIsendControlChange(7, 100, activeMIDIchannel - 1); dinMIDIsendControlChange(7, 100, activeMIDIchannel - 1);
usbMIDI.sendControlChange(11, 127, activeMIDIchannel); usbMIDI.sendControlChange(11, 127, activeMIDIchannel);
@ -1312,52 +1334,74 @@ void breath(){
void pitch_bend(){ void pitch_bend(){
// handle input from pitchbend touchpads and // handle input from pitchbend touchpads and
// on-pcb variable capacitor for vibrato. // on-pcb variable capacitor for vibrato.
float nudge; int vibMax;
int calculatedPBdepth; int calculatedPBdepth;
byte vibratoMoved = 0; byte vibratoMoved = 0;
pbUp = touchRead(pbUpPin); // SENSOR PIN 23 - PCB PIN "Pu" pbUp = touchRead(pbUpPin); // SENSOR PIN 23 - PCB PIN "Pu"
pbDn = touchRead(pbDnPin); // SENSOR PIN 22 - PCB PIN "Pd" pbDn = touchRead(pbDnPin); // SENSOR PIN 22 - PCB PIN "Pd"
halfPitchBendKey = (pinkySetting == PBD) && (touchRead(halfPitchBendKeyPin) > touch_Thr); // SENSOR PIN 1 - PCB PIN "S1" - hold for 1/2 pitchbend value halfPitchBendKey = (pinkySetting == PBD) && (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 int vibRead = touchRead(vibratoPin); // SENSOR PIN 15 - built in var cap
if (PBdepth){ calculatedPBdepth = pbDepthList[PBdepth];
calculatedPBdepth = pbDepthList[PBdepth]; if (halfPitchBendKey) calculatedPBdepth = calculatedPBdepth*0.5;
if (halfPitchBendKey) calculatedPBdepth = calculatedPBdepth*0.5;
switch(vibRetn){ // moving baseline
case 1:
vibZero = vibZero*0.95+vibRead*0.05;
break;
case 2:
vibZero = vibZero*0.9+vibRead*0.1;
break;
case 3:
vibZero = vibZero*0.8+vibRead*0.2;
break;
case 4:
vibZero = vibZero*0.6+vibRead*0.4;
} }
if (((vibRead < vibThr) || (vibRead > vibThrLo))&&(vibRead > oldvibRead)){ vibThr=vibZero-20;
nudge = 0.01*constrain(abs(vibRead - oldvibRead),0,100); vibThrLo=vibZero+20;
if (!dirUp){ switch(vibSens){
pitchBend=oldpb*(1-nudge)+nudge*(8192 + calculatedPBdepth*vibDepth[vibrato]); case 1:
vibratoMoved = 1; vibMax = 200;
} else { break;
pitchBend=oldpb*(1-nudge)+nudge*(8191 - calculatedPBdepth*vibDepth[vibrato]); case 2:
vibratoMoved = 1; vibMax = 100;
} break;
} else if (((vibRead < vibThr) || (vibRead > vibThrLo))&&(vibRead < oldvibRead)){ case 3:
nudge = 0.01*constrain(abs(vibRead - oldvibRead),0,100); vibMax = 50;
if (!dirUp ){ break;
pitchBend=oldpb*(1-nudge)+nudge*(8191 - calculatedPBdepth*vibDepth[vibrato]); case 4:
vibratoMoved = 1; vibMax = 25;
} else { }
pitchBend=oldpb*(1-nudge)+nudge*(8192 + calculatedPBdepth*vibDepth[vibrato]);
vibratoMoved = 1;
} if (vibRead < vibThr){
} else { if (dirUp){
vibratoMoved = 0; vibSignal=vibSignal*0.5+0.5*map(constrain(vibRead,(vibZero-vibMax),vibThr),vibThr,(vibZero-vibMax),0,calculatedPBdepth*vibDepth[vibrato]);
} else {
vibSignal=vibSignal*0.5+0.5*map(constrain(vibRead,(vibZero-vibMax),vibThr),vibThr,(vibZero-vibMax),0,(0 - calculatedPBdepth*vibDepth[vibrato]));
}
} else if (vibRead > vibThrLo){
if (dirUp ){
vibSignal=vibSignal*0.5+0.5*map(constrain(vibRead,vibThrLo,(vibZero+vibMax)),vibThrLo,(vibZero+vibMax),0,(0 - calculatedPBdepth*vibDepth[vibrato]));
} else {
vibSignal=vibSignal*0.5+0.5*map(constrain(vibRead,vibThrLo,(vibZero+vibMax)),vibThrLo,(vibZero+vibMax),0,calculatedPBdepth*vibDepth[vibrato]);
}
} else {
vibSignal = vibSignal*0.5;
} }
oldvibRead = vibRead;
if ((pbUp > pitchbThrVal) && PBdepth){ if ((pbUp > pitchbThrVal) && PBdepth){
pitchBend=pitchBend*0.6+0.4*map(constrain(pbUp,pitchbThrVal,pitchbMaxVal),pitchbThrVal,pitchbMaxVal,8192,(8193 + calculatedPBdepth)); pitchBend=pitchBend*0.6+0.4*map(constrain(pbUp,pitchbThrVal,pitchbMaxVal),pitchbThrVal,pitchbMaxVal,8192,(8193 + calculatedPBdepth));
} else if ((pbDn > pitchbThrVal) && PBdepth){ } else if ((pbDn > pitchbThrVal) && PBdepth){
pitchBend=pitchBend*0.6+0.4*map(constrain(pbDn,pitchbThrVal,pitchbMaxVal),pitchbThrVal,pitchbMaxVal,8192,(8192 - calculatedPBdepth)); pitchBend=pitchBend*0.6+0.4*map(constrain(pbDn,pitchbThrVal,pitchbMaxVal),pitchbThrVal,pitchbMaxVal,8192,(8192 - calculatedPBdepth));
} else if (oldvibRead > vibThr){ } else {
pitchBend = pitchBend*0.6+8192*0.4; // released, so smooth your way back to zero pitchBend = pitchBend*0.6+8192*0.4; // released, so smooth your way back to zero
if ((pitchBend > 8187) && (pitchBend < 8197)) pitchBend = 8192; // 8192 is 0 pitch bend, don't miss it bc of smoothing if ((pitchBend > 8187) && (pitchBend < 8197)) pitchBend = 8192; // 8192 is 0 pitch bend, don't miss it bc of smoothing
} else if (!vibratoMoved){ }
pitchBend = oldpb*0.8+8192*0.2; // released, so smooth your way back to zero
if ((pitchBend > 8187) && (pitchBend < 8197)) pitchBend = 8192; // 8192 is 0 pitch bend, don't miss it bc of smoothing pitchBend=pitchBend+vibSignal;
}
pitchBend=constrain(pitchBend, 0, 16383); pitchBend=constrain(pitchBend, 0, 16383);
if (pitchBend != oldpb){// only send midi data if pitch bend has changed from previous value if (pitchBend != oldpb){// only send midi data if pitch bend has changed from previous value
#if defined(NEWTEENSYDUINO) #if defined(NEWTEENSYDUINO)
@ -1372,6 +1416,40 @@ void pitch_bend(){
//*********************************************************** //***********************************************************
void doorKnobCheck(){
int touchValue[12];
for (byte i=0; i<12; i++){
touchValue[i]=touchSensor.filteredData(i);
}
if ((touchValue[K4Pin] < ctouchThrVal) && (touchValue[R1Pin] < ctouchThrVal) && (touchValue[R2Pin] < ctouchThrVal) && (touchValue[R3Pin] < ctouchThrVal)){ // doorknob grip on canister
if (pbUp > ((pitchbMaxVal + pitchbThrVal)/2)) {
gateOpen = 1;
digitalWrite(13,LOW);
delay(50);
digitalWrite(13,HIGH);
delay(50);
}
else if (pbDn > ((pitchbMaxVal + pitchbThrVal)/2)) {
gateOpen = 0;
midiPanic();
digitalWrite(13,LOW);
delay(50);
digitalWrite(13,HIGH);
delay(50);
digitalWrite(13,LOW);
delay(50);
digitalWrite(13,HIGH);
delay(50);
digitalWrite(13,LOW);
delay(50);
digitalWrite(13,HIGH);
delay(700);
}
}
}
//***********************************************************
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(extraPin); // 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)
@ -1410,20 +1488,26 @@ void extraController(){
} else if (extracIsOn) { // we have just gone below threshold, so send zero value } else if (extracIsOn) { // we have just gone below threshold, so send zero value
extracIsOn=0; extracIsOn=0;
if (extraCT == 1){ //MW if (extraCT == 1){ //MW
//send modulation 0 if (oldextrac != 0){
usbMIDI.sendControlChange(1,0, activeMIDIchannel); //send modulation 0
dinMIDIsendControlChange(1,0, activeMIDIchannel - 1); usbMIDI.sendControlChange(1,0, activeMIDIchannel);
oldextrac = 0; dinMIDIsendControlChange(1,0, activeMIDIchannel - 1);
oldextrac = 0;
}
} else if (extraCT == 2){ //FP } else if (extraCT == 2){ //FP
//send foot pedal 0 if (oldextrac != 0){
usbMIDI.sendControlChange(4,0, activeMIDIchannel); //send foot pedal 0
dinMIDIsendControlChange(4,0, activeMIDIchannel - 1); usbMIDI.sendControlChange(4,0, activeMIDIchannel);
oldextrac = 0; dinMIDIsendControlChange(4,0, activeMIDIchannel - 1);
oldextrac = 0;
}
} else if ((extraCT == 3) && (breathCC != 9)){ //CF } else if ((extraCT == 3) && (breathCC != 9)){ //CF
//send filter cutoff 0 if (oldextrac != 0){
usbMIDI.sendControlChange(74,0, activeMIDIchannel); //send filter cutoff 0
dinMIDIsendControlChange(74,0, activeMIDIchannel - 1); usbMIDI.sendControlChange(74,0, activeMIDIchannel);
oldextrac = 0; dinMIDIsendControlChange(74,0, activeMIDIchannel - 1);
oldextrac = 0;
}
} else if (extraCT == 4){ //SP } else if (extraCT == 4){ //SP
//send sustain off //send sustain off
usbMIDI.sendControlChange(64,0, activeMIDIchannel); usbMIDI.sendControlChange(64,0, activeMIDIchannel);
@ -1436,7 +1520,7 @@ 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(bitePin); // get sensor data, do some smoothing - SENSOR PIN 17 - PCB PINS LABELED "BITE" (GND left, sensor pin right) biteSensor=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();
@ -1472,8 +1556,10 @@ void port(){
//*********************************************************** //***********************************************************
void portOff(){ void portOff(){
usbMIDI.sendControlChange(CCN_Port, 0, activeMIDIchannel); if (oldport != 0){ //did a zero get sent? if not, then send one
dinMIDIsendControlChange(CCN_Port, 0, activeMIDIchannel - 1); usbMIDI.sendControlChange(CCN_Port, 0, activeMIDIchannel);
dinMIDIsendControlChange(CCN_Port, 0, activeMIDIchannel - 1);
}
if (portamento == 2){ // if portamento midi switching is enabled if (portamento == 2){ // if portamento midi switching is enabled
usbMIDI.sendControlChange(CCN_PortOnOff, 0, activeMIDIchannel); usbMIDI.sendControlChange(CCN_PortOnOff, 0, activeMIDIchannel);
dinMIDIsendControlChange(CCN_PortOnOff, 0, activeMIDIchannel - 1); dinMIDIsendControlChange(CCN_PortOnOff, 0, activeMIDIchannel - 1);
@ -1617,6 +1703,11 @@ void menu() {
subPinky = 0; subPinky = 0;
subVelSmpDl = 0; subVelSmpDl = 0;
subVelBias = 0; subVelBias = 0;
subParallel = 0;
subRotator = 0;
subPriority = 0;
subVibSens = 0;
subVibRetn = 0;
} }
@ -1668,8 +1759,19 @@ void menu() {
stateFirstRun = 1; stateFirstRun = 1;
break; break;
case 8: case 8:
// menu // menu
if (exSensor >= ((extracThrVal+extracMaxVal)/2)){ // switch legacy settings control on/off if (pinkyKey && (exSensor >= ((extracThrVal+extracMaxVal)/2))){ // switch breath activated legacy settings on/off
legacyBrAct = !legacyBrAct;
dipSwBits = dipSwBits ^ (1<<2);
writeSetting(DIPSW_BITS_ADDR,dipSwBits);
digitalWrite(13,LOW);
delay(150);
digitalWrite(13,HIGH);
delay(150);
digitalWrite(13,LOW);
delay(150);
digitalWrite(13,HIGH);
} else if ((exSensor >= ((extracThrVal+extracMaxVal)/2))){ // switch pb pad activated legacy settings control on/off
legacy = !legacy; legacy = !legacy;
dipSwBits = dipSwBits ^ (1<<1); dipSwBits = dipSwBits ^ (1<<1);
writeSetting(DIPSW_BITS_ADDR,dipSwBits); writeSetting(DIPSW_BITS_ADDR,dipSwBits);
@ -1706,6 +1808,7 @@ void menu() {
stateFirstRun = 1; stateFirstRun = 1;
doPatchUpdate = 1; doPatchUpdate = 1;
FPD = 0; FPD = 0;
if (readSetting(PATCH_ADDR) != patch) writeSetting(PATCH_ADDR,patch);
} }
if (buttonPressedAndNotUsed){ if (buttonPressedAndNotUsed){
buttonPressedAndNotUsed = 0; buttonPressedAndNotUsed = 0;
@ -1718,10 +1821,13 @@ void menu() {
activePatch = 0; activePatch = 0;
doPatchUpdate = 1; doPatchUpdate = 1;
FPD = 1; FPD = 1;
if (readSetting(PATCH_ADDR) != patch) writeSetting(PATCH_ADDR,patch);
} else if (!trills){ } else if (!trills){
if (patch > 1){ if (patch > 1){
patch--; patch--;
} else patch = 128; } else patch = 128;
activePatch = 0;
doPatchUpdate = 1;
FPD = 0; FPD = 0;
} }
drawPatchView(); drawPatchView();
@ -1745,10 +1851,13 @@ void menu() {
activePatch = 0; activePatch = 0;
doPatchUpdate = 1; doPatchUpdate = 1;
FPD = 1; FPD = 1;
if (readSetting(PATCH_ADDR) != patch) writeSetting(PATCH_ADDR,patch);
} else if (!trills){ } else if (!trills){
if (patch < 128){ if (patch < 128){
patch++; patch++;
} else patch = 1; } else patch = 1;
activePatch = 0;
doPatchUpdate = 1;
FPD = 0; FPD = 0;
} }
drawPatchView(); drawPatchView();
@ -1761,12 +1870,12 @@ void menu() {
stateFirstRun = 1; stateFirstRun = 1;
doPatchUpdate = 1; doPatchUpdate = 1;
} }
if (readSetting(PATCH_ADDR) != patch) writeSetting(PATCH_ADDR,patch);
FPD = 0; FPD = 0;
break; break;
case 10: case 10:
// enter + menu // enter + menu
midiPanic(); midiPanic();
midiReset();
display.clearDisplay(); display.clearDisplay();
display.setTextColor(WHITE); display.setTextColor(WHITE);
display.setTextSize(2); display.setTextSize(2);
@ -3406,56 +3515,6 @@ void menu() {
if (readSetting(EXTRA_ADDR) != extraCT) writeSetting(EXTRA_ADDR,extraCT); if (readSetting(EXTRA_ADDR) != extraCT) writeSetting(EXTRA_ADDR,extraCT);
break; break;
} }
}
} else if (subVibrato) {
if ((millis() - cursorBlinkTime) > cursorBlinkInterval) {
if (cursorNow == WHITE) cursorNow = BLACK; else cursorNow = WHITE;
plotVibrato(cursorNow);
display.display();
cursorBlinkTime = millis();
}
if (buttonPressedAndNotUsed){
buttonPressedAndNotUsed = 0;
switch (deumButtonState){
case 1:
// down
if (vibrato > 0){
plotVibrato(BLACK);
vibrato--;
plotVibrato(WHITE);
cursorNow = BLACK;
display.display();
cursorBlinkTime = millis();
}
break;
case 2:
// enter
plotVibrato(WHITE);
cursorNow = BLACK;
display.display();
subVibrato = 0;
if (readSetting(VIBRATO_ADDR) != vibrato) writeSetting(VIBRATO_ADDR,vibrato);
break;
case 4:
// up
if (vibrato < 9){
plotVibrato(BLACK);
vibrato++;
plotVibrato(WHITE);
cursorNow = BLACK;
display.display();
cursorBlinkTime = millis();
}
break;
case 8:
// menu
plotVibrato(WHITE);
cursorNow = BLACK;
display.display();
subVibrato = 0;
if (readSetting(VIBRATO_ADDR) != vibrato) writeSetting(VIBRATO_ADDR,vibrato);
break;
}
} }
} else if (subDeglitch) { } else if (subDeglitch) {
if ((millis() - cursorBlinkTime) > cursorBlinkInterval) { if ((millis() - cursorBlinkTime) > cursorBlinkInterval) {
@ -3601,7 +3660,213 @@ void menu() {
} }
} }
} }
} else if (state == VIBRATO_MENU) { // VIBRATO MENU HERE <<<<<<<<<<<<<
if (stateFirstRun) {
drawVibratoMenuScreen();
stateFirstRun = 0;
}
if (subVibrato) {
if ((millis() - cursorBlinkTime) > cursorBlinkInterval) {
if (cursorNow == WHITE) cursorNow = BLACK; else cursorNow = WHITE;
plotVibrato(cursorNow);
display.display();
cursorBlinkTime = millis();
}
if (buttonPressedAndNotUsed){
buttonPressedAndNotUsed = 0;
switch (deumButtonState){
case 1:
// down
if (vibrato > 0){
plotVibrato(BLACK);
vibrato--;
plotVibrato(WHITE);
cursorNow = BLACK;
display.display();
cursorBlinkTime = millis();
}
break;
case 2:
// enter
plotVibrato(WHITE);
cursorNow = BLACK;
display.display();
subVibrato = 0;
if (readSetting(VIBRATO_ADDR) != vibrato) writeSetting(VIBRATO_ADDR,vibrato);
break;
case 4:
// up
if (vibrato < 9){
plotVibrato(BLACK);
vibrato++;
plotVibrato(WHITE);
cursorNow = BLACK;
display.display();
cursorBlinkTime = millis();
}
break;
case 8:
// menu
plotVibrato(WHITE);
cursorNow = BLACK;
display.display();
subVibrato = 0;
if (readSetting(VIBRATO_ADDR) != vibrato) writeSetting(VIBRATO_ADDR,vibrato);
break;
}
}
} else if (subVibSens) {
if ((millis() - cursorBlinkTime) > cursorBlinkInterval) {
if (cursorNow == WHITE) cursorNow = BLACK; else cursorNow = WHITE;
plotVibSens(cursorNow);
display.display();
cursorBlinkTime = millis();
}
if (buttonPressedAndNotUsed){
buttonPressedAndNotUsed = 0;
switch (deumButtonState){
case 1:
// down
if (vibSens > 1){
plotVibSens(BLACK);
vibSens--;
plotVibSens(WHITE);
cursorNow = BLACK;
display.display();
cursorBlinkTime = millis();
}
break;
case 2:
// enter
plotVibSens(WHITE);
cursorNow = BLACK;
display.display();
subVibSens = 0;
if (readSetting(VIB_SENS_ADDR) != vibSens) writeSetting(VIB_SENS_ADDR,vibSens);
break;
case 4:
// up
if (vibSens < 4){
plotVibSens(BLACK);
vibSens++;
plotVibSens(WHITE);
cursorNow = BLACK;
display.display();
cursorBlinkTime = millis();
}
break;
case 8:
// menu
plotVibSens(WHITE);
cursorNow = BLACK;
display.display();
subVibSens = 0;
if (readSetting(VIB_SENS_ADDR) != vibSens) writeSetting(VIB_SENS_ADDR,vibSens);
break;
}
}
} else if (subVibRetn) {
if ((millis() - cursorBlinkTime) > cursorBlinkInterval) {
if (cursorNow == WHITE) cursorNow = BLACK; else cursorNow = WHITE;
plotVibRetn(cursorNow);
display.display();
cursorBlinkTime = millis();
}
if (buttonPressedAndNotUsed){
buttonPressedAndNotUsed = 0;
switch (deumButtonState){
case 1:
// down
plotVibRetn(BLACK);
if (vibRetn > 1){
vibRetn--;
}
plotVibRetn(WHITE);
cursorNow = BLACK;
display.display();
cursorBlinkTime = millis();
break;
case 2:
// enter
plotVibRetn(WHITE);
cursorNow = BLACK;
display.display();
subVibRetn = 0;
if (readSetting(VIB_RETN_ADDR) != vibRetn) writeSetting(VIB_RETN_ADDR,vibRetn);
break;
case 4:
// up
plotVibRetn(BLACK);
if (vibRetn < 4){
vibRetn++;
}
plotVibRetn(WHITE);
cursorNow = BLACK;
display.display();
cursorBlinkTime = millis();
break;
case 8:
// menu
plotVibRetn(WHITE);
cursorNow = BLACK;
display.display();
subVibRetn = 0;
if (readSetting(VIB_RETN_ADDR) != vibRetn) writeSetting(VIB_RETN_ADDR,vibRetn);
break;
}
}
} else {
if ((millis() - cursorBlinkTime) > cursorBlinkInterval) {
if (cursorNow == WHITE) cursorNow = BLACK; else cursorNow = WHITE;
drawMenuCursor(vibratoMenuCursor, cursorNow);
display.display();
cursorBlinkTime = millis();
}
if (buttonPressedAndNotUsed){
buttonPressedAndNotUsed = 0;
switch (deumButtonState){
case 1:
// down
if (vibratoMenuCursor < 6){
drawMenuCursor(vibratoMenuCursor, BLACK);
vibratoMenuCursor++;
drawMenuCursor(vibratoMenuCursor, WHITE);
cursorNow = BLACK;
clearSub();
display.display();
}
break;
case 2:
// enter
selectVibratoMenu();
break;
case 4:
// up
if (vibratoMenuCursor > 1){
drawMenuCursor(vibratoMenuCursor, BLACK);
vibratoMenuCursor--;
drawMenuCursor(vibratoMenuCursor, WHITE);
cursorNow = BLACK;
clearSub();
display.display();
}
break;
case 8:
// menu
state = SETUP_CT_MENU;
stateFirstRun = 1;
break;
}
}
}
} }
} }
@ -3761,11 +4026,13 @@ void selectSetupCtMenu(){
drawSubExtra(); drawSubExtra();
break; break;
case 4: case 4:
subVibrato = 1; //subVibrato = 1;
drawMenuCursor(setupCtMenuCursor, WHITE); //drawMenuCursor(setupCtMenuCursor, WHITE);
display.display(); //display.display();
cursorBlinkTime = millis(); //cursorBlinkTime = millis();
drawSubVibrato(); //drawSubVibrato();
state = VIBRATO_MENU;
stateFirstRun = 1;
break; break;
case 5: case 5:
subDeglitch = 1; subDeglitch = 1;
@ -3782,6 +4049,34 @@ void selectSetupCtMenu(){
drawSubPinkyKey(); drawSubPinkyKey();
} }
} }
void selectVibratoMenu(){
switch (vibratoMenuCursor){
case 1:
subVibrato = 1;
drawMenuCursor(vibratoMenuCursor, WHITE);
display.display();
cursorBlinkTime = millis();
drawSubVibrato();
break;
case 2:
subVibSens = 1;
drawMenuCursor(vibratoMenuCursor, WHITE);
display.display();
cursorBlinkTime = millis();
drawSubVibSens();
break;
case 3:
subVibRetn = 1;
drawMenuCursor(vibratoMenuCursor, WHITE);
display.display();
cursorBlinkTime = millis();
drawSubVibRetn();
break;
}
}
void drawBreathScreen(){ void drawBreathScreen(){
// Clear the buffer. // Clear the buffer.
display.clearDisplay(); display.clearDisplay();
@ -4482,8 +4777,8 @@ void drawSubVibrato(){
display.drawRect(63,11,64,52,WHITE); display.drawRect(63,11,64,52,WHITE);
display.setTextColor(WHITE); display.setTextColor(WHITE);
display.setTextSize(1); display.setTextSize(1);
display.setCursor(74,15); display.setCursor(81,15);
display.println("VIBRATO"); display.println("LEVEL");
plotVibrato(WHITE); plotVibrato(WHITE);
display.display(); display.display();
} }
@ -4500,6 +4795,43 @@ void plotVibrato(int color){
} }
} }
void drawSubVibSens(){
display.fillRect(63,11,64,52,BLACK);
display.drawRect(63,11,64,52,WHITE);
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(81,15);
display.println("LEVEL");
plotVibSens(WHITE);
display.display();
}
void plotVibSens(int color){
display.setTextColor(color);
display.setTextSize(2);
display.setCursor(90,33);
display.println(vibSens);
}
void drawSubVibRetn(){
display.fillRect(63,11,64,52,BLACK);
display.drawRect(63,11,64,52,WHITE);
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(81,15);
display.println("LEVEL");
plotVibRetn(WHITE);
display.display();
}
void plotVibRetn(int color){
display.setTextColor(color);
display.setTextSize(2);
display.setCursor(90,33);
display.println(vibRetn);
}
void drawSubDeglitch(){ void drawSubDeglitch(){
display.fillRect(63,11,64,52,BLACK); display.fillRect(63,11,64,52,BLACK);
display.drawRect(63,11,64,52,WHITE); display.drawRect(63,11,64,52,WHITE);
@ -4646,6 +4978,32 @@ void drawSetupCtMenuScreen(){
display.display(); display.display();
} }
void drawVibratoMenuScreen(){
// Clear the buffer.
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("VIBRATO");
display.drawLine(0,9,127,9,WHITE);
display.setCursor(0,12);
display.println("DEPTH");
display.setCursor(0,21);
display.println("SENSE");
display.setCursor(0,30);
display.println("RETURN");
display.setCursor(0,39);
display.println("");
display.setCursor(0,48);
display.println("");
display.setCursor(0,57);
display.println("");
display.display();
}
void drawSensorPixels(){ void drawSensorPixels(){
int pos,oldpos; int pos,oldpos;
int redraw=0; int redraw=0;