Add MIDI panic function
This commit is contained in:
@@ -63,4 +63,13 @@ const unsigned char savetorom [] PROGMEM = {
|
|||||||
0x00, 0x05, 0x55, 0x54, 0x00, 0x0f, 0xff, 0xfe, 0x01, 0x0c, 0x00, 0x02, 0x01, 0x8c, 0x00, 0x02,
|
0x00, 0x05, 0x55, 0x54, 0x00, 0x0f, 0xff, 0xfe, 0x01, 0x0c, 0x00, 0x02, 0x01, 0x8c, 0x00, 0x02,
|
||||||
0x01, 0xcd, 0x89, 0xb2, 0xbf, 0xed, 0x55, 0x54, 0x5f, 0xed, 0x95, 0x14, 0x01, 0xcd, 0x49, 0x12,
|
0x01, 0xcd, 0x89, 0xb2, 0xbf, 0xed, 0x55, 0x54, 0x5f, 0xed, 0x95, 0x14, 0x01, 0xcd, 0x49, 0x12,
|
||||||
0x01, 0x8c, 0x00, 0x02, 0x01, 0x0c, 0x00, 0x02, 0x00, 0x0f, 0xff, 0xfe, 0x00, 0x05, 0x55, 0x54
|
0x01, 0x8c, 0x00, 0x02, 0x01, 0x0c, 0x00, 0x02, 0x00, 0x0f, 0xff, 0xfe, 0x00, 0x05, 0x55, 0x54
|
||||||
|
};
|
||||||
|
|
||||||
|
// 'panic', 32x12px
|
||||||
|
#define ICONPANIC_WIDTH 32
|
||||||
|
#define ICONPANIC_HEIGHT 12
|
||||||
|
const unsigned char iconpanic [] PROGMEM = {
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x01, 0x8e, 0x38, 0xc9, 0x4d, 0x91, 0x25, 0x29, 0x51,
|
||||||
|
0xa4, 0xa5, 0x2d, 0x51, 0xa4, 0xb9, 0xed, 0x51, 0xa0, 0xa1, 0x2b, 0x51, 0xa4, 0xa1, 0x2b, 0x51,
|
||||||
|
0x91, 0x21, 0x29, 0x51, 0x8e, 0x21, 0x29, 0x4d, 0x80, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff
|
||||||
};
|
};
|
||||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@@ -1,6 +1,7 @@
|
|||||||
#define FW_VER 1.01
|
#define FW_VER 1.02
|
||||||
#define USE_OLED true // OLED displays
|
#define USE_OLED true // OLED displays
|
||||||
#define USE_ENCODER true
|
#define USE_ENCODER true
|
||||||
|
#define USE_PANIC true
|
||||||
#define EEPROM_MIDI_CHANNEL_ADDR 0 // Address to save MIDI channel in EEPROM
|
#define EEPROM_MIDI_CHANNEL_ADDR 0 // Address to save MIDI channel in EEPROM
|
||||||
|
|
||||||
// include libraries
|
// include libraries
|
||||||
@@ -25,13 +26,18 @@
|
|||||||
int lastClk = HIGH;
|
int lastClk = HIGH;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if USE_PANIC
|
||||||
|
#define PANIC_BUTTON 4
|
||||||
|
bool midiPanic = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned long lastChannelChangeTime = 0;
|
unsigned long lastChannelChangeTime = 0;
|
||||||
bool channelChanged = false;
|
bool channelChanged = false;
|
||||||
const unsigned long saveDelay = 2000; // 2 seconds
|
const unsigned long saveDelay = 2000; // 2 seconds
|
||||||
|
|
||||||
bool showSavedMessage = false;
|
bool showSavedMessage = false;
|
||||||
unsigned long savedMessageStart = 0;
|
unsigned long savedMessageStart = 0;
|
||||||
const unsigned long savedMessageDuration = 3000; // 1 second
|
const unsigned long savedMessageDuration = 3000; // 3 seconds
|
||||||
|
|
||||||
// Instantiate libraries
|
// Instantiate libraries
|
||||||
Adafruit_MCP23X17 mcp1; // First MCP23017
|
Adafruit_MCP23X17 mcp1; // First MCP23017
|
||||||
@@ -112,6 +118,12 @@ void updateOLED() {
|
|||||||
oled.drawBitmap(88, 0, savetorom, SAVETOROM_WIDTH, SAVETOROM_HEIGHT, 1);
|
oled.drawBitmap(88, 0, savetorom, SAVETOROM_WIDTH, SAVETOROM_HEIGHT, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_PANIC
|
||||||
|
if (midiPanic) {
|
||||||
|
oled.drawBitmap(1, 0, iconpanic, ICONPANIC_WIDTH, ICONPANIC_HEIGHT, 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
oled.display();
|
oled.display();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -148,6 +160,84 @@ void checkEncoder() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleNoteOn(byte channel, byte pitch, byte velocity) {
|
||||||
|
#if USE_PANIC
|
||||||
|
if (midiPanic) return; // suppress all notes during panic
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (currentMidiChannel == MIDI_CHANNEL_OMNI || channel == currentMidiChannel) {
|
||||||
|
|
||||||
|
if (pitch >= 57 && pitch <= 88) {
|
||||||
|
MCPOutput out = noteToMCP[pitch - 57];
|
||||||
|
if (out.chip == 0) {
|
||||||
|
mcp1.digitalWrite(out.pin, HIGH);
|
||||||
|
} else if (out.chip == 1) {
|
||||||
|
mcp2.digitalWrite(out.pin, HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flash LED on Note On
|
||||||
|
digitalWrite(LED_BUILTIN, HIGH);
|
||||||
|
ledOnTime = millis();
|
||||||
|
ledActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleNoteOff(byte channel, byte pitch, byte velocity) {
|
||||||
|
#if USE_PANIC
|
||||||
|
if (midiPanic) return; // suppress all notes during panic
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (currentMidiChannel == MIDI_CHANNEL_OMNI || channel == currentMidiChannel) {
|
||||||
|
if (pitch >= 57 && pitch <= 88) {
|
||||||
|
MCPOutput out = noteToMCP[pitch - 57];
|
||||||
|
if (out.chip == 0) {
|
||||||
|
mcp1.digitalWrite(out.pin, LOW);
|
||||||
|
} else if (out.chip == 1) {
|
||||||
|
mcp2.digitalWrite(out.pin, LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkMidiPanic() {
|
||||||
|
#if USE_PANIC
|
||||||
|
static bool lastButtonState = HIGH;
|
||||||
|
static unsigned long lastToggleTime = 0;
|
||||||
|
const unsigned long debounceDelay = 50;
|
||||||
|
|
||||||
|
bool currentButtonState = digitalRead(PANIC_BUTTON);
|
||||||
|
|
||||||
|
if (lastButtonState == HIGH && currentButtonState == LOW) {
|
||||||
|
unsigned long now = millis();
|
||||||
|
if (now - lastToggleTime > debounceDelay) {
|
||||||
|
midiPanic = !midiPanic;
|
||||||
|
lastToggleTime = now;
|
||||||
|
|
||||||
|
if (midiPanic) {
|
||||||
|
// Turn off all notes immediately
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (noteToMCP[i].chip == 0) {
|
||||||
|
mcp1.digitalWrite(noteToMCP[i].pin, LOW);
|
||||||
|
} else {
|
||||||
|
mcp2.digitalWrite(noteToMCP[i].pin, LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USE_OLED
|
||||||
|
updateOLED(); // Only update display when state changes
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastButtonState = currentButtonState;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
// Validate saved midi channel in EEPROM
|
// Validate saved midi channel in EEPROM
|
||||||
if (savedChannel <= 16) {
|
if (savedChannel <= 16) {
|
||||||
@@ -175,6 +265,10 @@ void setup() {
|
|||||||
pinMode(ENCODER_CLK, INPUT_PULLUP);
|
pinMode(ENCODER_CLK, INPUT_PULLUP);
|
||||||
pinMode(ENCODER_DT, INPUT_PULLUP);
|
pinMode(ENCODER_DT, INPUT_PULLUP);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if USE_PANIC
|
||||||
|
pinMode(PANIC_BUTTON, INPUT_PULLUP);
|
||||||
|
#endif
|
||||||
// Midi Activity LED on Pin 13 (aka LED_BUILTIN)
|
// Midi Activity LED on Pin 13 (aka LED_BUILTIN)
|
||||||
pinMode(LED_BUILTIN, OUTPUT);
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
|
||||||
@@ -196,12 +290,18 @@ void setup() {
|
|||||||
updateOLED();
|
updateOLED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
MIDI.read();
|
MIDI.read();
|
||||||
|
|
||||||
#if USE_ENCODER
|
#if USE_ENCODER
|
||||||
checkEncoder();
|
checkEncoder();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if USE_PANIC
|
||||||
|
checkMidiPanic();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Save channel if change timeout has passed
|
// Save channel if change timeout has passed
|
||||||
if (channelChanged && (millis() - lastChannelChangeTime >= saveDelay)) {
|
if (channelChanged && (millis() - lastChannelChangeTime >= saveDelay)) {
|
||||||
@@ -228,37 +328,4 @@ void loop() {
|
|||||||
digitalWrite(LED_BUILTIN, LOW);
|
digitalWrite(LED_BUILTIN, LOW);
|
||||||
ledActive = false;
|
ledActive = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void handleNoteOn(byte channel, byte pitch, byte velocity) {
|
|
||||||
if (currentMidiChannel == MIDI_CHANNEL_OMNI || channel == currentMidiChannel) {
|
|
||||||
|
|
||||||
if (pitch >= 57 && pitch <= 88) {
|
|
||||||
MCPOutput out = noteToMCP[pitch - 57];
|
|
||||||
if (out.chip == 0) {
|
|
||||||
mcp1.digitalWrite(out.pin, HIGH);
|
|
||||||
} else if (out.chip == 1) {
|
|
||||||
mcp2.digitalWrite(out.pin, HIGH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flash LED on Note On
|
|
||||||
digitalWrite(LED_BUILTIN, HIGH);
|
|
||||||
ledOnTime = millis();
|
|
||||||
ledActive = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleNoteOff(byte channel, byte pitch, byte velocity) {
|
|
||||||
if (currentMidiChannel == MIDI_CHANNEL_OMNI || channel == currentMidiChannel) {
|
|
||||||
if (pitch >= 57 && pitch <= 88) {
|
|
||||||
MCPOutput out = noteToMCP[pitch - 57];
|
|
||||||
if (out.chip == 0) {
|
|
||||||
mcp1.digitalWrite(out.pin, LOW);
|
|
||||||
} else if (out.chip == 1) {
|
|
||||||
mcp2.digitalWrite(out.pin, LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user