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:
parent
cd8acba87c
commit
01069d8f64
4 changed files with 5473 additions and 254 deletions
Binary file not shown.
Binary file not shown.
5204
NuEVI-v131.ino.hex
Normal file
5204
NuEVI-v131.ino.hex
Normal file
File diff suppressed because it is too large
Load diff
129
NuEVI.ino
129
NuEVI.ino
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue