Added CC#20 as option for breath CC (to work well with IK Multimedia UNO synth). Made compile option for Bruce Cassidy special version (third trill key +3 instead of +4). Bug fix, check for number of added intervals during slur sustain (memory got overwritten, making the pitch bend functions to fail). Increased required sucking force for legacy controls, and added the combination with PB up for patch select (less risk for accidental activation). Added CV output from DAC pin to unused pin of MIDI jack.

This commit is contained in:
Johan Berglund 2018-12-18 13:09:26 +01:00
parent cd8acba87c
commit 01069d8f64
4 changed files with 5473 additions and 254 deletions

5204
NuEVI-v131.ino.hex Normal file

File diff suppressed because it is too large Load diff

129
NuEVI.ino
View file

@ -1,4 +1,5 @@
#include <Wire.h>
#include <Adafruit_MPR121.h>
#include <SPI.h>
#include <EEPROM.h>
@ -22,10 +23,12 @@ PROGRAMME FUNCTION: EVI Wind Controller using the Freescale MP3V5004GP breath
// Compile options, comment/uncomment to change
#define FIRMWARE_VERSION "1.2.9" // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<<
#define FIRMWARE_VERSION "1.3.1" // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<<
#define REVB
//#define CASSIDY
//Comment out the following line if you have Teensyduino 1.4.0 or earlier, to make pitch bend over USB-MIDI work.
#define NEWTEENSYDUINO
@ -434,7 +437,7 @@ byte subVibRetn = 0;
byte subVibSquelch = 0;
byte subVibDirection = 0;
byte ccList[10] = {0,1,2,7,11,1,2,7,11,74}; // OFF, Modulation, Breath, Volume, Expression (then same sent in hires)
byte ccList[11] = {0,1,2,7,11,1,2,7,11,74,20}; // OFF, Modulation, Breath, Volume, Expression (then same sent in hires), CC74 (cutoff/brightness), CC20
int pbDepthList[13] = {8192,8192,4096,2731,2048,1638,1365,1170,1024,910,819,744,683};
@ -454,7 +457,7 @@ unsigned long buttonPressedTime = 0;
unsigned long buttonRepeatInterval = 50;
unsigned long buttonRepeatDelay = 400;
unsigned long pixelUpdateTime = 0;
unsigned long pixelUpdateInterval = 100;
unsigned long pixelUpdateInterval = 80;
unsigned long cursorBlinkTime = 0; // the last time the cursor was toggled
unsigned long cursorBlinkInterval = 300; // the cursor blink toggle interval time
unsigned long patchViewTime = 0;
@ -571,8 +574,8 @@ byte slurSustain = 0;
byte parallelChord = 0;
byte subOctaveDouble = 0;
byte breathLedBrightness = 100; // up to 255, PWM
byte portamLedBrightness = 100; // up to 255, PWM
byte breathLedBrightness = 2000; // up to 4095, PWM
byte portamLedBrightness = 2000; // up to 4095, PWM
Adafruit_MPR121 touchSensor = Adafruit_MPR121(); // This is the 12-input touch sensor
@ -582,6 +585,7 @@ Adafruit_MPR121 touchSensor = Adafruit_MPR121(); // This is the 12-input touch s
void setup() {
analogReadResolution(12); // set resolution of ADCs to 12 bit
analogWriteResolution(12);
pinMode(dPin, INPUT_PULLUP);
pinMode(ePin, INPUT_PULLUP);
@ -594,6 +598,20 @@ void setup() {
// if stored settings are not for current version, or Enter+Menu are pressed at startup, they are replaced by factory settings
// if stored settings are not for current version, or Enter+Menu are pressed at startup, they are replaced by factory settings
if ((readSetting(VERSION_ADDR) != VERSION) && (readSetting(VERSION_ADDR) < 24) || (!digitalRead(ePin) && !digitalRead(mPin))){
writeSetting(VERSION_ADDR,VERSION);
writeSetting(BREATH_THR_ADDR,BREATH_THR_FACTORY);
writeSetting(BREATH_MAX_ADDR,BREATH_MAX_FACTORY);
writeSetting(PORTAM_THR_ADDR,PORTAM_THR_FACTORY);
writeSetting(PORTAM_MAX_ADDR,PORTAM_MAX_FACTORY);
writeSetting(PITCHB_THR_ADDR,PITCHB_THR_FACTORY);
writeSetting(PITCHB_MAX_ADDR,PITCHB_MAX_FACTORY);
writeSetting(EXTRAC_THR_ADDR,EXTRAC_THR_FACTORY);
writeSetting(EXTRAC_MAX_ADDR,EXTRAC_MAX_FACTORY);
writeSetting(CTOUCH_THR_ADDR,CTOUCH_THR_FACTORY);
}
if ((readSetting(VERSION_ADDR) != VERSION) || (!digitalRead(ePin) && !digitalRead(mPin))){
writeSetting(VERSION_ADDR,VERSION);
@ -632,22 +650,7 @@ void setup() {
writeSetting(VIB_RETN_ADDR,VIB_RETN_FACTORY);
writeSetting(VIB_SQUELCH_ADDR,VIB_SQUELCH_FACTORY);
writeSetting(VIB_DIRECTION_ADDR,VIB_DIRECTION_FACTORY);
// if stored settings are not for current version, or Enter+Menu are pressed at startup, they are replaced by factory settings
if (((readSetting(VERSION_ADDR) != VERSION) && (readSetting(VERSION_ADDR) < 24)) || (!digitalRead(ePin) && !digitalRead(mPin))){
writeSetting(VERSION_ADDR,VERSION);
writeSetting(BREATH_THR_ADDR,BREATH_THR_FACTORY);
writeSetting(BREATH_MAX_ADDR,BREATH_MAX_FACTORY);
writeSetting(PORTAM_THR_ADDR,PORTAM_THR_FACTORY);
writeSetting(PORTAM_MAX_ADDR,PORTAM_MAX_FACTORY);
writeSetting(PITCHB_THR_ADDR,PITCHB_THR_FACTORY);
writeSetting(PITCHB_MAX_ADDR,PITCHB_MAX_FACTORY);
writeSetting(EXTRAC_THR_ADDR,EXTRAC_THR_FACTORY);
writeSetting(EXTRAC_MAX_ADDR,EXTRAC_MAX_FACTORY);
writeSetting(CTOUCH_THR_ADDR,CTOUCH_THR_FACTORY);
}
}
// read settings from EEPROM
breathThrVal = readSetting(BREATH_THR_ADDR);
breathMaxVal = readSetting(BREATH_MAX_ADDR);
@ -695,8 +698,8 @@ void setup() {
legacy = dipSwBits & (1<<1);
legacyBrAct = dipSwBits & (1<<2);
activePatch = patch;
slowMidi = dipSwBits & (1<<3);
activePatch = patch;
breathStep = (breathHiLimit - breathLoLimit)/92; // 92 is the number of pixels in the settings bar
portamStep = (portamHiLimit - portamLoLimit)/92;
@ -749,6 +752,10 @@ void setup() {
digitalWrite(statusLedPin,LOW);
display.setTextColor(WHITE);
display.setTextSize(1);
#if defined(CASSIDY)
display.setCursor(0,0);
display.print("BC");
#endif
display.setCursor(85,52);
display.print("v.");
display.println(FIRMWARE_VERSION);
@ -767,6 +774,8 @@ void setup() {
Serial3.begin(31250); // start serial with midi baudrate 31250
Serial3.flush();
//Serial.begin(9600); // debug
digitalWrite(statusLedPin,HIGH); // Switch on the onboard LED to indicate power on/ready
}
@ -803,69 +812,56 @@ void mainLoop() {
mainState = RISE_WAIT; // Go to next state
}
if (legacy || legacyBrAct){
if (((pbUp > ((pitchbMaxVal + pitchbThrVal) / 2)) && (pbDn > ((pitchbMaxVal + pitchbThrVal) / 2)) && legacy) ||
(((analogRead(0) < (breathCalZero - 500)) && legacyBrAct) && (pbDn < ((pitchbMaxVal + pitchbThrVal) / 2)))) { // both pb pads touched or br suck
if (((pbUp > ((pitchbMaxVal + pitchbThrVal)/2)) && (pbDn > ((pitchbMaxVal + pitchbThrVal)/2)) && legacy) || ((analogRead(0) < (breathCalZero - 800)) && legacyBrAct) && (pbUp > ((pitchbMaxVal + pitchbThrVal)/2)) && (pbDn < ((pitchbMaxVal + pitchbThrVal)/2))) { // both pb pads touched or br suck
readSwitches();
fingeredNoteUntransposed=patchLimit(fingeredNoteUntransposed+1);
if (exSensor >= ((extracThrVal+extracMaxVal)/2)){ // instant midi setting
if ((fingeredNoteUntransposed >= 73) && (fingeredNoteUntransposed <= 88)) {
MIDIchannel = fingeredNoteUntransposed - 72; // Mid C and up
digitalWrite(statusLedPin, LOW);
digitalWrite(13,LOW);
delay(150);
digitalWrite(statusLedPin, HIGH);
digitalWrite(13,HIGH);
}
} else {
if (!pinkyKey){ // note number to patch number
if (patch != fingeredNoteUntransposed){
patch = fingeredNoteUntransposed;
doPatchUpdate = 1;
digitalWrite(statusLedPin, LOW);
digitalWrite(13,LOW);
delay(150);
digitalWrite(statusLedPin, HIGH);
digitalWrite(13,HIGH);
}
} else { // hi and lo patch numbers
if (fingeredNoteUntransposed > 75){
if (patch != patchLimit(fingeredNoteUntransposed + 24)){
patch = patchLimit(fingeredNoteUntransposed + 24); // add 24 to get high numbers 108 to 127
doPatchUpdate = 1;
digitalWrite(statusLedPin, LOW);
digitalWrite(13,LOW);
delay(150);
digitalWrite(statusLedPin, HIGH);
digitalWrite(13,HIGH);
}
} else {
if (patch != patchLimit(fingeredNoteUntransposed - 36)){
patch = patchLimit(fingeredNoteUntransposed - 36); // subtract 36 to get low numbers 0 to 36
doPatchUpdate = 1;
digitalWrite(statusLedPin, LOW);
digitalWrite(13,LOW);
delay(150);
digitalWrite(statusLedPin, HIGH);
digitalWrite(13,HIGH);
}
}
}
}
}
else {
if (pbDn > (pitchbMaxVal + pitchbThrVal) / 2 && (analogRead(0) < (breathCalZero - 500)) && programonce == false) { // down bend for suck programming button
if (pbDn > (pitchbMaxVal + pitchbThrVal)/2 && (analogRead(0) < (breathCalZero - 800)) && programonce == false) { // down bend for suck programming button
programonce = true;
readSwitches();
if (octaveR == 0) { //lowest octave position
if (K1 && K2 && !K3 && K4) { // e28 send patch change -10
patch = patch - 10;
doPatchUpdate = 1;
}
else if (K1 && !K2 && !K3 && K4) { //f29 decrement and send patch change
patch--;
doPatchUpdate = 1;
}
else if (!K1 && K2 && !K3 && K4) { //f#30 send patch change +10
patch = patch + 10;
doPatchUpdate = 1;
}
else if (!K1 && !K2 && !K3 && K4) { //g31 increment and send patch change
patch++;
doPatchUpdate = 1;
}
if (K1 && K2 && !K3 &&K4) { patch = patch -10; doPatchUpdate = 1; } // e28 send patch change -10
else if (K1 && !K2 && !K3 && K4) { patch--; doPatchUpdate = 1; } //f29 decrement and send patch change
else if (!K1 && K2 && !K3 && K4) {patch = patch +10; doPatchUpdate = 1; } //f#30 send patch change +10
else if (!K1 && !K2 && !K3 &&K4) { patch++; doPatchUpdate = 1; } //g31 increment and send patch change
if (!K1 && !K2 && K3 &&!K4) { //send reverb pitchlatch value
reverb = ((pitchlatch - 36) * 2);
if (reverb > 127) {reverb = 127;}
@ -877,7 +873,6 @@ void mainLoop() {
if (octaveR == 3) { //middle octave position to set breath parameters
// breathCC value is from cclist[] which assigns controller number
if (K1) { //turn on midi volume
breathCC = 3;
usbMIDI.sendControlChange(7,0, activeMIDIchannel); //midi vol to 0
@ -927,7 +922,9 @@ void mainLoop() {
}
}
if (analogRead(0) > (breathCalZero - 400)) programonce = false;
if (analogRead(0) > (breathCalZero - 800)) programonce = false;
specialKey=(touchRead(specialKeyPin) > touch_Thr); //S2 on pcb
if (lastSpecialKey != specialKey){
if (specialKey){
@ -1123,6 +1120,8 @@ void mainLoop() {
usbMIDI.sendNoteOff(activeNote, velocitySend, activeMIDIchannel); // send Note Off message for old note
dinMIDIsendNoteOff(activeNote, velocitySend, activeMIDIchannel - 1);
}
fingeredNote=noteValueCheck(fingeredNote);
if (priority){
usbMIDI.sendNoteOn(fingeredNote, velocitySend, activeMIDIchannel); // send Note On message for new note
@ -1163,9 +1162,11 @@ void mainLoop() {
}
if (slurSustain){
if (addedIntervals < 9){
addedIntervals++;
slurInterval[addedIntervals-1] = fingeredNote - slurBase;
}
}
activeNote=fingeredNote;
}
}
@ -1192,6 +1193,11 @@ void mainLoop() {
// 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
if (rotatorOn || slurSustain || parallelChord || subOctaveDouble || gateOpen) {
digitalWrite(statusLedPin,!digitalRead(statusLedPin));
} else if (!digitalRead(statusLedPin)) {
digitalWrite(statusLedPin,HIGH);
}
pixelUpdateTime = millis();
}
lastFingering=fingeredNote;
@ -1500,12 +1506,10 @@ void pitch_bend(){
}
vibThr=vibZero-vibSquelch;
vibThrLo=vibZero+vibSquelch;
int pbPos = map(constrain(pbUp,pitchbThrVal,pitchbMaxVal),pitchbThrVal,pitchbMaxVal,0,calculatedPBdepth);
int pbNeg = map(constrain(pbDn,pitchbThrVal,pitchbMaxVal),pitchbThrVal,pitchbMaxVal,0,calculatedPBdepth);
int pbSum = 8193 + pbPos - pbNeg;
int pbDif = abs(pbPos - pbNeg);
/*
if ((pbUp > pitchbThrVal) && PBdepth){
pitchBend=pitchBend*0.6+0.4*map(constrain(pbUp,pitchbThrVal,pitchbMaxVal),pitchbThrVal,pitchbMaxVal,8192,(8193 + calculatedPBdepth));
@ -1516,7 +1520,6 @@ void pitch_bend(){
pbTouched++;
}
*/
if (((pbUp > pitchbThrVal) && PBdepth) || ((pbDn > pitchbThrVal) && PBdepth)){
if (pbDif < 10){
pitchBend = 8192;
@ -1525,7 +1528,6 @@ void pitch_bend(){
}
pbTouched = 1;
}
if (!pbTouched) {
pitchBend = pitchBend*0.6+8192*0.4; // released, so smooth your way back to zero
if ((pitchBend > 8187) && (pitchBend < 8197)) pitchBend = 8192; // 8192 is 0 pitch bend, don't miss it bc of smoothing
@ -1543,6 +1545,10 @@ void pitch_bend(){
vibLedOff = 0;
}
//Serial.print(pitchBend);
//Serial.print(" - ");
//Serial.println(oldpb);
if (pitchBend != oldpb){// only send midi data if pitch bend has changed from previous value
#if defined(NEWTEENSYDUINO)
usbMIDI.sendPitchBend(pitchBend-8192, activeMIDIchannel); // newer teensyduino "pitchBend-8192" older just "pitchBend"... strange thing to change
@ -1748,9 +1754,14 @@ void readSwitches(){
// Calculate midi note number from pressed keys
#if defined(CASSIDY)
fingeredNote=startNote-2*K1-K2-3*K3-5*K4+2*K5+K6+3*K7+octaveR*12+(octave-3)*12+transpose-12+qTransp;
fingeredNoteUntransposed=startNote-2*K1-K2-3*K3-5*K4+2*K5+K6+3*K7+octaveR*12;
#else
fingeredNote=startNote-2*K1-K2-3*K3-5*K4+2*K5+K6+4*K7+octaveR*12+(octave-3)*12+transpose-12+qTransp;
fingeredNoteUntransposed=startNote-2*K1-K2-3*K3-5*K4+2*K5+K6+4*K7+octaveR*12;
#endif
//}
if (pinkyKey) pitchlatch = fingeredNoteUntransposed; //use pitchlatch to make settings based on note fingered
}
@ -3163,7 +3174,7 @@ void menu() {
cursorBlinkTime = millis();
} else {
plotBreathCC(BLACK);
breathCC = 9;
breathCC = 10;
plotBreathCC(WHITE);
cursorNow = BLACK;
display.display();
@ -3183,7 +3194,7 @@ void menu() {
break;
case 4:
// up
if (breathCC < 9){
if (breathCC < 10){
plotBreathCC(BLACK);
breathCC++;
plotBreathCC(WHITE);
@ -4834,6 +4845,10 @@ void plotBreathCC(int color){
display.setCursor(83,33);
display.println("CF");
break;
case 10:
display.setCursor(83,33);
display.println("20");
break;
}
} else {
display.setCursor(79,33);