#include <MIDI.h>
// Updated GPIO pins to 74HC595
const int dataPin = 19; // DS (Pin 14 of Shift Register 1)
const int clockPin = 18; // SH_CP (Clock Pin for all Shift Registers)
const int latchPin = 5; // ST_CP (Latch Pin for all Shift Registers)
const int numShiftRegisters = 11; // Total number of 74HC595 shift registers
// Array to hold the state of each shift register
byte shiftRegisterStates[numShiftRegisters] = {0};
void setup() {
// Initialize Serial Communication
Serial.begin(115200);
Serial.println("Hello, ESP32-S2!");
// Initialize Shift Register Control Pins
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);
// Initialize control pins to LOW
digitalWrite(dataPin, LOW);
digitalWrite(clockPin, LOW);
digitalWrite(latchPin, LOW);
}
void loop() {
playMozartMelody(); // Play the simulated Mozart melody
delay(5000); // Pause for 5 seconds before repeating
}
// Function to simulate a simple Mozart melody using MIDI Note On/Off events
void playMozartMelody() {
int melody[] = {60, 60, 67, 67, 69, 69, 67, // C4 C4 G4 G4 A4 A4 G4
65, 65, 64, 64, 62, 62, 60}; // F4 F4 E4 E4 D4 D4 C4
int noteDurations[] = {500, 500, 500, 500, 500, 500, 1000, // Durations for first phrase
500, 500, 500, 500, 500, 500, 2000}; // Durations for second phrase
int length = sizeof(melody) / sizeof(melody[0]);
for (int i = 0; i < length; i++) {
// Simulate Note On event
handleNoteOn(1, melody[i], 127); // Channel 1, velocity 127
delay(noteDurations[i]); // Hold the note for its duration
// Simulate Note Off event
handleNoteOff(1, melody[i], 0); // Channel 1, velocity 0
delay(100); // Short delay between notes
}
}
// Function to map MIDI note to LED index
int midiNoteToLED(int note) {
if (note < 21 || note > 108) return -1; // Out of range
return note - 21; // Maps MIDI note to LED index (0-87)
}
// Handle MIDI Note On Event
void handleNoteOn(byte channel, byte note, byte velocity) {
int ledNumber = midiNoteToLED(note);
if (ledNumber == -1) return; // Invalid note
// Calculate which shift register and which bit
int srIndex = ledNumber / 8; // 0 to 10
int bitIndex = ledNumber % 8; // 0 to 7
// Set the corresponding bit to turn on the LED
shiftRegisterStates[srIndex] |= (1 << bitIndex);
// Update the shift registers
shiftOutMultiple(shiftRegisterStates, numShiftRegisters);
}
// Handle MIDI Note Off Event
void handleNoteOff(byte channel, byte note, byte velocity) {
int ledNumber = midiNoteToLED(note);
if (ledNumber == -1) return; // Invalid note
// Calculate which shift register and which bit
int srIndex = ledNumber / 8; // 0 to 10
int bitIndex = ledNumber % 8; // 0 to 7
// Clear the corresponding bit to turn off the LED
shiftRegisterStates[srIndex] &= ~(1 << bitIndex);
// Update the shift registers
shiftOutMultiple(shiftRegisterStates, numShiftRegisters);
}
// Function to shift out data to multiple 74HC595s
void shiftOutMultiple(byte data[], int numRegisters) {
digitalWrite(latchPin, LOW); // Begin data transmission
// Shift out all bytes from last to first shift register
for (int i = numRegisters - 1; i >= 0; i--) {
shiftOutData(data[i]);
}
digitalWrite(latchPin, HIGH); // Update outputs
}
// Function to shift out a single byte to 74HC595
void shiftOutData(byte data) {
// Shift out the data byte, MSB first
for (int i = 7; i >= 0; i--) {
// Write bit by bit
digitalWrite(clockPin, LOW);
digitalWrite(dataPin, (data & (1 << i)) ? HIGH : LOW);
digitalWrite(clockPin, HIGH);
}
}