Add MIDI panic function

This commit is contained in:
2025-07-01 21:20:19 +02:00
parent cc95ee8aa5
commit 5a3783d948
4 changed files with 111 additions and 35 deletions
+9
View File
@@ -64,3 +64,12 @@ const unsigned char savetorom [] PROGMEM = {
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

+102 -35
View File
@@ -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,6 +290,8 @@ void setup() {
updateOLED(); updateOLED();
} }
void loop() { void loop() {
MIDI.read(); MIDI.read();
@@ -203,6 +299,10 @@ void loop() {
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)) {
EEPROM.update(EEPROM_MIDI_CHANNEL_ADDR, currentMidiChannel); EEPROM.update(EEPROM_MIDI_CHANNEL_ADDR, currentMidiChannel);
@@ -229,36 +329,3 @@ void loop() {
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);
}
}
}
}