commit
44b91a1a89
16 changed files with 798 additions and 328 deletions
240
NuEVI/FilterOnePole.cpp
Normal file
240
NuEVI/FilterOnePole.cpp
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
// Copyright 2014 Jonathan Driscoll
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "FilterOnePole.h"
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
FilterOnePole::FilterOnePole( FILTER_TYPE ft, float fc, float initialValue ) {
|
||||||
|
setFilter( ft, fc, initialValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterOnePole::setFilter( FILTER_TYPE ft, float fc, float initialValue ) {
|
||||||
|
FT = ft;
|
||||||
|
setFrequency( fc );
|
||||||
|
|
||||||
|
Y = initialValue;
|
||||||
|
Ylast = initialValue;
|
||||||
|
X = initialValue;
|
||||||
|
|
||||||
|
LastUS = micros();
|
||||||
|
}
|
||||||
|
|
||||||
|
float FilterOnePole::input( float inVal ) {
|
||||||
|
long time = micros();
|
||||||
|
ElapsedUS = float(time - LastUS); // cast to float here, for math
|
||||||
|
LastUS = time; // update this now
|
||||||
|
|
||||||
|
// shift the data values
|
||||||
|
Ylast = Y;
|
||||||
|
X = inVal; // this is now the most recent input value
|
||||||
|
|
||||||
|
// filter value is controlled by a parameter called X
|
||||||
|
// tau is set by the user in microseconds, but must be converted to samples here
|
||||||
|
TauSamps = TauUS / ElapsedUS;
|
||||||
|
|
||||||
|
float ampFactor;
|
||||||
|
#ifdef ARM_FLOAT
|
||||||
|
ampFactor = expf( -1.0 / TauSamps ); // this is 1 if called quickly
|
||||||
|
#else
|
||||||
|
ampFactor = exp( -1.0 / TauSamps ); // this is 1 if called quickly
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Y = (1.0-ampFactor)*X + ampFactor*Ylast; // set the new value
|
||||||
|
|
||||||
|
return output();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterOnePole::setFrequency( float newFrequency ) {
|
||||||
|
setTau( 1.0/(TWO_PI*newFrequency ) ); // τ=1/ω
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterOnePole::setTau( float newTau ) {
|
||||||
|
TauUS = newTau * 1e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FilterOnePole::output() {
|
||||||
|
// figure out which button to read
|
||||||
|
switch (FT) {
|
||||||
|
case LOWPASS:
|
||||||
|
// return the last value
|
||||||
|
return Y;
|
||||||
|
break;
|
||||||
|
case INTEGRATOR:
|
||||||
|
// using a lowpass, but normaize
|
||||||
|
return Y * (TauUS/1.0e6);
|
||||||
|
break;
|
||||||
|
case HIGHPASS:
|
||||||
|
// highpass is the _difference_
|
||||||
|
return X-Y;
|
||||||
|
break;
|
||||||
|
case DIFFERENTIATOR:
|
||||||
|
// like a highpass, but normalize
|
||||||
|
return (X-Y)/(TauUS/1.0e6);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// should never get to here, return 0 just in case
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterOnePole::print() {
|
||||||
|
Serial.println("");
|
||||||
|
Serial.print(" Y: "); Serial.print( Y );
|
||||||
|
Serial.print(" Ylast: "); Serial.print( Ylast );
|
||||||
|
Serial.print(" X "); Serial.print( X );
|
||||||
|
Serial.print(" ElapsedUS "); Serial.print( ElapsedUS );
|
||||||
|
Serial.print(" TauSamps: "); Serial.print( TauSamps );
|
||||||
|
//Serial.print(" ampFactor " ); Serial.print( ampFactor );
|
||||||
|
Serial.print(" TauUS: "); Serial.print( TauUS );
|
||||||
|
Serial.println("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterOnePole::test() {
|
||||||
|
float tau = 10;
|
||||||
|
float updateInterval = 1;
|
||||||
|
float nextupdateTime = millis()*1e-3;
|
||||||
|
|
||||||
|
float inputValue = 0;
|
||||||
|
FilterOnePole hp( HIGHPASS, tau, inputValue );
|
||||||
|
FilterOnePole lp( LOWPASS, tau, inputValue );
|
||||||
|
|
||||||
|
while( true ) {
|
||||||
|
float now = millis()*1e-3;
|
||||||
|
|
||||||
|
// switch input values on a 20 second cycle
|
||||||
|
if( round(now/20.0)-(now/20.0) < 0 )
|
||||||
|
inputValue = 0;
|
||||||
|
else
|
||||||
|
inputValue = 100;
|
||||||
|
|
||||||
|
hp.input(inputValue);
|
||||||
|
lp.input(inputValue);
|
||||||
|
|
||||||
|
if( now > nextupdateTime ) {
|
||||||
|
nextupdateTime += updateInterval;
|
||||||
|
|
||||||
|
Serial.print("inputValue: "); Serial.print( inputValue );
|
||||||
|
Serial.print("\t high-passed: "); Serial.print( hp.output() );
|
||||||
|
Serial.print("\t low-passed: "); Serial.print( lp.output() );
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterOnePole::setToNewValue( float newVal ) {
|
||||||
|
Y = Ylast = X = newVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// stuff for filter2 (lowpass only)
|
||||||
|
// should be able to set a separate fall time as well
|
||||||
|
FilterOnePoleCascade::FilterOnePoleCascade( float riseTime, float initialValue ) {
|
||||||
|
setRiseTime( riseTime );
|
||||||
|
setToNewValue( initialValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterOnePoleCascade::setRiseTime( float riseTime ) {
|
||||||
|
float tauScale = 3.36; // found emperically, by running test();
|
||||||
|
|
||||||
|
Pole1.setTau( riseTime / tauScale );
|
||||||
|
Pole2.setTau( riseTime / tauScale );
|
||||||
|
}
|
||||||
|
|
||||||
|
float FilterOnePoleCascade::input( float inVal ) {
|
||||||
|
Pole2.input( Pole1.input( inVal ));
|
||||||
|
return output();
|
||||||
|
}
|
||||||
|
|
||||||
|
// clears out the values in the filter
|
||||||
|
void FilterOnePoleCascade::setToNewValue( float newVal ) {
|
||||||
|
Pole1.setToNewValue( newVal );
|
||||||
|
Pole2.setToNewValue( newVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
float FilterOnePoleCascade::output() {
|
||||||
|
return Pole2.output();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterOnePoleCascade::test() {
|
||||||
|
// make a filter, how fast does it run:
|
||||||
|
|
||||||
|
float rise = 1.0;
|
||||||
|
FilterOnePoleCascade myFilter( rise );
|
||||||
|
|
||||||
|
// first, test the filter speed ...
|
||||||
|
long nLoops = 1000;
|
||||||
|
|
||||||
|
Serial.print( "testing filter with a rise time of ");
|
||||||
|
Serial.print( rise ); Serial.print( "s" );
|
||||||
|
|
||||||
|
Serial.print( "\n running filter speed loop ... ");
|
||||||
|
|
||||||
|
float startTime, stopTime;
|
||||||
|
|
||||||
|
startTime = millis()*1e-3;
|
||||||
|
for( long i=0; i<nLoops; ++i ) {
|
||||||
|
myFilter.input( PI ); // use pi, so it will actually do a full calculation
|
||||||
|
}
|
||||||
|
stopTime = millis()*1e-3;
|
||||||
|
|
||||||
|
Serial.print( "done, filter runs at " );
|
||||||
|
Serial.print( float(nLoops) / (stopTime - startTime) );
|
||||||
|
Serial.print( " hz " );
|
||||||
|
Serial.print( "\n filter value: " ); Serial.print( myFilter.output() );
|
||||||
|
|
||||||
|
myFilter.setToNewValue( 0.0 );
|
||||||
|
Serial.print( "\n after reset to 0: "); Serial.print( myFilter.output() );
|
||||||
|
|
||||||
|
Serial.print( "\n testing rise time (10% to 90%) ...");
|
||||||
|
|
||||||
|
bool crossedTenPercent = false;
|
||||||
|
while( myFilter.output() < 0.9 ) {
|
||||||
|
myFilter.input( 1.0 );
|
||||||
|
if( myFilter.output() > 0.1 && !crossedTenPercent ) {
|
||||||
|
// filter first crossed the 10% point
|
||||||
|
startTime = millis()*1e-3;
|
||||||
|
crossedTenPercent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stopTime = millis()*1e-3;
|
||||||
|
|
||||||
|
Serial.print( "done, rise time: " ); Serial.print( stopTime-startTime );
|
||||||
|
|
||||||
|
Serial.print( "testing attenuation at f = 1/risetime" );
|
||||||
|
|
||||||
|
myFilter.setToNewValue( 0.0 );
|
||||||
|
|
||||||
|
float maxVal = 0;
|
||||||
|
float valWasOutputThisCycle = true;
|
||||||
|
|
||||||
|
__unused float lastFilterVal = 0;
|
||||||
|
|
||||||
|
while( true ) {
|
||||||
|
float now = 1e-3*millis();
|
||||||
|
|
||||||
|
float currentFilterVal = myFilter.input( sin( TWO_PI*now) );
|
||||||
|
|
||||||
|
if( currentFilterVal < 0.0 ) {
|
||||||
|
if( !valWasOutputThisCycle ) {
|
||||||
|
// just crossed below zero, output the max
|
||||||
|
Serial.print( maxVal*100 ); Serial.print( " %\n" );
|
||||||
|
valWasOutputThisCycle = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
89
NuEVI/FilterOnePole.h
Normal file
89
NuEVI/FilterOnePole.h
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
// Copyright 2014 Jonathan Driscoll
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// FilterOnePole has been copied from https://github.com/JonHub/Filters
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FilterOnePole_h
|
||||||
|
#define FilterOnePole_h
|
||||||
|
|
||||||
|
enum FILTER_TYPE {
|
||||||
|
HIGHPASS,
|
||||||
|
LOWPASS,
|
||||||
|
INTEGRATOR,
|
||||||
|
DIFFERENTIATOR
|
||||||
|
};
|
||||||
|
|
||||||
|
// the recursive filter class implements a recursive filter (low / pass / highpass
|
||||||
|
// note that this must be updated in a loop, using the most recent acquired values and the time acquired
|
||||||
|
// Y = a0*X + a1*Xm1
|
||||||
|
// + b1*Ylast
|
||||||
|
struct FilterOnePole {
|
||||||
|
FILTER_TYPE FT;
|
||||||
|
float TauUS; // decay constant of the filter, in US
|
||||||
|
float TauSamps; // tau, measued in samples (this changes, depending on how long between input()s
|
||||||
|
|
||||||
|
// filter values - these are public, but should not be set externally
|
||||||
|
float Y; // most recent output value (gets computed on update)
|
||||||
|
float Ylast; // prevous output value
|
||||||
|
|
||||||
|
float X; // most recent input value
|
||||||
|
|
||||||
|
// elapsed times are kept in long, and will wrap every
|
||||||
|
// 35 mins, 47 seconds ... however, the wrap does not matter,
|
||||||
|
// because the delta will still be correct (always positive and small)
|
||||||
|
float ElapsedUS; // time since last update
|
||||||
|
long LastUS; // last time measured
|
||||||
|
|
||||||
|
FilterOnePole( FILTER_TYPE ft=LOWPASS, float fc=1.0, float initialValue=0 );
|
||||||
|
|
||||||
|
// sets or resets the parameters and state of the filter
|
||||||
|
void setFilter( FILTER_TYPE ft, float tauS, float initialValue );
|
||||||
|
|
||||||
|
void setFrequency( float newFrequency );
|
||||||
|
|
||||||
|
void setTau( float newTau );
|
||||||
|
|
||||||
|
float input( float inVal );
|
||||||
|
|
||||||
|
float output();
|
||||||
|
|
||||||
|
void print();
|
||||||
|
|
||||||
|
void test();
|
||||||
|
|
||||||
|
void setToNewValue( float newVal ); // resets the filter to a new value
|
||||||
|
};
|
||||||
|
|
||||||
|
// two pole filter, these are very useful
|
||||||
|
struct FilterOnePoleCascade {
|
||||||
|
|
||||||
|
FilterOnePole Pole1;
|
||||||
|
FilterOnePole Pole2;
|
||||||
|
|
||||||
|
FilterOnePoleCascade( float riseTime=1.0, float initialValue=0 ); // rise time to step function, 10% to 90%
|
||||||
|
|
||||||
|
// rise time is 10% to 90%, for a step input
|
||||||
|
void setRiseTime( float riseTime );
|
||||||
|
|
||||||
|
void setToNewValue( float newVal );
|
||||||
|
|
||||||
|
float input( float inVal );
|
||||||
|
|
||||||
|
float output();
|
||||||
|
|
||||||
|
void test();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
305
NuEVI/NuEVI.ino
305
NuEVI/NuEVI.ino
|
@ -1,16 +1,16 @@
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
|
|
||||||
#include <Adafruit_MPR121.h>
|
#include <Adafruit_MPR121.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
#include <Filters.h> // for the breath signal LP filtering, https://github.com/edgar-bonet/Filters
|
|
||||||
|
|
||||||
|
#include "FilterOnePole.h" // for the breath signal low-pass filtering, from https://github.com/JonHub/Filters
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "midi.h"
|
#include "midi.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "led.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NAME: NuEVI
|
NAME: NuEVI
|
||||||
|
@ -80,6 +80,11 @@ unsigned short vibControl = 0;
|
||||||
|
|
||||||
unsigned short fastPatch[7] = {0,0,0,0,0,0,0};
|
unsigned short fastPatch[7] = {0,0,0,0,0,0,0};
|
||||||
|
|
||||||
|
uint16_t bcasMode; //Legacy CASSIDY compile flag
|
||||||
|
uint16_t trill3_interval;
|
||||||
|
uint16_t fastBoot;
|
||||||
|
uint16_t dacMode;
|
||||||
|
|
||||||
byte rotatorOn = 0;
|
byte rotatorOn = 0;
|
||||||
byte currentRotation = 0;
|
byte currentRotation = 0;
|
||||||
uint16_t rotations[4]; // semitones { -5, -10, -7, -14 };
|
uint16_t rotations[4]; // semitones { -5, -10, -7, -14 };
|
||||||
|
@ -90,8 +95,6 @@ uint16_t gateOpenEnable = 0;
|
||||||
|
|
||||||
uint16_t specialKeyEnable = 0;
|
uint16_t specialKeyEnable = 0;
|
||||||
|
|
||||||
uint16_t wlPower = 0;
|
|
||||||
|
|
||||||
int touch_Thr = 1300;
|
int touch_Thr = 1300;
|
||||||
|
|
||||||
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 (UNO Cutoff)
|
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 (UNO Cutoff)
|
||||||
|
@ -230,9 +233,6 @@ byte slurSustain = 0;
|
||||||
byte parallelChord = 0;
|
byte parallelChord = 0;
|
||||||
byte subOctaveDouble = 0;
|
byte subOctaveDouble = 0;
|
||||||
|
|
||||||
const int breathLedBrightness = 500; // up to 4095, PWM
|
|
||||||
const int portamLedBrightness = 500; // up to 4095, PWM
|
|
||||||
|
|
||||||
Adafruit_MPR121 touchSensor = Adafruit_MPR121(); // This is the 12-input touch sensor
|
Adafruit_MPR121 touchSensor = Adafruit_MPR121(); // This is the 12-input touch sensor
|
||||||
FilterOnePole breathFilter;
|
FilterOnePole breathFilter;
|
||||||
|
|
||||||
|
@ -260,126 +260,10 @@ void setup() {
|
||||||
pinMode(biteJumperGndPin, OUTPUT); //PBITE
|
pinMode(biteJumperGndPin, OUTPUT); //PBITE
|
||||||
digitalWrite(biteJumperGndPin, LOW); //PBITE
|
digitalWrite(biteJumperGndPin, LOW); //PBITE
|
||||||
|
|
||||||
// if stored settings are not for current version, or Enter+Menu are pressed at startup, they are replaced by factory settings
|
|
||||||
|
|
||||||
uint16_t settingsVersion = readSetting(VERSION_ADDR);
|
//Read eeprom data into global vars
|
||||||
|
readEEPROM();
|
||||||
|
|
||||||
if (((settingsVersion != VERSION) && (settingsVersion < 24)) || (!digitalRead(ePin) && !digitalRead(mPin)) || (settingsVersion == 0xffffu)) {
|
|
||||||
writeSetting(VERSION_ADDR,VERSION);
|
|
||||||
writeSetting(BREATH_THR_ADDR,BREATH_THR_FACTORY);
|
|
||||||
writeSetting(BREATH_MAX_ADDR,BREATH_MAX_FACTORY);
|
|
||||||
if (digitalRead(biteJumperPin)){ //PBITE (if pulled low with jumper, pressure sensor is used instead of capacitive bite sensing)
|
|
||||||
writeSetting(PORTAM_THR_ADDR,PORTAM_THR_FACTORY);
|
|
||||||
writeSetting(PORTAM_MAX_ADDR,PORTAM_MAX_FACTORY);
|
|
||||||
} else {
|
|
||||||
writeSetting(PORTAM_THR_ADDR,PORTPR_THR_FACTORY);
|
|
||||||
writeSetting(PORTAM_MAX_ADDR,PORTPR_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 ((settingsVersion != VERSION) || (!digitalRead(ePin) && !digitalRead(mPin))) {
|
|
||||||
writeSetting(VERSION_ADDR,VERSION);
|
|
||||||
|
|
||||||
writeSetting(TRANSP_ADDR,TRANSP_FACTORY);
|
|
||||||
writeSetting(MIDI_ADDR,MIDI_FACTORY);
|
|
||||||
writeSetting(BREATH_CC_ADDR,BREATH_CC_FACTORY);
|
|
||||||
writeSetting(BREATH_AT_ADDR,BREATH_AT_FACTORY);
|
|
||||||
writeSetting(VELOCITY_ADDR,VELOCITY_FACTORY);
|
|
||||||
writeSetting(PORTAM_ADDR,PORTAM_FACTORY);
|
|
||||||
writeSetting(PB_ADDR,PB_FACTORY);
|
|
||||||
writeSetting(EXTRA_ADDR,EXTRA_FACTORY);
|
|
||||||
writeSetting(VIBRATO_ADDR,VIBRATO_FACTORY);
|
|
||||||
writeSetting(DEGLITCH_ADDR,DEGLITCH_FACTORY);
|
|
||||||
writeSetting(PATCH_ADDR,PATCH_FACTORY);
|
|
||||||
writeSetting(OCTAVE_ADDR,OCTAVE_FACTORY);
|
|
||||||
writeSetting(BREATHCURVE_ADDR,BREATHCURVE_FACTORY);
|
|
||||||
writeSetting(VEL_SMP_DL_ADDR,VEL_SMP_DL_FACTORY);
|
|
||||||
writeSetting(VEL_BIAS_ADDR,VEL_BIAS_FACTORY);
|
|
||||||
writeSetting(PINKY_KEY_ADDR,PINKY_KEY_FACTORY);
|
|
||||||
writeSetting(FP1_ADDR,0);
|
|
||||||
writeSetting(FP2_ADDR,0);
|
|
||||||
writeSetting(FP3_ADDR,0);
|
|
||||||
writeSetting(FP4_ADDR,0);
|
|
||||||
writeSetting(FP5_ADDR,0);
|
|
||||||
writeSetting(FP6_ADDR,0);
|
|
||||||
writeSetting(FP7_ADDR,0);
|
|
||||||
writeSetting(DIPSW_BITS_ADDR,DIPSW_BITS_FACTORY);
|
|
||||||
writeSetting(PARAL_ADDR,PARAL_FACTORY);
|
|
||||||
writeSetting(ROTN1_ADDR,ROTN1_FACTORY);
|
|
||||||
writeSetting(ROTN2_ADDR,ROTN2_FACTORY);
|
|
||||||
writeSetting(ROTN3_ADDR,ROTN3_FACTORY);
|
|
||||||
writeSetting(ROTN4_ADDR,ROTN4_FACTORY);
|
|
||||||
writeSetting(PRIO_ADDR,PRIO_FACTORY);
|
|
||||||
writeSetting(VIB_SENS_ADDR,VIB_SENS_FACTORY);
|
|
||||||
writeSetting(VIB_RETN_ADDR,VIB_RETN_FACTORY);
|
|
||||||
writeSetting(VIB_SQUELCH_ADDR,VIB_SQUELCH_FACTORY);
|
|
||||||
writeSetting(VIB_DIRECTION_ADDR,VIB_DIRECTION_FACTORY);
|
|
||||||
writeSetting(BREATH_CC2_ADDR,BREATH_CC2_FACTORY);
|
|
||||||
writeSetting(BREATH_CC2_RISE_ADDR,BREATH_CC2_RISE_FACTORY);
|
|
||||||
writeSetting(VIB_SENS_BITE_ADDR,VIB_SENS_BITE_FACTORY);
|
|
||||||
writeSetting(VIB_SQUELCH_BITE_ADDR,VIB_SQUELCH_BITE_FACTORY);
|
|
||||||
writeSetting(VIB_CONTROL_ADDR,VIB_CONTROL_FACTORY);
|
|
||||||
}
|
|
||||||
// read settings from EEPROM
|
|
||||||
breathThrVal = readSetting(BREATH_THR_ADDR);
|
|
||||||
breathMaxVal = readSetting(BREATH_MAX_ADDR);
|
|
||||||
portamThrVal = readSetting(PORTAM_THR_ADDR);
|
|
||||||
portamMaxVal = readSetting(PORTAM_MAX_ADDR);
|
|
||||||
pitchbThrVal = readSetting(PITCHB_THR_ADDR);
|
|
||||||
pitchbMaxVal = readSetting(PITCHB_MAX_ADDR);
|
|
||||||
transpose = readSetting(TRANSP_ADDR);
|
|
||||||
MIDIchannel = readSetting(MIDI_ADDR);
|
|
||||||
breathCC = readSetting(BREATH_CC_ADDR);
|
|
||||||
breathAT = readSetting(BREATH_AT_ADDR);
|
|
||||||
velocity = readSetting(VELOCITY_ADDR);
|
|
||||||
portamento = readSetting(PORTAM_ADDR);
|
|
||||||
PBdepth = readSetting(PB_ADDR);
|
|
||||||
extraCT = readSetting(EXTRA_ADDR);
|
|
||||||
vibrato = readSetting(VIBRATO_ADDR);
|
|
||||||
deglitch = readSetting(DEGLITCH_ADDR);
|
|
||||||
extracThrVal = readSetting(EXTRAC_THR_ADDR);
|
|
||||||
extracMaxVal = readSetting(EXTRAC_MAX_ADDR);
|
|
||||||
patch = readSetting(PATCH_ADDR);
|
|
||||||
octave = readSetting(OCTAVE_ADDR);
|
|
||||||
ctouchThrVal = readSetting(CTOUCH_THR_ADDR);
|
|
||||||
curve = readSetting(BREATHCURVE_ADDR);
|
|
||||||
velSmpDl = readSetting(VEL_SMP_DL_ADDR);
|
|
||||||
velBias = readSetting(VEL_BIAS_ADDR);
|
|
||||||
pinkySetting = readSetting(PINKY_KEY_ADDR);
|
|
||||||
fastPatch[0] = readSetting(FP1_ADDR);
|
|
||||||
fastPatch[1] = readSetting(FP2_ADDR);
|
|
||||||
fastPatch[2] = readSetting(FP3_ADDR);
|
|
||||||
fastPatch[3] = readSetting(FP4_ADDR);
|
|
||||||
fastPatch[4] = readSetting(FP5_ADDR);
|
|
||||||
fastPatch[5] = readSetting(FP6_ADDR);
|
|
||||||
fastPatch[6] = readSetting(FP7_ADDR);
|
|
||||||
dipSwBits = readSetting(DIPSW_BITS_ADDR);
|
|
||||||
parallel = readSetting(PARAL_ADDR);
|
|
||||||
rotations[0] = readSetting(ROTN1_ADDR);
|
|
||||||
rotations[1] = readSetting(ROTN2_ADDR);
|
|
||||||
rotations[2] = readSetting(ROTN3_ADDR);
|
|
||||||
rotations[3] = readSetting(ROTN4_ADDR);
|
|
||||||
priority = readSetting(PRIO_ADDR);
|
|
||||||
vibSens = readSetting(VIB_SENS_ADDR);
|
|
||||||
vibRetn = readSetting(VIB_RETN_ADDR);
|
|
||||||
vibSquelch = readSetting(VIB_SQUELCH_ADDR);
|
|
||||||
vibDirection = readSetting(VIB_DIRECTION_ADDR);
|
|
||||||
breathCC2 = readSetting(BREATH_CC2_ADDR);
|
|
||||||
breathCC2Rise = readSetting(BREATH_CC2_RISE_ADDR);
|
|
||||||
vibSensBite = readSetting(VIB_SENS_BITE_ADDR);
|
|
||||||
vibSquelchBite = readSetting(VIB_SQUELCH_BITE_ADDR);
|
|
||||||
vibControl = readSetting(VIB_CONTROL_ADDR);
|
|
||||||
|
|
||||||
legacy = dipSwBits & (1<<1);
|
|
||||||
legacyBrAct = dipSwBits & (1<<2);
|
|
||||||
slowMidi = dipSwBits & (1<<3);
|
|
||||||
gateOpenEnable = dipSwBits & (1<<4);
|
|
||||||
specialKeyEnable = dipSwBits & (1<<5);
|
|
||||||
activePatch = patch;
|
activePatch = patch;
|
||||||
|
|
||||||
touch_Thr = map(ctouchThrVal,ctouchHiLimit,ctouchLoLimit,ttouchLoLimit,ttouchHiLimit);
|
touch_Thr = map(ctouchThrVal,ctouchHiLimit,ctouchLoLimit,ttouchLoLimit,ttouchHiLimit);
|
||||||
|
@ -404,9 +288,10 @@ void setup() {
|
||||||
vibZero += touchRead(vibratoPin);
|
vibZero += touchRead(vibratoPin);
|
||||||
breathCalZero += analogRead(breathSensorPin);
|
breathCalZero += analogRead(breathSensorPin);
|
||||||
if (biteJumper) vibZeroBite += analogRead(A7); else vibZeroBite += touchRead(bitePin);
|
if (biteJumper) vibZeroBite += analogRead(A7); else vibZeroBite += touchRead(bitePin);
|
||||||
digitalWrite( statusLedPin, i&1 );
|
statusLed(i&1);
|
||||||
delay(250);
|
delay(fastBoot?75:250); //Shorter delay for fastboot
|
||||||
}
|
}
|
||||||
|
|
||||||
vibZero /= sampleCount;
|
vibZero /= sampleCount;
|
||||||
breathCalZero /= sampleCount;
|
breathCalZero /= sampleCount;
|
||||||
vibZeroBite /= sampleCount;
|
vibZeroBite /= sampleCount;
|
||||||
|
@ -416,15 +301,14 @@ void setup() {
|
||||||
vibThrBite = vibZeroBite - vibSquelchBite;
|
vibThrBite = vibZeroBite - vibSquelchBite;
|
||||||
vibThrBiteLo = vibZeroBite + vibSquelchBite;
|
vibThrBiteLo = vibZeroBite + vibSquelchBite;
|
||||||
|
|
||||||
digitalWrite(statusLedPin, LOW);
|
if(!fastBoot) {
|
||||||
delay(250);
|
statusLedFlash(500);
|
||||||
digitalWrite(statusLedPin,HIGH);
|
statusLedOff();
|
||||||
delay(250);
|
|
||||||
digitalWrite(statusLedPin,LOW);
|
|
||||||
|
|
||||||
showVersion();
|
showVersion();
|
||||||
|
|
||||||
delay(1500);
|
delay(1500);
|
||||||
|
}
|
||||||
|
|
||||||
mainState = NOTE_OFF; // initialize main state machine
|
mainState = NOTE_OFF; // initialize main state machine
|
||||||
|
|
||||||
|
@ -438,7 +322,7 @@ void setup() {
|
||||||
|
|
||||||
//Serial.begin(9600); // debug
|
//Serial.begin(9600); // debug
|
||||||
|
|
||||||
digitalWrite(statusLedPin,HIGH); // Switch on the onboard LED to indicate power on/ready
|
statusLedOn(); // Switch on the onboard LED to indicate power on/ready
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,54 +353,37 @@ void loop() {
|
||||||
mainState = RISE_WAIT; // Go to next state
|
mainState = RISE_WAIT; // Go to next state
|
||||||
}
|
}
|
||||||
if (legacy || legacyBrAct) {
|
if (legacy || legacyBrAct) {
|
||||||
#if defined(CASSIDY)
|
|
||||||
if (((pbUp > ((pitchbMaxVal + pitchbThrVal) / 2)) && (pbDn > ((pitchbMaxVal + pitchbThrVal) / 2)) && legacy) ||
|
bool bothPB = (pbUp > ((pitchbMaxVal + pitchbThrVal) / 2)) && (pbDn > ((pitchbMaxVal + pitchbThrVal) / 2));
|
||||||
((analogRead(breathSensorPin) < breathCalZero - 900) && legacyBrAct)) { // both pb pads touched or br suck
|
bool brSuck = analogRead(breathSensorPin) < (breathCalZero - (bcasMode?900:800));
|
||||||
#else
|
|
||||||
if (((pbUp > ((pitchbMaxVal + pitchbThrVal) / 2)) && (pbDn > ((pitchbMaxVal + pitchbThrVal) / 2)) && legacy) ||
|
if (
|
||||||
((analogRead(breathSensorPin) < breathCalZero - 800) && legacyBrAct && (pbUp > (pitchbMaxVal + pitchbThrVal) / 2) && (pbDn < (pitchbMaxVal + pitchbThrVal) / 2))) { // both pb pads touched or br suck
|
(bothPB && legacy) ||
|
||||||
#endif
|
(brSuck && legacyBrAct && (bothPB || bcasMode))
|
||||||
|
) { // both pb pads touched or br suck
|
||||||
|
|
||||||
|
|
||||||
fingeredNoteUntransposed = patchLimit(fingeredNoteUntransposed + 1);
|
fingeredNoteUntransposed = patchLimit(fingeredNoteUntransposed + 1);
|
||||||
if (exSensor >= ((extracThrVal + extracMaxVal) / 2)) { // instant midi setting
|
if (exSensor >= ((extracThrVal + extracMaxVal) / 2)) { // instant midi setting
|
||||||
if ((fingeredNoteUntransposed >= 73) && (fingeredNoteUntransposed <= 88)) {
|
if ((fingeredNoteUntransposed >= 73) && (fingeredNoteUntransposed <= 88)) {
|
||||||
MIDIchannel = fingeredNoteUntransposed - 72; // Mid C and up
|
MIDIchannel = fingeredNoteUntransposed - 72; // Mid C and up
|
||||||
#if !defined(CASSIDY)
|
|
||||||
digitalWrite(statusLedPin, LOW);
|
|
||||||
delay(150);
|
|
||||||
digitalWrite(statusLedPin, HIGH);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!pinkyKey) { // note number to patch number
|
if (!pinkyKey) { // note number to patch number
|
||||||
if (patch != fingeredNoteUntransposed) {
|
if (patch != fingeredNoteUntransposed) {
|
||||||
patch = fingeredNoteUntransposed;
|
patch = fingeredNoteUntransposed;
|
||||||
doPatchUpdate = 1;
|
doPatchUpdate = 1;
|
||||||
#if !defined(CASSIDY)
|
|
||||||
digitalWrite(statusLedPin, LOW);
|
|
||||||
delay(150);
|
|
||||||
digitalWrite(statusLedPin, HIGH);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
} else { // hi and lo patch numbers
|
} else { // hi and lo patch numbers
|
||||||
if (fingeredNoteUntransposed > 75) {
|
if (fingeredNoteUntransposed > 75) {
|
||||||
if (patch != patchLimit(fingeredNoteUntransposed + 24)) {
|
if (patch != patchLimit(fingeredNoteUntransposed + 24)) {
|
||||||
patch = patchLimit(fingeredNoteUntransposed + 24); // add 24 to get high numbers 108 to 127
|
patch = patchLimit(fingeredNoteUntransposed + 24); // add 24 to get high numbers 108 to 127
|
||||||
doPatchUpdate = 1;
|
doPatchUpdate = 1;
|
||||||
#if !defined(CASSIDY)
|
|
||||||
digitalWrite(statusLedPin, LOW);
|
|
||||||
delay(150);
|
|
||||||
digitalWrite(statusLedPin, HIGH);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (patch != patchLimit(fingeredNoteUntransposed - 36)) {
|
if (patch != patchLimit(fingeredNoteUntransposed - 36)) {
|
||||||
patch = patchLimit(fingeredNoteUntransposed - 36); // subtract 36 to get low numbers 0 to 36
|
patch = patchLimit(fingeredNoteUntransposed - 36); // subtract 36 to get low numbers 0 to 36
|
||||||
doPatchUpdate = 1;
|
doPatchUpdate = 1;
|
||||||
#if !defined(CASSIDY)
|
|
||||||
digitalWrite(statusLedPin, LOW);
|
|
||||||
delay(150);
|
|
||||||
digitalWrite(statusLedPin, HIGH);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -817,7 +684,7 @@ void loop() {
|
||||||
} else {
|
} else {
|
||||||
if (slowMidi) breath();
|
if (slowMidi) breath();
|
||||||
extraController();
|
extraController();
|
||||||
statusLEDs();
|
updateSensorLEDs();
|
||||||
doorKnobCheck();
|
doorKnobCheck();
|
||||||
}
|
}
|
||||||
ccSendTime = millis();
|
ccSendTime = millis();
|
||||||
|
@ -827,14 +694,14 @@ void loop() {
|
||||||
// this is one of the big reasons the display is for setup use only
|
// this is one of the big reasons the display is for setup use only
|
||||||
drawSensorPixels(); // live sensor monitoring for the setup screens
|
drawSensorPixels(); // live sensor monitoring for the setup screens
|
||||||
if (rotatorOn || slurSustain || parallelChord || subOctaveDouble || gateOpen) {
|
if (rotatorOn || slurSustain || parallelChord || subOctaveDouble || gateOpen) {
|
||||||
digitalWrite(statusLedPin, !digitalRead(statusLedPin));
|
statusLedFlip();
|
||||||
} else if (!digitalRead(statusLedPin)) {
|
} else {
|
||||||
digitalWrite(statusLedPin, HIGH);
|
statusLedOn();
|
||||||
}
|
}
|
||||||
pixelUpdateTime = millis();
|
pixelUpdateTime = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CVSCALEBOARD) // pitch CV from DAC and breath CV from PWM on pin 6, for filtering and scaling on separate board
|
if(dacMode == DAC_MODE_PITCH) { // pitch CV from DAC and breath CV from PWM on pin 6, for filtering and scaling on separate board
|
||||||
targetPitch = (fingeredNote-24)*42;
|
targetPitch = (fingeredNote-24)*42;
|
||||||
if (portIsOn){
|
if (portIsOn){
|
||||||
if (targetPitch > cvPitch){
|
if (targetPitch > cvPitch){
|
||||||
|
@ -851,9 +718,9 @@ void loop() {
|
||||||
}
|
}
|
||||||
analogWrite(dacPin,constrain(cvPitch+map(pitchBend,0,16383,-84,84),0,4095));
|
analogWrite(dacPin,constrain(cvPitch+map(pitchBend,0,16383,-84,84),0,4095));
|
||||||
analogWrite(pwmDacPin,breathCurve(map(constrain(pressureSensor,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,500,4095))); //starting at 0.6V to match use of cv from sensor, so recalibration of cv offset/scaler is not needed
|
analogWrite(pwmDacPin,breathCurve(map(constrain(pressureSensor,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,500,4095))); //starting at 0.6V to match use of cv from sensor, so recalibration of cv offset/scaler is not needed
|
||||||
#else // else breath CV on DAC pin, directly to unused pin of MIDI DIN jack
|
} else if(dacMode == DAC_MODE_BREATH) { // else breath CV on DAC pin, directly to unused pin of MIDI DIN jack
|
||||||
analogWrite(dacPin,breathCurve(map(constrain(pressureSensor,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,4095)));
|
analogWrite(dacPin,breathCurve(map(constrain(pressureSensor,breathThrVal,breathMaxVal),breathThrVal,breathMaxVal,0,4095)));
|
||||||
#endif
|
}
|
||||||
|
|
||||||
midiDiscardInput();
|
midiDiscardInput();
|
||||||
|
|
||||||
|
@ -908,23 +775,6 @@ int patchLimit(int value) {
|
||||||
|
|
||||||
//**************************************************************
|
//**************************************************************
|
||||||
|
|
||||||
void statusLEDs() {
|
|
||||||
if (breathLevel > breathThrVal) { // breath indicator LED, labeled "B" on PCB
|
|
||||||
//analogWrite(bLedPin, map(breathLevel,0,4096,5,breathLedBrightness));
|
|
||||||
analogWrite(bLedPin, map(constrain(breathLevel, breathThrVal, breathMaxVal), breathThrVal, breathMaxVal, 5, breathLedBrightness));
|
|
||||||
} else {
|
|
||||||
analogWrite(bLedPin, 0);
|
|
||||||
}
|
|
||||||
if (portIsOn) { // portamento indicator LED, labeled "P" on PCB
|
|
||||||
//analogWrite(pLedPin, map(biteSensor,0,4096,5,portamLedBrightness));
|
|
||||||
analogWrite(pLedPin, map(constrain(oldport, 0, 127), 0, 127, 5, portamLedBrightness));
|
|
||||||
} else {
|
|
||||||
analogWrite(pLedPin, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//**************************************************************
|
|
||||||
|
|
||||||
void breath() {
|
void breath() {
|
||||||
int breathCCval, breathCCvalFine,breathCC2val;
|
int breathCCval, breathCCvalFine,breathCC2val;
|
||||||
unsigned int breathCCvalHires;
|
unsigned int breathCCvalHires;
|
||||||
|
@ -970,8 +820,8 @@ void pitch_bend() {
|
||||||
int vibMax;
|
int vibMax;
|
||||||
int calculatedPBdepth;
|
int calculatedPBdepth;
|
||||||
byte pbTouched = 0;
|
byte pbTouched = 0;
|
||||||
int vibRead;
|
int vibRead = 0;
|
||||||
int vibReadBite;
|
int vibReadBite = 0;
|
||||||
pbUp = touchRead(pbUpPin); // SENSOR PIN 23 - PCB PIN "Pu"
|
pbUp = touchRead(pbUpPin); // SENSOR PIN 23 - PCB PIN "Pu"
|
||||||
pbDn = touchRead(pbDnPin); // SENSOR PIN 22 - PCB PIN "Pd"
|
pbDn = touchRead(pbDnPin); // SENSOR PIN 22 - PCB PIN "Pd"
|
||||||
halfPitchBendKey = (pinkySetting == PBD) && (touchRead(halfPitchBendKeyPin) > touch_Thr); // SENSOR PIN 1 - PCB PIN "S1" - hold for 1/2 pitchbend value
|
halfPitchBendKey = (pinkySetting == PBD) && (touchRead(halfPitchBendKeyPin) > touch_Thr); // SENSOR PIN 1 - PCB PIN "S1" - hold for 1/2 pitchbend value
|
||||||
|
@ -1071,10 +921,10 @@ void pitch_bend() {
|
||||||
pitchBend = constrain(pitchBend, 0, 16383);
|
pitchBend = constrain(pitchBend, 0, 16383);
|
||||||
|
|
||||||
if (subVibSquelch && (8192 != pitchBend)) {
|
if (subVibSquelch && (8192 != pitchBend)) {
|
||||||
digitalWrite(statusLedPin, LOW);
|
statusLedOff();
|
||||||
vibLedOff = 1;
|
vibLedOff = 1;
|
||||||
} else if (vibLedOff) {
|
} else if (vibLedOff) {
|
||||||
digitalWrite(statusLedPin, HIGH);
|
statusLedOn();
|
||||||
vibLedOff = 0;
|
vibLedOff = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1099,25 +949,14 @@ void doorKnobCheck() {
|
||||||
if ((touchValue[K4Pin] < ctouchThrVal) && (touchValue[R1Pin] < ctouchThrVal) && (touchValue[R2Pin] < ctouchThrVal) && (touchValue[R3Pin] < ctouchThrVal)) { // doorknob grip on canister
|
if ((touchValue[K4Pin] < ctouchThrVal) && (touchValue[R1Pin] < ctouchThrVal) && (touchValue[R2Pin] < ctouchThrVal) && (touchValue[R3Pin] < ctouchThrVal)) { // doorknob grip on canister
|
||||||
if (!gateOpen && (pbUp > ((pitchbMaxVal + pitchbThrVal) / 2))) {
|
if (!gateOpen && (pbUp > ((pitchbMaxVal + pitchbThrVal) / 2))) {
|
||||||
gateOpen = 1;
|
gateOpen = 1;
|
||||||
digitalWrite(statusLedPin, LOW);
|
statusLedFlash(100);
|
||||||
delay(50);
|
|
||||||
digitalWrite(statusLedPin, HIGH);
|
|
||||||
delay(50);
|
|
||||||
} else if (gateOpen && (pbDn > ((pitchbMaxVal + pitchbThrVal) / 2))) {
|
} else if (gateOpen && (pbDn > ((pitchbMaxVal + pitchbThrVal) / 2))) {
|
||||||
gateOpen = 0;
|
gateOpen = 0;
|
||||||
midiPanic();
|
midiPanic();
|
||||||
digitalWrite(statusLedPin, LOW);
|
statusLedFlash(100);
|
||||||
delay(50);
|
statusLedFlash(100);
|
||||||
digitalWrite(statusLedPin, HIGH);
|
statusLedFlash(100);
|
||||||
delay(50);
|
delay(600);
|
||||||
digitalWrite(statusLedPin, LOW);
|
|
||||||
delay(50);
|
|
||||||
digitalWrite(statusLedPin, HIGH);
|
|
||||||
delay(50);
|
|
||||||
digitalWrite(statusLedPin, LOW);
|
|
||||||
delay(50);
|
|
||||||
digitalWrite(statusLedPin, HIGH);
|
|
||||||
delay(700);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (gateOpen) {
|
} else if (gateOpen) {
|
||||||
|
@ -1258,62 +1097,44 @@ void portOff() {
|
||||||
|
|
||||||
void readSwitches() {
|
void readSwitches() {
|
||||||
|
|
||||||
int qTransp;
|
// Read touch pads (MPR121), compare against threshold value
|
||||||
// Read touch pads (MPR121) and put value in variables
|
bool touchKeys[12];
|
||||||
int touchValue[12];
|
|
||||||
for (byte i = 0; i < 12; i++) {
|
for (byte i = 0; i < 12; i++) {
|
||||||
touchValue[i] = touchSensor.filteredData(i);
|
touchKeys[i] = touchSensor.filteredData(i) < ctouchThrVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Octave rollers
|
// Octave rollers
|
||||||
octaveR = 0;
|
octaveR = 0;
|
||||||
if ((touchValue[R5Pin] < ctouchThrVal) && (touchValue[R3Pin] < ctouchThrVal)) octaveR = 6; //R6 = R5 && R3
|
if (touchKeys[R5Pin] && touchKeys[R3Pin]) octaveR = 6; //R6 = R5 && R3
|
||||||
else if (touchValue[R5Pin] < ctouchThrVal) octaveR = 5; //R5
|
else if (touchKeys[R5Pin]) octaveR = 5; //R5
|
||||||
else if (touchValue[R4Pin] < ctouchThrVal) octaveR = 4; //R4
|
else if (touchKeys[R4Pin]) octaveR = 4; //R4
|
||||||
else if ((touchValue[R3Pin] < ctouchThrVal) && lastOctaveR) octaveR = 3; //R3
|
else if (touchKeys[R3Pin] && lastOctaveR) octaveR = 3; //R3
|
||||||
else if (touchValue[R2Pin] < ctouchThrVal) octaveR = 2; //R2
|
else if (touchKeys[R2Pin]) octaveR = 2; //R2
|
||||||
else if (touchValue[R1Pin] < ctouchThrVal) octaveR = 1; //R1
|
else if (touchKeys[R1Pin]) octaveR = 1; //R1
|
||||||
|
|
||||||
lastOctaveR = octaveR;
|
lastOctaveR = octaveR;
|
||||||
|
|
||||||
// Valves and trill keys
|
// Valves and trill keys
|
||||||
K4 = (touchValue[K4Pin] < ctouchThrVal);
|
K1 = touchKeys[K1Pin];
|
||||||
K1 = (touchValue[K1Pin] < ctouchThrVal);
|
K2 = touchKeys[K2Pin];
|
||||||
K2 = (touchValue[K2Pin] < ctouchThrVal);
|
K3 = touchKeys[K3Pin];
|
||||||
K3 = (touchValue[K3Pin] < ctouchThrVal);
|
K4 = touchKeys[K4Pin];
|
||||||
K5 = (touchValue[K5Pin] < ctouchThrVal);
|
K5 = touchKeys[K5Pin];
|
||||||
K6 = (touchValue[K6Pin] < ctouchThrVal);
|
K6 = touchKeys[K6Pin];
|
||||||
K7 = (touchValue[K7Pin] < ctouchThrVal);
|
K7 = touchKeys[K7Pin];
|
||||||
|
|
||||||
pinkyKey = (touchRead(halfPitchBendKeyPin) > touch_Thr); // SENSOR PIN 1 - PCB PIN "S1"
|
pinkyKey = (touchRead(halfPitchBendKeyPin) > touch_Thr); // SENSOR PIN 1 - PCB PIN "S1"
|
||||||
|
|
||||||
if ((pinkySetting < 12) && pinkyKey) {
|
int qTransp = pinkyKey ? pinkySetting-12 : 0;
|
||||||
qTransp = pinkySetting - 12;
|
|
||||||
} else if ((pinkySetting > 12) && pinkyKey) {
|
|
||||||
qTransp = pinkySetting - 12;
|
|
||||||
} else {
|
|
||||||
qTransp = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate midi note number from pressed keys
|
// Calculate midi note number from pressed keys
|
||||||
#if defined(CASSIDY)
|
|
||||||
|
|
||||||
fingeredNoteUntransposed = startNote
|
fingeredNoteUntransposed = startNote
|
||||||
- 2*K1 - K2 - 3*K3 //"Trumpet valves"
|
- 2*K1 - K2 - 3*K3 //"Trumpet valves"
|
||||||
- 5*K4 //Fifth key
|
- 5*K4 //Fifth key
|
||||||
+ 2*K5 + K6 + 3*K7 //Trill keys (different from standard)
|
+ 2*K5 + K6 + trill3_interval*K7 //Trill keys. 3rd trill key interval controlled by setting
|
||||||
+ octaveR*12; //Octave rollers
|
+ octaveR*12; //Octave rollers
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
fingeredNoteUntransposed = startNote
|
|
||||||
- 2*K1 - K2 - 3*K3 //"Trumpet valves"
|
|
||||||
- 5*K4 //Fifth key
|
|
||||||
+ 2*K5 + K6 + 4*K7 //Trill keys
|
|
||||||
+ octaveR*12; //Octave rollers
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int fingeredNoteRead = fingeredNoteUntransposed + transpose - 12 + qTransp;
|
int fingeredNoteRead = fingeredNoteUntransposed + transpose - 12 + qTransp;
|
||||||
|
|
||||||
if (pinkyKey) pitchlatch = fingeredNoteUntransposed; //use pitchlatch to make settings based on note fingered
|
if (pinkyKey) pitchlatch = fingeredNoteUntransposed; //use pitchlatch to make settings based on note fingered
|
||||||
|
|
|
@ -5,14 +5,9 @@
|
||||||
|
|
||||||
// Compile options, comment/uncomment to change
|
// Compile options, comment/uncomment to change
|
||||||
|
|
||||||
#define FIRMWARE_VERSION "1.3.9" // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<<
|
#define FIRMWARE_VERSION "1.4.0" // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<<
|
||||||
|
|
||||||
|
|
||||||
//#define CASSIDY
|
|
||||||
#define CVSCALEBOARD
|
|
||||||
|
|
||||||
#define ON_Delay 20 // Set Delay after ON threshold before velocity is checked (wait for tounging peak)
|
#define ON_Delay 20 // Set Delay after ON threshold before velocity is checked (wait for tounging peak)
|
||||||
//#define touch_Thr 1200 // sensitivity for Teensy touch sensors
|
|
||||||
#define CCN_Port 5 // Controller number for portamento level
|
#define CCN_Port 5 // Controller number for portamento level
|
||||||
#define CCN_PortOnOff 65// Controller number for portamento on/off
|
#define CCN_PortOnOff 65// Controller number for portamento on/off
|
||||||
|
|
||||||
|
@ -21,7 +16,6 @@
|
||||||
#define CC_INTERVAL 2
|
#define CC_INTERVAL 2
|
||||||
|
|
||||||
|
|
||||||
// MAybe move these to config.h (as defines?)
|
|
||||||
#define breathLoLimit 0
|
#define breathLoLimit 0
|
||||||
#define breathHiLimit 4095
|
#define breathHiLimit 4095
|
||||||
#define portamLoLimit 700
|
#define portamLoLimit 700
|
||||||
|
@ -36,4 +30,9 @@
|
||||||
#define ttouchHiLimit 1900
|
#define ttouchHiLimit 1900
|
||||||
|
|
||||||
|
|
||||||
|
#define MIN_LED_BRIGHTNESS 5 // lowest PWM value that still is visible
|
||||||
|
#define BREATH_LED_BRIGHTNESS 500 // up to 4095, PWM
|
||||||
|
#define PORTAM_LED_BRIGHTNESS 500 // up to 4095, PWM
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -73,7 +73,11 @@ extern byte currentRotation;
|
||||||
extern uint16_t rotations[4];
|
extern uint16_t rotations[4];
|
||||||
extern uint16_t parallel; // semitones
|
extern uint16_t parallel; // semitones
|
||||||
|
|
||||||
extern uint16_t wlPower;
|
extern uint16_t bcasMode; //Legacy CASSIDY compile flag
|
||||||
|
extern uint16_t trill3_interval;
|
||||||
|
extern uint16_t fastBoot;
|
||||||
|
extern uint16_t dacMode;
|
||||||
|
|
||||||
|
|
||||||
extern int touch_Thr;
|
extern int touch_Thr;
|
||||||
|
|
||||||
|
@ -112,6 +116,10 @@ extern int vibZeroBite;
|
||||||
extern int vibThrBite;
|
extern int vibThrBite;
|
||||||
extern int vibThrBiteLo;
|
extern int vibThrBiteLo;
|
||||||
|
|
||||||
|
extern int breathLevel;
|
||||||
|
extern byte portIsOn;
|
||||||
|
extern int oldport;
|
||||||
|
|
||||||
// Key variables, TRUE (1) for pressed, FALSE (0) for not pressed
|
// Key variables, TRUE (1) for pressed, FALSE (0) for not pressed
|
||||||
extern byte K1; // Valve 1 (pitch change -2)
|
extern byte K1; // Valve 1 (pitch change -2)
|
||||||
extern byte K2; // Valve 2 (pitch change -1)
|
extern byte K2; // Valve 2 (pitch change -1)
|
||||||
|
|
48
NuEVI/led.cpp
Normal file
48
NuEVI/led.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "hardware.h"
|
||||||
|
#include "globals.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
// Do things with status LED.
|
||||||
|
void statusLedOn() {
|
||||||
|
digitalWrite(statusLedPin, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void statusLedOff() {
|
||||||
|
digitalWrite(statusLedPin, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void statusLed(bool state) {
|
||||||
|
digitalWrite(statusLedPin, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void statusLedFlip() {
|
||||||
|
digitalWrite(statusLedPin, !digitalRead(statusLedPin));
|
||||||
|
}
|
||||||
|
|
||||||
|
void statusLedFlash(uint16_t delayTime) {
|
||||||
|
statusLedOff();
|
||||||
|
delay(delayTime/2);
|
||||||
|
statusLedOn();
|
||||||
|
delay(delayTime/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void statusLedBlink() {
|
||||||
|
statusLedFlash(300);
|
||||||
|
statusLedFlash(300);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateSensorLEDs() {
|
||||||
|
if (breathLevel > breathThrVal) { // breath indicator LED, labeled "B" on PCB
|
||||||
|
//analogWrite(bLedPin, map(breathLevel,0,4096,5,breathLedBrightness));
|
||||||
|
analogWrite(bLedPin, map(constrain(breathLevel, breathThrVal, breathMaxVal), breathThrVal, breathMaxVal, MIN_LED_BRIGHTNESS, BREATH_LED_BRIGHTNESS));
|
||||||
|
} else {
|
||||||
|
analogWrite(bLedPin, 0);
|
||||||
|
}
|
||||||
|
if (portIsOn) { // portamento indicator LED, labeled "P" on PCB
|
||||||
|
//analogWrite(pLedPin, map(biteSensor,0,4096,5,portamLedBrightness));
|
||||||
|
analogWrite(pLedPin, map(constrain(oldport, 0, 127), 0, 127, MIN_LED_BRIGHTNESS, PORTAM_LED_BRIGHTNESS));
|
||||||
|
} else {
|
||||||
|
analogWrite(pLedPin, 0);
|
||||||
|
}
|
||||||
|
}
|
12
NuEVI/led.h
Normal file
12
NuEVI/led.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef __LED_H
|
||||||
|
#define __LED_H
|
||||||
|
|
||||||
|
void statusLedOn();
|
||||||
|
void statusLedOff();
|
||||||
|
void statusLedFlip();
|
||||||
|
void statusLed(bool state);
|
||||||
|
void statusLedFlash(uint16_t delayTime);
|
||||||
|
void statusLedBlink();
|
||||||
|
void updateSensorLEDs();
|
||||||
|
|
||||||
|
#endif
|
137
NuEVI/menu.cpp
137
NuEVI/menu.cpp
|
@ -1,5 +1,3 @@
|
||||||
|
|
||||||
#include <EEPROM.h>
|
|
||||||
#include <Adafruit_GFX.h>
|
#include <Adafruit_GFX.h>
|
||||||
#include <Adafruit_SSD1306.h>
|
#include <Adafruit_SSD1306.h>
|
||||||
#include <Adafruit_MPR121.h>
|
#include <Adafruit_MPR121.h>
|
||||||
|
@ -12,6 +10,7 @@
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "midi.h"
|
#include "midi.h"
|
||||||
#include "numenu.h"
|
#include "numenu.h"
|
||||||
|
#include "led.h"
|
||||||
|
|
||||||
enum CursorIdx {
|
enum CursorIdx {
|
||||||
EMain,
|
EMain,
|
||||||
|
@ -156,14 +155,6 @@ void initDisplay() {
|
||||||
void showVersion() {
|
void showVersion() {
|
||||||
display.setTextColor(WHITE);
|
display.setTextColor(WHITE);
|
||||||
display.setTextSize(1);
|
display.setTextSize(1);
|
||||||
#if defined(CASSIDY)
|
|
||||||
display.setCursor(0,0);
|
|
||||||
display.print("BC");
|
|
||||||
#endif
|
|
||||||
#if defined(CVSCALEBOARD)
|
|
||||||
display.setCursor(15,0);
|
|
||||||
display.print("CV");
|
|
||||||
#endif
|
|
||||||
display.setCursor(85,52);
|
display.setCursor(85,52);
|
||||||
display.print("v.");
|
display.print("v.");
|
||||||
display.println(FIRMWARE_VERSION);
|
display.println(FIRMWARE_VERSION);
|
||||||
|
@ -374,32 +365,9 @@ void drawMenuCursor(byte itemNo, byte color){
|
||||||
|
|
||||||
//***********************************************************
|
//***********************************************************
|
||||||
|
|
||||||
// TODO: Move these to a settings.cpp maybe?
|
|
||||||
void writeSetting(byte address, unsigned short value){
|
|
||||||
union {
|
|
||||||
byte v[2];
|
|
||||||
unsigned short val;
|
|
||||||
} data;
|
|
||||||
data.val = value;
|
|
||||||
EEPROM.update(address, data.v[0]);
|
|
||||||
EEPROM.update(address+1, data.v[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short readSetting(byte address){
|
|
||||||
union {
|
|
||||||
byte v[2];
|
|
||||||
unsigned short val;
|
|
||||||
} data;
|
|
||||||
data.v[0] = EEPROM.read(address);
|
|
||||||
data.v[1] = EEPROM.read(address+1);
|
|
||||||
return data.val;
|
|
||||||
}
|
|
||||||
|
|
||||||
//***********************************************************
|
|
||||||
|
|
||||||
static int readTrills() {
|
static int readTrills() {
|
||||||
readSwitches();
|
readSwitches();
|
||||||
return K5+2*K6+4*K7;
|
return K5+2*K6+trill3_interval*K7;
|
||||||
}
|
}
|
||||||
|
|
||||||
//***********************************************************
|
//***********************************************************
|
||||||
|
@ -450,7 +418,6 @@ static void midiCustomDrawFunc(SubMenuRef __unused, char* __unused, const char**
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//***********************************************************
|
//***********************************************************
|
||||||
|
|
||||||
const MenuEntrySub legacyPBMenu = {
|
const MenuEntrySub legacyPBMenu = {
|
||||||
|
@ -458,8 +425,7 @@ const MenuEntrySub legacyPBMenu = {
|
||||||
[](SubMenuRef __unused, char* out, const char ** __unused unit) {
|
[](SubMenuRef __unused, char* out, const char ** __unused unit) {
|
||||||
strncpy(out, legacy?"ON":"OFF", 4);
|
strncpy(out, legacy?"ON":"OFF", 4);
|
||||||
}, [](const MenuEntrySub & __unused sub) {
|
}, [](const MenuEntrySub & __unused sub) {
|
||||||
dipSwBits = dipSwBits & ~(1<<1);
|
setBit(dipSwBits, DIPSW_LEGACY, legacy);
|
||||||
dipSwBits |= (legacy <<1);
|
|
||||||
writeSetting(DIPSW_BITS_ADDR,dipSwBits);
|
writeSetting(DIPSW_BITS_ADDR,dipSwBits);
|
||||||
}
|
}
|
||||||
, nullptr
|
, nullptr
|
||||||
|
@ -470,9 +436,8 @@ const MenuEntrySub legacyBRMenu = {
|
||||||
[](SubMenuRef __unused, char* out, const char ** __unused unit) {
|
[](SubMenuRef __unused, char* out, const char ** __unused unit) {
|
||||||
strncpy(out, legacyBrAct?"ON":"OFF", 4);
|
strncpy(out, legacyBrAct?"ON":"OFF", 4);
|
||||||
}, [](const MenuEntrySub & __unused sub) {
|
}, [](const MenuEntrySub & __unused sub) {
|
||||||
dipSwBits = dipSwBits & ~(1<<2);
|
setBit(dipSwBits, DIPSW_LEGACYBRACT, legacyBrAct);
|
||||||
dipSwBits |= (legacyBrAct <<2);
|
writeSetting(DIPSW_BITS_ADDR, dipSwBits);
|
||||||
writeSetting(DIPSW_BITS_ADDR,dipSwBits);
|
|
||||||
}
|
}
|
||||||
, nullptr
|
, nullptr
|
||||||
};
|
};
|
||||||
|
@ -482,9 +447,8 @@ const MenuEntrySub gateOpenMenu = {
|
||||||
[](SubMenuRef __unused, char* out, const char ** __unused unit) {
|
[](SubMenuRef __unused, char* out, const char ** __unused unit) {
|
||||||
strncpy(out, gateOpenEnable?"ON":"OFF", 4);
|
strncpy(out, gateOpenEnable?"ON":"OFF", 4);
|
||||||
}, [](const MenuEntrySub & __unused sub) {
|
}, [](const MenuEntrySub & __unused sub) {
|
||||||
dipSwBits = dipSwBits & ~(1<<4);
|
setBit(dipSwBits, DIPSW_GATEOPEN, gateOpenEnable);
|
||||||
dipSwBits |= (gateOpenEnable <<4);
|
writeSetting(DIPSW_BITS_ADDR, dipSwBits);
|
||||||
writeSetting(DIPSW_BITS_ADDR,dipSwBits);
|
|
||||||
}
|
}
|
||||||
, nullptr
|
, nullptr
|
||||||
};
|
};
|
||||||
|
@ -494,29 +458,89 @@ const MenuEntrySub specialKeyMenu = {
|
||||||
[](SubMenuRef __unused, char* out, const char ** __unused unit) {
|
[](SubMenuRef __unused, char* out, const char ** __unused unit) {
|
||||||
strncpy(out, specialKeyEnable?"ON":"OFF", 4);
|
strncpy(out, specialKeyEnable?"ON":"OFF", 4);
|
||||||
}, [](const MenuEntrySub & __unused sub) {
|
}, [](const MenuEntrySub & __unused sub) {
|
||||||
dipSwBits = dipSwBits & ~(1<<5);
|
setBit(dipSwBits, DIPSW_SPKEYENABLE, specialKeyEnable);
|
||||||
dipSwBits |= (specialKeyEnable <<5);
|
writeSetting(DIPSW_BITS_ADDR, dipSwBits);
|
||||||
writeSetting(DIPSW_BITS_ADDR,dipSwBits);
|
}
|
||||||
|
, nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
const MenuEntrySub trill3Menu = {
|
||||||
|
MenuType::ESub, "3RD TRILL", "3RD TRILL", &trill3_interval, 3, 4, MenuEntryFlags::ENone,
|
||||||
|
[](SubMenuRef __unused, char* out, const char** __unused unit) {
|
||||||
|
numToString(trill3_interval, out, true);
|
||||||
|
},
|
||||||
|
[](SubMenuRef __unused) { writeSetting(TRILL3_INTERVAL_ADDR, trill3_interval); }
|
||||||
|
, nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
const MenuEntrySub bcasModeMenu = {
|
||||||
|
MenuType::ESub, "BCAS MODE", "BCAS MODE", &bcasMode, 0, 1, MenuEntryFlags::ENone,
|
||||||
|
[](SubMenuRef __unused, char* out, const char** __unused unit) {
|
||||||
|
strncpy(out, bcasMode?"ON":"OFF", 4);
|
||||||
|
},
|
||||||
|
[](SubMenuRef __unused) {
|
||||||
|
setBit(dipSwBits, DIPSW_BCASMODE, bcasMode);
|
||||||
|
writeSetting(DIPSW_BITS_ADDR, dipSwBits);
|
||||||
|
}
|
||||||
|
, nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
const MenuEntrySub dacModeMenu = {
|
||||||
|
MenuType::ESub, "DAC OUT", "DAC OUT", &dacMode, 0, 1, MenuEntryFlags::ENone,
|
||||||
|
[](SubMenuRef __unused, char* out, const char** __unused unit) {
|
||||||
|
const char* dacModeLabels[] = { "BRTH", "PTCH"};
|
||||||
|
strncpy(out, dacModeLabels[dacMode], 5);
|
||||||
|
},
|
||||||
|
[](SubMenuRef __unused) { writeSetting(DAC_MODE_ADDR, dacMode); }
|
||||||
|
, nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
const MenuEntrySub fastBootMenu = {
|
||||||
|
MenuType::ESub, "FAST BOOT", "FAST BOOT", &fastBoot, 0, 1, MenuEntryFlags::ENone,
|
||||||
|
[](SubMenuRef __unused, char* out, const char** __unused unit) {
|
||||||
|
strncpy(out, fastBoot?"ON":"OFF", 4);
|
||||||
|
},
|
||||||
|
[](SubMenuRef __unused) {
|
||||||
|
setBit(dipSwBits, DIPSW_FASTBOOT, fastBoot);
|
||||||
|
writeSetting(DIPSW_BITS_ADDR, dipSwBits);
|
||||||
}
|
}
|
||||||
, nullptr
|
, nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static uint16_t wireless_power=0;
|
||||||
|
static uint16_t wireless_channel=4;
|
||||||
|
|
||||||
const MenuEntrySub wlPowerMenu = {
|
const MenuEntrySub wlPowerMenu = {
|
||||||
MenuType::ESub, "WL POWER", "WL POWER", &wlPower, 0, 3, MenuEntryFlags::ENone,
|
MenuType::ESub, "WL POWER", "WL POWER", &wireless_power, 0, 3, MenuEntryFlags::ENone,
|
||||||
[](SubMenuRef __unused, char* out, const char** __unused unit) {
|
[](SubMenuRef __unused, char* out, const char** __unused unit) {
|
||||||
numToString(-6*wlPower, out, true);
|
numToString(-6*wireless_power, out, true);
|
||||||
},
|
},
|
||||||
[](SubMenuRef __unused) { sendWLPower(wlPower); }
|
[](SubMenuRef __unused) { sendWLPower(wireless_power); }
|
||||||
, nullptr
|
, nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const MenuEntrySub wlChannelMenu = {
|
||||||
|
MenuType::ESub, "WL CHAN", "WL CHAN", &wireless_channel, 4, 80, MenuEntryFlags::ENone,
|
||||||
|
[](SubMenuRef __unused, char* out, const char** __unused unit) {
|
||||||
|
numToString(wireless_channel, out, false);
|
||||||
|
},
|
||||||
|
[](SubMenuRef __unused) { sendWLChannel(wireless_channel); }
|
||||||
|
, nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const MenuEntry* extrasMenuEntries[] = {
|
const MenuEntry* extrasMenuEntries[] = {
|
||||||
(MenuEntry*)&legacyPBMenu,
|
(MenuEntry*)&legacyPBMenu,
|
||||||
(MenuEntry*)&legacyBRMenu,
|
(MenuEntry*)&legacyBRMenu,
|
||||||
(MenuEntry*)&gateOpenMenu,
|
(MenuEntry*)&gateOpenMenu,
|
||||||
(MenuEntry*)&specialKeyMenu,
|
(MenuEntry*)&specialKeyMenu,
|
||||||
|
(MenuEntry*)&trill3Menu,
|
||||||
|
(MenuEntry*)&bcasModeMenu,
|
||||||
|
(MenuEntry*)&dacModeMenu,
|
||||||
|
(MenuEntry*)&fastBootMenu,
|
||||||
(MenuEntry*)&wlPowerMenu,
|
(MenuEntry*)&wlPowerMenu,
|
||||||
|
(MenuEntry*)&wlChannelMenu,
|
||||||
};
|
};
|
||||||
|
|
||||||
const MenuPage extrasMenuPage = {
|
const MenuPage extrasMenuPage = {
|
||||||
|
@ -1205,17 +1229,6 @@ static bool updatePage(const MenuPage *page, KeyState &input, uint32_t timeNow)
|
||||||
return redraw;
|
return redraw;
|
||||||
}
|
}
|
||||||
|
|
||||||
//***********************************************************
|
|
||||||
// This should be moved to a separate file/process that handles only led
|
|
||||||
static void statusBlink() {
|
|
||||||
digitalWrite(statusLedPin,LOW);
|
|
||||||
delay(150);
|
|
||||||
digitalWrite(statusLedPin,HIGH);
|
|
||||||
delay(150);
|
|
||||||
digitalWrite(statusLedPin,LOW);
|
|
||||||
delay(150);
|
|
||||||
digitalWrite(statusLedPin,HIGH);
|
|
||||||
}
|
|
||||||
|
|
||||||
//***********************************************************
|
//***********************************************************
|
||||||
|
|
||||||
|
@ -1368,12 +1381,12 @@ static bool idlePageUpdate(KeyState& __unused input, uint32_t __unused timeNow)
|
||||||
legacyBrAct = !legacyBrAct;
|
legacyBrAct = !legacyBrAct;
|
||||||
dipSwBits = dipSwBits ^ (1<<2);
|
dipSwBits = dipSwBits ^ (1<<2);
|
||||||
writeSetting(DIPSW_BITS_ADDR,dipSwBits);
|
writeSetting(DIPSW_BITS_ADDR,dipSwBits);
|
||||||
statusBlink();
|
statusLedBlink();
|
||||||
} else if ((exSensor >= ((extracThrVal+extracMaxVal)/2))) { // switch pb pad activated legacy settings control on/off
|
} else if ((exSensor >= ((extracThrVal+extracMaxVal)/2))) { // switch pb pad activated legacy settings control on/off
|
||||||
legacy = !legacy;
|
legacy = !legacy;
|
||||||
dipSwBits = dipSwBits ^ (1<<1);
|
dipSwBits = dipSwBits ^ (1<<1);
|
||||||
writeSetting(DIPSW_BITS_ADDR,dipSwBits);
|
writeSetting(DIPSW_BITS_ADDR,dipSwBits);
|
||||||
statusBlink();
|
statusLedBlink();
|
||||||
} else if (pinkyKey && !specialKey){ //hold pinky key for rotator menu, and if too high touch sensing blocks regular menu, touching special key helps
|
} else if (pinkyKey && !specialKey){ //hold pinky key for rotator menu, and if too high touch sensing blocks regular menu, touching special key helps
|
||||||
display.ssd1306_command(SSD1306_DISPLAYON);
|
display.ssd1306_command(SSD1306_DISPLAYON);
|
||||||
menuState= ROTATOR_MENU;
|
menuState= ROTATOR_MENU;
|
||||||
|
|
|
@ -41,8 +41,6 @@ void initDisplay();
|
||||||
void showVersion();
|
void showVersion();
|
||||||
void menu();
|
void menu();
|
||||||
void drawSensorPixels();
|
void drawSensorPixels();
|
||||||
unsigned short readSetting(byte address);
|
|
||||||
void writeSetting(byte address, unsigned short value);
|
|
||||||
|
|
||||||
int updateAdjustMenu(uint32_t timeNow, KeyState &input, bool firstRun, bool drawSensor);
|
int updateAdjustMenu(uint32_t timeNow, KeyState &input, bool firstRun, bool drawSensor);
|
||||||
bool adjustPageUpdate(KeyState &input, uint32_t timeNow);
|
bool adjustPageUpdate(KeyState &input, uint32_t timeNow);
|
||||||
|
|
|
@ -163,4 +163,20 @@ void sendWLPower(const uint8_t level) {
|
||||||
buf[5] = level;
|
buf[5] = level;
|
||||||
dinMIDIsendSysex(buf, 6);
|
dinMIDIsendSysex(buf, 6);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sendWLChannel(const uint8_t channel) {
|
||||||
|
uint8_t buf[6] = {
|
||||||
|
0x00, 0x21, 0x11, //Manufacturer id
|
||||||
|
0x02, //TX02
|
||||||
|
0x05, //Set channel
|
||||||
|
0x04 //Channel value (4-80)
|
||||||
|
};
|
||||||
|
|
||||||
|
if(channel<4 || channel>80) return; //Don't send invalid values
|
||||||
|
|
||||||
|
buf[5] = channel;
|
||||||
|
dinMIDIsendSysex(buf, 6);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -30,8 +30,7 @@ void dinMIDIsendProgramChange(uint8_t value, uint8_t ch);
|
||||||
void dinMIDIsendPitchBend(uint16_t pb, uint8_t ch);
|
void dinMIDIsendPitchBend(uint16_t pb, uint8_t ch);
|
||||||
void dinMIDIsendSysex(const uint8_t data[], const uint8_t length);
|
void dinMIDIsendSysex(const uint8_t data[], const uint8_t length);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void sendWLPower(const uint8_t level);
|
void sendWLPower(const uint8_t level);
|
||||||
|
void sendWLChannel(const uint8_t channel);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
201
NuEVI/settings.cpp
Normal file
201
NuEVI/settings.cpp
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
|
||||||
|
#include "settings.h"
|
||||||
|
#include "globals.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "hardware.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
//Read settings from eeprom. Returns wether or not anything was written (due to factory reset or upgrade)
|
||||||
|
void readEEPROM() {
|
||||||
|
bool factoryReset = !digitalRead(ePin) && !digitalRead(mPin);
|
||||||
|
|
||||||
|
// if stored settings are not for current version, or Enter+Menu are pressed at startup, they are replaced by factory settings
|
||||||
|
uint16_t settingsVersion = readSetting(VERSION_ADDR);
|
||||||
|
|
||||||
|
// blank eeprom will be 0xFFFF. For a full reset, call it "version 0" so everything gets overwritten.
|
||||||
|
if (factoryReset || settingsVersion == 0xffffu) {
|
||||||
|
settingsVersion = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(settingsVersion != EEPROM_VERSION) {
|
||||||
|
|
||||||
|
if(settingsVersion < 24) { //Oldest version from which any settings are recognized
|
||||||
|
writeSetting(BREATH_THR_ADDR, BREATH_THR_FACTORY);
|
||||||
|
writeSetting(BREATH_MAX_ADDR, BREATH_MAX_FACTORY);
|
||||||
|
if (digitalRead(biteJumperPin)){ //PBITE (if pulled low with jumper, pressure sensor is used instead of capacitive bite sensing)
|
||||||
|
writeSetting(PORTAM_THR_ADDR, PORTAM_THR_FACTORY);
|
||||||
|
writeSetting(PORTAM_MAX_ADDR, PORTAM_MAX_FACTORY);
|
||||||
|
} else {
|
||||||
|
writeSetting(PORTAM_THR_ADDR, PORTPR_THR_FACTORY);
|
||||||
|
writeSetting(PORTAM_MAX_ADDR, PORTPR_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);
|
||||||
|
|
||||||
|
writeSetting(TRANSP_ADDR, TRANSP_FACTORY);
|
||||||
|
writeSetting(MIDI_ADDR, MIDI_FACTORY);
|
||||||
|
writeSetting(BREATH_CC_ADDR, BREATH_CC_FACTORY);
|
||||||
|
writeSetting(BREATH_AT_ADDR, BREATH_AT_FACTORY);
|
||||||
|
writeSetting(VELOCITY_ADDR, VELOCITY_FACTORY);
|
||||||
|
writeSetting(PORTAM_ADDR, PORTAM_FACTORY);
|
||||||
|
writeSetting(PB_ADDR, PB_FACTORY);
|
||||||
|
writeSetting(EXTRA_ADDR, EXTRA_FACTORY);
|
||||||
|
writeSetting(VIBRATO_ADDR, VIBRATO_FACTORY);
|
||||||
|
writeSetting(DEGLITCH_ADDR, DEGLITCH_FACTORY);
|
||||||
|
writeSetting(PATCH_ADDR, PATCH_FACTORY);
|
||||||
|
writeSetting(OCTAVE_ADDR, OCTAVE_FACTORY);
|
||||||
|
writeSetting(BREATHCURVE_ADDR, BREATHCURVE_FACTORY);
|
||||||
|
writeSetting(VEL_SMP_DL_ADDR, VEL_SMP_DL_FACTORY);
|
||||||
|
writeSetting(VEL_BIAS_ADDR, VEL_BIAS_FACTORY);
|
||||||
|
writeSetting(PINKY_KEY_ADDR, PINKY_KEY_FACTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(settingsVersion < 26) {
|
||||||
|
writeSetting(FP1_ADDR, 0);
|
||||||
|
writeSetting(FP2_ADDR, 0);
|
||||||
|
writeSetting(FP3_ADDR, 0);
|
||||||
|
writeSetting(FP4_ADDR, 0);
|
||||||
|
writeSetting(FP5_ADDR, 0);
|
||||||
|
writeSetting(FP6_ADDR, 0);
|
||||||
|
writeSetting(FP7_ADDR, 0);
|
||||||
|
writeSetting(DIPSW_BITS_ADDR, DIPSW_BITS_FACTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(settingsVersion < 28) {
|
||||||
|
writeSetting(PARAL_ADDR, PARAL_FACTORY);
|
||||||
|
writeSetting(ROTN1_ADDR, ROTN1_FACTORY);
|
||||||
|
writeSetting(ROTN2_ADDR, ROTN2_FACTORY);
|
||||||
|
writeSetting(ROTN3_ADDR, ROTN3_FACTORY);
|
||||||
|
writeSetting(ROTN4_ADDR, ROTN4_FACTORY);
|
||||||
|
writeSetting(PRIO_ADDR, PRIO_FACTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(settingsVersion < 29) {
|
||||||
|
writeSetting(VIB_SENS_ADDR, VIB_SENS_FACTORY);
|
||||||
|
writeSetting(VIB_RETN_ADDR, VIB_RETN_FACTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(settingsVersion < 31) {
|
||||||
|
writeSetting(VIB_SQUELCH_ADDR, VIB_SQUELCH_FACTORY);
|
||||||
|
writeSetting(VIB_DIRECTION_ADDR, VIB_DIRECTION_FACTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(settingsVersion < 32) {
|
||||||
|
writeSetting(BREATH_CC2_ADDR, BREATH_CC2_FACTORY);
|
||||||
|
writeSetting(BREATH_CC2_RISE_ADDR, BREATH_CC2_RISE_FACTORY);
|
||||||
|
writeSetting(VIB_SENS_BITE_ADDR, VIB_SENS_BITE_FACTORY);
|
||||||
|
writeSetting(VIB_SQUELCH_BITE_ADDR, VIB_SQUELCH_BITE_FACTORY);
|
||||||
|
writeSetting(VIB_CONTROL_ADDR, VIB_CONTROL_FACTORY);
|
||||||
|
writeSetting(TRILL3_INTERVAL_ADDR, TRILL3_INTERVAL_FACTORY);
|
||||||
|
writeSetting(DAC_MODE_ADDR, DAC_MODE_FACTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeSetting(VERSION_ADDR, EEPROM_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read all settings from EEPROM
|
||||||
|
breathThrVal = readSettingBounded(BREATH_THR_ADDR, breathLoLimit, breathHiLimit, BREATH_THR_FACTORY);
|
||||||
|
breathMaxVal = readSettingBounded(BREATH_MAX_ADDR, breathLoLimit, breathHiLimit, BREATH_MAX_FACTORY);
|
||||||
|
portamThrVal = readSettingBounded(PORTAM_THR_ADDR, portamLoLimit, portamHiLimit, PORTAM_THR_FACTORY);
|
||||||
|
portamMaxVal = readSettingBounded(PORTAM_MAX_ADDR, portamLoLimit, portamHiLimit, PORTAM_MAX_FACTORY);
|
||||||
|
pitchbThrVal = readSettingBounded(PITCHB_THR_ADDR, pitchbLoLimit, pitchbHiLimit, PITCHB_THR_FACTORY);
|
||||||
|
pitchbMaxVal = readSettingBounded(PITCHB_MAX_ADDR, pitchbLoLimit, pitchbHiLimit, PITCHB_MAX_FACTORY);
|
||||||
|
transpose = readSettingBounded(TRANSP_ADDR, 0, 24, TRANSP_FACTORY);
|
||||||
|
MIDIchannel = readSettingBounded(MIDI_ADDR, 1, 16, MIDI_FACTORY);
|
||||||
|
breathCC = readSettingBounded(BREATH_CC_ADDR, 0, 127, 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, 2, 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);
|
||||||
|
deglitch = readSettingBounded(DEGLITCH_ADDR, 0, 70, DEGLITCH_FACTORY);
|
||||||
|
extracThrVal = readSettingBounded(EXTRAC_THR_ADDR, extracLoLimit, extracHiLimit, EXTRAC_THR_FACTORY);
|
||||||
|
extracMaxVal = readSettingBounded(EXTRAC_MAX_ADDR, extracLoLimit, extracHiLimit, EXTRAC_MAX_FACTORY);
|
||||||
|
patch = readSettingBounded(PATCH_ADDR, 0, 127, PATCH_FACTORY);
|
||||||
|
octave = readSettingBounded(OCTAVE_ADDR, 0, 6, OCTAVE_FACTORY);
|
||||||
|
ctouchThrVal = readSettingBounded(CTOUCH_THR_ADDR, ctouchLoLimit, ctouchHiLimit, CTOUCH_THR_FACTORY);
|
||||||
|
curve = readSettingBounded(BREATHCURVE_ADDR, 0, 12, BREATHCURVE_FACTORY);
|
||||||
|
velSmpDl = readSettingBounded(VEL_SMP_DL_ADDR, 0, 30, VEL_SMP_DL_FACTORY);
|
||||||
|
velBias = readSettingBounded(VEL_BIAS_ADDR, 0, 9, VEL_BIAS_FACTORY);
|
||||||
|
pinkySetting = readSettingBounded(PINKY_KEY_ADDR, 0, 24, PINKY_KEY_FACTORY);
|
||||||
|
fastPatch[0] = readSettingBounded(FP1_ADDR, 0, 127, 0);
|
||||||
|
fastPatch[1] = readSettingBounded(FP2_ADDR, 0, 127, 0);
|
||||||
|
fastPatch[2] = readSettingBounded(FP3_ADDR, 0, 127, 0);
|
||||||
|
fastPatch[3] = readSettingBounded(FP4_ADDR, 0, 127, 0);
|
||||||
|
fastPatch[4] = readSettingBounded(FP5_ADDR, 0, 127, 0);
|
||||||
|
fastPatch[5] = readSettingBounded(FP6_ADDR, 0, 127, 0);
|
||||||
|
fastPatch[6] = readSettingBounded(FP7_ADDR, 0, 127, 0);
|
||||||
|
dipSwBits = readSetting(DIPSW_BITS_ADDR);
|
||||||
|
parallel = readSettingBounded(PARAL_ADDR, 0, 48, PARAL_FACTORY);
|
||||||
|
rotations[0] = readSettingBounded(ROTN1_ADDR, 0, 48, ROTN1_FACTORY);
|
||||||
|
rotations[1] = readSettingBounded(ROTN2_ADDR, 0, 48, ROTN2_FACTORY);
|
||||||
|
rotations[2] = readSettingBounded(ROTN3_ADDR, 0, 48, ROTN3_FACTORY);
|
||||||
|
rotations[3] = readSettingBounded(ROTN4_ADDR, 0, 48, ROTN4_FACTORY);
|
||||||
|
priority = readSettingBounded(PRIO_ADDR, 0, 1, PRIO_FACTORY);
|
||||||
|
vibSens = readSettingBounded(VIB_SENS_ADDR, 1, 12, VIB_SENS_FACTORY);
|
||||||
|
vibRetn = readSettingBounded(VIB_RETN_ADDR, 0, 4, VIB_RETN_FACTORY);
|
||||||
|
vibSquelch = readSettingBounded(VIB_SQUELCH_ADDR, 1, 30, VIB_SQUELCH_FACTORY);
|
||||||
|
vibDirection = readSettingBounded(VIB_DIRECTION_ADDR, 0, 1, VIB_DIRECTION_FACTORY);
|
||||||
|
breathCC2 = readSettingBounded(BREATH_CC2_ADDR, 0, 127, BREATH_CC2_FACTORY);
|
||||||
|
breathCC2Rise = readSettingBounded(BREATH_CC2_RISE_ADDR, 1, 10, BREATH_CC2_RISE_FACTORY);
|
||||||
|
vibSensBite = readSettingBounded(VIB_SENS_BITE_ADDR, 1, 12, VIB_SENS_BITE_FACTORY);
|
||||||
|
vibSquelchBite = readSettingBounded(VIB_SQUELCH_BITE_ADDR, 1, 30, VIB_SQUELCH_BITE_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);
|
||||||
|
trill3_interval = readSettingBounded(TRILL3_INTERVAL_ADDR, 3, 4, TRILL3_INTERVAL_FACTORY);
|
||||||
|
|
||||||
|
//Flags stored in bit field
|
||||||
|
fastBoot = (dipSwBits & (1<<DIPSW_FASTBOOT))?1:0;
|
||||||
|
legacy = (dipSwBits & (1<<DIPSW_LEGACY))?1:0;
|
||||||
|
legacyBrAct = (dipSwBits & (1<<DIPSW_LEGACYBRACT))?1:0;
|
||||||
|
slowMidi = (dipSwBits & (1<<DIPSW_SLOWMIDI))?1:0;
|
||||||
|
gateOpenEnable = (dipSwBits & (1<<DIPSW_GATEOPEN))?1:0;
|
||||||
|
specialKeyEnable = (dipSwBits & (1<<DIPSW_SPKEYENABLE))?1:0;
|
||||||
|
bcasMode = (dipSwBits & (1<<DIPSW_BCASMODE))?1:0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Poke at a certain bit in a bit field
|
||||||
|
void setBit(uint16_t &bitfield, const uint8_t pos, const uint16_t value) {
|
||||||
|
bitfield = (bitfield & ~(1<<pos)) | ((value?1:0)<<pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Read and write EEPROM data
|
||||||
|
void writeSetting(uint16_t address, uint16_t value) {
|
||||||
|
union {
|
||||||
|
uint8_t v[2];
|
||||||
|
uint16_t val;
|
||||||
|
} data;
|
||||||
|
data.val = value;
|
||||||
|
EEPROM.update(address, data.v[0]);
|
||||||
|
EEPROM.update(address+1, data.v[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t readSetting(uint16_t address) {
|
||||||
|
union {
|
||||||
|
uint8_t v[2];
|
||||||
|
uint16_t val;
|
||||||
|
} data;
|
||||||
|
data.v[0] = EEPROM.read(address);
|
||||||
|
data.v[1] = EEPROM.read(address+1);
|
||||||
|
return data.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t readSettingBounded(uint16_t address, uint16_t min, uint16_t max, uint16_t defaultValue) {
|
||||||
|
uint16_t val = readSetting(address);
|
||||||
|
if(val < min || val > max) {
|
||||||
|
val = defaultValue;
|
||||||
|
writeSetting(address, val);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
|
@ -1,8 +1,7 @@
|
||||||
|
|
||||||
#ifndef __SETTINGS_H
|
#ifndef __SETTINGS_H
|
||||||
#define __SETTINGS_H
|
#define __SETTINGS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
// EEPROM addresses for settings
|
// EEPROM addresses for settings
|
||||||
#define VERSION_ADDR 0
|
#define VERSION_ADDR 0
|
||||||
|
@ -54,9 +53,26 @@
|
||||||
#define VIB_SENS_BITE_ADDR 92
|
#define VIB_SENS_BITE_ADDR 92
|
||||||
#define VIB_SQUELCH_BITE_ADDR 94
|
#define VIB_SQUELCH_BITE_ADDR 94
|
||||||
#define VIB_CONTROL_ADDR 96
|
#define VIB_CONTROL_ADDR 96
|
||||||
|
#define TRILL3_INTERVAL_ADDR 98
|
||||||
|
#define DAC_MODE_ADDR 100
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//DAC output modes
|
||||||
|
#define DAC_MODE_BREATH 0
|
||||||
|
#define DAC_MODE_PITCH 1
|
||||||
|
|
||||||
|
#define DIPSW_FASTBOOT 0
|
||||||
|
#define DIPSW_LEGACY 1
|
||||||
|
#define DIPSW_LEGACYBRACT 2
|
||||||
|
#define DIPSW_SLOWMIDI 3
|
||||||
|
#define DIPSW_GATEOPEN 4
|
||||||
|
#define DIPSW_SPKEYENABLE 5
|
||||||
|
#define DIPSW_BCASMODE 6
|
||||||
|
|
||||||
|
|
||||||
//"factory" values for settings
|
//"factory" values for settings
|
||||||
#define VERSION 32
|
#define EEPROM_VERSION 32
|
||||||
#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
|
||||||
|
@ -101,4 +117,15 @@
|
||||||
#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 DAC_MODE_FACTORY DAC_MODE_BREATH
|
||||||
|
|
||||||
|
|
||||||
|
void readEEPROM();
|
||||||
|
void setBit(uint16_t &bitfield, const uint8_t pos, const uint16_t value);
|
||||||
|
uint16_t readSetting(uint16_t address);
|
||||||
|
void writeSetting(uint16_t address, uint16_t value);
|
||||||
|
uint16_t readSettingBounded(uint16_t address, uint16_t min, uint16_t max, uint16_t defaultValue);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,11 +16,7 @@ added directly via the Library Manager in the Arduino IDE:
|
||||||
* Adafruit MPR121
|
* Adafruit MPR121
|
||||||
* Adafruit GFX
|
* Adafruit GFX
|
||||||
* Adafruit SSD1306 (version 1.2.9 or above)
|
* Adafruit SSD1306 (version 1.2.9 or above)
|
||||||
|
* NuEVI also includes on the [Filters](https://github.com/JonHub/Filters) library by Jonathan Driscoll, but that is no longer an external dependency.
|
||||||
You also need to install [Edgar Bonet's Filters library](https://github.com/edgar-bonet/Filters),
|
|
||||||
specifically the `fix-integer-overflow` branch. One of the easiest way to do that is to download the
|
|
||||||
git repo [as a zip file](https://github.com/edgar-bonet/Filters/archive/fix-integer-overflow.zip),
|
|
||||||
and then add that in the Arduino IDE (under Sketch -> Include Library -> Add .ZIP library)
|
|
||||||
|
|
||||||
|
|
||||||
### Compile options
|
### Compile options
|
||||||
|
|
|
@ -17,7 +17,7 @@ CXXFLAGS= $(CFLAGS) -std=c++14
|
||||||
LIBS=-framework SDL2 -lc++ -lc -framework OpenGL
|
LIBS=-framework SDL2 -lc++ -lc -framework OpenGL
|
||||||
LDFLAGS=-macosx_version_min 10.9 -rpath @executable_path/../Frameworks
|
LDFLAGS=-macosx_version_min 10.9 -rpath @executable_path/../Frameworks
|
||||||
|
|
||||||
SYSINC = ~/Documents/Arduino/libraries/Filters ./include
|
SYSINC = ./include
|
||||||
INCS = ../NuEVI ./include ./imgui ./gl3w
|
INCS = ../NuEVI ./include ./imgui ./gl3w
|
||||||
|
|
||||||
INCDIRS = $(addprefix -isystem ,$(SYSINC))
|
INCDIRS = $(addprefix -isystem ,$(SYSINC))
|
||||||
|
@ -28,6 +28,9 @@ TARGET=nuevisim
|
||||||
|
|
||||||
CXXFILES= ../NuEVI/menu.cpp \
|
CXXFILES= ../NuEVI/menu.cpp \
|
||||||
../NuEVI/adjustmenu.cpp \
|
../NuEVI/adjustmenu.cpp \
|
||||||
|
../NuEVI/midi.cpp \
|
||||||
|
../NuEVI/settings.cpp \
|
||||||
|
../NuEVI/led.cpp \
|
||||||
src/nuevisim.cpp \
|
src/nuevisim.cpp \
|
||||||
src/simeeprom.cpp \
|
src/simeeprom.cpp \
|
||||||
src/Print.cpp \
|
src/Print.cpp \
|
||||||
|
@ -35,7 +38,6 @@ CXXFILES= ../NuEVI/menu.cpp \
|
||||||
src/simwire.cpp \
|
src/simwire.cpp \
|
||||||
src/simusbmidi.cpp \
|
src/simusbmidi.cpp \
|
||||||
src/filters.cpp \
|
src/filters.cpp \
|
||||||
../NuEVI/midi.cpp \
|
|
||||||
src/Adafruit_GFX_sim.cpp \
|
src/Adafruit_GFX_sim.cpp \
|
||||||
src/Adafruit_SSD1306_sim.cpp \
|
src/Adafruit_SSD1306_sim.cpp \
|
||||||
src/Adafruit_MPR121_sim.cpp \
|
src/Adafruit_MPR121_sim.cpp \
|
||||||
|
@ -45,6 +47,7 @@ CXXFILES= ../NuEVI/menu.cpp \
|
||||||
imgui/examples/imgui_impl_sdl.cpp \
|
imgui/examples/imgui_impl_sdl.cpp \
|
||||||
imgui/examples/imgui_impl_opengl3.cpp
|
imgui/examples/imgui_impl_opengl3.cpp
|
||||||
|
|
||||||
|
|
||||||
CFILES= gl3w/gl3w.c
|
CFILES= gl3w/gl3w.c
|
||||||
|
|
||||||
OBJS=$(CXXFILES:.cpp=.o) $(CFILES:.c=.o)
|
OBJS=$(CXXFILES:.cpp=.o) $(CFILES:.c=.o)
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "FilterOnepole.cpp"
|
#include "FilterOnePole.cpp"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue