2

I altered code for the Simple Simon says to work with a Midi controller instead of push buttons. i am having trouble with the input of the song sequence with the Midi Controller. during the time where the code is waiting for input from the Midi controller waitForButton(int delay) the notes being inputted should sound but it dose not . i need help in figuring this out. any advice would be appreciated. Here's my code :https://pastebin.com/dV73eF9U

const int PLAY = 1;
const int TRYAGIN = 2;
long currentMillis = 0;
long previousMillis = 0;
int state;
void songlearn(int tune);
void showsequence();
void readsequnce();
void incorrect();
int tune;

void loop() {
  if (state == PLAY) {
    showsequence();
    readsequnce();
  }
  else if (state == TRYAGIN) {
    incorrect();
    state = PLAY;
  }
}

void MyHandleNoteOn(byte channel, byte pitch, byte velocity) {
  data1 = MIDI.getData1();
  if (data1 == 48) { //C3
    Status[0][0] = 1;
    noteOn(0, data1, 100);
    input[0] = data1;
  }
  if (data1 == 49) { //C3#
    Status[0][1] = 1;
    noteOn(0, data1, 100);
    input[1] = data1;
  }
  if (data1 == 50) { //D3
    Status[0][2] = 1;
    noteOn(0, data1, 100);
    input[2] = data1;
  }
  if (data1 == 51) { //D3#
    Status[0][3] = 1;
    noteOn(0, data1, 100);
    input[3] = data1;
  }
  if (data1 == 52) { //E3
    Status[0][4] = 1;
    noteOn(0, data1, 100);
    input[4] = data1;
  }
  if (data1 == 53) { //F3
    Status[1][0] = 1;
    noteOn(0, data1, 100);
    input[5] = data1;
  }
  if (data1 == 54) { //F3#
    Status[1][1] = 1;
    noteOn(0, data1, 100);
    input[6] = data1;
  }
  if (data1 == 55) { //G3
    Status[1][2] = 1;
    noteOn(0, data1, 100);
    input[7] = data1;
  }
  if (data1 == 56) { //G3#
    Status[1][3] = 1;
    noteOn(0, data1, 100);
    input[8] = data1;
  }
  if (data1 == 57) { //A3
    Status[1][4] = 1;
    noteOn(0, data1, 100);
    input[9] = data1;
  }
  if (data1 == 58) { //A3#
    Status[2][0] = 1;
    noteOn(0, data1, 100);
    input[10] = data1;
  }
  if (data1 == 59) { //B3
    Status[2][1] = 1;
    noteOn(0, data1, 100);
    input[11] = data1;
  }
  if (data1 == 60) { //C4
    Status[2][2] = 1;
    noteOn(0, data1, 100);
    input[12] = data1;
  }
  if (data1 == 61) { //C4#
    Status[2][3] = 1;
    noteOn(0, data1, 100);
    input[13] = data1;
  }
  if (data1 == 62) { //D4
    Status[2][4] = 1;
    noteOn(0, data1, 100);
    input[14] = data1;
  }
  if (data1 == 63) { //D4#
    Status[3][0] = 1;
    noteOn(0, data1, 100);
    input[15] = data1;
  }
  if (data1 == 64) { //E4
    Status[3][1] = 1;
    noteOn(0, data1, 100);
    input[16] = data1;
  }
  if (data1 == 65) { //F4
    Status[3][2] = 1;
    noteOn(0, data1, 100);
    input[17] = data1;
  }
  if (data1 == 66) { //F4#
    Status[3][3] = 1;
    noteOn(0, data1, 100);
    input[18] = data1;
  }
  if (data1 == 67) { //G4
    Status[3][4] = 1;
    noteOn(0, data1, 100);
    input[19] = data1;
  }
  if (data1 == 68) { //G4#
    Status[4][0] = 1;
    noteOn(0, data1, 100);
    input[20] = data1;
  }
  if (data1 == 69) { //A4
    Status[4][1] = 1;
    noteOn(0, data1, 100);
    input[21] = data1;
  }
  if (data1 == 70) { //A4#
    Status[4][2] = 1;
    noteOn(0, data1, 100);
    input[22] = data1;
  }
  if (data1 == 71) { //B4
    Status[4][3] = 1;
    noteOn(0, data1, 100);
    input[23] = data1;
  }
  if (data1 == 72) { //C5
    Status[4][4] = 1;
    noteOn(0, data1, 100);
    input[24] = data1;
  }
}

