diff --git a/NuEVI/NuEVI.ino b/NuEVI/NuEVI.ino index 204a63f..e500075 100644 --- a/NuEVI/NuEVI.ino +++ b/NuEVI/NuEVI.ino @@ -64,6 +64,8 @@ unsigned short pitchbMaxVal;// = 2400; unsigned short extracThrVal;// = 1200; unsigned short extracMaxVal;// = 2400; unsigned short ctouchThrVal;// = 120; +unsigned short leverThrVal; +unsigned short leverMaxVal; unsigned short transpose; unsigned short MIDIchannel; unsigned short breathCC; // OFF:MW:BR:VL:EX:MW+:BR+:VL+:EX+:CF @@ -72,6 +74,7 @@ unsigned short breathCC2Rise; // 1X:2X:3X:4X:5X unsigned short breathAT; unsigned short velocity; unsigned short portamento;// switching on cc65? just cc5 enabled? SW:ON:OFF +unsigned short portLimit; // 1-127 unsigned short PBdepth; // OFF:1-12 divider unsigned short extraCT; // OFF:MW:FP:CF:SP unsigned short vibrato; // OFF:1-9 @@ -157,6 +160,7 @@ unsigned long lastDeglitchTime = 0; // The last time the fingering was c unsigned long ccSendTime = 0L; // The last time we sent CC values unsigned long ccSendTime2 = 0L; // The last time we sent CC values 2 (slower) unsigned long ccSendTime3 = 0L; // The last time we sent CC values 3 (and slower) +unsigned long lvlTime = 0L; unsigned long ccBreathSendTime = 0L; // The last time we sent breath CC values unsigned long breath_on_time = 0L; // Time when breath sensor value went over the ON threshold unsigned long currentTime; @@ -194,9 +198,9 @@ int breathCalZero; int leverPortZero; #if defined(NURAD) -int leverPortThr = 50; +int leverPortThr = 70; #else -int leverPortThr = 50; +int leverPortThr = 70; #endif int leverPortRead; @@ -909,33 +913,45 @@ void loop() { subOctaveDouble = 0; } if ((pinkySetting == LVL) || (pinkySetting == LVLP)){ - if (pinkyKey){ + if (pinkyKey && K7){ ledMeter(levelVal); if (K6 && (levelVal < 127)){ - levelVal++; - if (levelCC) midiSendControlChange(levelCC, levelVal); - else midiSendAfterTouch(levelVal); + if (currentTime - lvlTime > (LVL_TIMER_INTERVAL)){ + levelVal++; + if (levelCC) midiSendControlChange(levelCC, levelVal); + else midiSendAfterTouch(levelVal); + lvlTime = currentTime; + } } else if (K5 && (levelVal > 0)){ - levelVal--; - if (levelCC) midiSendControlChange(levelCC, levelVal); - else midiSendAfterTouch(levelVal); + if (currentTime - lvlTime > (LVL_TIMER_INTERVAL)){ + levelVal--; + if (levelCC) midiSendControlChange(levelCC, levelVal); + else midiSendAfterTouch(levelVal); + lvlTime = currentTime; + } } - } else if (lastPinkyKey){ + } else if (!pinkyKey && lastPinkyKey){ writeSetting(LEVEL_VAL_ADDR,levelVal); } lastPinkyKey = pinkyKey; } else if (pinkySetting == GLD){ - if (pinkyKey){ - ledMeter(levelVal); - if (K6 && (levelVal < 127)){ - levelVal++; - midiSendControlChange(CCN_Port, levelVal); - } else if (K5 && (levelVal > 0)){ - levelVal--; - midiSendControlChange(CCN_Port, levelVal); + if (pinkyKey && K7){ + ledMeter(portLimit); + if (K6 && (portLimit < 127)){ + if (currentTime - lvlTime > (LVL_TIMER_INTERVAL)){ + portLimit++; + if (portamento && (portamento != 5)) midiSendControlChange(CCN_Port, portLimit); + lvlTime = currentTime; + } + } else if (K5 && (portLimit > 0)){ + if (currentTime - lvlTime > (LVL_TIMER_INTERVAL)){ + portLimit--; + if (portamento && (portamento != 5)) midiSendControlChange(CCN_Port, portLimit); + lvlTime = currentTime; + } } - } else if (lastPinkyKey){ - writeSetting(LEVEL_VAL_ADDR,levelVal); + } else if (!pinkyKey && lastPinkyKey){ + writeSetting(PORTLIMIT_ADDR,portLimit); } lastPinkyKey = pinkyKey; } @@ -1283,6 +1299,7 @@ void loop() { } if (!parallelChord && !subOctaveDouble && !rotatorOn) { // mono playing, send old note off after new note on + delayMicroseconds(2000); //delay for midi recording fix midiSendNoteOff(activeNote); // send Note Off message } @@ -1317,7 +1334,7 @@ void loop() { if (currentTime - ccSendTime3 > CC_INTERVAL3) { if (gateOpenEnable || gateOpen) doorKnobCheck(); battCheck(); - if (((pinkySetting == LVL) || (pinkySetting == LVLP) || (pinkySetting == GLD)) && pinkyKey && (mainState == NOTE_OFF)){ + if (((pinkySetting == LVL) || (pinkySetting == LVLP) || (pinkySetting == GLD)) && pinkyKey && K7 && (mainState == NOTE_OFF)){ // show LVL indication } else updateSensorLEDs(); ccSendTime3 = currentTime; @@ -1768,7 +1785,7 @@ void portamento_() { biteSensor = touchRead(bitePin); // get sensor data, do some smoothing - SENSOR PIN 17 - PCB PINS LABELED "BITE" (GND left, sensor pin right) } if (pinkySetting == GLD){ - if (pinkyKey){ + if (portamento && pinkyKey){ if (!portIsOn) { portOn(); } @@ -1789,7 +1806,7 @@ void portamento_() { } else if (1 == vibControl) { // Portamento is switched to lever control leverPortRead = touchRead(vibratoPin); - if (portamento && (leverPortRead <= (leverPortZero-leverPortThr))) { // if we are enabled and over the threshold, send portamento + if (portamento && ((3000-leverPortRead) >= leverThrVal)) { // if we are enabled and over the threshold, send portamento if (!portIsOn) { portOn(); } @@ -1807,7 +1824,7 @@ void portamento_() { //*********************************************************** void portOn() { - if (portamento == 2) { // if portamento midi switching is enabled + if ((portamento == 2) || (portamento == 5)) { // if portamento midi switching is enabled midiSendControlChange(CCN_PortOnOff, 127); } else if (portamento == 3) { // if portamento midi switching is enabled - SE02 OFF/LIN midiSendControlChange(CCN_PortSE02, 64); @@ -1822,12 +1839,12 @@ void portOn() { void port() { int portCC; if (pinkySetting == GLD){ - portCC = levelVal; - } else if (1 != vibControl) - portCC = map(constrain(biteSensor, portamThrVal, portamMaxVal), portamThrVal, portamMaxVal, 0, 127); - else - portCC = constrain((leverPortZero-leverPortThr-leverPortRead),0,127); - if (portCC != oldport) { + portCC = portLimit; + } else if (1 == vibControl) + portCC = map(constrain((3000-leverPortRead), leverThrVal, leverMaxVal), leverThrVal, leverMaxVal, 0, portLimit); + else + portCC = map(constrain(biteSensor, portamThrVal, portamMaxVal), portamThrVal, portamMaxVal, 0, portLimit); + if ((portamento != 5) && (portCC != oldport)) { // portamento setting 5 is switch only, do not transmit glide rate midiSendControlChange(CCN_Port, portCC); } oldport = portCC; @@ -1836,10 +1853,10 @@ void port() { //*********************************************************** void portOff() { - if (oldport != 0) { //did a zero get sent? if not, then send one + if ((portamento != 5) && (oldport != 0)) { //did a zero get sent? if not, then send one (unless portamento is switch only) midiSendControlChange(CCN_Port, 0); } - if (portamento == 2) { // if portamento midi switching is enabled + if ((portamento == 2) || (portamento == 5)) { // if portamento midi switching is enabled midiSendControlChange(CCN_PortOnOff, 0); } else if (portamento == 3) { // if portamento midi switching is enabled - SE02 OFF/LIN midiSendControlChange(CCN_PortSE02, 0); @@ -1876,6 +1893,12 @@ void autoCal() { pitchbMaxVal = constrain(pitchbThrVal+800, pitchbLoLimit, pitchbHiLimit); writeSetting(PITCHB_THR_ADDR, pitchbThrVal); writeSetting(PITCHB_MAX_ADDR, pitchbMaxVal); + // Lever + calRead = 3000-touchRead(vibratoPin); + leverThrVal = constrain(calRead+70, leverLoLimit, leverHiLimit); + leverMaxVal = constrain(calRead+150, leverLoLimit, leverHiLimit); + writeSetting(LEVER_THR_ADDR, leverThrVal); + writeSetting(LEVER_MAX_ADDR, leverMaxVal); #if defined(NURAD) // NuRAD sensor calibration // Pressure sensor calRead = analogRead(bitePressurePin); diff --git a/NuEVI/adjustmenu.cpp b/NuEVI/adjustmenu.cpp index 02d50d7..c4bd7e7 100644 --- a/NuEVI/adjustmenu.cpp +++ b/NuEVI/adjustmenu.cpp @@ -113,12 +113,29 @@ const AdjustMenuEntry ctouchAdjustMenu = { ctouchThrSave }; + +static void leverSave(const AdjustMenuEntry& e) { + writeSetting(LEVER_THR_ADDR, *e.entries[0].value); + writeSetting(LEVER_MAX_ADDR, *e.entries[1].value); +} + +const AdjustMenuEntry leverAdjustMenu = { + "THUMB LEVER", + { + { &leverThrVal, leverLoLimit, leverHiLimit }, + { &leverMaxVal, leverLoLimit, leverHiLimit } + }, + leverSave +}; + + const AdjustMenuEntry* adjustMenuEntries[] = { &breathAdjustMenu, &portamentoAdjustMenu, &pitchBendAdjustMenu, &extraSensorAdjustMenu, &ctouchAdjustMenu, + &leverAdjustMenu, }; static const int numAdjustEntries = ARR_LEN(adjustMenuEntries); @@ -277,6 +294,12 @@ void plotSensorPixels(){ redraw = 1; } #endif + else if(adjustOption == 5) { + int pos = map(constrain(3000-touchRead(vibratoPin), leverLoLimit, leverHiLimit), leverLoLimit, leverHiLimit, 28, 118); + redraw = updateSensorPixel(pos, -1); + } + + if (redraw){ display.display(); } diff --git a/NuEVI/config.h b/NuEVI/config.h index 703b441..d390f45 100644 --- a/NuEVI/config.h +++ b/NuEVI/config.h @@ -5,7 +5,7 @@ // Compile options, comment/uncomment to change -#define FIRMWARE_VERSION "1.5b1" // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<< +#define FIRMWARE_VERSION "1.5b2" // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<< #define ON_Delay 20 // Set Delay after ON threshold before velocity is checked (wait for tounging peak) #define CCN_Port 5 // Controller number for portamento level @@ -19,6 +19,7 @@ #define CC_INTERVAL 13 #define CC_INTERVAL2 19 #define CC_INTERVAL3 37 +#define LVL_TIMER_INTERVAL 15 #define CVPORTATUNE 2 @@ -34,6 +35,8 @@ #define ctouchHiLimit 350 #define ttouchLoLimit 50 #define ttouchHiLimit 1900 +#define leverLoLimit 1400 +#define leverHiLimit 2000 #define MIN_LED_BRIGHTNESS 5 // lowest PWM value that still is visible diff --git a/NuEVI/globals.h b/NuEVI/globals.h index 53747dd..e77bb24 100644 --- a/NuEVI/globals.h +++ b/NuEVI/globals.h @@ -65,6 +65,8 @@ extern unsigned short pitchbMaxVal; extern unsigned short extracThrVal; extern unsigned short extracMaxVal; extern unsigned short ctouchThrVal; +extern unsigned short leverThrVal; +extern unsigned short leverMaxVal; extern unsigned short transpose; extern unsigned short MIDIchannel; extern unsigned short breathCC; // OFF:MW:BR:VL:EX:MW+:BR+:VL+:EX+:CF:UNO @@ -73,6 +75,7 @@ extern unsigned short breathCC2Rise; // 1X:2X:3X:4X:5X extern unsigned short breathAT; extern unsigned short velocity; extern unsigned short portamento;// switching on cc65? just cc5 enabled? SW:ON:OFF +extern unsigned short portLimit; // 1-127 extern unsigned short PBdepth; // OFF:1-12 divider extern unsigned short extraCT; // OFF:MW:FP:CF:SP extern unsigned short vibrato; // OFF:1-9 @@ -128,6 +131,8 @@ extern uint16_t dacMode; extern int touch_Thr; +extern int leverPortZero; + extern unsigned long cursorBlinkTime; // the last time the cursor was toggled extern byte activePatch; diff --git a/NuEVI/menu.cpp b/NuEVI/menu.cpp index 7f6b6a7..c90a432 100644 --- a/NuEVI/menu.cpp +++ b/NuEVI/menu.cpp @@ -413,7 +413,7 @@ static void mainTitleGetStr(char* out) { case 2: vLowLimit = LIP_BAT_LOW; } - if (vMeterReading < vLowLimit) { //2300 alkaline, 2250 lipo, 2200 nimh + if (vMeterReading <= vLowLimit) { //2300 alkaline, 2250 lipo, 2200 nimh memcpy(splice2, "LOW ", 4); } else { int voltage = map(vMeterReading,2200,3060,36,50); @@ -1269,15 +1269,27 @@ const MenuPage breathMenuPage = { //*********************************************************** // Control menu const MenuEntrySub portMenu = { - MenuType::ESub, "PORT/GLD", "PORT/GLD", &portamento, 0, 4, MenuEntryFlags::EMenuEntryWrap, + MenuType::ESub, "GLIDE CTL", "PORT/GLD", &portamento, 0, 5, MenuEntryFlags::EMenuEntryWrap, [](SubMenuRef __unused,char* out, const char ** __unused unit) { - const char* labs[] = { "OFF", "ON", "SW", "SEL", "SEE" }; + const char* labs[] = { "OFF", "ON", "SW", "SEL", "SEE", "SWO" }; strncpy(out, labs[portamento], 4); }, [](SubMenuRef __unused sub) { writeSetting(PORTAM_ADDR,portamento); } , nullptr }; + +const MenuEntrySub portLimitMenu = { + MenuType::ESub, "GLIDE LMT", "MAX LEVEL", &portLimit, 1, 127, MenuEntryFlags::EMenuEntryWrap, + [](SubMenuRef __unused, char* out, const char** __unused unit) { + numToString(portLimit, out); + }, +[](const SubMenuRef & __unused sub) { writeSetting(PORTLIMIT_ADDR,portLimit); } + , nullptr +}; + + + const MenuEntrySub pitchBendMenu = { MenuType::ESub, "PITCHBEND", "PITCHBEND", &PBdepth, 0, 12, MenuEntryFlags::ENone, [](SubMenuRef __unused, char* out, const char** __unused unit) { @@ -1429,6 +1441,7 @@ const MenuEntrySub lpinky3Menu = { #if defined(NURAD) const MenuEntry* controlMenuEntries[] = { (MenuEntry*)&portMenu, + (MenuEntry*)&portLimitMenu, (MenuEntry*)&extraMenu, (MenuEntry*)&extraCC2Menu, (MenuEntry*)&harmonicsMenu, @@ -1444,6 +1457,7 @@ const MenuEntry* controlMenuEntries[] = { #else const MenuEntry* controlMenuEntries[] = { (MenuEntry*)&portMenu, + (MenuEntry*)&portLimitMenu, (MenuEntry*)&extraMenu, (MenuEntry*)&extraCC2Menu, (MenuEntry*)&harmonicsMenu, diff --git a/NuEVI/settings.cpp b/NuEVI/settings.cpp index 16c7251..2acad39 100644 --- a/NuEVI/settings.cpp +++ b/NuEVI/settings.cpp @@ -151,6 +151,12 @@ void readEEPROM(const bool factoryReset) { writeSetting(BRINTERV_ADDR, BRINTERV_FACTORY); writeSetting(OTFKEY_ADDR, OTFKEY_FACTORY); } + + if(settingsVersion < 40) { + writeSetting(PORTLIMIT_ADDR, PORTLIMIT_FACTORY); + writeSetting(LEVER_THR_ADDR, LEVER_THR_FACTORY); + writeSetting(LEVER_MAX_ADDR, LEVER_MAX_FACTORY); + } writeSetting(VERSION_ADDR, EEPROM_VERSION); @@ -168,7 +174,7 @@ void readEEPROM(const bool factoryReset) { breathCC = readSettingBounded(BREATH_CC_ADDR, 0, 10, BREATH_CC_FACTORY); breathAT = readSettingBounded(BREATH_AT_ADDR, 0, 1, BREATH_AT_FACTORY); velocity = readSettingBounded(VELOCITY_ADDR, 0, 127, VELOCITY_FACTORY); - portamento = readSettingBounded(PORTAM_ADDR, 0, 4, PORTAM_FACTORY); + portamento = readSettingBounded(PORTAM_ADDR, 0, 5, PORTAM_FACTORY); PBdepth = readSettingBounded(PB_ADDR, 0, 12, PB_FACTORY); extraCT = readSettingBounded(EXTRA_ADDR, 0, 4, EXTRA_FACTORY); vibrato = readSettingBounded(VIBRATO_ADDR, 0, 9, VIBRATO_FACTORY); @@ -237,6 +243,9 @@ void readEEPROM(const bool factoryReset) { rotationsc[3] = readSettingBounded(ROTC4_ADDR, 0, 48, ROTC4_FACTORY); otfKey = readSettingBounded(OTFKEY_ADDR, 0, 1, OTFKEY_FACTORY); breathInterval = readSettingBounded(BRINTERV_ADDR, 3, 15, BRINTERV_FACTORY); + portLimit = readSettingBounded(PORTLIMIT_ADDR, 1, 127, PORTLIMIT_FACTORY); + leverThrVal = readSettingBounded(LEVER_THR_ADDR, leverLoLimit, leverHiLimit, LEVER_THR_FACTORY); + leverMaxVal = readSettingBounded(LEVER_MAX_ADDR, leverLoLimit, leverHiLimit, LEVER_MAX_FACTORY); //Flags stored in bit field fastBoot = (dipSwBits & (1<