Added secondary CC for extra controller and a Level CC control (stored), both with new settings for pinky key. New pinky settings: "EC2" sends on/off (127/0) for extra ctr CC2. "ECS" uses pinky key as switch between sending primary and secondary CC with extra controller. "LVL" lights up breath and portamento LEDs to indicate level (breath LED on full is max level, portamento LED full is min level), and level can be adjusted with K5 (up) and K1 (down). "LVP" is the same as "LVL", but with stored level transmitted at power up.

This commit is contained in:
Johan Berglund 2019-08-21 08:44:22 +02:00
parent fcf3bf2e17
commit d5506ff2b9
7 changed files with 147 additions and 22 deletions

View file

@ -66,10 +66,14 @@ 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) unsigned short pinkySetting; // 0 - 11 (QuickTranspose -12 to -1), 12 (pb/2), 13 - 24 (QuickTranspose +1 to +12), 25 (EC2), 26 (ECSW), 27 (LVL), 28 (LVLP)
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 extraCT2; // OFF:1-127
unsigned short levelCC; // 0-127
unsigned short levelVal; // 0-127
unsigned short vibSens = 2; // vibrato sensitivity unsigned short vibSens = 2; // vibrato sensitivity
unsigned short vibRetn = 2; // vibrato return speed unsigned short vibRetn = 2; // vibrato return speed
unsigned short vibSquelch = 12; //vibrato signal squelch unsigned short vibSquelch = 12; //vibrato signal squelch
@ -158,7 +162,7 @@ int targetPitch;
int exSensor=0; int exSensor=0;
byte extracIsOn=0; byte extracIsOn=0;
int oldextrac=0; int oldextrac=0;
int lastEx=0; int oldextrac2=0;
int pitchBend=8192; int pitchBend=8192;
int oldpb=8192; int oldpb=8192;
@ -226,6 +230,7 @@ byte halfPitchBendKey;
byte specialKey; byte specialKey;
byte pinkyKey; byte pinkyKey;
byte lastSpecialKey = 0; byte lastSpecialKey = 0;
byte lastPinkyKey = 0;
byte pitchlatch; byte pitchlatch;
int reverb; int reverb;
@ -317,6 +322,10 @@ void setup() {
doPatchUpdate=1; doPatchUpdate=1;
} }
if ((pinkySetting == LVLP) && levelCC){
midiSendControlChange(levelCC, levelVal);
}
activeMIDIchannel = MIDIchannel; activeMIDIchannel = MIDIchannel;
midiInitialize(MIDIchannel); midiInitialize(MIDIchannel);
@ -507,6 +516,21 @@ void loop() {
parallelChord = 0; parallelChord = 0;
subOctaveDouble = 0; subOctaveDouble = 0;
} }
if ((pinkySetting == LVL) || (pinkySetting == LVLP)){
if (pinkyKey){
ledMeter(levelVal);
if (K5 && (levelVal < 127)){
levelVal++;
if (levelCC) midiSendControlChange(levelCC, levelVal);
} else if (K1 && (levelVal > 0)){
levelVal--;
if (levelCC) midiSendControlChange(levelCC, levelVal);
}
} else if (lastPinkyKey){
writeSetting(LEVEL_VAL_ADDR,levelVal);
}
lastPinkyKey = pinkyKey;
}
} else if (mainState == RISE_WAIT) { } else if (mainState == RISE_WAIT) {
if ((pressureSensor > breathThrVal) || gateOpen) { if ((pressureSensor > breathThrVal) || gateOpen) {
// Has enough time passed for us to collect our second // Has enough time passed for us to collect our second
@ -684,7 +708,9 @@ void loop() {
} else { } else {
if (slowMidi) breath(); if (slowMidi) breath();
extraController(); extraController();
updateSensorLEDs(); if (((pinkySetting == LVL) || (pinkySetting == LVLP)) && pinkyKey){
// show LVL indication
} else updateSensorLEDs();
doorKnobCheck(); doorKnobCheck();
} }
ccSendTime = millis(); ccSendTime = millis();
@ -970,60 +996,103 @@ void doorKnobCheck() {
//*********************************************************** //***********************************************************
void extraController() { void extraController() {
bool CC2sw;
bool CC1sw;
int extracCC;
// 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)
if (pinkySetting == EC2){
//send 0 or 127 on extra controller CC2 depending on pinky key touch
if (pinkyKey && extraCT2) {
if (lastPinkyKey != pinkyKey){
midiSendControlChange(extraCT2, 127);
lastPinkyKey = pinkyKey;
}
} else {
if (lastPinkyKey != pinkyKey){
midiSendControlChange(extraCT2, 0);
lastPinkyKey = pinkyKey;
}
}
} else if (pinkySetting == ECSW){
if (pinkyKey){
//send extra controller CC2 only
CC2sw = 1;
CC1sw = 0;
} else {
//send extra controller primary CC only
CC2sw = 0;
CC1sw = 1;
}
} else {
//send both primary CC and CC2
CC2sw = 1;
CC1sw = 1;
}
if (extraCT && (exSensor >= extracThrVal)) { // if we are enabled and over the threshold, send data if (extraCT && (exSensor >= extracThrVal)) { // if we are enabled and over the threshold, send data
if (!extracIsOn) { if (!extracIsOn) {
extracIsOn = 1; extracIsOn = 1;
if (extraCT == 4) { //Sustain ON if ((extraCT == 4) && CC1sw) { //Sustain ON
midiSendControlChange(64, 127); midiSendControlChange(64, 127);
} }
} }
if (extraCT == 1) { //Send modulation if ((extraCT == 1) && CC1sw) { //Send modulation
int extracCC = map(constrain(exSensor, extracThrVal, extracMaxVal), extracThrVal, extracMaxVal, 1, 127); extracCC = map(constrain(exSensor, extracThrVal, extracMaxVal), extracThrVal, extracMaxVal, 1, 127);
if (extracCC != oldextrac) { if (extracCC != oldextrac) {
midiSendControlChange(1, extracCC); midiSendControlChange(1, extracCC);
} }
oldextrac = extracCC; oldextrac = extracCC;
} }
if (extraCT == 2) { //Send foot pedal (CC#4) if ((extraCT == 2) && CC1sw) { //Send foot pedal (CC#4)
int extracCC = map(constrain(exSensor, extracThrVal, extracMaxVal), extracThrVal, extracMaxVal, 1, 127); extracCC = map(constrain(exSensor, extracThrVal, extracMaxVal), extracThrVal, extracMaxVal, 1, 127);
if (extracCC != oldextrac) { if (extracCC != oldextrac) {
midiSendControlChange(4, extracCC); midiSendControlChange(4, extracCC);
} }
oldextrac = extracCC; oldextrac = extracCC;
} }
if ((extraCT == 3) && (breathCC != 9)) { //Send filter cutoff (CC#74) if ((extraCT == 3) && (breathCC != 9) && CC1sw) { //Send filter cutoff (CC#74)
int extracCC = map(constrain(exSensor, extracThrVal, extracMaxVal), extracThrVal, extracMaxVal, 1, 127); extracCC = map(constrain(exSensor, extracThrVal, extracMaxVal), extracThrVal, extracMaxVal, 1, 127);
if (extracCC != oldextrac) { if (extracCC != oldextrac) {
midiSendControlChange(74, extracCC); midiSendControlChange(74, extracCC);
} }
oldextrac = extracCC; oldextrac = extracCC;
} }
if ((extraCT2 ) && CC2sw){ //Send extra controller CC2
extracCC = map(constrain(exSensor, extracThrVal, extracMaxVal), extracThrVal, extracMaxVal, 1, 127);
if (extracCC != oldextrac2) {
midiSendControlChange(extraCT2, extracCC);
}
oldextrac2 = extracCC;
}
} 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) && CC1sw) { //MW
if (oldextrac != 0) { if (oldextrac != 0) {
//send modulation 0 //send modulation 0
midiSendControlChange(1, 0); midiSendControlChange(1, 0);
oldextrac = 0; oldextrac = 0;
} }
} else if (extraCT == 2) { //FP } else if ((extraCT == 2) && CC1sw) { //FP
if (oldextrac != 0) { if (oldextrac != 0) {
//send foot pedal 0 //send foot pedal 0
midiSendControlChange(4, 0); midiSendControlChange(4, 0);
oldextrac = 0; oldextrac = 0;
} }
} else if ((extraCT == 3) && (breathCC != 9)) { //CF } else if ((extraCT == 3) && (breathCC != 9) && CC1sw) { //CF
if (oldextrac != 0) { if (oldextrac != 0) {
//send filter cutoff 0 //send filter cutoff 0
midiSendControlChange(74, 0); midiSendControlChange(74, 0);
oldextrac = 0; oldextrac = 0;
} }
} else if (extraCT == 4) { //SP } else if ((extraCT == 4) && CC1sw) { //SP
//send sustain off //send sustain off
midiSendControlChange(64, 0); midiSendControlChange(64, 0);
} }
if ((extraCT2 ) && CC2sw){ //CC2
//send 0 for extra ctr CC2
midiSendControlChange(extraCT2, 0);
oldextrac2 = 0;
}
} }
} }
@ -1127,7 +1196,7 @@ void readSwitches() {
pinkyKey = (touchRead(halfPitchBendKeyPin) > touch_Thr); // SENSOR PIN 1 - PCB PIN "S1" pinkyKey = (touchRead(halfPitchBendKeyPin) > touch_Thr); // SENSOR PIN 1 - PCB PIN "S1"
int qTransp = pinkyKey ? pinkySetting-12 : 0; int qTransp = (pinkyKey && (pinkySetting < 25)) ? pinkySetting-12 : 0;
// Calculate midi note number from pressed keys // Calculate midi note number from pressed keys

View file

@ -20,6 +20,10 @@
//Magic value where pinky button means "pitch bend" //Magic value where pinky button means "pitch bend"
#define PBD 12 #define PBD 12
#define EC2 25
#define ECSW 26
#define LVL 27
#define LVLP 28
//Vibrato direction //Vibrato direction
#define UPWD 1 #define UPWD 1
@ -55,7 +59,7 @@ extern unsigned short octave;
extern unsigned short curve; extern unsigned short curve;
extern unsigned short velSmpDl; // 0-30 ms extern unsigned short velSmpDl; // 0-30 ms
extern unsigned short velBias; // 0-9 extern unsigned short velBias; // 0-9
extern unsigned short pinkySetting; // 0 - 11 (QuickTranspose -12 to -1), 12 (pb/2), 13 - 24 (QuickTranspose +1 to +12) extern unsigned short pinkySetting; // 0 - 11 (QuickTranspose -12 to -1), 12 (pb/2), 13 - 24 (QuickTranspose +1 to +12), 25 (EC2), 26 (ECSW), 27 (LVL), 28 (LVLP)
extern unsigned short dipSwBits; // virtual dip switch settings for special modes (work in progress) extern unsigned short dipSwBits; // virtual dip switch settings for special modes (work in progress)
extern unsigned short priority; // mono priority for rotator chords extern unsigned short priority; // mono priority for rotator chords
extern unsigned short vibSens; // vibrato sensitivity extern unsigned short vibSens; // vibrato sensitivity
@ -66,6 +70,9 @@ extern unsigned short vibSensBite; // vibrato sensitivity (bite)
extern unsigned short vibSquelchBite; //vibrato signal squelch (bite) extern unsigned short vibSquelchBite; //vibrato signal squelch (bite)
extern unsigned short vibControl; extern unsigned short vibControl;
extern unsigned short fastPatch[7]; extern unsigned short fastPatch[7];
extern unsigned short extraCT2; // OFF:1-127
extern unsigned short levelCC; // 0-127
extern unsigned short levelVal; // 0-127
extern uint16_t gateOpenEnable; extern uint16_t gateOpenEnable;
extern uint16_t specialKeyEnable; extern uint16_t specialKeyEnable;
extern byte rotatorOn; extern byte rotatorOn;
@ -99,7 +106,6 @@ extern int lastBite;
extern byte biteJumper; extern byte biteJumper;
extern int exSensor; extern int exSensor;
extern int lastEx;
extern int pitchBend; extern int pitchBend;

View file

@ -46,3 +46,8 @@ void updateSensorLEDs() {
analogWrite(pLedPin, 0); analogWrite(pLedPin, 0);
} }
} }
void ledMeter(byte indicatedValue){
analogWrite(bLedPin, map(constrain(indicatedValue, 0, 127), 0, 127, 0, BREATH_LED_BRIGHTNESS)); // full glow at maximum value
analogWrite(pLedPin, map(constrain(indicatedValue, 0, 127), 127, 0, 0, PORTAM_LED_BRIGHTNESS)); // full glow at minimum value
}

