Lighted Stops with a Twist


/*

Arduino Decoder with dimly lit enabled stops: by John Coenraads

=====================================

This sketch accepts MIDI commands on channel 1, decodes them and turns the appropriate IO pins on and off.

Bottom C (note 36) outputs on pin 2. Total outputs = 68 (pins 2 to 69).

If boards are daisy chained, each one can be "tuned" to a specific channel.

**This sketch handles Running Status,..**

If a stop is turned ON, it becomes enabled meaning it will continue to glow dimly even after being turned off.

For testing purposes only, when top C (note 96) is pressed, the array that keeps track of enabled stops is cleared.

Equipment: Arduino Mega + MIDI shield

created 2021 APR 08, modified 2021 AUG 25

*/

// Declarations==========================================

int i, j, k; //Counters (old Fortran habit)

byte noteStatusRx, noteNumberRx, noteVelocityRx, tempVar; //Receive variables

const byte status90 = 0x90, status80 = 0x80; //Define status bytes for channel 1


const int n = 100; // Number of scan cycles for which enabled LED is OFF. Larger number = dimmer

const int m = 20; // Number of scan cycles for which enabled LED is ON. Larger number = brighter

// If n = m, LED duty cycle = 50%. If n and m are too large, the LED will flicker


byte notesON [110]; //if note is on, value is 1, otherwise 0

byte notesEnabled [110]; //if note is enabled, value is 1, otherwise 0


//Initialize ============================================

void setup()

{

Serial.begin(31250); // Set MIDI baud rate:

while (Serial.available() > 0) {Serial.read();} //Clear serial input buffer

Serial1.end(); Serial2.end(); Serial3.end(); //Relieve ports 1,2,3 of serial IO duty


//Initialize 68 pins for output.

for (i = 2; i < 70; i++)

{

pinMode (i, OUTPUT);

digitalWrite (i, LOW);

}

//Initialize notesON array and notesEnabled array to 0

for (i = 0; i < 111; i++)

{

notesON [i] = 0;

notesEnabled [i] = 0;

}

}


//Main Loop =============================================

void loop()

{

for (i = 1; i < n; i++)

{

processSerial ();

}

enabledON();

for (j = 1; j < m; j++)

{

processSerial ();

}

enabledOFF();

}

void processSerial ()

{

if (Serial.available())

{

tempVar = Serial.read ();

if ((tempVar == status90) || (tempVar == status80))

{noteStatusRx = tempVar;

while (!Serial.available()) {} //wait for serial data, port 0

noteNumberRx = Serial.read ();

while (!Serial.available()) {} //wait for serial data, port 0

noteVelocityRx = Serial.read ();

if ((noteVelocityRx == 0) ||(noteStatusRx == status80))

{

digitalWrite (noteNumberRx - 34, LOW);

notesON [noteNumberRx] = 0;

}

else

{

digitalWrite (noteNumberRx - 34, HIGH);

notesEnabled [noteNumberRx] = 1;

notesON [noteNumberRx] = 1;

}

}

if (tempVar <= 0x7F) //is data byte (Running Status)

{noteNumberRx = tempVar;

while (!Serial.available()) {} //wait for serial data, port 0

noteVelocityRx = Serial.read ();


if ((noteVelocityRx == 0) ||(noteStatusRx == status80))

{

digitalWrite (noteNumberRx - 34, LOW);

notesON [noteNumberRx] = 0;

}

else

{

digitalWrite (noteNumberRx - 34, HIGH);

notesEnabled [noteNumberRx] = 1;

notesON [noteNumberRx] = 1;

}

}

if (noteNumberRx == 96)

{

for (i = 0; i < 111; i++)

{

notesEnabled [i] = 0;

}

}

}

}


void enabledON ()

{

for (i = 36; i < 96; i++)

{

if (notesEnabled [i] != 0)

{ digitalWrite (i - 34, HIGH);}

}

}

void enabledOFF ()

{

for (i = 36; i < 96; i++)

{

if (notesON [i] == 0)

{ digitalWrite (i - 34, LOW);}

}

}