diff --git a/NuEVI/NuEVI.ino b/NuEVI/NuEVI.ino index c2ce486..4227d67 100644 --- a/NuEVI/NuEVI.ino +++ b/NuEVI/NuEVI.ino @@ -114,6 +114,10 @@ unsigned short vibDirection = DNWD; //direction of first vibrato wave UPWD or DN unsigned short vibSensBite = 2; // vibrato sensitivity (bite) unsigned short vibSquelchBite = 12; //vibrato signal squelch (bite) unsigned short vibControl = 0; +unsigned short biteControl = 0; // OFF, VIB, GLD, CC +unsigned short leverControl = 0; // OFF, VIB, GLD, CC +unsigned short biteCC = 0; // 0 - 127 +unsigned short leverCC = 0; // 0 -127 unsigned short fastPatch[7] = {0,0,0,0,0,0,0}; @@ -209,9 +213,13 @@ int leverPortRead; 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 biteIsOn=0; // keep track and make sure we send CC with 0 value when off threshold +byte leverIsOn=0; // keep track and make sure we send CC with 0 value when off threshold int oldport=0; int lastBite=0; byte biteJumper=0; +int oldbitecc=0; +int oldlevercc=0; int cvPitch; int targetPitch; @@ -542,6 +550,7 @@ FilterOnePole breathFilter; IntervalTimer cvTimer; bool configManagementMode = false; +bool i2cScan = false; //_______________________________________________________________________________________________ SETUP @@ -563,6 +572,8 @@ void cvUpdate(){ #endif } + + void setup() { analogReadResolution(12); // set resolution of ADCs to 12 bit @@ -592,7 +603,8 @@ void setup() { bool factoryReset = !digitalRead(ePin) && !digitalRead(mPin); configManagementMode = !factoryReset && !digitalRead(uPin) && !digitalRead(dPin); - + i2cScan = !factoryReset && !digitalRead(mPin); + initDisplay(); //Start up display and show logo //If going into config management mode, stop here before we even touch the EEPROM. @@ -601,6 +613,14 @@ void setup() { return; } + #if defined(I2CSCANNER) + if(i2cScan){ + delay(2000); + i2cScanDisplay(); + } + #endif + + //Read eeprom data into global vars readEEPROM(factoryReset); @@ -1335,6 +1355,8 @@ void loop() { // deal with Pitch Bend, Modulation, etc. pitch_bend(); extraController(); + biteCC_(); + leverCC_(); ccSendTime = currentTime; } if (currentTime - ccSendTime2 > CC_INTERVAL2) { @@ -1507,7 +1529,7 @@ void pitch_bend() { vibMax = vibMaxList[vibSens - 1]; vibMaxBite = vibMaxBiteList[vibSensBite - 1]; - if (vibControl){ //bite vibrato + if (1 == biteControl){ //bite vibrato if (biteJumper){ //PBITE (if pulled low with jumper, or NuRAD compile, use pressure sensor instead of capacitive bite sensor) vibReadBite = analogRead(bitePressurePin); // alternative kind bite sensor (air pressure tube and sensor) PBITE } else { @@ -1529,7 +1551,7 @@ void pitch_bend() { vibSignal = vibSignal / 2; } } - if (vibControl != 1) { //lever vibrato + if (1 == leverControl) { //lever vibrato vibRead = touchRead(vibratoPin); // SENSOR PIN 15 - built in var cap if (vibRead < vibThr) { if (UPWD == vibDirection) { @@ -1788,7 +1810,8 @@ void extraController() { //*********************************************************** -void portamento_() { +/* +void portamento_() { //old version if (biteJumper) { //PBITE (if pulled low with jumper, use pressure sensor instead of capacitive bite sensor) biteSensor=analogRead(bitePressurePin); // alternative kind bite sensor (air pressure tube and sensor) PBITE } else { @@ -1831,6 +1854,7 @@ void portamento_() { } } + //*********************************************************** void portOn() { @@ -1878,6 +1902,135 @@ void portOff() { } //*********************************************************** +*/ + + +void portamento_() { + int portSumCC = 0; + if (pinkySetting == GLD){ + if (portamento && pinkyKey){ + portSumCC += portLimit; + } + } + if (2 == biteControl) { + // Portamento is controlled with the bite sensor in the mouthpiece + if (biteJumper) { //PBITE (if pulled low with jumper or if on a NuRAD, use pressure sensor instead of capacitive bite sensor) + biteSensor=analogRead(bitePressurePin); // alternative kind bite sensor (air pressure tube and sensor) PBITE + } else { + 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 + portSumCC += map(constrain(biteSensor, portamThrVal, portamMaxVal), portamThrVal, portamMaxVal, 0, portLimit); + } + } + if (2 == leverControl) { + // Portamento is controlled with thumb lever + leverPortRead = touchRead(vibratoPin); + if (portamento && ((3000-leverPortRead) >= leverThrVal)) { // if we are enabled and over the threshold, send portamento + portSumCC += map(constrain((3000-leverPortRead), leverThrVal, leverMaxVal), leverThrVal, leverMaxVal, 0, portLimit); + } + } + portSumCC = constrain(portSumCC, 0, portLimit); // Total output glide rate limited to glide max setting + if (portSumCC) { // there is a portamento level, so go for it + if (!portIsOn) { + portOn(); + } + port(portSumCC); + }else if (portIsOn) { + portOff(); + } +} + +//*********************************************************** + +void portOn() { + 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); + } else if (portamento == 4) { // if portamento midi switching is enabled - SE02 OFF/EXP + midiSendControlChange(CCN_PortSE02, 127); + } + portIsOn = 1; +} + +//*********************************************************** + +void port(int portCC) { + if ((portamento != 5) && (portCC != oldport)) { // portamento setting 5 is switch only, do not transmit glide rate + midiSendControlChange(CCN_Port, portCC); + } + oldport = portCC; +} + +//*********************************************************** + +void portOff() { + 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) || (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); + } else if (portamento == 4) { // if portamento midi switching is enabled - SE02 OFF/EXP + midiSendControlChange(CCN_PortSE02, 0); + } + portIsOn = 0; + oldport = 0; +} + +//*********************************************************** + +void biteCC_() { + int biteCClevel = 0; + if (3 == biteControl){ + if (biteJumper) { //PBITE (if pulled low with jumper or if on a NuRAD, use pressure sensor instead of capacitive bite sensor) + biteSensor=analogRead(bitePressurePin); // alternative kind bite sensor (air pressure tube and sensor) PBITE + } else { + biteSensor = touchRead(bitePin); // get sensor data, do some smoothing - SENSOR PIN 17 - PCB PINS LABELED "BITE" (GND left, sensor pin right) + } + if (biteSensor >= portamThrVal) { // we are over the threshold, calculate CC value + biteCClevel = map(constrain(biteSensor, portamThrVal, portamMaxVal), portamThrVal, portamMaxVal, 0, 127); + } + if (biteCClevel) { // there is a bite CC level, so go for it + if (!biteIsOn) { + biteIsOn = 1; + } + if (biteCClevel != oldbitecc) { + midiSendControlChange(biteCC, biteCClevel); + } + oldbitecc = biteCClevel; + } else if (biteIsOn) { + midiSendControlChange(biteCC, 0); + biteIsOn = 0; + oldbitecc = 0; + } + } +} + +void leverCC_() { + int leverCClevel = 0; + if (3 == leverControl){ + leverPortRead = touchRead(vibratoPin); + if (((3000-leverPortRead) >= leverThrVal)) { // we are over the threshold, calculate CC value + leverCClevel = map(constrain((3000-leverPortRead), leverThrVal, leverMaxVal), leverThrVal, leverMaxVal, 0, 127); + } + if (leverCClevel) { // there is a lever CC level, so go for it + if (!leverIsOn) { + leverIsOn = 1; + } + if (leverCClevel != oldlevercc) { + midiSendControlChange(leverCC, leverCClevel); + } + oldlevercc = leverCClevel; + } else if (leverIsOn) { + midiSendControlChange(leverCC, 0); + leverIsOn = 0; + oldlevercc = 0; + } + } +} void autoCal() { int calRead; diff --git a/NuEVI/config.h b/NuEVI/config.h index 7b70176..bbc359e 100644 --- a/NuEVI/config.h +++ b/NuEVI/config.h @@ -5,7 +5,7 @@ // Compile options, comment/uncomment to change -#define FIRMWARE_VERSION "1.5b3" // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<< +#define FIRMWARE_VERSION "1.5b4" // 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 diff --git a/NuEVI/globals.h b/NuEVI/globals.h index ee7f5a5..673c5cd 100644 --- a/NuEVI/globals.h +++ b/NuEVI/globals.h @@ -18,7 +18,7 @@ #define NOTE_ON 3 -//Magic value where pinky button means "pitch bend" +//Magic values #define PBD 12 #define EC2 25 #define ECSW 26 @@ -41,7 +41,6 @@ #define MOD 13 - //Vibrato direction #define UPWD 1 #define DNWD 0 @@ -114,6 +113,10 @@ extern unsigned short hmzKey; // 0-11 (0 is C) extern unsigned short hmzLimit; // 2-5 extern unsigned short otfKey; //OFF:ON extern unsigned short breathInterval; // 3-15 +extern unsigned short biteControl; // OFF, VIB, GLD, CC +extern unsigned short leverControl; // OFF, VIB, GLD, CC +extern unsigned short biteCC; // 0 - 127 +extern unsigned short leverCC; // 0 -127 extern uint16_t gateOpenEnable; extern uint16_t specialKeyEnable; extern byte rotatorOn; diff --git a/NuEVI/hardware.h b/NuEVI/hardware.h index e777da1..9dac779 100644 --- a/NuEVI/hardware.h +++ b/NuEVI/hardware.h @@ -4,6 +4,8 @@ #define REVB //#define NURAD +#define I2CSCANNER + #if defined(NURAD) //NuRAD <<<<<<<<<<<<<<<<<<<<<<< // Pin definitions diff --git a/NuEVI/menu.cpp b/NuEVI/menu.cpp index cea21d1..99a3bd3 100644 --- a/NuEVI/menu.cpp +++ b/NuEVI/menu.cpp @@ -258,6 +258,40 @@ void showVersion() { display.display(); } +void i2cScanDisplay(){ + uint8_t target; // slave addr + byte error; + while(1){ + display.clearDisplay(); + display.setTextColor(WHITE); + display.setTextSize(1); + display.setCursor(0,0); + display.println("MPR121 board scan"); + display.display(); + for(target = 0x5A; target <= 0x5D; target++) // sweep addr + { + Wire.beginTransmission(target); // slave addr + error = Wire.endTransmission(); + delay(500); + display.print("Addr 0x"); + display.print(target,HEX); + if (error) + display.print(" N\n"); + else + display.print(" Y\n"); + display.display(); + } + delay(1000); + display.println(); + display.println("MENU to rescan"); + display.println("Power off to exit"); + display.display(); + while (digitalRead(mPin)){ + delay(100); + } + } +} + // Assumes dest points to a buffer of atleast 7 bytes. static const char* numToString(int16_t value, char* dest, bool plusSign = false) { char* ptr = dest; @@ -1294,8 +1328,47 @@ const MenuPage breathMenuPage = { //*********************************************************** // Control menu + +const MenuEntrySub biteCtlMenu = { + MenuType::ESub, "BITE CTL", "BITE DEST", &biteControl, 0, 3, MenuEntryFlags::EMenuEntryWrap, + [](SubMenuRef __unused,char* out, const char ** __unused unit) { + const char* labs[] = { "OFF", "VIB", "GLD", "CC" }; + strncpy(out, labs[biteControl], 4); + }, + [](SubMenuRef __unused sub) { writeSetting(BITECTL_ADDR,biteControl); } + , nullptr +}; + +const MenuEntrySub biteCCMenu = { + MenuType::ESub, "BITE CC", "CC NUMBER", &biteCC, 0, 127, MenuEntryFlags::EMenuEntryWrap, + [](SubMenuRef __unused, char* out, const char** __unused unit) { + numToString(biteCC, out); + }, +[](const MenuEntrySub & __unused sub) { writeSetting(BITECC_ADDR,biteCC); } + , nullptr +}; + +const MenuEntrySub leverCtlMenu = { + MenuType::ESub, "LEVER CTL", "LEVER DEST", &leverControl, 0, 3, MenuEntryFlags::EMenuEntryWrap, + [](SubMenuRef __unused,char* out, const char ** __unused unit) { + const char* labs[] = { "OFF", "VIB", "GLD", "CC" }; + strncpy(out, labs[leverControl], 4); + }, + [](SubMenuRef __unused sub) { writeSetting(LEVERCTL_ADDR,leverControl); } + , nullptr +}; + +const MenuEntrySub leverCCMenu = { + MenuType::ESub, "LEVER CC", "CC NUMBER", &leverCC, 0, 127, MenuEntryFlags::EMenuEntryWrap, + [](SubMenuRef __unused, char* out, const char** __unused unit) { + numToString(leverCC, out); + }, +[](const MenuEntrySub & __unused sub) { writeSetting(LEVERCC_ADDR,leverCC); } + , nullptr +}; + const MenuEntrySub portMenu = { - MenuType::ESub, "GLIDE CTL", "PORT/GLD", &portamento, 0, 5, MenuEntryFlags::EMenuEntryWrap, + MenuType::ESub, "GLIDE MOD", "PORT/GLD", &portamento, 0, 5, MenuEntryFlags::EMenuEntryWrap, [](SubMenuRef __unused,char* out, const char ** __unused unit) { const char* labs[] = { "OFF", "ON", "SW", "SEL", "SEE", "SWO" }; strncpy(out, labs[portamento], 4); @@ -1451,7 +1524,7 @@ const MenuEntrySub fingeringMenu = { const MenuEntrySub lpinky3Menu = { - MenuType::ESub, "EXTRA PKEY", "EXTRA PKEY", &lpinky3, 0, 25, MenuEntryFlags::ENone, + MenuType::ESub, "EXTRA KEY", "EXTRA PKEY", &lpinky3, 0, 25, MenuEntryFlags::ENone, [](SubMenuRef __unused,char* textBuffer, const char** __unused unit) { if (lpinky3 == 0) strncpy(textBuffer, "OFF", 4); @@ -1466,13 +1539,17 @@ const MenuEntrySub lpinky3Menu = { #if defined(NURAD) const MenuEntry* controlMenuEntries[] = { + (MenuEntry*)&biteCtlMenu, + (MenuEntry*)&biteCCMenu, + (MenuEntry*)&leverCtlMenu, + (MenuEntry*)&leverCCMenu, (MenuEntry*)&portMenu, (MenuEntry*)&portLimitMenu, + (MenuEntry*)&vibratoSubMenu, (MenuEntry*)&extraMenu, (MenuEntry*)&extraCC2Menu, (MenuEntry*)&harmonicsMenu, (MenuEntry*)&harmSelectMenu, - (MenuEntry*)&vibratoSubMenu, (MenuEntry*)°litchMenu, (MenuEntry*)&pinkyMenu, (MenuEntry*)&lvlCtrlCCMenu, @@ -1482,13 +1559,17 @@ const MenuEntry* controlMenuEntries[] = { }; #else const MenuEntry* controlMenuEntries[] = { + (MenuEntry*)&biteCtlMenu, + (MenuEntry*)&biteCCMenu, + (MenuEntry*)&leverCtlMenu, + (MenuEntry*)&leverCCMenu, (MenuEntry*)&portMenu, (MenuEntry*)&portLimitMenu, + (MenuEntry*)&vibratoSubMenu, (MenuEntry*)&extraMenu, (MenuEntry*)&extraCC2Menu, (MenuEntry*)&harmonicsMenu, (MenuEntry*)&harmSelectMenu, - (MenuEntry*)&vibratoSubMenu, (MenuEntry*)°litchMenu, (MenuEntry*)&pinkyMenu, (MenuEntry*)&lvlCtrlCCMenu, @@ -1600,7 +1681,7 @@ const MenuEntrySub vibDirMenu = { }; const MenuEntry* vibratorMenuEntries[] = { - (MenuEntry*)&vibControlMenu, + //(MenuEntry*)&vibControlMenu, (MenuEntry*)&vibDepthMenu, (MenuEntry*)&vibRetnMenu, (MenuEntry*)&vibDirMenu, diff --git a/NuEVI/menu.h b/NuEVI/menu.h old mode 100755 new mode 100644 index 8fd4016..e65cc3e --- a/NuEVI/menu.h +++ b/NuEVI/menu.h @@ -41,6 +41,7 @@ void initDisplay(); void showVersion(); void menu(); void drawSensorPixels(); +void i2cScanDisplay(); int updateAdjustMenu(uint32_t timeNow, KeyState &input, bool firstRun, bool drawSensor); bool adjustPageUpdate(KeyState &input, uint32_t timeNow); diff --git a/NuEVI/settings.cpp b/NuEVI/settings.cpp index 06453f0..407ce9d 100644 --- a/NuEVI/settings.cpp +++ b/NuEVI/settings.cpp @@ -162,6 +162,13 @@ void readEEPROM(const bool factoryReset) { writeSetting(BRHARMSET_ADDR, BRHARMSET_FACTORY); writeSetting(BRHARMSEL_ADDR, BRHARMSEL_FACTORY); } + + if(settingsVersion < 42) { + writeSetting(BITECTL_ADDR, BITECTL_FACTORY); + writeSetting(BITECC_ADDR, BITECC_FACTORY); + writeSetting(LEVERCTL_ADDR, LEVERCTL_FACTORY); + writeSetting(LEVERCC_ADDR, LEVERCC_FACTORY); + } writeSetting(VERSION_ADDR, EEPROM_VERSION); @@ -253,6 +260,10 @@ void readEEPROM(const bool factoryReset) { leverMaxVal = readSettingBounded(LEVER_MAX_ADDR, leverLoLimit, leverHiLimit, LEVER_MAX_FACTORY); brHarmSetting = readSettingBounded(BRHARMSET_ADDR, 0, 6, BRHARMSET_FACTORY); brHarmSelect = readSettingBounded(BRHARMSEL_ADDR, 0, 3, BRHARMSEL_FACTORY); + biteControl = readSettingBounded(BITECTL_ADDR, 0, 3, BITECTL_FACTORY); + leverControl = readSettingBounded(LEVERCTL_ADDR, 0, 3, LEVERCTL_FACTORY); + biteCC = readSettingBounded(BITECC_ADDR, 0, 127, BITECC_FACTORY); + leverCC = readSettingBounded(LEVERCC_ADDR, 0, 127, LEVERCC_FACTORY); //Flags stored in bit field fastBoot = (dipSwBits & (1<