View file

@ -8,5 +8,6 @@ void statusLed(bool state);
void statusLedFlash(uint16_t delayTime); void statusLedFlash(uint16_t delayTime);
void statusLedBlink(); void statusLedBlink();
void updateSensorLEDs(); void updateSensorLEDs();
void ledMeter(byte indicatedValue);
#endif #endif

View file

@ -840,6 +840,16 @@ const MenuEntrySub extraMenu = {
, nullptr , nullptr
}; };
const MenuEntrySub extraCC2Menu = {
MenuType::ESub, "EXCTR CC2", "EXCTR CC2", &extraCT2, 0, 127, MenuEntryFlags::EMenuEntryWrap,
[](SubMenuRef __unused, char* out, const char** __unused unit) {
if(extraCT2) numToString(extraCT2, out);
else strncpy(out, "OFF", 4);
},
[](const MenuEntrySub & __unused sub) { writeSetting(EXTRA2_ADDR,extraCT2); }
, nullptr
};
const MenuEntryStateCh vibratoSubMenu = { MenuType::EStateChange, "VIBRATO", VIBRATO_MENU }; const MenuEntryStateCh vibratoSubMenu = { MenuType::EStateChange, "VIBRATO", VIBRATO_MENU };
const MenuEntrySub deglitchMenu = { const MenuEntrySub deglitchMenu = {
@ -856,10 +866,18 @@ const MenuEntrySub deglitchMenu = {
}; };
const MenuEntrySub pinkyMenu = { const MenuEntrySub pinkyMenu = {
MenuType::ESub, "PINKY KEY", "PINKY KEY", &pinkySetting, 0, 24, MenuEntryFlags::ENone, MenuType::ESub, "PINKY KEY", "PINKY KEY", &pinkySetting, 0, 28, MenuEntryFlags::ENone,
[](SubMenuRef __unused,char* textBuffer, const char** __unused unit) { [](SubMenuRef __unused,char* textBuffer, const char** __unused unit) {
if (pinkySetting == PBD) if (pinkySetting == PBD)
strncpy(textBuffer, "PBD", 4); strncpy(textBuffer, "PBD", 4);
else if (pinkySetting == EC2)
strncpy(textBuffer, "EC2", 4);
else if (pinkySetting == ECSW)
strncpy(textBuffer, "ECS", 4);
else if (pinkySetting == LVL)
strncpy(textBuffer, "LVL", 4);
else if (pinkySetting == LVLP)
strncpy(textBuffer, "LVP", 4);
else else
numToString(pinkySetting-12, textBuffer, true); numToString(pinkySetting-12, textBuffer, true);
}, },
@ -867,13 +885,25 @@ const MenuEntrySub pinkyMenu = {
, nullptr , nullptr
}; };
const MenuEntrySub lvlCtrlCCMenu = {
MenuType::ESub, "LEVEL CC", "LEVEL CC", &levelCC, 0, 127, MenuEntryFlags::EMenuEntryWrap,
[](SubMenuRef __unused, char* out, const char** __unused unit) {
if(levelCC) numToString(levelCC, out);
else strncpy(out, "OFF", 4);
},
[](const MenuEntrySub & __unused sub) { writeSetting(LEVEL_CC_ADDR,levelCC); }
, nullptr
};
const MenuEntry* controlMenuEntries[] = { const MenuEntry* controlMenuEntries[] = {
(MenuEntry*)&portMenu, (MenuEntry*)&portMenu,
(MenuEntry*)&pitchBendMenu, (MenuEntry*)&pitchBendMenu,
(MenuEntry*)&extraMenu, (MenuEntry*)&extraMenu,
(MenuEntry*)&extraCC2Menu,
(MenuEntry*)&vibratoSubMenu, (MenuEntry*)&vibratoSubMenu,
(MenuEntry*)&deglitchMenu, (MenuEntry*)&deglitchMenu,
(MenuEntry*)&pinkyMenu (MenuEntry*)&pinkyMenu,
(MenuEntry*)&lvlCtrlCCMenu
}; };
const MenuPage controlMenuPage = { const MenuPage controlMenuPage = {

View file

@ -96,6 +96,12 @@ void readEEPROM() {
writeSetting(DAC_MODE_ADDR, DAC_MODE_FACTORY); writeSetting(DAC_MODE_ADDR, DAC_MODE_FACTORY);
} }
if(settingsVersion < 33) {
writeSetting(EXTRA2_ADDR, EXTRA2_FACTORY);
writeSetting(LEVEL_CC_ADDR, LEVEL_CC_FACTORY);
writeSetting(LEVEL_VAL_ADDR, LEVEL_VAL_FACTORY);
}
writeSetting(VERSION_ADDR, EEPROM_VERSION); writeSetting(VERSION_ADDR, EEPROM_VERSION);
} }
@ -124,7 +130,7 @@ void readEEPROM() {
curve = readSettingBounded(BREATHCURVE_ADDR, 0, 12, BREATHCURVE_FACTORY); curve = readSettingBounded(BREATHCURVE_ADDR, 0, 12, BREATHCURVE_FACTORY);
velSmpDl = readSettingBounded(VEL_SMP_DL_ADDR, 0, 30, VEL_SMP_DL_FACTORY); velSmpDl = readSettingBounded(VEL_SMP_DL_ADDR, 0, 30, VEL_SMP_DL_FACTORY);
velBias = readSettingBounded(VEL_BIAS_ADDR, 0, 9, VEL_BIAS_FACTORY); velBias = readSettingBounded(VEL_BIAS_ADDR, 0, 9, VEL_BIAS_FACTORY);
pinkySetting = readSettingBounded(PINKY_KEY_ADDR, 0, 24, PINKY_KEY_FACTORY); pinkySetting = readSettingBounded(PINKY_KEY_ADDR, 0, 28, PINKY_KEY_FACTORY);
fastPatch[0] = readSettingBounded(FP1_ADDR, 0, 127, 0); fastPatch[0] = readSettingBounded(FP1_ADDR, 0, 127, 0);
fastPatch[1] = readSettingBounded(FP2_ADDR, 0, 127, 0); fastPatch[1] = readSettingBounded(FP2_ADDR, 0, 127, 0);
fastPatch[2] = readSettingBounded(FP3_ADDR, 0, 127, 0); fastPatch[2] = readSettingBounded(FP3_ADDR, 0, 127, 0);
@ -150,6 +156,9 @@ void readEEPROM() {
vibControl = readSettingBounded(VIB_CONTROL_ADDR, 0, 1, VIB_CONTROL_FACTORY); vibControl = readSettingBounded(VIB_CONTROL_ADDR, 0, 1, VIB_CONTROL_FACTORY);
dacMode = readSettingBounded(DAC_MODE_ADDR, DAC_MODE_BREATH, DAC_MODE_PITCH, DAC_MODE_FACTORY); dacMode = readSettingBounded(DAC_MODE_ADDR, DAC_MODE_BREATH, DAC_MODE_PITCH, DAC_MODE_FACTORY);
trill3_interval = readSettingBounded(TRILL3_INTERVAL_ADDR, 3, 4, TRILL3_INTERVAL_FACTORY); trill3_interval = readSettingBounded(TRILL3_INTERVAL_ADDR, 3, 4, TRILL3_INTERVAL_FACTORY);
extraCT2 = readSettingBounded(EXTRA2_ADDR, 0, 127, EXTRA2_FACTORY);
levelCC = readSettingBounded(LEVEL_CC_ADDR, 0, 127, LEVEL_CC_FACTORY);
levelVal = readSettingBounded(LEVEL_VAL_ADDR, 0, 127, LEVEL_VAL_FACTORY);
//Flags stored in bit field //Flags stored in bit field
fastBoot = (dipSwBits & (1<<DIPSW_FASTBOOT))?1:0; fastBoot = (dipSwBits & (1<<DIPSW_FASTBOOT))?1:0;

View file

@ -55,6 +55,9 @@
#define VIB_CONTROL_ADDR 96 #define VIB_CONTROL_ADDR 96
#define TRILL3_INTERVAL_ADDR 98 #define TRILL3_INTERVAL_ADDR 98
#define DAC_MODE_ADDR 100 #define DAC_MODE_ADDR 100
#define EXTRA2_ADDR 102
#define LEVEL_CC_ADDR 104
#define LEVEL_VAL_ADDR 106
@ -72,7 +75,7 @@
//"factory" values for settings //"factory" values for settings
#define EEPROM_VERSION 32 #define EEPROM_VERSION 33
#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
@ -116,9 +119,11 @@
#define VIB_SENS_BITE_FACTORY 3 #define VIB_SENS_BITE_FACTORY 3
#define VIB_SQUELCH_BITE_FACTORY 10 #define VIB_SQUELCH_BITE_FACTORY 10
#define VIB_CONTROL_FACTORY 0 #define VIB_CONTROL_FACTORY 0
#define TRILL3_INTERVAL_FACTORY 4 #define TRILL3_INTERVAL_FACTORY 4
#define DAC_MODE_FACTORY DAC_MODE_BREATH #define DAC_MODE_FACTORY DAC_MODE_BREATH
#define EXTRA2_FACTORY 0
#define LEVEL_CC_FACTORY 11
#define LEVEL_VAL_FACTORY 127
void readEEPROM(); void readEEPROM();