void MyHandleNoteOff(byte channel, byte pitch, byte velocity) {
  data1 = MIDI.getData1();
  if (data1 == 48) { //C3
    Status[0][0] = 0;
    noteOff(0, data1, 100);
    input[0] = 0;
  }
  if (data1 == 49) { //C3#
    Status[0][1] = 0;
    noteOff(0, data1, 100);
    input[1] = 0;
  }
  if (data1 == 50) { //D3
    Status[0][2] = 0;
    noteOff(0, data1, 100);
    input[2] = 0;
  }
  if (data1 == 51) { //D3#
    Status[0][3] = 0;
    noteOff(0, data1, 100);
    input[3] = 0;
  }
  if (data1 == 52) { //E3
    Status[0][4] = 0;
    noteOff(0, data1, 100);
    input[4] = 0;
  }
  if (data1 == 53) { //F3
    Status[1][0] = 0;
    noteOff(0, data1, 100);
    input[5] = 0;
  }
  if (data1 == 54) { //F3#
    Status[1][1] = 0;
    noteOff(0, data1, 100);
    input[6] = 0;
  }
  if (data1 == 55) { //G3
    Status[1][2] = 0;
    noteOff(0, data1, 100);
    input[7] = 0;
  }
  if (data1 == 56) { //G3#
    Status[1][3] = 0;
    noteOff(0, data1, 100);
    input[8] = 0;
  }
  if (data1 == 57) { //A3
    Status[1][4] = 0;
    noteOff(0, data1, 100);
    input[9] = 0;
  }
  if (data1 == 58) { //A3#
    Status[2][0] = 0;
    noteOff(0, data1, 100);
    input[10] = 0;
  }
  if (data1 == 59) { //B3
    Status[2][1] = 0;
    noteOff(0, data1, 100);
    input[11] = 0;
  }
  if (data1 == 60) { //C4
    Status[2][2] = 0;
    noteOff(0, data1, 100);
    input[12] = 0;
  }
  if (data1 == 61) { //C4#
    Status[2][3] = 0;
    noteOff(0, data1, 100);
    input[13] = 0;
  }
  if (data1 == 62) { //D4
    Status[2][4] = 0;
    noteOff(0, data1, 100);
    input[14] = 0;
  }
  if (data1 == 63) { //D4#
    Status[3][0] = 0;
    noteOff(0, data1, 100);
    input[15] = 0;
  }
  if (data1 == 64) { //E4
    Status[3][1] = 0;
    noteOff(0, data1, 100);
    input[16] = 0;
  }
  if (data1 == 65) { //F4
    Status[3][2] = 0;
    noteOff(0, data1, 100);
    input[17] = 0;
  }
  if (data1 == 66) { //F4#
    Status[3][3] = 0;
    noteOff(0, data1, 100);
    input[18] = 0;
  }
  if (data1 == 67) { //G4
    Status[3][4] = 0;
    noteOff(0, data1, 100);
    input[19] = 0;
  }
  if (data1 == 68) { //G4#
    Status[4][0] = 0;
    noteOff(0, data1, 100);
    input[20] = 0;
  }
  if (data1 == 69) { //A4
    Status[4][1] = 0;
    noteOff(0, data1, 100);
    input[21] = 0;
  }
  if (data1 == 70) { //A4#
    Status[4][2] = 0;
    noteOff(0, data1, 100);
    input[22] = 0;
  }
  if (data1 == 71) { //B4
    Status[4][3] = 0;
    noteOff(0, data1, 100);
    input[23] = 0;
  }
  if (data1 == 72) { //C5
    Status[4][4] = 0;
    noteOff(0, data1, 100);
    input[24] = 0;
  }
}

//Send a MIDI note-on message.  Like Pressing a piano key
void noteOn(byte channel, byte note, byte attack_velocity) {
  talkMIDI( (0x90 | channel), note, attack_velocity);
}

//Send a MIDI note-off message.  Like releasing a piano key
void noteOff(byte channel, byte note, byte release_velocity) {
  talkMIDI( (0x80 | channel), note, release_velocity);
}

//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
  mySerial.write(cmd);
  mySerial.write(data1);
  //Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes
  //(sort of: http://253.ccarh.org/handout/midiprotocol/)
  if ( (cmd & 0xF0) <= 0xB0)
    mySerial.write(data2);
}

void playNote(int midi, int row, int col, int len, bool short_led = false)
{
  int len1, len2;
  if (short_led) {
    len1 = len * 3 / 4;
    len2 = len * 1 / 4;
  } else {
    len1 = len;
    len2 = 0;
  }
  noteOn(0x90, midi, 100);
  digitalWrite(LedR[row], HIGH);
  digitalWrite(LedC[col], LOW);
  delay(len1);
  digitalWrite(LedR[row], LOW);
  digitalWrite(LedC[col], HIGH);
  delay(len2);
  noteOff(0x90, midi, 0);
}

void songlearn (int tune) {
  if (tune == 1) {

    lcd.clear();
    lcd.setCursor(4, 0);
    lcd.print("Learning Song :");// Print a message to the LCD.
    lcd.setCursor(1, 1);
    lcd.print(menuP1);

    //Plays Mary Had a Little Lamb on a loop at 145 BPM

    //Bar 1
    note[0] = 0x40;
    note[1] = 0x3e;
    note[2] = 0x3c;
    note[3] = 0x3e;
    //Bar 2
    note[4] = 0x40;
    note[5] = 0x40;
    note[6] = 0x40;
    //Bar 3
    note[7] = 0x3e;
    note[8] = 0x3e;
    note[9] = 0x3e;
    //Bar 4
    note[10] = 0x40;
    note[11] = 0x43;
    note[12] = 0x43;
    //Bar 5
    note[13] = 0x40;
    note[14] = 0x3e;
    note[15] = 0x3c;
    note[16] = 0x3e;
    //Bar 6
    note[17] = 0x40;
    note[18] = 0x40;
    note[19] = 0x40;
    note[20] = 0x40;
    //Bar 7
    note[21] = 0x3e;
    note[22] = 0x3e;
    note[23] = 0x40;
    note[24] = 0x3e;
    //Bar 8
    note[25] = 0x3c;
    //End song
  }
}

void (*SongSeq[x])() =
{ //Bar 1
  [] { playNote(0x40, 3, 1, 414); } ,//Quarter note: E
  [] { playNote(0x3e, 2, 4, 414); } ,//Quarter note: D
  [] { playNote(0x3c, 2, 2, 414); } ,//Quarter note: C
  [] { playNote(0x3e, 2, 4, 414); } ,//Quarter note: D
  //Bar 2
  [] {playNote(0x40, 3, 1, 414, 1);} , //Quarter note: E
  [] {playNote(0x40, 3, 1, 414, 1); }, //Quarter note: E
  [] {playNote(0x40, 3, 1, 828, 1); }, //Half note: E
  //Bar 3
  []{playNote(0x3e, 2, 4, 414, 1);}, //Quarter note: D
  []{playNote(0x3e, 2, 4, 414, 1);}, //Quarter note: D
  []{playNote(0x3e, 2, 4, 828, 1);}, //Half note: D
  //Bar 4
  []{playNote(0x40, 3, 1, 414);}, //Quarter note: E
  []{playNote(0x43, 3, 4, 414, 1);}, //Quarter note: G
  []{playNote(0x43, 3, 4, 828, 1);}, //Half note: G
  //Bar 5
  []{playNote(0x40, 3, 1, 414);}, //Quarter note: E
  []{playNote(0x3e, 2, 4, 414);}, //Quarter note: D
  []{playNote(0x3c, 2, 2, 414);}, //Quarter note: C
  []{playNote(0x3e, 2, 4, 414);}, //Quarter note: D
  //Bar 6
  []{playNote(0x40, 3, 1, 414, 1);}, //Quarter note: E
  []{playNote(0x40, 3, 1, 414, 1);}, //Quarter note: E
  []{playNote(0x40, 3, 1, 414, 1);}, //Quarter note: E
  []{playNote(0x40, 3, 1, 414, 1);}, //Quarter note: E
  //Bar 7
  []{playNote(0x3e, 2, 4, 414, 1);}, //Quarter note: D
  []{playNote(0x3e, 2, 4, 414, 1);}, //Quarter note: D
  []{playNote(0x40, 3, 1, 414);}, //Quarter note: E
  []{playNote(0x3e, 2, 4, 414);}, //Quarter note: D
  //Bar 8
  []{playNote(0x3c, 2, 2, 1656);}, //Whole note: C
  //End song

};

void showsequence() {
  //Add a new index to the end of the songseq
  SongSeq[largestindex];
  largestindex++;
  //loop through the songseq
  for (int index = 0; index < largestindex; index++) {
    SongSeq[index]();
  }
}

