Cleanup pair octaves
This commit is contained in:
parent
00cdfc08e0
commit
c09177c0ee
9 changed files with 119 additions and 70 deletions
|
@ -1,9 +1,6 @@
|
|||
1. LED abstraction code
|
||||
5. Refactor CV behavior into module
|
||||
6. 9dof sensor code
|
||||
7. Alternate fingerings
|
||||
8. Encoder midi
|
||||
7. LH fingerings
|
||||
|
||||
- Lever mode: pb
|
||||
- Breath suck control?
|
||||
-
|
||||
- Breath suck control?
|
|
@ -10,8 +10,9 @@
|
|||
#define ON_Delay 20 // Set Delay after ON threshold before velocity is checked (wait for tounging peak)
|
||||
#define CCN_Port 5 // Controller number for portamento level
|
||||
#define CCN_PortOnOff 65// Controller number for portamento on/off
|
||||
#define START_NOTE 24 // 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 BREATH_THR_MAX_BOOST 40.0
|
||||
#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 CALIBRATE_SAMPLE_COUNT 4
|
||||
|
@ -31,6 +32,7 @@
|
|||
#define BTN_PRESET 0x8
|
||||
#define KNOB_CURVE_THRESHOLD 100
|
||||
#define KNOB_CURVE_MULTIPLIER 5
|
||||
#define KNOB_DISPLAY_TIME 500
|
||||
|
||||
// Send breath CC data no more than every CC_BREATH_INTERVAL
|
||||
// milliseconds
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
|
||||
enum PinkyMode : uint8_t {
|
||||
PBD = 12,
|
||||
GLD = 25,
|
||||
MOD = 26,
|
||||
QTN = 27,
|
||||
GLD = 26,
|
||||
MOD = 27,
|
||||
QTN = 28,
|
||||
};
|
||||
|
||||
enum FingeringMode : uint8_t {
|
||||
|
@ -105,6 +105,8 @@ struct instrument_state_t {
|
|||
int pitchBend = 8192;
|
||||
int pbSend = 8192; // Pitch bend actually sent, modified by vibrato, etc
|
||||
byte knobVals[4];
|
||||
byte lastKnobVal;
|
||||
unsigned long lastKnobTime;
|
||||
byte rollCCVal = 0;
|
||||
byte tiltCCVal = 0;
|
||||
|
||||
|
@ -119,6 +121,7 @@ struct instrument_state_t {
|
|||
// Calibration
|
||||
int16_t breathZero; // this gets auto calibrated in setup
|
||||
int16_t breathThrVal; // this gets auto calibrated in setup
|
||||
int16_t breathMovingThrVal;
|
||||
int16_t breathMaxVal; // this gets auto calibrated in setup
|
||||
int16_t breathAltZero; // this gets auto calibrated in setup
|
||||
int16_t breathAltThrVal; // this gets auto calibrated in setup
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
FilterOnePole breathFilter;
|
||||
FilterOnePole breathAltFilter;
|
||||
FilterOnePole spikeFilter;
|
||||
FilterOnePole tiltFilter;
|
||||
FilterOnePole rollFilter;
|
||||
|
||||
Adafruit_MPR121 touchSensorKeys = Adafruit_MPR121();
|
||||
Adafruit_MPR121 touchSensorUtil = Adafruit_MPR121();
|
||||
|
@ -44,6 +46,8 @@ void initHardware() {
|
|||
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
|
||||
spikeFilter.setFilter(HIGHPASS, 200, 0.0); // create a one pole (RC) lowpass filter
|
||||
tiltFilter.setFilter(LOWPASS, 2, 0.0); // create a one pole (RC) lowpass filter
|
||||
rollFilter.setFilter(LOWPASS, 2, 0.0); // create a one pole (RC) lowpass filter
|
||||
icmSensor.begin_I2C(ICM20948_I2CADDR_DEFAULT, &MainI2CBus);
|
||||
|
||||
ledStrip.begin();
|
||||
|
@ -179,7 +183,7 @@ icm_result_t readICM() {
|
|||
icmSensor.getEvent(&accel, &gyro, &temp, &mag);
|
||||
|
||||
return {
|
||||
mag.magnetic.y,
|
||||
mag.magnetic.x,
|
||||
tiltFilter.input(mag.magnetic.y),
|
||||
rollFilter.input(mag.magnetic.x),
|
||||
};
|
||||
}
|
25
NuEVI/src/icm.cpp
Normal file
25
NuEVI/src/icm.cpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include "hardware.h"
|
||||
#include "midi.h"
|
||||
|
||||
void checkICM(state_t &state) {
|
||||
icm_result_t icmSignal = readICM();
|
||||
Serial.print(">roll: ");
|
||||
Serial.println(icmSignal.roll);
|
||||
Serial.print(">tilt: ");
|
||||
Serial.println(icmSignal.tilt);
|
||||
if (ExtraControl::CC == state.currentPreset->icmRollMode) {
|
||||
byte roll = mapConstrain(abs(icmSignal.roll), 0, 40, 127, 0);
|
||||
if (roll != state.instrument->rollCCVal) {
|
||||
midiSendControlChange(state.currentPreset->icmRollCC, roll);
|
||||
state.instrument->rollCCVal = roll;
|
||||
}
|
||||
}
|
||||
|
||||
if (ExtraControl::CC == state.currentPreset->icmTiltMode) {
|
||||
byte tilt = mapConstrain(abs(icmSignal.tilt), -20, 40, 0, 127);
|
||||
if (tilt != state.instrument->tiltCCVal) {
|
||||
midiSendControlChange(state.currentPreset->icmTiltCC, tilt);
|
||||
state.instrument->tiltCCVal = tilt;
|
||||
}
|
||||
}
|
||||
}
|
8
NuEVI/src/icm.h
Normal file
8
NuEVI/src/icm.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef __ICM_H
|
||||
#define __ICM_H
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
void checkICM(state_t &state);
|
||||
|
||||
#endif
|
|
@ -25,6 +25,14 @@ void singleLED(int n, int color) {
|
|||
// 0 -> 0, 0, 0, 0, 0, 0, 0, 0
|
||||
|
||||
void ledFullMeter(byte indicatedValue, int color){
|
||||
static byte lastVal = 0;
|
||||
static int lastColor = 0;
|
||||
if (lastVal == indicatedValue && lastColor == color) {
|
||||
return;
|
||||
}
|
||||
lastVal = indicatedValue;
|
||||
lastColor = color;
|
||||
|
||||
int scaledVal = indicatedValue;
|
||||
ledStrip.setBrightness(1);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
|
@ -79,5 +87,9 @@ void statusLedBlink() {
|
|||
}
|
||||
|
||||
void updateSensorLEDs(instrument_state_t &state) {
|
||||
ledFullMeter(state.breathCCVal, 0x0000FF);
|
||||
if (millis() - state.lastKnobTime < KNOB_DISPLAY_TIME) {
|
||||
ledFullMeter(state.lastKnobVal, 0x00FF00);
|
||||
} else {
|
||||
ledFullMeter(state.breathCCVal, 0x0000FF);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -516,7 +516,7 @@ public:
|
|||
}
|
||||
|
||||
if (_focused && input.changed && input.knobMenu != 0) {
|
||||
_cursorPos = (_cursorPos + input.knobMenu) % _entries.size();
|
||||
_cursorPos = ((_cursorPos + input.knobMenu) + _entries.size()) % _entries.size();
|
||||
draw(false);
|
||||
redrawValue = true;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "led.h"
|
||||
#include "test.h"
|
||||
#include "FilterOnePole.h"
|
||||
#include "icm.h"
|
||||
|
||||
/*
|
||||
NAME: xEVI
|
||||
|
@ -92,6 +93,7 @@ bool configManagementMode = false;
|
|||
bool testMode = false;
|
||||
|
||||
FilterOnePole breathCCFilter;
|
||||
FilterOnePole breathBaselineFilter;
|
||||
|
||||
//_______________________________________________________________________________________________ SETUP
|
||||
|
||||
|
@ -444,33 +446,13 @@ void sendCC() {
|
|||
midiSendControlChange(state.currentPreset->knob4CC, val);
|
||||
break;
|
||||
}
|
||||
|
||||
state.instrument->knobVals[i] = val;
|
||||
state.instrument->lastKnobVal = val;
|
||||
state.instrument->lastKnobTime = millis();
|
||||
}
|
||||
|
||||
state.instrument->knobVals[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
icm_result_t icmSignal = readICM();
|
||||
Serial.print(">roll: ");
|
||||
Serial.println(icmSignal.roll);
|
||||
Serial.print(">tilt: ");
|
||||
Serial.println(icmSignal.tilt);
|
||||
if (ExtraControl::CC == state.currentPreset->icmRollMode) {
|
||||
byte roll = mapConstrain(abs(icmSignal.roll), 0, 40, 127, 0);
|
||||
if (roll != state.instrument->rollCCVal) {
|
||||
midiSendControlChange(state.currentPreset->icmRollCC, roll);
|
||||
state.instrument->rollCCVal = roll;
|
||||
}
|
||||
}
|
||||
|
||||
if (ExtraControl::CC == state.currentPreset->icmTiltMode) {
|
||||
byte tilt = mapConstrain(abs(icmSignal.tilt), -20, 40, 0, 127);
|
||||
if (tilt != state.instrument->tiltCCVal) {
|
||||
midiSendControlChange(state.currentPreset->icmTiltCC, tilt);
|
||||
state.instrument->tiltCCVal = tilt;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Re-zero floating calibration values
|
||||
|
@ -602,7 +584,7 @@ int readOctave() {
|
|||
if (rollers[0]) {
|
||||
octaveR = 1;
|
||||
} else if (rollers[5]) {
|
||||
octaveR = 6;
|
||||
octaveR = 7;
|
||||
}
|
||||
}
|
||||
} else if (rollerMode == RollerMode::PARTIAL || rollerMode == RollerMode::PARTIAL_EXTEND) {
|
||||
|
@ -632,6 +614,8 @@ int readOctave() {
|
|||
if (extend && octaveR == 0) {
|
||||
if (rollerMode == RollerMode::HIGHEST_EXTEND && lastOctaveR == 6) {
|
||||
octaveR = 7;
|
||||
} else if (rollerMode == RollerMode::HIGHEST_PAIR_EXTEND && lastOctaveR == 7) {
|
||||
octaveR = 8;
|
||||
} else if (rollerMode == RollerMode::PARTIAL_EXTEND && lastOctaveR == 7) {
|
||||
octaveR = 8;
|
||||
} else if (lastOctaveR == 1) {
|
||||
|
@ -785,7 +769,8 @@ void initState() {
|
|||
|
||||
instrument.activeMIDIchannel = state.currentPreset->MIDIchannel;
|
||||
midiInitialize(state.currentPreset->MIDIchannel);
|
||||
breathCCFilter.setFilter(LOWPASS, 3, 0.0); // create a one pole (RC) lowpass filter
|
||||
breathCCFilter.setFilter(LOWPASS, 3, 0.0);
|
||||
breathBaselineFilter.setFilter(LOWPASS, 1, 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -802,7 +787,7 @@ void readUtil() {
|
|||
/**
|
||||
* Send CC data when needed
|
||||
*/
|
||||
void sendCCs() {
|
||||
void handleCCs() {
|
||||
static unsigned long ccBreathSendTime = 0L; // The last time we sent breath CC values
|
||||
static unsigned long ccSendTime = 0L; // The last time we sent CC values
|
||||
static unsigned long ccSendTime2 = 0L; // The last time we sent CC values 2 (slower)
|
||||
|
@ -819,6 +804,7 @@ void sendCCs() {
|
|||
readUtil();
|
||||
pitch_bend();
|
||||
sendCC();
|
||||
checkICM(state);
|
||||
ccSendTime = currentTime;
|
||||
}
|
||||
if (currentTime - ccSendTime2 > CC_INTERVAL_PORT) {
|
||||
|
@ -833,6 +819,43 @@ void sendCCs() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the breath sensors according to the active mode
|
||||
*/
|
||||
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
|
||||
int16_t spikeSignal = constrain(readSpikePressure(), -SPIKE_HI_LIMIT, SPIKE_HI_LIMIT);
|
||||
instrument.breathMovingThrVal = constrain(
|
||||
breathBaselineFilter.input((breathSignal + instrument.breathZero) / 2),
|
||||
instrument.breathThrVal,
|
||||
instrument.breathMaxVal
|
||||
);
|
||||
|
||||
if (state.currentPreset->breathMode == BREATH_ACC || state.currentPreset->breathMode == BREATH_ACC_AT) {
|
||||
int delta = breathSignal - instrument.breathZero;
|
||||
if (abs(delta) > state.calibration->breathAltThrValOffset) {
|
||||
instrument.breathSignal = constrain(instrument.breathSignal + delta / 10, instrument.breathZero, instrument.breathMaxVal);
|
||||
}
|
||||
} else {
|
||||
instrument.breathSignal = breathSignal + (spikeSignal > 0 ? spikeSignal * state.currentPreset->spikeOnFactor : spikeSignal * state.currentPreset->spikeOffFactor);
|
||||
}
|
||||
instrument.breathAltSignal = constrain(readAltPressure(), BREATH_LO_LIMIT, BREATH_HI_LIMIT); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP
|
||||
|
||||
Serial.print(">breathThr:");
|
||||
Serial.println(instrument.breathThrVal);
|
||||
Serial.print(">breathMovingThr:");
|
||||
Serial.println(instrument.breathMovingThrVal);
|
||||
Serial.print(">note:");
|
||||
Serial.println(state.mainState);
|
||||
Serial.print(">spike:");
|
||||
Serial.println(spikeSignal);
|
||||
Serial.print(">breath:");
|
||||
Serial.println(breathSignal);
|
||||
Serial.print(">combo:");
|
||||
Serial.println(instrument.breathSignal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main instrument state machine
|
||||
*/
|
||||
|
@ -842,7 +865,7 @@ void runStateMachine() {
|
|||
int fingeredNote = noteValueCheck(readSwitches() + readOctave());
|
||||
if (state.mainState == NOTE_OFF) {
|
||||
handleOffStateActions();
|
||||
if (instrument.breathSignal > instrument.breathThrVal && state.mainState == NOTE_OFF) {
|
||||
if (instrument.breathSignal > instrument.breathMovingThrVal && state.mainState == NOTE_OFF) {
|
||||
// Value has risen above threshold. Move to the RISE_WAIT
|
||||
// state. Record time and initial breath value.
|
||||
breath_on_time = millis();
|
||||
|
@ -850,7 +873,7 @@ void runStateMachine() {
|
|||
state.mainState = RISE_WAIT; // Go to next state
|
||||
}
|
||||
} else if (state.mainState == RISE_WAIT) {
|
||||
if ((instrument.breathSignal > instrument.breathThrVal)) {
|
||||
if ((instrument.breathSignal > instrument.breathMovingThrVal)) {
|
||||
// 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) {
|
||||
noteOn(fingeredNote, instrument.breathSignal, initial_breath_value);
|
||||
|
@ -862,7 +885,7 @@ void runStateMachine() {
|
|||
state.mainState = NOTE_OFF;
|
||||
}
|
||||
} else if (state.mainState == NOTE_ON) {
|
||||
if (instrument.breathSignal < instrument.breathThrVal) {
|
||||
if (instrument.breathSignal < instrument.breathMovingThrVal) {
|
||||
// Value has fallen below threshold - turn the note off
|
||||
midiSendNoteOff(instrument.activeNote); // send Note Off message
|
||||
instrument.breathSignal = 0;
|
||||
|
@ -954,35 +977,10 @@ void loop() {
|
|||
return;
|
||||
}
|
||||
|
||||
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
|
||||
int16_t spikeSignal = constrain(readSpikePressure(), -SPIKE_HI_LIMIT, SPIKE_HI_LIMIT);
|
||||
|
||||
|
||||
if (state.currentPreset->breathMode == BREATH_ACC || state.currentPreset->breathMode == BREATH_ACC_AT) {
|
||||
int delta = breathSignal - instrument.breathZero;
|
||||
if (abs(delta) > state.calibration->breathAltThrValOffset) {
|
||||
instrument.breathSignal = constrain(instrument.breathSignal + delta / 10, instrument.breathZero, instrument.breathMaxVal);
|
||||
}
|
||||
} else {
|
||||
instrument.breathSignal = breathSignal + (spikeSignal > 0 ? spikeSignal * state.currentPreset->spikeOnFactor : spikeSignal * state.currentPreset->spikeOffFactor);
|
||||
}
|
||||
instrument.breathAltSignal = constrain(readAltPressure(), BREATH_LO_LIMIT, BREATH_HI_LIMIT); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP
|
||||
|
||||
/*
|
||||
Serial.print(">breathThr:");
|
||||
Serial.println(instrument.breathThrVal);
|
||||
Serial.print(">note:");
|
||||
Serial.println(state.mainState);
|
||||
Serial.print(">spike:");
|
||||
Serial.println(spikeSignal);
|
||||
Serial.print(">breath:");
|
||||
Serial.println(breathSignal);
|
||||
Serial.print(">combo:");
|
||||
Serial.println(instrument.breathSignal);
|
||||
*/
|
||||
readBreath();
|
||||
|
||||
runStateMachine();
|
||||
sendCCs();
|
||||
handleCCs();
|
||||
|
||||
// cvUpdate();
|
||||
midiDiscardInput();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue