Hi, I have an old 88 key piano keybed. Its just the buttons and 2 ribbon cables, and I'm trying to get a little arduino device going that can play MIDI notes depending on the key pressed. I finally achieved a prototype that has 2 keys working the way I want, but when I tried to convert the pattern into a function, it stopped working the way I wanted. For some reason, the 2 versions of the code are NOT identical, but I don't really understand why. Any insights would be appreciated.
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
int latchClock = 12; // Latch pin to 12 chip
int shiftClock = 11; // Clock pin to 11 chip
int serialData = 10; // Data pin to 14 chip
int clearPin = 13;
//These gates will eventually be an 88 element array...
bool gate77 = 0;
bool gate78 = 0;
//This array is used to scan the outputs of the keybed ribbon in conjunction with the shift register...
byte myByte[9] = {0b01111111,
0b10111111,
0b11011111,
0b11101111,
0b11110111,
0b11111011,
0b11111101,
0b11111110
};
byte byteHigh = 0b11111111;
//These will eventually hold multiple inputs and their current states, but right not only element 0 is used...
int rowState[9] = {1, 1, 1, 1, 1, 1, 1, 1};
int inputPin[9] = {14, 2, 2, 2, 2, 2, 2, 2};
void setup() {
Serial.begin(31250); //MIDI serial baud rate
MIDI.begin(MIDI_CHANNEL_OMNI);
pinMode(A0, INPUT);
pinMode(2, INPUT);
pinMode(latchClock, OUTPUT);
pinMode(serialData, OUTPUT);
pinMode(shiftClock, OUTPUT);
pinMode(clearPin, OUTPUT);
digitalWrite(clearPin, LOW);
digitalWrite(clearPin, HIGH);
}
void loop() {
for (int i = 0; i < 8; i++) {
shiftDouble(byteHigh, byteHigh); //make all outputs high
shiftDouble(myByte[i], byteHigh); //then a specific one low
for (int j = 0; j < 8; j++) { //read ALL inputs for EACH output i above
rowState[j] = digitalRead(inputPin[j]);
}
/* Below is the part of the code under question. This uncommented version
* works perfectly. Basically what makes a note trigger is the combination of
* an output pulled LOW (handled by the for loop i) and an input read LOW (handled
* by the rowState array). The gates make it to where the notes don't retrigger,
* that you can hold multiple notes at once and they release as expected.
*/
if (i == 0) {
if (rowState[0] == 0 && gate77 == 0) {
MIDI.sendNoteOn(77, 63, 1); //plays pitch of F5
gate77 = 1;
}
else if (rowState[0] == 1 && gate77 == 1) {
MIDI.sendNoteOff(77, 0, 1);
gate77 = 0;
}
}
//---------------
if (i == 1) {
if (rowState[0] == 0 && gate78 == 0) {
MIDI.sendNoteOn(78, 63, 1); //plays pitch of F5#
gate78 = 1;
}
else if (rowState[0] == 1 && gate78 == 1) {
MIDI.sendNoteOff(78, 0, 1);
gate78 = 0;
}
}
/* However this code, along with the function definition below, does not.
* I don't understand why they wouldn't be identical in the assembler.
* if (i==0){gateNote(rowState[0],gate77,77);}
* if (i==1){gateNote(rowState[0],gate78,78);}
*
*/
}
}
//This handles the 2 shift registers for an eventual 16 outputs
void shiftDouble(byte topChip, byte bottomChip) {
digitalWrite(latchClock, LOW); //so outputs dont change while shifting
shiftOut(serialData, shiftClock, LSBFIRST, bottomChip); //shift out the bits
shiftOut(serialData, shiftClock, LSBFIRST, topChip); //shift out the bits
digitalWrite(latchClock, HIGH); //change outputs with shifted in values
}
//Function that tried to convert the working code into a one-liner but failed...
//void gateNote(int myRowState, int myGate, int myNote){
// if (myRowState == 0 && myGate == 0) {
// MIDI.sendNoteOn(myNote, 63, 1);
// myGate = 1;
// }
// else if (myRowState == 1 && myGate == 1) {
// MIDI.sendNoteOff(myNote, 0, 1);
// myGate = 0;
// }
//}