void readsequnce() {
  bool mademistake = false;
  int key;
  for (int index = 0; index < largestindex & mademistake == false; index++) {
    key = waitForButton(5000);
    if (key == -1 | key != note[index]) {
      mademistake = true;
      SongSeq[index]();
      SongSeq[index]();
      state = 2;
    }
  }
}

int waitForButton(int delay)
{
  int keyPressed = -1;
  int check;
  boolean keyBackUp = false;

  currentMillis = millis();      // The number of ms since the program started running
  previousMillis = currentMillis;   // Records the point when we start spinning the loop.

  // Keep spinning the loop until "delay" seconds have passed.
  while (currentMillis - previousMillis < delay & keyBackUp == false)
  {
    // Read the button and record when it has been pushed down.
    for (int i = 0; i < 25 & keyBackUp == false; i++)
    {
      if (input[i] != 0)
      {
        keyPressed = input[i];

        // Show the LED pushed.
        noteOn(0, keyPressed, 100);
        //  digitalWrite(leds[pin], HIGH);

        // It is possible the button is still being pushed.
        // This loop spins until the button is let up.
        while (currentMillis - previousMillis < delay & keyBackUp == false)
        {
          check = input[i];
          if (check == 0)
          {
            keyBackUp = true;
          }
          currentMillis = millis();
        }

        // Turn the LED pushed off.
        noteOff(0, keyPressed, 0);
        // digitalWrite(leds[pin], LOW);

        // See if they took to long.
        if (currentMillis - previousMillis > delay)
        {
          keyPressed = -1; // They took to long to let the button up so they lose.
        }
      }
    }

    currentMillis = millis();

  }

  return keyPressed;
}
  • Include the properly formatted code into the question. And your incomplete code is missing two }. – gre_gor Apr 21 '17 at 12:55
  • the proper code has been added – Hjhk90 Apr 21 '17 at 15:01
  • Please run your code through the formatter in the Arduino IDE. It's very difficult to read right now due to poor formatting, that discourages people from reading enough of it to answer your question. (It certainly discouraged me! I gave up trying to read it.) It's worth spending time on making your posts easy to read if you want people to take the time to answer. – Curt J. Sampson Apr 22 '17 at 14:43
  • @CurtJ.Sampson thanks for letting me know i set the auto format in the arduino IDE. i hope its easier to read now. – Hjhk90 Apr 22 '17 at 19:10
  • It's considerably better, but there are still some things you should do manually, such as adding blank lines between functions. (I've submitted an edit for that.) Now that I can read it, I can see that the code is incomplete: for example you have no init() function, no definitions of state or Status, PLAY, TRYAGIN, etc. You really need to cut down the program to much smaller size (e.g., by removing most of the keys) and post the complete smaller version. Also, you say you altered some code; where is the original code? – Curt J. Sampson Apr 23 '17 at 2:16
1

I notice that nothing in the code you posted calls the MyHandleNoteOn() function, which is the only thing that reads MIDI data in the code you posted.

The waitForButton() function where you say you're having the problem never does any input or output, it simply checks to see if something else has changed the input array. MyHandleNoteOn() above does change it.

This leads me to believe that code you haven't posted sets up an interrupt handler that calls MyHandleNoteOn() (and probably MyHandleNodeOff()). If that doesn't mean anything to you, the main problem here is that the program is a bit beyond your abilities and you need to start learning on something simpler. If it does mean something to you, the problem here is that the program is rather badly written and you need to write something simpler to practice using interrupts and shared memory communication.

Have you written simpler programs before that read MIDI events, do a bit of processing, and play back things based on that? Building a Simon Says game on top of that would be a good learning project.

  • yes i have written simpler programs for midi. the MyHandleNoteOn() & MyHandleNodeOff() both are functions from the midi library and are called when the keys on the midi controller are pressed. – Hjhk90 Apr 23 '17 at 2:48
  • Did your MIDI code use in-memory communication between interrupt handlers and your main loop? If not, you want to write some simpler programs that do that first, if you're going to use that technique. Alternatively, you could write a Simon Says game on top of non-interrupt-driven code that uses wait-loops (which would look quite different from the above). Either way, if you have further questions, pare your code down to the bare minimum that demonstrates the problem so that others can load it up and run it. – Curt J. Sampson Apr 23 '17 at 2:56
  • maybe my approach is off how would you go about it ? – Hjhk90 Apr 23 '17 at 3:09
  • Start as small and as basic as I could, and then expand from there. – Curt J. Sampson Apr 23 '17 at 3:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.