Added LP filter for breath signal (instead of prev simple smoothing). More settings för vibrato. Pinky key settings added, now you can use pinky key for quick transpose instead of 1/2 pitch bend.
This commit is contained in:
parent
eda4c12d49
commit
f7b1df76d9
1 changed files with 344 additions and 213 deletions
557
NuEVI.ino
557
NuEVI.ino
|
@ -4,6 +4,7 @@
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
#include <Adafruit_GFX.h>
|
#include <Adafruit_GFX.h>
|
||||||
#include <Adafruit_SSD1306.h>
|
#include <Adafruit_SSD1306.h>
|
||||||
|
#include <Filters.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NAME: NuEVI
|
NAME: NuEVI
|
||||||
|
@ -47,6 +48,9 @@ PROGRAMME FUNCTION: EVI Wind Controller using the Freescale MP3V5004GP breath
|
||||||
|
|
||||||
#define vMeterPin A11
|
#define vMeterPin A11
|
||||||
|
|
||||||
|
//#define RTR 13
|
||||||
|
#define PBD 12
|
||||||
|
|
||||||
#if defined(REVB)
|
#if defined(REVB)
|
||||||
|
|
||||||
// MPR121 pins Rev B (angled pins at top edge for main keys and rollers)
|
// MPR121 pins Rev B (angled pins at top edge for main keys and rollers)
|
||||||
|
@ -178,9 +182,10 @@ PROGRAMME FUNCTION: EVI Wind Controller using the Freescale MP3V5004GP breath
|
||||||
#define BREATHCURVE_ADDR 44
|
#define BREATHCURVE_ADDR 44
|
||||||
#define VEL_SMP_DL_ADDR 46
|
#define VEL_SMP_DL_ADDR 46
|
||||||
#define VEL_BIAS_ADDR 48
|
#define VEL_BIAS_ADDR 48
|
||||||
|
#define PINKY_KEY_ADDR 50
|
||||||
|
|
||||||
//"factory" values for settings
|
//"factory" values for settings
|
||||||
#define VERSION 23
|
#define VERSION 24
|
||||||
#define BREATH_THR_FACTORY 1400
|
#define BREATH_THR_FACTORY 1400
|
||||||
#define BREATH_MAX_FACTORY 4000
|
#define BREATH_MAX_FACTORY 4000
|
||||||
#define PORTAM_THR_FACTORY 2200
|
#define PORTAM_THR_FACTORY 2200
|
||||||
|
@ -197,14 +202,15 @@ PROGRAMME FUNCTION: EVI Wind Controller using the Freescale MP3V5004GP breath
|
||||||
#define PORTAM_FACTORY 2 // 0 - OFF, 1 - ON, 2 - SW
|
#define PORTAM_FACTORY 2 // 0 - OFF, 1 - ON, 2 - SW
|
||||||
#define PB_FACTORY 1 // 0 - OFF, 1 - 12
|
#define PB_FACTORY 1 // 0 - OFF, 1 - 12
|
||||||
#define EXTRA_FACTORY 2 // 0 - OFF, 1 - Modulation wheel, 2 - Foot pedal, 3 - Filter Cutoff, 4 - Sustain pedal
|
#define EXTRA_FACTORY 2 // 0 - OFF, 1 - Modulation wheel, 2 - Foot pedal, 3 - Filter Cutoff, 4 - Sustain pedal
|
||||||
#define VIBRATO_FACTORY 3 // 0 - OFF, 1 - 6 depth
|
#define VIBRATO_FACTORY 4 // 0 - OFF, 1 - 9 depth
|
||||||
#define DEGLITCH_FACTORY 20 // 0 - OFF, 5 to 70 ms in steps of 5
|
#define DEGLITCH_FACTORY 20 // 0 - OFF, 5 to 70 ms in steps of 5
|
||||||
#define PATCH_FACTORY 1 // MIDI program change 1-128
|
#define PATCH_FACTORY 1 // MIDI program change 1-128
|
||||||
#define OCTAVE_FACTORY 3 // 3 is 0 octave change
|
#define OCTAVE_FACTORY 3 // 3 is 0 octave change
|
||||||
#define CTOUCH_THR_FACTORY 125 // MPR121 touch threshold
|
#define CTOUCH_THR_FACTORY 125 // MPR121 touch threshold
|
||||||
#define BREATHCURVE_FACTORY 4 // 0 to 12 (-4 to +4, S1 to S4)
|
#define BREATHCURVE_FACTORY 4 // 0 to 12 (-4 to +4, S1 to S4)
|
||||||
#define VEL_SMP_DL_FACTORY 20 // 0 to 30 ms in steps of 5
|
#define VEL_SMP_DL_FACTORY 20 // 0 to 30 ms in steps of 5
|
||||||
#define VEL_BIAS_FACTORY 0 // 0 to 9
|
#define VEL_BIAS_FACTORY 0 // 0 to 9
|
||||||
|
#define PINKY_KEY_FACTORY 12 // 0 - 11 (QuickTranspose -12 to -1), 12 (pb/2), 13 - 22 (QuickTranspose +1 to +12)
|
||||||
|
|
||||||
#define OLED_RESET 4
|
#define OLED_RESET 4
|
||||||
Adafruit_SSD1306 display(OLED_RESET);
|
Adafruit_SSD1306 display(OLED_RESET);
|
||||||
|
@ -304,13 +310,14 @@ unsigned short velocity;
|
||||||
unsigned short portamento;// switching on cc65? just cc5 enabled? SW:ON:OFF
|
unsigned short portamento;// switching on cc65? just cc5 enabled? SW:ON:OFF
|
||||||
unsigned short PBdepth; // OFF:1-12 divider
|
unsigned short PBdepth; // OFF:1-12 divider
|
||||||
unsigned short extraCT; // OFF:MW:FP:FC:SP
|
unsigned short extraCT; // OFF:MW:FP:FC:SP
|
||||||
unsigned short vibrato; // OFF:1-6
|
unsigned short vibrato; // OFF:1-9
|
||||||
unsigned short deglitch; // 0-70 ms in steps of 5
|
unsigned short deglitch; // 0-70 ms in steps of 5
|
||||||
unsigned short patch; // 1-128
|
unsigned short patch; // 1-128
|
||||||
unsigned short octave;
|
unsigned short octave;
|
||||||
unsigned short curve;
|
unsigned short curve;
|
||||||
unsigned short velSmpDl; // 0-30 ms
|
unsigned short velSmpDl; // 0-30 ms
|
||||||
unsigned short velBias; // 0-9
|
unsigned short velBias; // 0-9
|
||||||
|
unsigned short pinkySetting; // 0 - 11 (QuickTranspose -12 to -1), 12 (pb/2), 13 - 24 (QuickTranspose +1 to +12)
|
||||||
|
|
||||||
int breathLoLimit = 0;
|
int breathLoLimit = 0;
|
||||||
int breathHiLimit = 4095;
|
int breathHiLimit = 4095;
|
||||||
|
@ -355,8 +362,10 @@ byte subPB = 0;
|
||||||
byte subExtra = 0;
|
byte subExtra = 0;
|
||||||
byte subVibrato = 0;
|
byte subVibrato = 0;
|
||||||
byte subDeglitch = 0;
|
byte subDeglitch = 0;
|
||||||
|
byte subPinky = 0;
|
||||||
byte subVelSmpDl = 0;
|
byte subVelSmpDl = 0;
|
||||||
byte subVelBias = 0;
|
byte subVelBias = 0;
|
||||||
|
byte reTrig = 0;
|
||||||
|
|
||||||
byte ccList[9] = {0,1,2,7,11,1,2,7,11}; // OFF, Modulation, Breath, Volume, Expression (then same sent in hires)
|
byte ccList[9] = {0,1,2,7,11,1,2,7,11}; // OFF, Modulation, Breath, Volume, Expression (then same sent in hires)
|
||||||
|
|
||||||
|
@ -401,6 +410,7 @@ byte doPatchUpdate=0;
|
||||||
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;
|
unsigned int oldbreathhires=0;
|
||||||
|
float filterFreq = 30.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;
|
||||||
|
@ -423,12 +433,14 @@ int pbDn=0;
|
||||||
int lastPbUp=0;
|
int lastPbUp=0;
|
||||||
int lastPbDn=0;
|
int lastPbDn=0;
|
||||||
|
|
||||||
float vibDepth[7] = {0,0.05,0.1,0.15,0.2,0.25,0.3}; // max pitch bend values (+/-) for the vibrato settings
|
byte oldpkey = 0;
|
||||||
|
|
||||||
|
float vibDepth[10] = {0,0.05,0.1,0.15,0.2,0.25,0.3,0.35,0.40,0.45}; // max pitch bend values (+/-) for the vibrato settings
|
||||||
|
|
||||||
unsigned int curveM4[] = {0,4300,7000,8700,9900,10950,11900,12600,13300,13900,14500,15000,15450,15700,16000,16250,16383};
|
unsigned int curveM4[] = {0,4300,7000,8700,9900,10950,11900,12600,13300,13900,14500,15000,15450,15700,16000,16250,16383};
|
||||||
unsigned int curveM3[] = {0,2900,5100,6650,8200,9500,10550,11500,12300,13100,13800,14450,14950,15350,15750,16150,16383};
|
unsigned int curveM3[] = {0,2900,5100,6650,8200,9500,10550,11500,12300,13100,13800,14450,14950,15350,15750,16150,16383};
|
||||||
unsigned int curveM2[] = {0,2000,3600,5000,6450,7850,9000,10100,11100,12100,12900,13700,14400,14950,15500,16000,16383};
|
unsigned int curveM2[] = {0,2000,3600,5000,6450,7850,9000,10100,11100,12100,12900,13700,14400,14950,15500,16000,16383};
|
||||||
unsigned int curveM1[] = {0,1400,2850,4100,5300,6450,7600,8700,9800,10750,11650,12600,13350,14150,14950,15650,16838};
|
unsigned int curveM1[] = {0,1400,2850,4100,5300,6450,7600,8700,9800,10750,11650,12600,13350,14150,14950,15650,16383};
|
||||||
unsigned int curveIn[] = {0,1023,2047,3071,4095,5119,6143,7167,8191,9215,10239,11263,12287,13311,14335,15359,16383};
|
unsigned int curveIn[] = {0,1023,2047,3071,4095,5119,6143,7167,8191,9215,10239,11263,12287,13311,14335,15359,16383};
|
||||||
unsigned int curveP1[] = {0,600,1350,2150,2900,3800,4700,5600,6650,7700,8800,9900,11100,12300,13500,14850,16838};
|
unsigned int curveP1[] = {0,600,1350,2150,2900,3800,4700,5600,6650,7700,8800,9900,11100,12300,13500,14850,16838};
|
||||||
unsigned int curveP2[] = {0,400,800,1300,2000,2650,3500,4300,5300,6250,7400,8500,9600,11050,12400,14100,16383};
|
unsigned int curveP2[] = {0,400,800,1300,2000,2650,3500,4300,5300,6250,7400,8500,9600,11050,12400,14100,16383};
|
||||||
|
@ -436,8 +448,11 @@ unsigned int curveP3[] = {0,200,500,900,1300,1800,2350,3100,3800,4600,5550,6550,
|
||||||
unsigned int curveP4[] = {0,100,200,400,700,1050,1500,1950,2550,3200,4000,4900,6050,7500,9300,12100,16282};
|
unsigned int curveP4[] = {0,100,200,400,700,1050,1500,1950,2550,3200,4000,4900,6050,7500,9300,12100,16282};
|
||||||
unsigned int curveS1[] = {0,600,1350,2150,2900,3800,4700,6000,8700,11000,12400,13400,14300,14950,15500,16000,16383};
|
unsigned int curveS1[] = {0,600,1350,2150,2900,3800,4700,6000,8700,11000,12400,13400,14300,14950,15500,16000,16383};
|
||||||
unsigned int curveS2[] = {0,600,1350,2150,2900,4000,6100,9000,11000,12100,12900,13700,14400,14950,15500,16000,16383};
|
unsigned int curveS2[] = {0,600,1350,2150,2900,4000,6100,9000,11000,12100,12900,13700,14400,14950,15500,16000,16383};
|
||||||
unsigned int curveS3[] = {0,600,1350,2300,3800,6200,8700,10200,11100,12100,12900,13700,14400,14950,15500,16000,16383};
|
//unsigned int curveS3[] = {0,600,1350,2300,3800,6200,8700,10200,11100,12100,12900,13700,14400,14950,15500,16000,16383};
|
||||||
unsigned int curveS4[] = {0,600,1700,4000,6600,8550,9700,10550,11400,12200,12900,13700,14400,14950,15500,16000,16383};
|
//unsigned int curveS4[] = {0,600,1700,4000,6600,8550,9700,10550,11400,12200,12900,13700,14400,14950,15500,16000,16383};
|
||||||
|
|
||||||
|
unsigned int curveZ1[] = {0,1400,2100,2900,3200,3900,4700,5600,6650,7700,8800,9900,11100,12300,13500,14850,16383};
|
||||||
|
unsigned int curveZ2[] = {0,2000,3200,3800,4096,4800,5100,5900,6650,7700,8800,9900,11100,12300,13500,14850,16383};
|
||||||
|
|
||||||
int vibThr=1900; // this gets auto calibrated in setup
|
int vibThr=1900; // this gets auto calibrated in setup
|
||||||
int oldvibRead=0;
|
int oldvibRead=0;
|
||||||
|
@ -519,6 +534,8 @@ void setup() {
|
||||||
writeSetting(BREATHCURVE_ADDR,BREATHCURVE_FACTORY);
|
writeSetting(BREATHCURVE_ADDR,BREATHCURVE_FACTORY);
|
||||||
writeSetting(VEL_SMP_DL_ADDR,VEL_SMP_DL_FACTORY);
|
writeSetting(VEL_SMP_DL_ADDR,VEL_SMP_DL_FACTORY);
|
||||||
writeSetting(VEL_BIAS_ADDR,VEL_BIAS_FACTORY);
|
writeSetting(VEL_BIAS_ADDR,VEL_BIAS_FACTORY);
|
||||||
|
writeSetting(PINKY_KEY_ADDR,PINKY_KEY_FACTORY);
|
||||||
|
//writeSetting(QTRANSP_ADDR,QTRANSP_FACTORY);
|
||||||
}
|
}
|
||||||
// read settings from EEPROM
|
// read settings from EEPROM
|
||||||
breathThrVal = readSetting(BREATH_THR_ADDR);
|
breathThrVal = readSetting(BREATH_THR_ADDR);
|
||||||
|
@ -545,6 +562,7 @@ void setup() {
|
||||||
curve = readSetting(BREATHCURVE_ADDR);
|
curve = readSetting(BREATHCURVE_ADDR);
|
||||||
velSmpDl = readSetting(VEL_SMP_DL_ADDR);
|
velSmpDl = readSetting(VEL_SMP_DL_ADDR);
|
||||||
velBias = readSetting(VEL_BIAS_ADDR);
|
velBias = readSetting(VEL_BIAS_ADDR);
|
||||||
|
pinkySetting = readSetting(PINKY_KEY_ADDR);
|
||||||
|
|
||||||
activePatch = patch;
|
activePatch = patch;
|
||||||
|
|
||||||
|
@ -559,6 +577,7 @@ void setup() {
|
||||||
while (1); // Touch sensor initialization failed - stop doing stuff
|
while (1); // Touch sensor initialization failed - stop doing stuff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
|
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
|
||||||
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
|
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
|
||||||
// init done
|
// init done
|
||||||
|
@ -591,7 +610,7 @@ 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.0.1"); // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<<
|
display.println("v.1.0.3"); // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<<
|
||||||
display.display();
|
display.display();
|
||||||
|
|
||||||
delay(2000);
|
delay(2000);
|
||||||
|
@ -614,169 +633,77 @@ void setup() {
|
||||||
//_______________________________________________________________________________________________ MAIN LOOP
|
//_______________________________________________________________________________________________ MAIN LOOP
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
pressureSensor = analogRead(A0); // Get the pressure sensor reading from analog pin A0, input from sensor MP3V5004GP
|
mainLoop();
|
||||||
|
}
|
||||||
|
|
||||||
if (mainState == NOTE_OFF) {
|
void mainLoop() {
|
||||||
if (activeMIDIchannel != MIDIchannel) activeMIDIchannel = MIDIchannel; // only switch channel if no active note
|
FilterOnePole breathFilter( LOWPASS, filterFreq ); // create a one pole (RC) lowpass filter
|
||||||
if ((activePatch != patch) && doPatchUpdate){
|
while (1){
|
||||||
activePatch = patch;
|
breathFilter.input(analogRead(A0));
|
||||||
usbMIDI.sendProgramChange(activePatch-1,activeMIDIchannel);
|
pressureSensor = breathFilter.output(); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP
|
||||||
dinMIDIsendProgramChange(activePatch-1,activeMIDIchannel-1);
|
|
||||||
if (readSetting(PATCH_ADDR) != activePatch) writeSetting(PATCH_ADDR,activePatch);
|
if (mainState == NOTE_OFF) {
|
||||||
slurSustain = 0;
|
if (activeMIDIchannel != MIDIchannel) activeMIDIchannel = MIDIchannel; // only switch channel if no active note
|
||||||
parallelChord = 0;
|
if ((activePatch != patch) && doPatchUpdate){
|
||||||
subOctaveDouble = 0;
|
activePatch = patch;
|
||||||
doPatchUpdate = 0;
|
usbMIDI.sendProgramChange(activePatch-1,activeMIDIchannel);
|
||||||
}
|
dinMIDIsendProgramChange(activePatch-1,activeMIDIchannel-1);
|
||||||
if (pressureSensor > breathThrVal) {
|
if (readSetting(PATCH_ADDR) != activePatch) writeSetting(PATCH_ADDR,activePatch);
|
||||||
// Value has risen above threshold. Move to the RISE_WAIT
|
slurSustain = 0;
|
||||||
// state. Record time and initial breath value.
|
parallelChord = 0;
|
||||||
breath_on_time = millis();
|
subOctaveDouble = 0;
|
||||||
initial_breath_value = pressureSensor;
|
doPatchUpdate = 0;
|
||||||
mainState = RISE_WAIT; // Go to next state
|
}
|
||||||
}
|
if (pressureSensor > breathThrVal) {
|
||||||
specialKey=(touchRead(specialKeyPin) > touch_Thr); //S2 on pcb
|
// Value has risen above threshold. Move to the RISE_WAIT
|
||||||
if (lastSpecialKey != specialKey){
|
// state. Record time and initial breath value.
|
||||||
if (specialKey){
|
breath_on_time = millis();
|
||||||
// special key just pressed, check other keys
|
initial_breath_value = pressureSensor;
|
||||||
readSwitches();
|
mainState = RISE_WAIT; // Go to next state
|
||||||
if (K4) {
|
}
|
||||||
if (!slurSustain) {
|
specialKey=(touchRead(specialKeyPin) > touch_Thr); //S2 on pcb
|
||||||
slurSustain = 1;
|
if (lastSpecialKey != specialKey){
|
||||||
parallelChord = 0;
|
if (specialKey){
|
||||||
} else slurSustain = 0;
|
// special key just pressed, check other keys
|
||||||
}
|
readSwitches();
|
||||||
if (K5) {
|
if (K4) {
|
||||||
if (!parallelChord) {
|
if (!slurSustain) {
|
||||||
parallelChord = 1;
|
slurSustain = 1;
|
||||||
|
parallelChord = 0;
|
||||||
|
} else slurSustain = 0;
|
||||||
|
}
|
||||||
|
if (K5) {
|
||||||
|
if (!parallelChord) {
|
||||||
|
parallelChord = 1;
|
||||||
|
slurSustain = 0;
|
||||||
|
} else parallelChord = 0;
|
||||||
|
}
|
||||||
|
if (K1) subOctaveDouble = !subOctaveDouble;
|
||||||
|
if (!K1 && !K4 && !K5){
|
||||||
slurSustain = 0;
|
slurSustain = 0;
|
||||||
} else parallelChord = 0;
|
parallelChord = 0;
|
||||||
}
|
subOctaveDouble = 0;
|
||||||
if (K1) subOctaveDouble = !subOctaveDouble;
|
if (halfPitchBendKey) midiPanic();
|
||||||
if (halfPitchBendKey) midiPanic();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
lastSpecialKey = specialKey;
|
|
||||||
} else if (mainState == RISE_WAIT) {
|
|
||||||
if (pressureSensor > breathThrVal) {
|
|
||||||
// Has enough time passed for us to collect our second
|
|
||||||
// sample?
|
|
||||||
if (millis() - breath_on_time > velSmpDl) {
|
|
||||||
// Yes, so calculate MIDI note and velocity, then send a note on event
|
|
||||||
readSwitches();
|
|
||||||
// We should be at tonguing peak, so set velocity based on current pressureSensor value unless fixed velocity is set
|
|
||||||
breathLevel=constrain(max(pressureSensor,initial_breath_value),breathThrVal,breathMaxVal);
|
|
||||||
if (!velocity) {
|
|
||||||
unsigned int breathValHires = breathCurve(map(constrain(breathLevel,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,16383));
|
|
||||||
velocitySend = (breathValHires >>7) & 0x007F;
|
|
||||||
velocitySend = constrain(velocitySend+velocitySend*.1*velBias,1,127);
|
|
||||||
//velocitySend = map(constrain(max(pressureSensor,initial_breath_value),breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,1,127);
|
|
||||||
} else velocitySend = velocity;
|
|
||||||
breath(); // send breath data
|
|
||||||
fingeredNote=noteValueCheck(fingeredNote);
|
|
||||||
usbMIDI.sendNoteOn(fingeredNote, velocitySend, activeMIDIchannel); // send Note On message for new note
|
|
||||||
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;
|
|
||||||
mainState = NOTE_ON;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Value fell below threshold before velocity sample delay time passed. Return to
|
|
||||||
// NOTE_OFF state (e.g. we're ignoring a short blip of breath)
|
|
||||||
mainState = NOTE_OFF;
|
|
||||||
}
|
|
||||||
} else if (mainState == NOTE_ON) {
|
|
||||||
cursorBlinkTime = millis(); // keep display from updating with cursor blinking if note on
|
|
||||||
if (pressureSensor < breathThrVal) {
|
|
||||||
// Value has fallen below threshold - turn the note off
|
|
||||||
activeNote=noteValueCheck(activeNote);
|
|
||||||
usbMIDI.sendNoteOff(activeNote, velocitySend, activeMIDIchannel); // send Note Off message
|
|
||||||
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){
|
lastSpecialKey = specialKey;
|
||||||
usbMIDI.sendNoteOff(noteValueCheck(activeNote-12), velocitySend, activeMIDIchannel);
|
} else if (mainState == RISE_WAIT) {
|
||||||
dinMIDIsendNoteOff(noteValueCheck(activeNote-12), velocitySend, activeMIDIchannel - 1);
|
if (pressureSensor > breathThrVal) {
|
||||||
if (parallelChord){
|
// Has enough time passed for us to collect our second
|
||||||
for (int i=0; i < addedIntervals; i++){
|
// sample?
|
||||||
usbMIDI.sendNoteOff(noteValueCheck(activeNote+slurInterval[i]-12), velocitySend, activeMIDIchannel); // send Note On message for new note
|
if ((millis() - breath_on_time > velSmpDl) || (0 == velSmpDl)) {
|
||||||
dinMIDIsendNoteOff(noteValueCheck(activeNote+slurInterval[i]-12), velocitySend, activeMIDIchannel - 1);
|
// Yes, so calculate MIDI note and velocity, then send a note on event
|
||||||
}
|
readSwitches();
|
||||||
}
|
// We should be at tonguing peak, so set velocity based on current pressureSensor value unless fixed velocity is set
|
||||||
}
|
breathLevel=constrain(max(pressureSensor,initial_breath_value),breathThrVal,breathMaxVal);
|
||||||
if (slurSustain){
|
if (!velocity) {
|
||||||
usbMIDI.sendControlChange(64,0, activeMIDIchannel);
|
|
||||||
dinMIDIsendControlChange(64,0, activeMIDIchannel - 1);
|
|
||||||
}
|
|
||||||
breathLevel=0;
|
|
||||||
mainState = NOTE_OFF;
|
|
||||||
} else {
|
|
||||||
readSwitches();
|
|
||||||
if (fingeredNote != lastFingering){ //
|
|
||||||
// reset the debouncing timer
|
|
||||||
lastDeglitchTime = millis();
|
|
||||||
}
|
|
||||||
if ((millis() - lastDeglitchTime) > deglitch) {
|
|
||||||
// whatever the reading is at, it's been there for longer
|
|
||||||
// than the debounce delay, so take it as the actual current state
|
|
||||||
if (noteValueCheck(fingeredNote) != activeNote) {
|
|
||||||
// Player has moved to a new fingering while still blowing.
|
|
||||||
// Send a note off for the current note and a note on for
|
|
||||||
// the new note.
|
|
||||||
if (!velocity){
|
|
||||||
unsigned int breathValHires = breathCurve(map(constrain(breathLevel,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,16383));
|
unsigned int breathValHires = breathCurve(map(constrain(breathLevel,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,16383));
|
||||||
velocitySend = (breathValHires >>7) & 0x007F;
|
velocitySend = (breathValHires >>7) & 0x007F;
|
||||||
velocitySend = constrain(velocitySend+velocitySend*.1*velBias,1,127);
|
velocitySend = constrain(velocitySend+velocitySend*.1*velBias,1,127);
|
||||||
//velocitySend = map(constrain(pressureSensor,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,7,127); // set new velocity value based on current pressure sensor level
|
//velocitySend = map(constrain(max(pressureSensor,initial_breath_value),breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,1,127);
|
||||||
}
|
} else velocitySend = velocity;
|
||||||
activeNote=noteValueCheck(activeNote);
|
breath(); // send breath data
|
||||||
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);
|
||||||
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);
|
||||||
|
@ -786,8 +713,14 @@ void loop() {
|
||||||
dinMIDIsendNoteOn(noteValueCheck(fingeredNote+slurInterval[i]), velocitySend, activeMIDIchannel - 1);
|
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){
|
if (subOctaveDouble){
|
||||||
usbMIDI.sendNoteOn(noteValueCheck(fingeredNote-12), velocitySend, activeMIDIchannel); // send Note On message for new note
|
usbMIDI.sendNoteOn(noteValueCheck(fingeredNote-12), velocitySend, activeMIDIchannel);
|
||||||
dinMIDIsendNoteOn(noteValueCheck(fingeredNote-12), velocitySend, activeMIDIchannel - 1);
|
dinMIDIsendNoteOn(noteValueCheck(fingeredNote-12), velocitySend, activeMIDIchannel - 1);
|
||||||
if (parallelChord){
|
if (parallelChord){
|
||||||
for (int i=0; i < addedIntervals; i++){
|
for (int i=0; i < addedIntervals; i++){
|
||||||
|
@ -796,40 +729,139 @@ void loop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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-1] = fingeredNote - slurBase;
|
|
||||||
}
|
|
||||||
activeNote=fingeredNote;
|
activeNote=fingeredNote;
|
||||||
|
mainState = NOTE_ON;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Value fell below threshold before velocity sample delay time passed. Return to
|
||||||
|
// NOTE_OFF state (e.g. we're ignoring a short blip of breath)
|
||||||
|
mainState = NOTE_OFF;
|
||||||
|
}
|
||||||
|
} else if (mainState == NOTE_ON) {
|
||||||
|
cursorBlinkTime = millis(); // keep display from updating with cursor blinking if note on
|
||||||
|
if (pressureSensor < breathThrVal) {
|
||||||
|
// Value has fallen below threshold - turn the note off
|
||||||
|
activeNote=noteValueCheck(activeNote);
|
||||||
|
usbMIDI.sendNoteOff(activeNote, velocitySend, activeMIDIchannel); // send Note Off message
|
||||||
|
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;
|
||||||
|
mainState = NOTE_OFF;
|
||||||
|
} else {
|
||||||
|
readSwitches();
|
||||||
|
if (fingeredNote != lastFingering){ //
|
||||||
|
// reset the debouncing timer
|
||||||
|
lastDeglitchTime = millis();
|
||||||
|
}
|
||||||
|
if ((millis() - lastDeglitchTime) > deglitch) {
|
||||||
|
// whatever the reading is at, it's been there for longer
|
||||||
|
// than the debounce delay, so take it as the actual current state
|
||||||
|
if (noteValueCheck(fingeredNote) != activeNote) {
|
||||||
|
// Player has moved to a new fingering while still blowing.
|
||||||
|
// Send a note off for the current note and a note on for
|
||||||
|
// the new note.
|
||||||
|
if (!velocity){
|
||||||
|
unsigned int breathValHires = breathCurve(map(constrain(breathLevel,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,16383));
|
||||||
|
velocitySend = (breathValHires >>7) & 0x007F;
|
||||||
|
velocitySend = constrain(velocitySend+velocitySend*.1*velBias,1,127);
|
||||||
|
//velocitySend = 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);
|
||||||
|
usbMIDI.sendNoteOn(fingeredNote, velocitySend, activeMIDIchannel); // send Note On message for new note
|
||||||
|
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 (subOctaveDouble){
|
||||||
|
usbMIDI.sendNoteOn(noteValueCheck(fingeredNote-12), velocitySend, activeMIDIchannel); // send Note On message for new note
|
||||||
|
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-1] = fingeredNote - slurBase;
|
||||||
|
}
|
||||||
|
activeNote=fingeredNote;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Is it time to send more CC data?
|
||||||
|
if (millis() - ccSendTime > CC_INTERVAL) {
|
||||||
|
// deal with Breath, Pitch Bend, Modulation, etc.
|
||||||
|
breath();
|
||||||
|
pitch_bend();
|
||||||
|
portamento_();
|
||||||
|
extraController();
|
||||||
|
statusLEDs();
|
||||||
|
ccSendTime = millis();
|
||||||
|
}
|
||||||
|
if (millis() - pixelUpdateTime > pixelUpdateInterval){
|
||||||
|
// even if we just alter a pixel, the whole display is redrawn (35ms of MPU lockup) and we can't do that all the time
|
||||||
|
// this is one of the big reasons the display is for setup use only
|
||||||
|
drawSensorPixels(); // live sensor monitoring for the setup screens
|
||||||
|
pixelUpdateTime = millis();
|
||||||
|
}
|
||||||
|
lastFingering=fingeredNote;
|
||||||
|
//do menu stuff
|
||||||
|
menu();
|
||||||
}
|
}
|
||||||
// Is it time to send more CC data?
|
|
||||||
if (millis() - ccSendTime > CC_INTERVAL) {
|
|
||||||
// deal with Breath, Pitch Bend, Modulation, etc.
|
|
||||||
breath();
|
|
||||||
pitch_bend();
|
|
||||||
portamento_();
|
|
||||||
extraController();
|
|
||||||
statusLEDs();
|
|
||||||
ccSendTime = millis();
|
|
||||||
}
|
|
||||||
if (millis() - pixelUpdateTime > pixelUpdateInterval){
|
|
||||||
// even if we just alter a pixel, the whole display is redrawn (35ms of MPU lockup) and we can't do that all the time
|
|
||||||
// this is one of the big reasons the display is for setup use only
|
|
||||||
drawSensorPixels(); // live sensor monitoring for the setup screens
|
|
||||||
pixelUpdateTime = millis();
|
|
||||||
}
|
|
||||||
lastFingering=fingeredNote;
|
|
||||||
//do menu stuff
|
|
||||||
menu();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//_______________________________________________________________________________________________ FUNCTIONS
|
//_______________________________________________________________________________________________ FUNCTIONS
|
||||||
|
@ -905,12 +937,12 @@ unsigned int breathCurve(unsigned int inputVal){
|
||||||
return multiMap(inputVal,curveIn,curveS2,17);
|
return multiMap(inputVal,curveIn,curveS2,17);
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
// S3
|
// Z1
|
||||||
return multiMap(inputVal,curveIn,curveS3,17);
|
return multiMap(inputVal,curveIn,curveZ1,17);
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
// S4
|
// Z2
|
||||||
return multiMap(inputVal,curveIn,curveS4,17);
|
return multiMap(inputVal,curveIn,curveZ2,17);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1017,8 +1049,9 @@ void statusLEDs() {
|
||||||
void breath(){
|
void breath(){
|
||||||
int breathCCval,breathCCvalFine;
|
int breathCCval,breathCCvalFine;
|
||||||
unsigned int breathCCvalHires;
|
unsigned int breathCCvalHires;
|
||||||
breathLevel = breathLevel*0.6+pressureSensor*0.4; // smoothing of breathLevel value
|
breathLevel = pressureSensor;
|
||||||
//breathCCval = map(constrain(breathLevel,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,127);
|
//breathLevel = breathLevel*0.6+pressureSensor*0.4; // smoothing of breathLevel value
|
||||||
|
////////breathCCval = map(constrain(breathLevel,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,127);
|
||||||
breathCCvalHires = breathCurve(map(constrain(breathLevel,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,16383));
|
breathCCvalHires = breathCurve(map(constrain(breathLevel,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,16383));
|
||||||
breathCCval = (breathCCvalHires >>7) & 0x007F;
|
breathCCval = (breathCCvalHires >>7) & 0x007F;
|
||||||
breathCCvalFine = breathCCvalHires & 0x007F;
|
breathCCvalFine = breathCCvalHires & 0x007F;
|
||||||
|
@ -1054,10 +1087,10 @@ void pitch_bend(){
|
||||||
float nudge;
|
float nudge;
|
||||||
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=(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){
|
if (PBdepth){
|
||||||
calculatedPBdepth = pbDepthList[PBdepth];
|
calculatedPBdepth = pbDepthList[PBdepth];
|
||||||
if (halfPitchBendKey) calculatedPBdepth = calculatedPBdepth*0.5;
|
if (halfPitchBendKey) calculatedPBdepth = calculatedPBdepth*0.5;
|
||||||
|
@ -1220,7 +1253,7 @@ void portOff(){
|
||||||
//***********************************************************
|
//***********************************************************
|
||||||
|
|
||||||
void readSwitches(){
|
void readSwitches(){
|
||||||
|
int qTransp;
|
||||||
// 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++){
|
||||||
|
@ -1244,9 +1277,21 @@ void readSwitches(){
|
||||||
K5=(touchValue[K5Pin] < ctouchThrVal);
|
K5=(touchValue[K5Pin] < ctouchThrVal);
|
||||||
K6=(touchValue[K6Pin] < ctouchThrVal);
|
K6=(touchValue[K6Pin] < ctouchThrVal);
|
||||||
K7=(touchValue[K7Pin] < ctouchThrVal);
|
K7=(touchValue[K7Pin] < ctouchThrVal);
|
||||||
|
|
||||||
|
int pKey = (touchRead(halfPitchBendKeyPin) > touch_Thr); // SENSOR PIN 1 - PCB PIN "S1"
|
||||||
|
|
||||||
|
if ((pinkySetting < 12) && pKey){
|
||||||
|
qTransp = pinkySetting - 12;
|
||||||
|
} else if ((pinkySetting > 12) && pKey){
|
||||||
|
qTransp = pinkySetting - 12;
|
||||||
|
} else {
|
||||||
|
qTransp = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//reTrig = ((pinkySetting == RTR) && pKey);
|
||||||
|
|
||||||
// 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+qTransp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1322,6 +1367,9 @@ void menu() {
|
||||||
subExtra = 0;
|
subExtra = 0;
|
||||||
subVibrato = 0;
|
subVibrato = 0;
|
||||||
subDeglitch = 0;
|
subDeglitch = 0;
|
||||||
|
subPinky = 0;
|
||||||
|
subVelSmpDl = 0;
|
||||||
|
subVelBias = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1360,6 +1408,9 @@ void menu() {
|
||||||
state = MAIN_MENU;
|
state = MAIN_MENU;
|
||||||
stateFirstRun = 1;
|
stateFirstRun = 1;
|
||||||
break;
|
break;
|
||||||
|
case 15:
|
||||||
|
//all keys depressed, reboot to programming mode
|
||||||
|
_reboot_Teensyduino_();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (state == PATCH_VIEW){
|
} else if (state == PATCH_VIEW){
|
||||||
|
@ -2799,7 +2850,7 @@ void menu() {
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
// up
|
// up
|
||||||
if (vibrato < 6){
|
if (vibrato < 9){
|
||||||
plotVibrato(BLACK);
|
plotVibrato(BLACK);
|
||||||
vibrato++;
|
vibrato++;
|
||||||
plotVibrato(WHITE);
|
plotVibrato(WHITE);
|
||||||
|
@ -2868,6 +2919,56 @@ void menu() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (subPinky) {
|
||||||
|
if ((millis() - cursorBlinkTime) > cursorBlinkInterval) {
|
||||||
|
if (cursorNow == WHITE) cursorNow = BLACK; else cursorNow = WHITE;
|
||||||
|
plotPinkyKey(cursorNow);
|
||||||
|
display.display();
|
||||||
|
cursorBlinkTime = millis();
|
||||||
|
}
|
||||||
|
if (buttonPressedAndNotUsed){
|
||||||
|
buttonPressedAndNotUsed = 0;
|
||||||
|
switch (deumButtonState){
|
||||||
|
case 1:
|
||||||
|
// down
|
||||||
|
if (pinkySetting > 0){
|
||||||
|
plotPinkyKey(BLACK);
|
||||||
|
pinkySetting-=1;
|
||||||
|
plotPinkyKey(WHITE);
|
||||||
|
cursorNow = BLACK;
|
||||||
|
display.display();
|
||||||
|
cursorBlinkTime = millis();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// enter
|
||||||
|
plotPinkyKey(WHITE);
|
||||||
|
cursorNow = BLACK;
|
||||||
|
display.display();
|
||||||
|
subPinky = 0;
|
||||||
|
if (readSetting(PINKY_KEY_ADDR) != pinkySetting) writeSetting(PINKY_KEY_ADDR,pinkySetting);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
// up
|
||||||
|
if (pinkySetting < 24){
|
||||||
|
plotPinkyKey(BLACK);
|
||||||
|
pinkySetting+=1;
|
||||||
|
plotPinkyKey(WHITE);
|
||||||
|
cursorNow = BLACK;
|
||||||
|
display.display();
|
||||||
|
cursorBlinkTime = millis();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
// menu
|
||||||
|
plotPinkyKey(WHITE);
|
||||||
|
cursorNow = BLACK;
|
||||||
|
display.display();
|
||||||
|
subPinky = 0;
|
||||||
|
if (readSetting(PINKY_KEY_ADDR) != pinkySetting) writeSetting(PINKY_KEY_ADDR,pinkySetting);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((millis() - cursorBlinkTime) > cursorBlinkInterval) {
|
if ((millis() - cursorBlinkTime) > cursorBlinkInterval) {
|
||||||
if (cursorNow == WHITE) cursorNow = BLACK; else cursorNow = WHITE;
|
if (cursorNow == WHITE) cursorNow = BLACK; else cursorNow = WHITE;
|
||||||
|
@ -2880,7 +2981,7 @@ void menu() {
|
||||||
switch (deumButtonState){
|
switch (deumButtonState){
|
||||||
case 1:
|
case 1:
|
||||||
// down
|
// down
|
||||||
if (setupCtMenuCursor < 5){
|
if (setupCtMenuCursor < 6){
|
||||||
drawMenuCursor(setupCtMenuCursor, BLACK);
|
drawMenuCursor(setupCtMenuCursor, BLACK);
|
||||||
setupCtMenuCursor++;
|
setupCtMenuCursor++;
|
||||||
drawMenuCursor(setupCtMenuCursor, WHITE);
|
drawMenuCursor(setupCtMenuCursor, WHITE);
|
||||||
|
@ -3037,6 +3138,13 @@ void selectSetupCtMenu(){
|
||||||
display.display();
|
display.display();
|
||||||
cursorBlinkTime = millis();
|
cursorBlinkTime = millis();
|
||||||
drawSubDeglitch();
|
drawSubDeglitch();
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
subPinky = 1;
|
||||||
|
drawMenuCursor(setupCtMenuCursor, WHITE);
|
||||||
|
display.display();
|
||||||
|
cursorBlinkTime = millis();
|
||||||
|
drawSubPinkyKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void drawBreathScreen(){
|
void drawBreathScreen(){
|
||||||
|
@ -3537,11 +3645,11 @@ void plotCurve(int color){
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
display.setCursor(83,33);
|
display.setCursor(83,33);
|
||||||
display.println("S3");
|
display.println("Z1");
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
display.setCursor(83,33);
|
display.setCursor(83,33);
|
||||||
display.println("S4");
|
display.println("Z2");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3681,7 +3789,30 @@ void plotDeglitch(int color){
|
||||||
display.println("OFF");
|
display.println("OFF");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void drawSubPinkyKey(){
|
||||||
|
display.fillRect(63,11,64,52,BLACK);
|
||||||
|
display.drawRect(63,11,64,52,WHITE);
|
||||||
|
display.setTextColor(WHITE);
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.setCursor(68,15);
|
||||||
|
display.println("PINKY KEY");
|
||||||
|
plotPinkyKey(WHITE);
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void plotPinkyKey(int color){
|
||||||
|
display.setTextColor(color);
|
||||||
|
display.setTextSize(2);
|
||||||
|
display.setCursor(79,33);
|
||||||
|
if (pinkySetting < 12){
|
||||||
|
display.println(pinkySetting - 12);
|
||||||
|
} else if (pinkySetting == PBD) {
|
||||||
|
display.println("PBD");
|
||||||
|
} else {
|
||||||
|
display.print("+");
|
||||||
|
display.println(pinkySetting - 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
void drawSubVelSmpDl(){
|
void drawSubVelSmpDl(){
|
||||||
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);
|
||||||
|
@ -3775,7 +3906,7 @@ void drawSetupCtMenuScreen(){
|
||||||
display.setCursor(0,48);
|
display.setCursor(0,48);
|
||||||
display.println("DEGLITCH");
|
display.println("DEGLITCH");
|
||||||
display.setCursor(0,57);
|
display.setCursor(0,57);
|
||||||
display.println("");
|
display.println("PINKY KEY");
|
||||||
|
|
||||||
display.display();
|
display.display();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue