Sensor updates
This commit is contained in:
parent
f4e95668ce
commit
80c8ccd54b
8 changed files with 251 additions and 179 deletions
|
@ -11,7 +11,9 @@
|
||||||
#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
|
||||||
#define START_NOTE 36 // set startNote to C (change this value in steps of 12 to start in other octaves)
|
#define START_NOTE 36 // set startNote to C (change this value in steps of 12 to start in other octaves)
|
||||||
#define FILTER_FREQ 10.0
|
#define FILTER_FREQ 30.0
|
||||||
|
#define SPIKE_FILTER_FREQ 150.0 // Detect fast changes in breath
|
||||||
|
#define ICM_FILTER_FREQ 2
|
||||||
#define BREATH_THR_MAX_BOOST 40.0
|
#define BREATH_THR_MAX_BOOST 40.0
|
||||||
#define CAP_SENS_ABSOLUTE_MAX 1000 // For inverting capacitive sensors
|
#define CAP_SENS_ABSOLUTE_MAX 1000 // For inverting capacitive sensors
|
||||||
#define PRESSURE_SENS_MULTIPLIER 10 // Multiply pressure sens so it's not a float
|
#define PRESSURE_SENS_MULTIPLIER 10 // Multiply pressure sens so it's not a float
|
||||||
|
@ -50,15 +52,16 @@
|
||||||
#define BREATH_HI_LIMIT 12000
|
#define BREATH_HI_LIMIT 12000
|
||||||
#define BITE_LO_LIMIT 500
|
#define BITE_LO_LIMIT 500
|
||||||
#define BITE_HI_LIMIT 1000
|
#define BITE_HI_LIMIT 1000
|
||||||
#define PITCHB_LO_LIMIT -100
|
#define PITCHB_LO_LIMIT -2000
|
||||||
#define PITCHB_HI_LIMIT 100
|
#define PITCHB_HI_LIMIT 2000
|
||||||
#define EXTRA_LO_LIMIT -100
|
#define EXTRA_LO_LIMIT -2000
|
||||||
#define EXTRA_HI_LIMIT 100
|
#define EXTRA_HI_LIMIT 2000
|
||||||
#define CTOUCH_LO_LIMIT 500
|
#define CTOUCH_LO_LIMIT 500
|
||||||
#define CTOUCH_HI_LIMIT 1000
|
#define CTOUCH_HI_LIMIT 1000
|
||||||
#define LEVER_LO_LIMIT -100
|
#define LEVER_LO_LIMIT -2000
|
||||||
#define LEVER_HI_LIMIT 100
|
#define LEVER_HI_LIMIT 2000
|
||||||
#define SPIKE_LO_LIMIT 0
|
#define SPIKE_LO_LIMIT 0
|
||||||
#define SPIKE_HI_LIMIT 200
|
#define SPIKE_HI_LIMIT 200
|
||||||
|
#define SLIDER_TOUCH_OFFSET 4
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -60,6 +60,8 @@ enum ExtraControl : uint8_t {
|
||||||
VIBRATO = 1,
|
VIBRATO = 1,
|
||||||
GLIDE = 2,
|
GLIDE = 2,
|
||||||
CC = 3,
|
CC = 3,
|
||||||
|
BEND = 4,
|
||||||
|
VIB_BEND = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PolySelect : uint8_t {
|
enum PolySelect : uint8_t {
|
||||||
|
@ -109,8 +111,10 @@ struct instrument_state_t {
|
||||||
byte portamentoVal = 0; // keep track and make sure we send CC with 0 value when off threshold
|
byte portamentoVal = 0; // keep track and make sure we send CC with 0 value when off threshold
|
||||||
byte extraVal = 0; // keep track and make sure we send CC with 0 value when off threshold
|
byte extraVal = 0; // keep track and make sure we send CC with 0 value when off threshold
|
||||||
byte leverVal = 0; // keep track and make sure we send CC with 0 value when off threshold
|
byte leverVal = 0; // keep track and make sure we send CC with 0 value when off threshold
|
||||||
|
byte pbVal = 0; // keep track and make sure we send CC with 0 value when off threshold
|
||||||
int pitchBend = 8192;
|
int pitchBend = 8192;
|
||||||
int pbSend = 8192; // Pitch bend actually sent, modified by vibrato, etc
|
int pbSend = 8192; // Pitch bend actually sent, modified by vibrato, etc
|
||||||
|
bool pbActive = false; // extra CC selection
|
||||||
byte knobVals[4];
|
byte knobVals[4];
|
||||||
byte lastKnobVal;
|
byte lastKnobVal;
|
||||||
unsigned long lastKnobTime;
|
unsigned long lastKnobTime;
|
||||||
|
@ -130,19 +134,20 @@ struct instrument_state_t {
|
||||||
|
|
||||||
// Calibration
|
// Calibration
|
||||||
int16_t breathZero; // this gets auto calibrated in setup
|
int16_t breathZero; // this gets auto calibrated in setup
|
||||||
|
int16_t breathAltZero; // this gets auto calibrated in setup
|
||||||
int16_t breathThrVal; // this gets auto calibrated in setup
|
int16_t breathThrVal; // this gets auto calibrated in setup
|
||||||
int16_t breathMovingThrVal;
|
int16_t breathMovingThrVal;
|
||||||
|
int16_t breathBaseline; // this gets auto calibrated in setup
|
||||||
int16_t breathMaxVal; // this gets auto calibrated in setup
|
int16_t breathMaxVal; // this gets auto calibrated in setup
|
||||||
int16_t breathAltZero; // this gets auto calibrated in setup
|
int16_t breathAltZeroOffset; // this gets auto calibrated in setup
|
||||||
int16_t breathAltThrVal; // this gets auto calibrated in setup
|
int16_t breathThrOffVal; // this gets auto calibrated in setup
|
||||||
int16_t breathAltMaxVal; // this gets auto calibrated in setup
|
|
||||||
|
|
||||||
int16_t vibThr; // this gets auto calibrated in setup
|
int16_t vibThr; // this gets auto calibrated in setup
|
||||||
int16_t vibThrLo;
|
int16_t vibThrLo;
|
||||||
int16_t vibZero;
|
int16_t vibZero;
|
||||||
int16_t vibZeroBite;
|
int16_t sliderPBThr;
|
||||||
int16_t vibThrBite;
|
int16_t sliderLeverThr;
|
||||||
int16_t vibThrBiteLo;
|
int16_t sliderExtraThr;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const std::array<const unsigned short*, 13> curves;
|
extern const std::array<const unsigned short*, 13> curves;
|
||||||
|
|
|
@ -14,6 +14,9 @@ FilterOnePole rollFilter;
|
||||||
FilterOnePole sliderFilterExtra;
|
FilterOnePole sliderFilterExtra;
|
||||||
FilterOnePole sliderFilterPB;
|
FilterOnePole sliderFilterPB;
|
||||||
FilterOnePole sliderFilterLever;
|
FilterOnePole sliderFilterLever;
|
||||||
|
float sliderMAExtra = 0.0;
|
||||||
|
float sliderMAPB = 0.0;
|
||||||
|
float sliderMALever = 0.0;
|
||||||
|
|
||||||
Adafruit_MPR121 touchSensorKeys = Adafruit_MPR121();
|
Adafruit_MPR121 touchSensorKeys = Adafruit_MPR121();
|
||||||
Adafruit_MPR121 touchSensorRoller = Adafruit_MPR121();
|
Adafruit_MPR121 touchSensorRoller = Adafruit_MPR121();
|
||||||
|
@ -49,13 +52,13 @@ void initHardware() {
|
||||||
|
|
||||||
breathFilter.setFilter(LOWPASS, FILTER_FREQ, 0.0); // create a one pole (RC) lowpass filter
|
breathFilter.setFilter(LOWPASS, FILTER_FREQ, 0.0); // create a one pole (RC) lowpass filter
|
||||||
breathAltFilter.setFilter(LOWPASS, FILTER_FREQ, 0.0); // create a one pole (RC) lowpass filter
|
breathAltFilter.setFilter(LOWPASS, FILTER_FREQ, 0.0); // create a one pole (RC) lowpass filter
|
||||||
spikeFilter.setFilter(HIGHPASS, 200, 0.0); // create a one pole (RC) lowpass filter
|
spikeFilter.setFilter(HIGHPASS, SPIKE_FILTER_FREQ, 0.0); // create a one pole (RC) lowpass filter
|
||||||
tiltFilter.setFilter(LOWPASS, 2, 0.0); // create a one pole (RC) lowpass filter
|
tiltFilter.setFilter(LOWPASS, ICM_FILTER_FREQ, 0.0); // create a one pole (RC) lowpass filter
|
||||||
rollFilter.setFilter(LOWPASS, 2, 0.0); // create a one pole (RC) lowpass filter
|
rollFilter.setFilter(LOWPASS, ICM_FILTER_FREQ, 0.0); // create a one pole (RC) lowpass filter
|
||||||
icmSensor.begin_I2C(ICM20948_I2CADDR_DEFAULT, &MainI2CBus);
|
icmSensor.begin_I2C(ICM20948_I2CADDR_DEFAULT, &MainI2CBus);
|
||||||
sliderFilterExtra.setFilter(LOWPASS, 1.0, 0.0);
|
sliderFilterExtra.setFilter(INTEGRATOR, 0.75, 0.0);
|
||||||
sliderFilterLever.setFilter(LOWPASS, 1.0, 0.0);
|
sliderFilterLever.setFilter(INTEGRATOR, 0.75, 0.0);
|
||||||
sliderFilterPB.setFilter(LOWPASS, 1.0, 0.0);
|
sliderFilterPB.setFilter(INTEGRATOR, 0.75, 0.0);
|
||||||
|
|
||||||
ledStrip.begin();
|
ledStrip.begin();
|
||||||
|
|
||||||
|
@ -76,16 +79,17 @@ void initHardware() {
|
||||||
//touchSensorUtil.writeRegister(MPR121_CONFIG1, 0x3f); // default, 16uA charge current
|
//touchSensorUtil.writeRegister(MPR121_CONFIG1, 0x3f); // default, 16uA charge current
|
||||||
//touchSensorUtil.writeRegister(MPR121_CONFIG2, 0xE0); // 0.5uS encoding, 1ms period
|
//touchSensorUtil.writeRegister(MPR121_CONFIG2, 0xE0); // 0.5uS encoding, 1ms period
|
||||||
|
|
||||||
if (!pressureSensorMain.begin(MPRLS_DEFAULT_ADDR, &MainI2CBus)) {
|
if (!pressureSensorMain.begin(MPRLS_DEFAULT_ADDR, &AuxI2CBus)) {
|
||||||
displayError("Main pressure sensor error");
|
displayError("Main pressure sensor error");
|
||||||
errorWait();
|
errorWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pressureSensorAlt.begin(MPRLS_DEFAULT_ADDR, &AuxI2CBus)) {
|
if (!pressureSensorAlt.begin(MPRLS_DEFAULT_ADDR, &MainI2CBus)) {
|
||||||
displayError("Alt pressure sensor error");
|
displayError("Alt pressure sensor error");
|
||||||
errorWait();
|
errorWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!icmSensor.begin_I2C(ICM20948_I2CADDR_DEFAULT, &MainI2CBus)) {
|
if (!icmSensor.begin_I2C(ICM20948_I2CADDR_DEFAULT, &MainI2CBus)) {
|
||||||
displayError("ICM sensor error");
|
displayError("ICM sensor error");
|
||||||
errorWait();
|
errorWait();
|
||||||
|
@ -180,37 +184,61 @@ uint16_t utilTouched() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int readSpikePressure() {
|
int readSpikePressure() {
|
||||||
return spikeFilter.input(pressureSensorMain.readPressure()) * PRESSURE_SENS_MULTIPLIER;
|
return spikeFilter.output();
|
||||||
}
|
}
|
||||||
|
|
||||||
int readPressure() {
|
int readPressure() {
|
||||||
float p = pressureSensorMain.readPressure();
|
float p = pressureSensorMain.readPressure();
|
||||||
return breathFilter.input(p) * PRESSURE_SENS_MULTIPLIER;
|
int r = breathFilter.input(p) * PRESSURE_SENS_MULTIPLIER;
|
||||||
|
spikeFilter.input(r);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int readAltPressure() {
|
int readAltPressure() {
|
||||||
return breathAltFilter.input(pressureSensorAlt.readPressure()) * PRESSURE_SENS_MULTIPLIER;
|
return breathAltFilter.input(pressureSensorAlt.readPressure()) * PRESSURE_SENS_MULTIPLIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
float readSlider(Slider id) {
|
int16_t readSlider(Slider id, int thr) {
|
||||||
float diff = 0.0;
|
|
||||||
float filtered = 0.0;
|
float filtered = 0.0;
|
||||||
|
float a = 0, b = 0;
|
||||||
|
FilterOnePole *filter;
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case SLIDER_PITCH_BEND:
|
case SLIDER_PITCH_BEND:
|
||||||
diff = touchSensorUtil.filteredData(pbSliderPin1) - touchSensorUtil.filteredData(pbSliderPin2);
|
a = touchSensorUtil.filteredData(pbSliderPin1);
|
||||||
filtered = sliderFilterPB.input(diff);
|
b = touchSensorUtil.filteredData(pbSliderPin2);
|
||||||
break;
|
filter = &sliderFilterPB;
|
||||||
|
break;
|
||||||
case SLIDER_EXTRA:
|
case SLIDER_EXTRA:
|
||||||
diff = touchSensorRoller.filteredData(extraSliderPin1) - touchSensorRoller.filteredData(extraSliderPin2);
|
a = touchSensorRoller.filteredData(extraSliderPin1);
|
||||||
filtered = sliderFilterExtra.input(diff);
|
b = touchSensorRoller.filteredData(extraSliderPin2);
|
||||||
break;
|
filter = &sliderFilterExtra;
|
||||||
|
/*
|
||||||
|
Serial.print(">a:");
|
||||||
|
Serial.println(a);
|
||||||
|
Serial.print(">b:");
|
||||||
|
Serial.println(b);
|
||||||
|
Serial.print(">thr:");
|
||||||
|
Serial.println(thr);
|
||||||
|
*/
|
||||||
|
break;
|
||||||
case SLIDER_LEVER:
|
case SLIDER_LEVER:
|
||||||
diff = touchSensorUtil.filteredData(leverSliderPin1) - touchSensorUtil.filteredData(leverSliderPin2);
|
a = touchSensorUtil.filteredData(leverSliderPin1);
|
||||||
filtered = sliderFilterLever.input(diff);
|
b = touchSensorUtil.filteredData(leverSliderPin2);
|
||||||
break;
|
filter = &sliderFilterLever;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0.0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return filtered;
|
if ((a + b) <= (thr + thr - SLIDER_TOUCH_OFFSET)) {
|
||||||
|
filtered = filter->input(a - b);
|
||||||
|
} else {
|
||||||
|
return INT16_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
icm_result_t readICM() {
|
icm_result_t readICM() {
|
||||||
|
@ -224,4 +252,27 @@ icm_result_t readICM() {
|
||||||
tiltFilter.input(mag.magnetic.y),
|
tiltFilter.input(mag.magnetic.y),
|
||||||
rollFilter.input(mag.magnetic.x),
|
rollFilter.input(mag.magnetic.x),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int readRawSlider(Slider id) {
|
||||||
|
float a, b;
|
||||||
|
switch (id) {
|
||||||
|
case SLIDER_PITCH_BEND:
|
||||||
|
a = touchSensorUtil.filteredData(pbSliderPin1);
|
||||||
|
b = touchSensorUtil.filteredData(pbSliderPin2);
|
||||||
|
break;
|
||||||
|
case SLIDER_EXTRA:
|
||||||
|
a = touchSensorRoller.filteredData(extraSliderPin1);
|
||||||
|
b = touchSensorRoller.filteredData(extraSliderPin2);
|
||||||
|
break;
|
||||||
|
case SLIDER_LEVER:
|
||||||
|
a = touchSensorUtil.filteredData(leverSliderPin1);
|
||||||
|
b = touchSensorUtil.filteredData(leverSliderPin2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (a + b) / 2;
|
||||||
|
}
|
||||||
|
|
|
@ -35,7 +35,9 @@ uint8_t buttonState(); // return true if the given buttons are pressed
|
||||||
int readKnob(uint8_t n);
|
int readKnob(uint8_t n);
|
||||||
int readTouchKey(uint8_t n);
|
int readTouchKey(uint8_t n);
|
||||||
int readTouchRoller(uint8_t n);
|
int readTouchRoller(uint8_t n);
|
||||||
float readSlider(Slider id);
|
int readTouchUtil(uint8_t n);
|
||||||
|
int readRawSlider(Slider id);
|
||||||
|
int16_t readSlider(Slider id, int thr);
|
||||||
uint16_t keysTouched();
|
uint16_t keysTouched();
|
||||||
uint16_t utilTouched();
|
uint16_t utilTouched();
|
||||||
int readPressure();
|
int readPressure();
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
|
|
||||||
void checkICM(state_t &state) {
|
void checkICM(state_t &state) {
|
||||||
icm_result_t icmSignal = readICM();
|
icm_result_t icmSignal = readICM();
|
||||||
|
/*
|
||||||
Serial.print(">roll: ");
|
Serial.print(">roll: ");
|
||||||
Serial.println(icmSignal.roll);
|
Serial.println(icmSignal.roll);
|
||||||
Serial.print(">tilt: ");
|
Serial.print(">tilt: ");
|
||||||
Serial.println(icmSignal.tilt);
|
Serial.println(icmSignal.tilt);
|
||||||
|
*/
|
||||||
if (ExtraControl::CC == state.currentPreset->icmRollMode) {
|
if (ExtraControl::CC == state.currentPreset->icmRollMode) {
|
||||||
byte roll = mapConstrain(abs(icmSignal.roll), 0, 40, 127, 0);
|
byte roll = mapConstrain(abs(icmSignal.roll), 0, 40, 127, 0);
|
||||||
if (roll != state.instrument->rollCCVal) {
|
if (roll != state.instrument->rollCCVal) {
|
||||||
|
|
|
@ -939,11 +939,9 @@ private:
|
||||||
std::array<AdjustValue, 7> adjustValues = { {
|
std::array<AdjustValue, 7> adjustValues = { {
|
||||||
{"BREATH", &instrument_state_t::breathSignal, &calibration_t::breathThrValOffset, &calibration_t::breathMaxValOffset,
|
{"BREATH", &instrument_state_t::breathSignal, &calibration_t::breathThrValOffset, &calibration_t::breathMaxValOffset,
|
||||||
BREATH_LO_LIMIT, BREATH_HI_LIMIT, &instrument_state_t::breathZero},
|
BREATH_LO_LIMIT, BREATH_HI_LIMIT, &instrument_state_t::breathZero},
|
||||||
{"BR ALT", &instrument_state_t::breathAltSignal, &calibration_t::breathAltThrValOffset, &calibration_t::breathAltMaxValOffset,
|
|
||||||
BREATH_LO_LIMIT, BREATH_HI_LIMIT, &instrument_state_t::breathAltZero},
|
|
||||||
{"BITE",&instrument_state_t::biteSignal, &calibration_t::biteThrVal, &calibration_t::biteMaxVal, BITE_LO_LIMIT, BITE_HI_LIMIT, NULL},
|
{"BITE",&instrument_state_t::biteSignal, &calibration_t::biteThrVal, &calibration_t::biteMaxVal, BITE_LO_LIMIT, BITE_HI_LIMIT, NULL},
|
||||||
{"PB",&instrument_state_t::pbSignal, &calibration_t::pbMinVal, &calibration_t::pbMaxVal, PITCHB_LO_LIMIT, PITCHB_HI_LIMIT, NULL},
|
{"PB",&instrument_state_t::pbSignal, &calibration_t::pbMinVal, &calibration_t::pbMaxVal, PITCHB_LO_LIMIT, PITCHB_HI_LIMIT, NULL},
|
||||||
{"PB DZ",&instrument_state_t::pbSignal, &calibration_t::pbDeadzone, &calibration_t::pbDeadzone, PITCHB_LO_LIMIT, PITCHB_HI_LIMIT, NULL},
|
{"PB Z/DZ",&instrument_state_t::pbSignal, &calibration_t::pbCenterVal, &calibration_t::pbDeadzone, PITCHB_LO_LIMIT, PITCHB_HI_LIMIT, NULL},
|
||||||
{"EXTRA", &instrument_state_t::extraSignal, &calibration_t::extraMinVal, &calibration_t::extraMaxVal, EXTRA_LO_LIMIT, EXTRA_HI_LIMIT, NULL},
|
{"EXTRA", &instrument_state_t::extraSignal, &calibration_t::extraMinVal, &calibration_t::extraMaxVal, EXTRA_LO_LIMIT, EXTRA_HI_LIMIT, NULL},
|
||||||
{"LEVER", &instrument_state_t::leverSignal, &calibration_t::leverMinVal, &calibration_t::leverMaxVal, LEVER_LO_LIMIT, LEVER_HI_LIMIT, NULL},
|
{"LEVER", &instrument_state_t::leverSignal, &calibration_t::leverMinVal, &calibration_t::leverMaxVal, LEVER_LO_LIMIT, LEVER_HI_LIMIT, NULL},
|
||||||
{"TOUCH", &instrument_state_t::avgCTouchSignal, &calibration_t::ctouchThrVal, &calibration_t::ctouchThrVal, CTOUCH_LO_LIMIT, CTOUCH_HI_LIMIT, NULL},
|
{"TOUCH", &instrument_state_t::avgCTouchSignal, &calibration_t::ctouchThrVal, &calibration_t::ctouchThrVal, CTOUCH_LO_LIMIT, CTOUCH_HI_LIMIT, NULL},
|
||||||
|
@ -960,7 +958,7 @@ CurveValueMenu<0, uint8_t> curveMenu("CURVE", &preset_t::breathCurve, 0, 12);
|
||||||
PresetValueMenu<1, uint8_t> velSmpDlMenu("VEL DELAY", &preset_t::velSmpDl, 0, 30, true, { "OFF" }, "ms");
|
PresetValueMenu<1, uint8_t> velSmpDlMenu("VEL DELAY", &preset_t::velSmpDl, 0, 30, true, { "OFF" }, "ms");
|
||||||
PresetValueMenu<1, uint8_t> velBiasMenu("VEL BOOST", &preset_t::velBias, 0, 30, true, { "OFF" });
|
PresetValueMenu<1, uint8_t> velBiasMenu("VEL BOOST", &preset_t::velBias, 0, 30, true, { "OFF" });
|
||||||
PresetValueMenu<0, uint8_t> breathIntervalMenu("BR INTV", &preset_t::breathInterval, 0, 30, true, {}, "ms");
|
PresetValueMenu<0, uint8_t> breathIntervalMenu("BR INTV", &preset_t::breathInterval, 0, 30, true, {}, "ms");
|
||||||
PresetValueMenu<0, uint8_t> filterMenu("FILTER CT", &preset_t::breathFilterFreq, 1, 100, false, {}, "hz");
|
PresetValueMenu<0, uint8_t> filterMenu("FILTER CT", &preset_t::breathFilterFreq, 1, 200, false, {}, "hz");
|
||||||
PresetValueMenu<1, uint8_t> spikeFilterMenu("FILTER TRG", &preset_t::spikeFilterFreq, 0, 100, false, {"OFF"}, "hz");
|
PresetValueMenu<1, uint8_t> spikeFilterMenu("FILTER TRG", &preset_t::spikeFilterFreq, 0, 100, false, {"OFF"}, "hz");
|
||||||
PresetValueMenu<0, int8_t> spikeOnFactorMenu("TRG ON MUL", &preset_t::spikeOnFactor, -25, 25, false, {}, "x");
|
PresetValueMenu<0, int8_t> spikeOnFactorMenu("TRG ON MUL", &preset_t::spikeOnFactor, -25, 25, false, {}, "x");
|
||||||
PresetValueMenu<0, int8_t> spikeOffFactorMenu("TRG OFF MUL", &preset_t::spikeOffFactor, -25, 25, false, {}, "x");
|
PresetValueMenu<0, int8_t> spikeOffFactorMenu("TRG OFF MUL", &preset_t::spikeOffFactor, -25, 25, false, {}, "x");
|
||||||
|
@ -1005,6 +1003,8 @@ PresetValueMenu<0, uint8_t> portLimitMenu("GLIDE LMT", &preset_t::portamentoLimi
|
||||||
PresetValueMenu<0, uint8_t> pitchBendMenu("PITCHBEND", &preset_t::PBdepth, 0, 12, true);
|
PresetValueMenu<0, uint8_t> pitchBendMenu("PITCHBEND", &preset_t::PBdepth, 0, 12, true);
|
||||||
ChoiceMenu<4, ExtraControl> extraCtlMenu("EXT CTL", &preset_t::extraControl, { {OFF, VIBRATO, GLIDE, CC} }, { "OFF", "VIBRATO", "GLIDE", "CC" });
|
ChoiceMenu<4, ExtraControl> extraCtlMenu("EXT CTL", &preset_t::extraControl, { {OFF, VIBRATO, GLIDE, CC} }, { "OFF", "VIBRATO", "GLIDE", "CC" });
|
||||||
PresetValueMenu<128, uint8_t> extraCCMenu("EXT CC", &preset_t::extraCC, 0, 127, true, CC_NAMES);
|
PresetValueMenu<128, uint8_t> extraCCMenu("EXT CC", &preset_t::extraCC, 0, 127, true, CC_NAMES);
|
||||||
|
ChoiceMenu<6, ExtraControl> pbCtlMenu("PB CTL", &preset_t::pbControl, { {OFF, VIBRATO, GLIDE, CC, BEND, VIB_BEND} }, { "OFF", "VIBRATO", "GLIDE", "CC", "BEND", "VIB_BEND" });
|
||||||
|
PresetValueMenu<128, uint8_t> pbCCMenu("PB CC", &preset_t::pbCC, 0, 127, true, CC_NAMES);
|
||||||
ChoiceMenu<4, ExtraControl> tiltModeMenu("TILT MODE", &preset_t::icmTiltMode, { {OFF, VIBRATO, GLIDE, CC} }, { "OFF", "VIBRATO", "GLIDE", "CC" });
|
ChoiceMenu<4, ExtraControl> tiltModeMenu("TILT MODE", &preset_t::icmTiltMode, { {OFF, VIBRATO, GLIDE, CC} }, { "OFF", "VIBRATO", "GLIDE", "CC" });
|
||||||
PresetValueMenu<128, uint8_t> tiltCCMenu("TILT CC", &preset_t::icmTiltCC, 0, 127, true, CC_NAMES);
|
PresetValueMenu<128, uint8_t> tiltCCMenu("TILT CC", &preset_t::icmTiltCC, 0, 127, true, CC_NAMES);
|
||||||
ChoiceMenu<4, ExtraControl> rollModeMenu("ROLL MODE", &preset_t::icmRollMode, { {OFF, VIBRATO, GLIDE, CC} }, { "OFF", "VIBRATO", "GLIDE", "CC" });
|
ChoiceMenu<4, ExtraControl> rollModeMenu("ROLL MODE", &preset_t::icmRollMode, { {OFF, VIBRATO, GLIDE, CC} }, { "OFF", "VIBRATO", "GLIDE", "CC" });
|
||||||
|
@ -1082,12 +1082,14 @@ std::array<MenuScreen *const, 11> breathMenuEntries = {
|
||||||
};
|
};
|
||||||
SubMenu<11> breathMenu("BR SETUP", breathMenuEntries);
|
SubMenu<11> breathMenu("BR SETUP", breathMenuEntries);
|
||||||
|
|
||||||
const std::array<MenuScreen *const, 20> controlMenuEntries = {
|
const std::array<MenuScreen *const, 22> controlMenuEntries = {
|
||||||
&fingeringMenu,
|
&fingeringMenu,
|
||||||
&polyMenu,
|
&polyMenu,
|
||||||
&rollerMenu,
|
&rollerMenu,
|
||||||
&biteCtlMenu,
|
&biteCtlMenu,
|
||||||
&biteCCMenu,
|
&biteCCMenu,
|
||||||
|
&pbCtlMenu,
|
||||||
|
&pbCCMenu,
|
||||||
&leverCtlMenu,
|
&leverCtlMenu,
|
||||||
&leverCCMenu,
|
&leverCCMenu,
|
||||||
&extraCtlMenu,
|
&extraCtlMenu,
|
||||||
|
@ -1104,7 +1106,7 @@ const std::array<MenuScreen *const, 20> controlMenuEntries = {
|
||||||
&accelModeMenu,
|
&accelModeMenu,
|
||||||
&accelCCMenu,
|
&accelCCMenu,
|
||||||
};
|
};
|
||||||
SubMenu<20> controlMenu("CTL SETUP", controlMenuEntries);
|
SubMenu<22> controlMenu("CTL SETUP", controlMenuEntries);
|
||||||
|
|
||||||
const std::array<MenuScreen *const, 5> vibratoMenuEntries = {
|
const std::array<MenuScreen *const, 5> vibratoMenuEntries = {
|
||||||
&vibDepthMenu,
|
&vibDepthMenu,
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
|
|
||||||
#define EEPROM_VERSION 4
|
#define EEPROM_VERSION 5
|
||||||
#define EEPROM_VERSION_ADDR 0
|
#define EEPROM_VERSION_ADDR 0
|
||||||
#define SETTINGS_OFFSET 2
|
#define SETTINGS_OFFSET 2
|
||||||
#define PRESET_MAX_SIZE 128 // Leave extra space for future settings
|
#define PRESET_MAX_SIZE 128 // Leave extra space for future settings
|
||||||
|
@ -26,14 +26,14 @@ struct calibration_t {
|
||||||
int16_t breathAltMaxValOffset = 1500;
|
int16_t breathAltMaxValOffset = 1500;
|
||||||
int16_t biteThrVal = 850;
|
int16_t biteThrVal = 850;
|
||||||
int16_t biteMaxVal = 1000;
|
int16_t biteMaxVal = 1000;
|
||||||
int16_t pbMinVal = -10;
|
int16_t pbMinVal = -1000;
|
||||||
int16_t pbMaxVal = 10;
|
int16_t pbMaxVal = 1000;
|
||||||
int16_t pbCenterVal = 0;
|
int16_t pbCenterVal = 0;
|
||||||
int16_t pbDeadzone = 2;
|
int16_t pbDeadzone = 20;
|
||||||
int16_t leverMinVal = -10;
|
int16_t leverMinVal = -1000;
|
||||||
int16_t leverMaxVal = 10;
|
int16_t leverMaxVal = 1000;
|
||||||
int16_t extraMinVal = -10;
|
int16_t extraMinVal = -1000;
|
||||||
int16_t extraMaxVal = 10;
|
int16_t extraMaxVal = 1000;
|
||||||
int16_t ctouchThrVal = 900;
|
int16_t ctouchThrVal = 900;
|
||||||
uint8_t _reserved[24];
|
uint8_t _reserved[24];
|
||||||
};
|
};
|
||||||
|
@ -95,8 +95,10 @@ struct preset_t {
|
||||||
int8_t spikeOnFactor = 5;
|
int8_t spikeOnFactor = 5;
|
||||||
int8_t spikeOffFactor = 5;
|
int8_t spikeOffFactor = 5;
|
||||||
PolySelect polyMode = PolySelect::EHarmonizerOff;
|
PolySelect polyMode = PolySelect::EHarmonizerOff;
|
||||||
|
ExtraControl pbControl = ExtraControl::VIB_BEND;
|
||||||
|
uint8_t pbCC = 12; // extra CC selection
|
||||||
|
|
||||||
uint8_t _reserved[82];
|
uint8_t _reserved[80];
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(preset_t) == PRESET_MAX_SIZE, "preset_t must be 128 bytes");
|
static_assert(sizeof(preset_t) == PRESET_MAX_SIZE, "preset_t must be 128 bytes");
|
||||||
|
|
|
@ -221,7 +221,7 @@ int breath() {
|
||||||
|
|
||||||
int breathCCval, breathCCvalFine;
|
int breathCCval, breathCCvalFine;
|
||||||
unsigned int breathCCvalHires;
|
unsigned int breathCCvalHires;
|
||||||
breathCCvalHires = breathCurve(mapConstrain(instrument.breathSignal, instrument.breathThrVal, instrument.breathMaxVal, 0, 16383));
|
breathCCvalHires = breathCurve(mapConstrain(instrument.breathSignal, instrument.breathBaseline, instrument.breathMaxVal, 0, 16383));
|
||||||
breathCCvalHires = breathCCFilter.input(breathCCvalHires);
|
breathCCvalHires = breathCCFilter.input(breathCCvalHires);
|
||||||
breathCCval = (breathCCvalHires >> 7) & 0x007F;
|
breathCCval = (breathCCvalHires >> 7) & 0x007F;
|
||||||
breathCCvalFine = breathCCvalHires & 0x007F;
|
breathCCvalFine = breathCCvalHires & 0x007F;
|
||||||
|
@ -252,24 +252,9 @@ int breath() {
|
||||||
|
|
||||||
//**************************************************************
|
//**************************************************************
|
||||||
|
|
||||||
void pitch_bend() {
|
void vibrato(int calculatedPBdepth) {
|
||||||
// handle input from pitchbend touchpads and
|
|
||||||
// on-pcb variable capacitor for vibrato.
|
|
||||||
static int oldpb = 0;
|
|
||||||
int vibMax;
|
int vibMax;
|
||||||
int vibMaxBite;
|
|
||||||
int calculatedPBdepth;
|
|
||||||
byte pbTouched = 0;
|
|
||||||
int vibRead = 0;
|
int vibRead = 0;
|
||||||
int vibReadBite = 0;
|
|
||||||
bool halfPitchBendKey = (state.currentPreset->pinkySetting == PBD) && instrument.pinkyKey; // hold pinky key for 1/2 pitchbend value
|
|
||||||
instrument.quarterToneTrigger = (state.currentPreset->pinkySetting == QTN) && instrument.pinkyKey; // pinky key for a quarter tone down using pitch bend (assuming PB range on synth is set to 2 semitones)
|
|
||||||
|
|
||||||
calculatedPBdepth = pbDepthList[state.currentPreset->PBdepth];
|
|
||||||
if (halfPitchBendKey)
|
|
||||||
calculatedPBdepth = calculatedPBdepth * 0.5;
|
|
||||||
|
|
||||||
vibMax = vibMaxList[state.currentPreset->vibSens - 1];
|
|
||||||
|
|
||||||
float calculatedDepth = 0;
|
float calculatedDepth = 0;
|
||||||
if (state.currentPreset->vibratoMode == VibratoMode::VSTART_DOWN) {
|
if (state.currentPreset->vibratoMode == VibratoMode::VSTART_DOWN) {
|
||||||
|
@ -278,36 +263,26 @@ void pitch_bend() {
|
||||||
calculatedDepth = (0 - calculatedPBdepth * vibDepth[state.currentPreset->vibratoDepth]);
|
calculatedDepth = (0 - calculatedPBdepth * vibDepth[state.currentPreset->vibratoDepth]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ExtraControl::VIBRATO == state.currentPreset->biteControl) { // bite vibrato
|
vibMax = vibMaxList[state.currentPreset->vibSens - 1];
|
||||||
vibMaxBite = vibMaxBiteList[state.currentPreset->vibSens - 1];
|
|
||||||
vibReadBite = instrument.biteSignal;
|
|
||||||
|
|
||||||
if (vibReadBite > instrument.vibThrBite) {
|
if (ExtraControl::VIBRATO == state.currentPreset->biteControl) { // bite vibrato
|
||||||
instrument.vibSignal = (instrument.vibSignal + mapConstrain(
|
vibRead = instrument.biteSignal;
|
||||||
vibReadBite, (instrument.vibZeroBite - vibMaxBite), instrument.vibThrBite, calculatedDepth, 0)
|
} else if (ExtraControl::VIBRATO == state.currentPreset->leverControl) { // lever vibrato
|
||||||
) / 2;
|
vibRead = instrument.leverSignal;
|
||||||
} else if (vibReadBite < instrument.vibThrBiteLo) {
|
} else if (ExtraControl::VIBRATO == state.currentPreset->extraControl) { // lever vibrato
|
||||||
instrument.vibSignal = (instrument.vibSignal + mapConstrain(
|
vibRead = instrument.extraSignal;
|
||||||
vibReadBite, (instrument.vibZeroBite + vibMaxBite), instrument.vibThrBite, calculatedDepth, 0)
|
} else if (ExtraControl::VIBRATO == state.currentPreset->pbControl) { // lever vibrato
|
||||||
) / 2;
|
vibRead = instrument.pbSignal;
|
||||||
} else {
|
} else if (ExtraControl::VIB_BEND == state.currentPreset->pbControl && !instrument.pbActive) { // lever vibrato
|
||||||
instrument.vibSignal = instrument.vibSignal / 2;
|
vibRead = instrument.pbSignal;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ExtraControl::VIBRATO == state.currentPreset->leverControl) { // lever vibrato
|
if (vibRead < instrument.vibThrLo) {
|
||||||
vibRead = instrument.leverSignal;
|
instrument.vibSignal = (instrument.vibSignal + mapConstrain(
|
||||||
if (vibRead > instrument.vibThr) {
|
vibRead, (instrument.vibZero + vibMax), instrument.vibThr, calculatedDepth, 0)
|
||||||
instrument.vibSignal = (instrument.vibSignal +
|
) / 2;
|
||||||
mapConstrain(vibRead, (instrument.vibZero - vibMax), instrument.vibThr, calculatedDepth, 0)
|
} else {
|
||||||
) / 2;
|
instrument.vibSignal = instrument.vibSignal / 2;
|
||||||
} else if (vibRead < instrument.vibThrLo) {
|
|
||||||
instrument.vibSignal = (instrument.vibSignal +
|
|
||||||
mapConstrain(vibRead, (instrument.vibZero + vibMax), instrument.vibThr, calculatedDepth, 0)
|
|
||||||
) / 2;
|
|
||||||
} else {
|
|
||||||
instrument.vibSignal = instrument.vibSignal / 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (state.currentPreset->vibRetn) { // moving baseline
|
switch (state.currentPreset->vibRetn) { // moving baseline
|
||||||
|
@ -316,40 +291,59 @@ void pitch_bend() {
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
instrument.vibZero = instrument.vibZero * 0.95 + vibRead * 0.05;
|
instrument.vibZero = instrument.vibZero * 0.95 + vibRead * 0.05;
|
||||||
instrument.vibZeroBite = instrument.vibZeroBite * 0.95 + vibReadBite * 0.05;
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
instrument.vibZero = instrument.vibZero * 0.9 + vibRead * 0.1;
|
instrument.vibZero = instrument.vibZero * 0.9 + vibRead * 0.1;
|
||||||
instrument.vibZeroBite = instrument.vibZeroBite * 0.9 + vibReadBite * 0.1;
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
instrument.vibZero = instrument.vibZero * 0.8 + vibRead * 0.2;
|
instrument.vibZero = instrument.vibZero * 0.8 + vibRead * 0.2;
|
||||||
instrument.vibZeroBite = instrument.vibZeroBite * 0.8 + vibReadBite * 0.2;
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
instrument.vibZero = instrument.vibZero * 0.6 + vibRead * 0.4;
|
instrument.vibZero = instrument.vibZero * 0.6 + vibRead * 0.4;
|
||||||
instrument.vibZeroBite = instrument.vibZeroBite * 0.6 + vibReadBite * 0.4;
|
|
||||||
}
|
}
|
||||||
instrument.vibThr = instrument.vibZero + state.currentPreset->vibSquelch;
|
instrument.vibThr = instrument.vibZero + state.currentPreset->vibSquelch;
|
||||||
instrument.vibThrLo = instrument.vibZero - state.currentPreset->vibSquelch;
|
instrument.vibThrLo = instrument.vibZero - state.currentPreset->vibSquelch;
|
||||||
instrument.vibThrBite = instrument.vibZeroBite + state.currentPreset->vibSquelch;
|
}
|
||||||
instrument.vibThrBiteLo = instrument.vibZeroBite - state.currentPreset->vibSquelch;
|
|
||||||
|
void pitch_bend() {
|
||||||
|
// handle input from pitchbend touchpads and
|
||||||
|
// on-pcb variable capacitor for vibrato.
|
||||||
|
static int oldpb = 0;
|
||||||
|
int calculatedPBdepth;
|
||||||
|
bool halfPitchBendKey = (state.currentPreset->pinkySetting == PBD) && instrument.pinkyKey; // hold pinky key for 1/2 pitchbend value
|
||||||
|
instrument.quarterToneTrigger = (state.currentPreset->pinkySetting == QTN) && instrument.pinkyKey; // pinky key for a quarter tone down using pitch bend (assuming PB range on synth is set to 2 semitones)
|
||||||
|
|
||||||
|
calculatedPBdepth = pbDepthList[state.currentPreset->PBdepth];
|
||||||
|
if (halfPitchBendKey)
|
||||||
|
calculatedPBdepth = calculatedPBdepth * 0.5;
|
||||||
|
|
||||||
|
instrument.pbActive = false;
|
||||||
|
|
||||||
|
if (ExtraControl::BEND == state.currentPreset->pbControl || ExtraControl::VIB_BEND == state.currentPreset->pbControl) {
|
||||||
|
// Only activate PB if we're outside the deadzone
|
||||||
|
if (
|
||||||
|
(instrument.pbSignal > state.calibration->pbCenterVal + state.calibration->pbDeadzone ||
|
||||||
|
instrument.pbSignal < state.calibration->pbCenterVal - state.calibration->pbDeadzone)
|
||||||
|
&& instrument.pbSignal != INT16_MIN) {
|
||||||
|
instrument.pbActive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vibrato(calculatedPBdepth);
|
||||||
|
|
||||||
// PB calculation
|
// PB calculation
|
||||||
int pbPos = mapConstrain(instrument.pbSignal, calibration.pbCenterVal, calibration.pbMaxVal, calculatedPBdepth, 0);
|
int pbPos = mapConstrain(instrument.pbSignal, calibration.pbCenterVal + calibration.pbDeadzone, calibration.pbMaxVal, 0, calculatedPBdepth);
|
||||||
int pbNeg = mapConstrain(instrument.pbSignal, calibration.pbCenterVal, calibration.pbMinVal, calculatedPBdepth, 0);
|
int pbNeg = mapConstrain(instrument.pbSignal, calibration.pbMinVal, calibration.pbCenterVal - calibration.pbDeadzone, calculatedPBdepth, 0);
|
||||||
int pbSum = 8193 + pbPos - pbNeg;
|
int pbSum = 8193 + pbPos - pbNeg;
|
||||||
int pbDif = abs(pbPos - pbNeg);
|
int pbDif = abs(pbPos - pbNeg);
|
||||||
|
|
||||||
if ((pbPos > calibration.pbDeadzone || pbNeg < calibration.pbDeadzone) && state.currentPreset->PBdepth) {
|
if (instrument.pbActive) {
|
||||||
if (pbDif < 10) {
|
if (pbDif < 10) {
|
||||||
instrument.pitchBend = 8192;
|
instrument.pitchBend = 8192;
|
||||||
} else {
|
} else {
|
||||||
instrument.pitchBend = instrument.pitchBend * 0.6 + 0.4 * pbSum;
|
instrument.pitchBend = instrument.pitchBend * 0.6 + 0.4 * pbSum;
|
||||||
}
|
}
|
||||||
pbTouched = 1;
|
} else {
|
||||||
}
|
|
||||||
if (!pbTouched) {
|
|
||||||
instrument.pitchBend = instrument.pitchBend * 0.6 + 8192 * 0.4; // released, so smooth your way back to zero
|
instrument.pitchBend = instrument.pitchBend * 0.6 + 8192 * 0.4; // released, so smooth your way back to zero
|
||||||
if ((instrument.pitchBend > 8187) && (instrument.pitchBend < 8197))
|
if ((instrument.pitchBend > 8187) && (instrument.pitchBend < 8197))
|
||||||
instrument.pitchBend = 8192; // 8192 is 0 pitch bend, don't miss it bc of smoothing
|
instrument.pitchBend = 8192; // 8192 is 0 pitch bend, don't miss it bc of smoothing
|
||||||
|
@ -390,9 +384,8 @@ void portamento_() {
|
||||||
|
|
||||||
if (ExtraControl::GLIDE == state.currentPreset->leverControl) {
|
if (ExtraControl::GLIDE == state.currentPreset->leverControl) {
|
||||||
// Portamento is controlled with thumb lever
|
// Portamento is controlled with thumb lever
|
||||||
// FIXME: Fix this for new lever signal
|
if (instrument.leverSignal >= calibration.leverMinVal) { // if we are enabled and over the threshold, send portamento
|
||||||
if (((3000 - instrument.leverSignal) >= calibration.leverMinVal)) { // if we are enabled and over the threshold, send portamento
|
portSumCC += mapConstrain(instrument.leverSignal, calibration.leverMinVal, calibration.leverMaxVal, 0, state.currentPreset->portamentoLimit);
|
||||||
portSumCC += mapConstrain((3000 - instrument.leverSignal), calibration.leverMinVal, calibration.leverMaxVal, 0, state.currentPreset->portamentoLimit);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +395,7 @@ void portamento_() {
|
||||||
//***********************************************************
|
//***********************************************************
|
||||||
|
|
||||||
void sendCC() {
|
void sendCC() {
|
||||||
int biteVal = 0;
|
int biteVal = instrument.biteSignal;
|
||||||
if (ExtraControl::CC == state.currentPreset->biteControl) {
|
if (ExtraControl::CC == state.currentPreset->biteControl) {
|
||||||
if (instrument.biteSignal >= calibration.biteThrVal) { // we are over the threshold, calculate CC value
|
if (instrument.biteSignal >= calibration.biteThrVal) { // we are over the threshold, calculate CC value
|
||||||
biteVal = mapConstrain(instrument.biteSignal, calibration.biteThrVal, calibration.biteMaxVal, 0, 127);
|
biteVal = mapConstrain(instrument.biteSignal, calibration.biteThrVal, calibration.biteMaxVal, 0, 127);
|
||||||
|
@ -414,10 +407,9 @@ void sendCC() {
|
||||||
instrument.biteVal = biteVal;
|
instrument.biteVal = biteVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
int extraVal = 0;
|
int extraVal = instrument.extraVal;
|
||||||
if (ExtraControl::CC == state.currentPreset->extraControl) {
|
if (ExtraControl::CC == state.currentPreset->extraControl) {
|
||||||
// FIXME: Fix this for new extra signal
|
if (instrument.extraSignal != INT16_MIN) { // we are over the threshold, calculate CC value
|
||||||
if (instrument.extraSignal >= calibration.extraMinVal) { // we are over the threshold, calculate CC value
|
|
||||||
extraVal = mapConstrain(instrument.extraSignal, calibration.extraMinVal, calibration.extraMaxVal, 0, 127);
|
extraVal = mapConstrain(instrument.extraSignal, calibration.extraMinVal, calibration.extraMaxVal, 0, 127);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,6 +419,30 @@ void sendCC() {
|
||||||
instrument.extraVal = extraVal;
|
instrument.extraVal = extraVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int leverVal = instrument.leverVal;
|
||||||
|
if (ExtraControl::CC == state.currentPreset->leverControl) {
|
||||||
|
if (instrument.leverSignal != INT16_MIN) { // we are over the threshold, calculate CC value
|
||||||
|
leverVal = mapConstrain(instrument.leverSignal, calibration.leverMinVal, calibration.leverMaxVal, 0, 127);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leverVal != instrument.leverVal) {
|
||||||
|
midiSendControlChange(state.currentPreset->leverCC, leverVal);
|
||||||
|
}
|
||||||
|
instrument.leverVal = leverVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pbVal = instrument.pbVal;
|
||||||
|
if (ExtraControl::CC == state.currentPreset->pbControl) {
|
||||||
|
if (instrument.pbSignal != INT16_MIN) { // we are over the threshold, calculate CC value
|
||||||
|
pbVal = mapConstrain(instrument.pbSignal, calibration.pbMinVal, calibration.pbMaxVal, 0, 127);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pbVal != instrument.pbVal) {
|
||||||
|
midiSendControlChange(state.currentPreset->pbCC, pbVal);
|
||||||
|
}
|
||||||
|
instrument.pbVal = pbVal;
|
||||||
|
}
|
||||||
|
|
||||||
if (!inMenu()) {
|
if (!inMenu()) {
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
byte val = constrain((int)state.instrument->knobVals[i] + readKnob(i), 0, 127);
|
byte val = constrain((int)state.instrument->knobVals[i] + readKnob(i), 0, 127);
|
||||||
|
@ -456,31 +472,34 @@ void sendCC() {
|
||||||
|
|
||||||
// Re-zero floating calibration values
|
// Re-zero floating calibration values
|
||||||
void rezero() {
|
void rezero() {
|
||||||
|
instrument.vibZero = 0;
|
||||||
instrument.vibThr = instrument.vibZero + state.currentPreset->vibSquelch;
|
instrument.vibThr = instrument.vibZero + state.currentPreset->vibSquelch;
|
||||||
instrument.vibThrLo = instrument.vibZero - state.currentPreset->vibSquelch;
|
instrument.vibThrLo = instrument.vibZero - state.currentPreset->vibSquelch;
|
||||||
instrument.vibThrBite = instrument.vibZeroBite + state.currentPreset->vibSquelch;
|
|
||||||
instrument.vibThrBiteLo = instrument.vibZeroBite - state.currentPreset->vibSquelch;
|
|
||||||
|
|
||||||
instrument.breathThrVal = instrument.breathZero + calibration.breathThrValOffset;
|
instrument.breathThrVal = instrument.breathZero + calibration.breathThrValOffset;
|
||||||
|
instrument.breathBaseline = instrument.breathZero + calibration.breathThrValOffset;
|
||||||
|
instrument.breathThrOffVal = instrument.breathZero + calibration.breathThrValOffset / 2;
|
||||||
instrument.breathMaxVal = instrument.breathThrVal + calibration.breathMaxValOffset;
|
instrument.breathMaxVal = instrument.breathThrVal + calibration.breathMaxValOffset;
|
||||||
instrument.breathAltThrVal = instrument.breathAltZero + calibration.breathAltThrValOffset;
|
instrument.breathAltZeroOffset = instrument.breathZero - instrument.breathAltZero;
|
||||||
instrument.breathAltMaxVal = instrument.breathAltThrVal + calibration.breathAltMaxValOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void autoCal() {
|
void autoCal() {
|
||||||
instrument.vibZero = instrument.vibZeroBite = 0;
|
|
||||||
long int bZero = 0;
|
long int bZero = 0;
|
||||||
long int bAltZero = 0;
|
long int bAltZero = 0;
|
||||||
|
long int bLeverTouchZero = 0, bExtraTouchZero = 0, bPBTouchZero = 0;
|
||||||
for (int i = 1; i <= CALIBRATE_SAMPLE_COUNT; ++i) {
|
for (int i = 1; i <= CALIBRATE_SAMPLE_COUNT; ++i) {
|
||||||
bZero += readPressure();
|
bZero += readPressure();
|
||||||
bAltZero += readAltPressure();
|
bAltZero += readAltPressure();
|
||||||
instrument.vibZeroBite += readTouchRoller(bitePin);
|
bLeverTouchZero += readRawSlider(Slider::SLIDER_LEVER);
|
||||||
|
bExtraTouchZero += readRawSlider(Slider::SLIDER_EXTRA);
|
||||||
|
bPBTouchZero += readRawSlider(Slider::SLIDER_PITCH_BEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
instrument.breathZero = bZero / CALIBRATE_SAMPLE_COUNT;
|
instrument.breathZero = bZero / CALIBRATE_SAMPLE_COUNT;
|
||||||
instrument.breathAltZero = bAltZero / CALIBRATE_SAMPLE_COUNT;
|
instrument.breathAltZero = (bAltZero / CALIBRATE_SAMPLE_COUNT);
|
||||||
instrument.vibZero /= CALIBRATE_SAMPLE_COUNT;
|
instrument.sliderPBThr = bPBTouchZero /= CALIBRATE_SAMPLE_COUNT;
|
||||||
instrument.vibZeroBite /= CALIBRATE_SAMPLE_COUNT;
|
instrument.sliderExtraThr = bExtraTouchZero /= CALIBRATE_SAMPLE_COUNT;
|
||||||
|
instrument.sliderLeverThr = bLeverTouchZero /= CALIBRATE_SAMPLE_COUNT;
|
||||||
|
|
||||||
rezero();
|
rezero();
|
||||||
}
|
}
|
||||||
|
@ -500,26 +519,6 @@ void fullAutoCal() {
|
||||||
calibration.biteThrVal = constrain(calRead + 100, BITE_LO_LIMIT, BITE_HI_LIMIT);
|
calibration.biteThrVal = constrain(calRead + 100, BITE_LO_LIMIT, BITE_HI_LIMIT);
|
||||||
calibration.biteMaxVal = constrain(calRead + 300, BITE_LO_LIMIT, BITE_HI_LIMIT);
|
calibration.biteMaxVal = constrain(calRead + 300, BITE_LO_LIMIT, BITE_HI_LIMIT);
|
||||||
|
|
||||||
/*
|
|
||||||
// Lever
|
|
||||||
calRead = readTouchRoller(leverPin);
|
|
||||||
calibration.leverThrVal = constrain(calRead + 100, LEVER_LO_LIMIT, LEVER_HI_LIMIT);
|
|
||||||
calibration.leverMaxVal = constrain(calRead + 300, LEVER_LO_LIMIT, LEVER_HI_LIMIT);
|
|
||||||
|
|
||||||
// Extra
|
|
||||||
calRead = readTouchRoller(extraPin);
|
|
||||||
calibration.extraThrVal = constrain(calRead + 100, EXTRA_LO_LIMIT, EXTRA_HI_LIMIT);
|
|
||||||
calibration.extraMaxVal = constrain(calRead + 300, EXTRA_LO_LIMIT, EXTRA_HI_LIMIT);
|
|
||||||
|
|
||||||
// PB
|
|
||||||
calRead = readTouchRoller(pbDnPin);
|
|
||||||
calibration.pbDnThrVal = constrain(calRead + 100, BITE_LO_LIMIT, BITE_HI_LIMIT);
|
|
||||||
calibration.pbDnMaxVal = constrain(calRead + 300, BITE_LO_LIMIT, BITE_HI_LIMIT);
|
|
||||||
|
|
||||||
calRead = readTouchRoller(pbUpPin);
|
|
||||||
calibration.pbUpThrVal = constrain(calRead + 100, BITE_LO_LIMIT, BITE_HI_LIMIT);
|
|
||||||
calibration.pbUpMaxVal = constrain(calRead + 300, BITE_LO_LIMIT, BITE_HI_LIMIT);
|
|
||||||
*/
|
|
||||||
// Touch sensors
|
// Touch sensors
|
||||||
calRead = CTOUCH_HI_LIMIT;
|
calRead = CTOUCH_HI_LIMIT;
|
||||||
for (byte i = 0; i < 12; i++) {
|
for (byte i = 0; i < 12; i++) {
|
||||||
|
@ -769,15 +768,17 @@ void readSwitches() {
|
||||||
void noteOn(int fingeredNote, int pressureSensor, int initial_breath_value) {
|
void noteOn(int fingeredNote, int pressureSensor, int initial_breath_value) {
|
||||||
// Yes, so calculate MIDI note and velocity, then send a note on event
|
// Yes, so calculate MIDI note and velocity, then send a note on event
|
||||||
// We should be at tonguing peak, so set velocity based on current pressureSensor value unless fixed velocity is set
|
// We should be at tonguing peak, so set velocity based on current pressureSensor value unless fixed velocity is set
|
||||||
instrument.breathSignal = constrain(max(pressureSensor, initial_breath_value), instrument.breathThrVal, instrument.breathMaxVal);
|
instrument.breathSignal = constrain(max(pressureSensor, initial_breath_value), instrument.breathBaseline, instrument.breathMaxVal);
|
||||||
byte velocitySend;
|
byte velocitySend;
|
||||||
if (!state.currentPreset->fixedVelocity) {
|
if (!state.currentPreset->fixedVelocity) {
|
||||||
unsigned int breathValHires = breathCurve(mapConstrain(instrument.breathSignal, instrument.breathThrVal, instrument.breathMaxVal, 0, 16383));
|
unsigned int breathValHires = breathCurve(mapConstrain(instrument.breathSignal, instrument.breathBaseline, instrument.breathMaxVal, 0, 16383));
|
||||||
velocitySend = (breathValHires >> 7) & 0x007F;
|
velocitySend = (breathValHires >> 7) & 0x007F;
|
||||||
velocitySend = constrain(velocitySend + velocitySend * .1 * state.currentPreset->velBias, 1, 127);
|
velocitySend = constrain(velocitySend + velocitySend * .1 * state.currentPreset->velBias, 1, 127);
|
||||||
} else {
|
} else {
|
||||||
velocitySend = state.currentPreset->fixedVelocity;
|
velocitySend = state.currentPreset->fixedVelocity;
|
||||||
}
|
}
|
||||||
|
Serial.print(">velocity:");
|
||||||
|
Serial.println(velocitySend);
|
||||||
|
|
||||||
midiSendNoteOn(fingeredNote, velocitySend); // send Note Off message
|
midiSendNoteOn(fingeredNote, velocitySend); // send Note Off message
|
||||||
}
|
}
|
||||||
|
@ -844,9 +845,9 @@ void initState() {
|
||||||
*/
|
*/
|
||||||
void readUtil() {
|
void readUtil() {
|
||||||
instrument.biteSignal = readTouchRoller(bitePin);
|
instrument.biteSignal = readTouchRoller(bitePin);
|
||||||
instrument.pbSignal = readSlider(SLIDER_PITCH_BEND);
|
instrument.pbSignal = readSlider(Slider::SLIDER_PITCH_BEND, instrument.sliderPBThr);
|
||||||
instrument.leverSignal = readSlider(SLIDER_LEVER);
|
instrument.leverSignal = readSlider(Slider::SLIDER_LEVER, instrument.sliderLeverThr);
|
||||||
instrument.extraSignal = readSlider(SLIDER_EXTRA);
|
instrument.extraSignal = readSlider(Slider::SLIDER_EXTRA, instrument.sliderExtraThr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -866,19 +867,16 @@ void handleCCs() {
|
||||||
}
|
}
|
||||||
if (currentTime - ccSendTime > CC_INTERVAL_PRIMARY) {
|
if (currentTime - ccSendTime > CC_INTERVAL_PRIMARY) {
|
||||||
// deal with Pitch Bend, Modulation, etc.
|
// deal with Pitch Bend, Modulation, etc.
|
||||||
readUtil();
|
|
||||||
pitch_bend();
|
pitch_bend();
|
||||||
sendCC();
|
sendCC();
|
||||||
checkICM(state);
|
checkICM(state);
|
||||||
ccSendTime = currentTime;
|
ccSendTime = currentTime;
|
||||||
}
|
}
|
||||||
if (currentTime - ccSendTime2 > CC_INTERVAL_PORT) {
|
if (currentTime - ccSendTime2 > CC_INTERVAL_PORT) {
|
||||||
readUtil();
|
|
||||||
portamento_();
|
portamento_();
|
||||||
ccSendTime2 = currentTime;
|
ccSendTime2 = currentTime;
|
||||||
}
|
}
|
||||||
if (currentTime - ccSendTime3 > CC_INTERVAL_OTHER) {
|
if (currentTime - ccSendTime3 > CC_INTERVAL_OTHER) {
|
||||||
readUtil();
|
|
||||||
updateSensorLEDs(*state.instrument);
|
updateSensorLEDs(*state.instrument);
|
||||||
ccSendTime3 = currentTime;
|
ccSendTime3 = currentTime;
|
||||||
}
|
}
|
||||||
|
@ -889,32 +887,36 @@ void handleCCs() {
|
||||||
*/
|
*/
|
||||||
void readBreath() {
|
void readBreath() {
|
||||||
|
|
||||||
int16_t breathSignal = constrain(readPressure(), BREATH_LO_LIMIT, BREATH_HI_LIMIT); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP
|
// Get the pressure sensor reading
|
||||||
int16_t breathAltSignal = constrain(readAltPressure(), BREATH_LO_LIMIT, BREATH_HI_LIMIT); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP
|
int16_t breathSignal = constrain(readPressure(), BREATH_LO_LIMIT, BREATH_HI_LIMIT);
|
||||||
|
int16_t breathAltSignal = constrain(readAltPressure(), BREATH_LO_LIMIT, BREATH_HI_LIMIT) + instrument.breathAltZeroOffset;
|
||||||
int16_t spikeSignal = constrain(readSpikePressure(), -SPIKE_HI_LIMIT, SPIKE_HI_LIMIT);
|
int16_t spikeSignal = constrain(readSpikePressure(), -SPIKE_HI_LIMIT, SPIKE_HI_LIMIT);
|
||||||
instrument.breathMovingThrVal = constrain(
|
int16_t diffSignal = breathAltSignal - breathSignal;
|
||||||
breathBaselineFilter.input((breathSignal + instrument.breathZero) / 2),
|
int16_t halfOffset = state.calibration->breathThrValOffset / 2;
|
||||||
instrument.breathThrVal,
|
|
||||||
instrument.breathMaxVal
|
|
||||||
);
|
|
||||||
|
|
||||||
if (state.currentPreset->breathMode == BREATH_ACC || state.currentPreset->breathMode == BREATH_ACC_AT) {
|
if (state.currentPreset->breathMode == BREATH_ACC || state.currentPreset->breathMode == BREATH_ACC_AT) {
|
||||||
int delta = breathSignal - instrument.breathZero;
|
int delta = breathSignal - instrument.breathZero;
|
||||||
if (abs(delta) > state.calibration->breathAltThrValOffset) {
|
if (abs(delta) > state.calibration->breathThrValOffset) {
|
||||||
instrument.breathSignal = constrain(instrument.breathSignal + delta / 15, instrument.breathZero, instrument.breathMaxVal);
|
instrument.breathSignal = constrain(instrument.breathSignal + delta / 15, instrument.breathZero, instrument.breathMaxVal);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
instrument.breathSignal = breathSignal + (spikeSignal > 0 ? spikeSignal * state.currentPreset->spikeOnFactor : spikeSignal * state.currentPreset->spikeOffFactor);
|
instrument.breathSignal = breathSignal + diffSignal + (spikeSignal > 0 ? spikeSignal * state.currentPreset->spikeOnFactor : spikeSignal * state.currentPreset->spikeOffFactor);
|
||||||
}
|
}
|
||||||
instrument.breathAltSignal = breathAltSignal;
|
instrument.breathAltSignal = breathAltSignal;
|
||||||
|
|
||||||
|
instrument.breathMovingThrVal = constrain(
|
||||||
|
breathBaselineFilter.input(instrument.breathBaseline + (instrument.breathSignal - instrument.breathBaseline) * .75),
|
||||||
|
instrument.breathZero + halfOffset,
|
||||||
|
instrument.breathMaxVal - halfOffset
|
||||||
|
);
|
||||||
|
|
||||||
|
instrument.breathThrVal = instrument.breathMovingThrVal + halfOffset;
|
||||||
|
instrument.breathThrOffVal = instrument.breathMovingThrVal - halfOffset;
|
||||||
|
|
||||||
if (instrument.mode == MODE_DEBUG) {
|
if (instrument.mode == MODE_DEBUG) {
|
||||||
Serial.print(">breath:");
|
Serial.print(">breath:");
|
||||||
Serial.println(breathSignal);
|
Serial.println(breathSignal);
|
||||||
Serial.print(">breathAlt:");
|
|
||||||
Serial.println(breathAltSignal);
|
|
||||||
Serial.print(">Diff:");
|
Serial.print(">Diff:");
|
||||||
Serial.println(breathSignal - breathAltSignal);
|
Serial.println(diffSignal);
|
||||||
Serial.print(">breathMovingThr:");
|
Serial.print(">breathMovingThr:");
|
||||||
Serial.println(instrument.breathMovingThrVal);
|
Serial.println(instrument.breathMovingThrVal);
|
||||||
Serial.print(">note:");
|
Serial.print(">note:");
|
||||||
|
@ -923,6 +925,12 @@ void readBreath() {
|
||||||
Serial.println(spikeSignal);
|
Serial.println(spikeSignal);
|
||||||
Serial.print(">combo:");
|
Serial.print(">combo:");
|
||||||
Serial.println(instrument.breathSignal);
|
Serial.println(instrument.breathSignal);
|
||||||
|
Serial.print(">zero:");
|
||||||
|
Serial.println(instrument.breathZero);
|
||||||
|
Serial.print(">thr:");
|
||||||
|
Serial.println(instrument.breathThrVal);
|
||||||
|
Serial.print(">off:");
|
||||||
|
Serial.println(instrument.breathThrOffVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -934,7 +942,7 @@ void runStateMachine() {
|
||||||
static int initial_breath_value = 0; // The breath value at the time we observed the transition
|
static int initial_breath_value = 0; // The breath value at the time we observed the transition
|
||||||
if (state.mainState == NOTE_OFF) {
|
if (state.mainState == NOTE_OFF) {
|
||||||
handleOffStateActions();
|
handleOffStateActions();
|
||||||
if (instrument.breathSignal > instrument.breathMovingThrVal && state.mainState == NOTE_OFF) {
|
if (instrument.breathSignal > instrument.breathThrVal && state.mainState == NOTE_OFF) {
|
||||||
// Value has risen above threshold. Move to the RISE_WAIT
|
// Value has risen above threshold. Move to the RISE_WAIT
|
||||||
// state. Record time and initial breath value.
|
// state. Record time and initial breath value.
|
||||||
breath_on_time = millis();
|
breath_on_time = millis();
|
||||||
|
@ -945,21 +953,21 @@ void runStateMachine() {
|
||||||
if ((instrument.breathSignal > instrument.breathMovingThrVal)) {
|
if ((instrument.breathSignal > instrument.breathMovingThrVal)) {
|
||||||
// Has enough time passed for us to collect our second sample?
|
// Has enough time passed for us to collect our second sample?
|
||||||
if ((millis() - breath_on_time > state.currentPreset->velSmpDl) || (0 == state.currentPreset->velSmpDl) || state.currentPreset->fixedVelocity) {
|
if ((millis() - breath_on_time > state.currentPreset->velSmpDl) || (0 == state.currentPreset->velSmpDl) || state.currentPreset->fixedVelocity) {
|
||||||
noteOn(instrument.fingeredNote, instrument.breathSignal, initial_breath_value);
|
noteOn(instrument.fingeredNote, instrument.breathSignal, initial_breath_value);
|
||||||
if (instrument.fingeredNote != instrument.fingeredNote2) {
|
if (instrument.fingeredNote != instrument.fingeredNote2) {
|
||||||
noteOn(instrument.fingeredNote2, instrument.breathSignal, initial_breath_value);
|
noteOn(instrument.fingeredNote2, instrument.breathSignal, initial_breath_value);
|
||||||
}
|
}
|
||||||
breath(); // send breath data
|
breath(); // send breath data
|
||||||
state.mainState = NOTE_ON;
|
state.mainState = NOTE_ON;
|
||||||
instrument.activeNote = instrument.fingeredNote;
|
instrument.activeNote = instrument.fingeredNote;
|
||||||
instrument.activeNote2 = instrument.fingeredNote2;
|
instrument.activeNote2 = instrument.fingeredNote2;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Value fell below threshold before velocity sample delay time passed. Return to NOTE_OFF state
|
// Value fell below threshold before velocity sample delay time passed. Return to NOTE_OFF state
|
||||||
state.mainState = NOTE_OFF;
|
state.mainState = NOTE_OFF;
|
||||||
}
|
}
|
||||||
} else if (state.mainState == NOTE_ON) {
|
} else if (state.mainState == NOTE_ON) {
|
||||||
if (instrument.breathSignal < instrument.breathMovingThrVal) {
|
if (instrument.breathSignal < instrument.breathThrOffVal) {
|
||||||
// Value has fallen below threshold - turn the note off
|
// Value has fallen below threshold - turn the note off
|
||||||
midiSendNoteOff(instrument.activeNote); // send Note Off message
|
midiSendNoteOff(instrument.activeNote); // send Note Off message
|
||||||
if (instrument.activeNote != instrument.activeNote2) {
|
if (instrument.activeNote != instrument.activeNote2) {
|
||||||
|
@ -1019,12 +1027,8 @@ void setup() {
|
||||||
//_______________________________________________________________________________________________ MAIN LOOP
|
//_______________________________________________________________________________________________ MAIN LOOP
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
static unsigned long lastUpdate = millis();
|
|
||||||
static unsigned long pixelUpdateTime = 0;
|
static unsigned long pixelUpdateTime = 0;
|
||||||
static const unsigned long pixelUpdateInterval = 80;
|
static const unsigned long pixelUpdateInterval = 80;
|
||||||
unsigned long time = millis();
|
|
||||||
unsigned long deltaTime = time - lastUpdate;
|
|
||||||
lastUpdate = time;
|
|
||||||
|
|
||||||
// If in config mgmt loop, do that and nothing else
|
// If in config mgmt loop, do that and nothing else
|
||||||
if (instrument.mode == MODE_CONFIG) {
|
if (instrument.mode == MODE_CONFIG) {
|
||||||
|
@ -1039,6 +1043,7 @@ void loop() {
|
||||||
|
|
||||||
readBreath();
|
readBreath();
|
||||||
readSwitches();
|
readSwitches();
|
||||||
|
readUtil();
|
||||||
runStateMachine();
|
runStateMachine();
|
||||||
handleCCs();
|
handleCCs();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue