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:
Johan Berglund 2018-03-31 18:51:16 +02:00
parent eda4c12d49
commit f7b1df76d9

179
NuEVI.ino
View file

@ -4,6 +4,7 @@
#include <EEPROM.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Filters.h>
/*
NAME: NuEVI
@ -47,6 +48,9 @@ PROGRAMME FUNCTION: EVI Wind Controller using the Freescale MP3V5004GP breath
#define vMeterPin A11
//#define RTR 13
#define PBD 12
#if defined(REVB)
// 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 VEL_SMP_DL_ADDR 46
#define VEL_BIAS_ADDR 48
#define PINKY_KEY_ADDR 50
//"factory" values for settings
#define VERSION 23
#define VERSION 24
#define BREATH_THR_FACTORY 1400
#define BREATH_MAX_FACTORY 4000
#define PORTAM_THR_FACTORY 2200
@ -197,7 +202,7 @@ PROGRAMME FUNCTION: EVI Wind Controller using the Freescale MP3V5004GP breath
#define PORTAM_FACTORY 2 // 0 - OFF, 1 - ON, 2 - SW
#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 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 PATCH_FACTORY 1 // MIDI program change 1-128
#define OCTAVE_FACTORY 3 // 3 is 0 octave change
@ -205,6 +210,7 @@ PROGRAMME FUNCTION: EVI Wind Controller using the Freescale MP3V5004GP breath
#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_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
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 PBdepth; // OFF:1-12 divider
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 patch; // 1-128
unsigned short octave;
unsigned short curve;
unsigned short velSmpDl; // 0-30 ms
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 breathHiLimit = 4095;
@ -355,8 +362,10 @@ byte subPB = 0;
byte subExtra = 0;
byte subVibrato = 0;
byte subDeglitch = 0;
byte subPinky = 0;
byte subVelSmpDl = 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)
@ -401,6 +410,7 @@ byte doPatchUpdate=0;
int breathLevel=0; // breath level (smoothed) not mapped to CC value
int oldbreath=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 lastPressure;
@ -423,12 +433,14 @@ int pbDn=0;
int lastPbUp=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 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 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 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};
@ -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 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 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 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 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 oldvibRead=0;
@ -519,6 +534,8 @@ void setup() {
writeSetting(BREATHCURVE_ADDR,BREATHCURVE_FACTORY);
writeSetting(VEL_SMP_DL_ADDR,VEL_SMP_DL_FACTORY);
writeSetting(VEL_BIAS_ADDR,VEL_BIAS_FACTORY);
writeSetting(PINKY_KEY_ADDR,PINKY_KEY_FACTORY);
//writeSetting(QTRANSP_ADDR,QTRANSP_FACTORY);
}
// read settings from EEPROM
breathThrVal = readSetting(BREATH_THR_ADDR);
@ -545,6 +562,7 @@ void setup() {
curve = readSetting(BREATHCURVE_ADDR);
velSmpDl = readSetting(VEL_SMP_DL_ADDR);
velBias = readSetting(VEL_BIAS_ADDR);
pinkySetting = readSetting(PINKY_KEY_ADDR);
activePatch = patch;
@ -559,6 +577,7 @@ void setup() {
while (1); // Touch sensor initialization failed - stop doing stuff
}
// 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)
// init done
@ -591,7 +610,7 @@ void setup() {
display.setTextColor(WHITE);
display.setTextSize(1);
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();
delay(2000);
@ -614,7 +633,14 @@ void setup() {
//_______________________________________________________________________________________________ MAIN LOOP
void loop() {
pressureSensor = analogRead(A0); // Get the pressure sensor reading from analog pin A0, input from sensor MP3V5004GP
mainLoop();
}
void mainLoop() {
FilterOnePole breathFilter( LOWPASS, filterFreq ); // create a one pole (RC) lowpass filter
while (1){
breathFilter.input(analogRead(A0));
pressureSensor = breathFilter.output(); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP
if (mainState == NOTE_OFF) {
if (activeMIDIchannel != MIDIchannel) activeMIDIchannel = MIDIchannel; // only switch channel if no active note
@ -653,15 +679,20 @@ void loop() {
} else parallelChord = 0;
}
if (K1) subOctaveDouble = !subOctaveDouble;
if (!K1 && !K4 && !K5){
slurSustain = 0;
parallelChord = 0;
subOctaveDouble = 0;
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) {
if ((millis() - breath_on_time > velSmpDl) || (0 == 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
@ -831,6 +862,7 @@ void loop() {
//do menu stuff
menu();
}
}
//_______________________________________________________________________________________________ FUNCTIONS
@ -905,12 +937,12 @@ unsigned int breathCurve(unsigned int inputVal){
return multiMap(inputVal,curveIn,curveS2,17);
break;
case 11:
// S3
return multiMap(inputVal,curveIn,curveS3,17);
// Z1
return multiMap(inputVal,curveIn,curveZ1,17);
break;
case 12:
// S4
return multiMap(inputVal,curveIn,curveS4,17);
// Z2
return multiMap(inputVal,curveIn,curveZ2,17);
break;
}
}
@ -1017,8 +1049,9 @@ void statusLEDs() {
void breath(){
int breathCCval,breathCCvalFine;
unsigned int breathCCvalHires;
breathLevel = breathLevel*0.6+pressureSensor*0.4; // smoothing of breathLevel value
//breathCCval = map(constrain(breathLevel,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,127);
breathLevel = pressureSensor;
//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));
breathCCval = (breathCCvalHires >>7) & 0x007F;
breathCCvalFine = breathCCvalHires & 0x007F;
@ -1056,7 +1089,7 @@ void pitch_bend(){
byte vibratoMoved = 0;
pbUp = touchRead(pbUpPin); // SENSOR PIN 23 - PCB PIN "Pu"
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
if (PBdepth){
calculatedPBdepth = pbDepthList[PBdepth];
@ -1220,7 +1253,7 @@ void portOff(){
//***********************************************************
void readSwitches(){
int qTransp;
// Read touch pads (MPR121) and put value in variables
int touchValue[12];
for (byte i=0; i<12; i++){
@ -1245,8 +1278,20 @@ void readSwitches(){
K6=(touchValue[K6Pin] < 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
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;
subVibrato = 0;
subDeglitch = 0;
subPinky = 0;
subVelSmpDl = 0;
subVelBias = 0;
}
@ -1360,6 +1408,9 @@ void menu() {
state = MAIN_MENU;
stateFirstRun = 1;
break;
case 15:
//all keys depressed, reboot to programming mode
_reboot_Teensyduino_();
}
}
} else if (state == PATCH_VIEW){
@ -2799,7 +2850,7 @@ void menu() {
break;
case 4:
// up
if (vibrato < 6){
if (vibrato < 9){
plotVibrato(BLACK);
vibrato++;
plotVibrato(WHITE);
@ -2868,6 +2919,56 @@ void menu() {
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 {
if ((millis() - cursorBlinkTime) > cursorBlinkInterval) {
if (cursorNow == WHITE) cursorNow = BLACK; else cursorNow = WHITE;
@ -2880,7 +2981,7 @@ void menu() {
switch (deumButtonState){
case 1:
// down
if (setupCtMenuCursor < 5){
if (setupCtMenuCursor < 6){
drawMenuCursor(setupCtMenuCursor, BLACK);
setupCtMenuCursor++;
drawMenuCursor(setupCtMenuCursor, WHITE);
@ -3037,6 +3138,13 @@ void selectSetupCtMenu(){
display.display();
cursorBlinkTime = millis();
drawSubDeglitch();
break;
case 6:
subPinky = 1;
drawMenuCursor(setupCtMenuCursor, WHITE);
display.display();
cursorBlinkTime = millis();
drawSubPinkyKey();
}
}
void drawBreathScreen(){
@ -3537,11 +3645,11 @@ void plotCurve(int color){
break;
case 11:
display.setCursor(83,33);
display.println("S3");
display.println("Z1");
break;
case 12:
display.setCursor(83,33);
display.println("S4");
display.println("Z2");
break;
}
}
@ -3681,7 +3789,30 @@ void plotDeglitch(int color){
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(){
display.fillRect(63,11,64,52,BLACK);
display.drawRect(63,11,64,52,WHITE);
@ -3775,7 +3906,7 @@ void drawSetupCtMenuScreen(){
display.setCursor(0,48);
display.println("DEGLITCH");
display.setCursor(0,57);
display.println("");
display.println("PINKY KEY");
display.display();
}