Go Down

Topic: MIDI stops playing in a menu (Read 361 times) previous topic - next topic

deseipel

Hi guys,   

I have a mega 2560 with a rugged circuits midi shield  & an adafruit 1.8" tft lcd w/sd card slot and joystick.  It successfully plays MIDI files, sends a master MIDI clock and can cue up the next song (in time with the master clock).  It uses an interrupt timer for master clock.  The TFT LCD is wired for highspeed hardware SPI  (and is not stacked, but mounted in a case & jumpered to the MEGA pins for hardware SPI).  The joystick is on A3.  I'm using a modified MIDIFile library, sdfat, SPI, Adafruit's libraries, etc.

The issue is that while a MIDI file is playing, when I go into my menu to cue up the next song, once I get to the MIDI file list to select the next file, playback stops (but the interrupt driven master clock still happens) until I exit the menu.  At which point all of the MIDI events that should've become active  while it was stopped, get "dumped" out. 

My hunch is that there's some kind of conflict between the SD card being read during playback & listing of the files once I get to that menu.  Or and SPI conflict between SD card & LCD?  I've also noticed my draw_menu function causes some funny stuff as well, I'll post it at the bottom.

on a side note, at one time I had the code that plays the MIDI file as part of the interrupt and this wasn't an issue then. 


https://github.com/deseipel/Arduino/tree/master


Code: [Select]
//  this is the function that is called when selecting a MIDI file.

void select_midi(int key){

  tft.setCursor(0,60);
  if (listStart==0) listStart=1;

  drawFilelist(listStart);

  for( uint8_t b = CheckJoystick(); b != Left   ; b = CheckJoystick() ) {
    if (b == Down){
      // filePOS = (filePOS++)%maxmidicount;  //wraps back to 0 if  = maximidicount
      filePOS = (filePOS+maxmidicount+1)%maxmidicount;
      if (filePOS==0)filePOS=1;
      listStart = filePOS; 
      setNextSong();
      drawFilelist(listStart);
      // sprintf(msg, "listStart: %d\n filePOS: %d\n fileIndex: %d\n", listStart,  filePOS, fileIndex);
      //  Serial.print(msg);
      //sychronize the MIDI file with the program change,  all these Changecontrols are necessary for the KORG ES1 for some reason.
      sendChangeControl(99,05,10);
      sendChangeControl(98,107,10);
      sendChangeControl(06,0,10);
      sendChangeControl(99,05,10);
      sendChangeControl(98,108,10);
      sendChangeControl(06,0,10);

      P=filePOS-1;
      sendProgramChange(P,10);
      //  P=filePOS;
    }
    //////////////////////////
    else  if (b==Up){

      filePOS = (filePOS+maxmidicount-1)%maxmidicount;  //wraps back to maximidicount if <0
      if (filePOS==0)filePOS=maxmidicount-1;
      setNextSong();
      listStart = filePOS;     
      drawFilelist(listStart);

      // sprintf(msg, "listStart: %d\n filePOS: %d\n fileIndex: %d\n", listStart,  filePOS, fileIndex);
      // Serial.print(msg);

      //try to sync the Program changes with MIDI filesj
      sendChangeControl(99,05,10);
      sendChangeControl(98,107,10);
      sendChangeControl(06,0,10);
      sendChangeControl(99,05,10);
      sendChangeControl(98,108,10);
      sendChangeControl(06,0,10);
      P=filePOS-1;
      sendProgramChange(P,10);
      //  P=filePOS;
    }
   
   
   
   
    //
    if( b ) // control repeat speed
      delay(125);
  }
  cls();
  draw_menu();
}



Code: [Select]
//  displays the currently selected menu (or uarr for menu if not enabled)
void draw_menu( ){
  String TempoString = "Tempo: ";
  //String BarString = "Bar: ";
  String String3;  // a string so I can concat tempo char and tempo bpm
  String3 = TempoString + bpm;
track_cnt = SMF.getTrackCount();

  if( ! menu_enable ) {
    cls();

    tft.setTextColor(ST7735_WHITE);
    sprintf( textx, "%c for menu", uarr );
    tft.print( textx );

    tft.setCursor(1, 20);
    tft.setTextColor(ST7735_GREEN);
    tft.print("File: ");
    // tft.println(nameFiles[filePOS]);
    tft.print(current_song);

    tft.setCursor(1,30);
    tft.setTextColor(ST7735_YELLOW);   
    tft.print("Next: ");
    tft.print(next_song);

    tft.setCursor(1,50);
    tft.setTextColor(ST7735_RED);
    tft.setTextSize(2);
    tft.println(String3);
   
        tft.setCursor(10, 70);
    tft.print("Tracks: ");
    tft.println(int(track_cnt));

    //testing
    /*    tft.setTextSize(1);
     tft.setCursor(1,80);
     tft.setTextColor(ST7735_WHITE);
     tft.print("ListStart ");
     tft.println(listStart);
     tft.print("fileIndex ");
     tft.println(fileIndex);
     tft.print("filePOS ");
     tft.println(filePOS);
     */


    tft.setTextSize(1);
    //guiFooter();
    return;

  }
  // //uint16_t colorsave = tft.getTextColor();
  tft.setTextColor( menu_color );
  tft.setCursor(0, 2);
  //Serial.println(freeMemory());
  // //  magic number alert! set %-20.20s to same value as MAX_PROMPT_LEN

  sprintf( textx, "%-20.20s\n", curr_menu->label );
  tft.print(textx);
  int selection_num = 0;
  // // Loop through the actual number of selections in THIS menu
  for(selection_num=0; selection_num < curr_menu->num_selections; selection_num++)
  {
    // // Create a pointer for convenience
    SELECTION *selptr = &curr_menu->selection[selection_num];
    // // If this is the "active" menu selection (determine by referencing the global
    // // variable 'curr_selection' then draw it in inverse text.
    if (selection_num == curr_selection)
      tft.setTextColor(ST7735_BLUE);
    // // Print the prompt string
    //tft.setCursor(selection_num + MENU_INDENT_Y, MENU_INDENT_X);
    sprintf( textx, "  %-20.20s\n", selptr->label );
    tft.print(textx);
    // // Turn inverse back off if need be
    if (selection_num == curr_selection)
      tft.setTextColor(ST7735_RED);
  }

  tft.setTextColor( ST7735_WHITE );

}


deseipel

update:  it actually stops at any menu where the menu is 3 levels deep. 

deseipel

Sorry to answer my own question, but i think the issue is simply the way my loop is setup

Code: [Select]

void loop() {
  CheckMIDI();
  if( doMenu() ){

    // //  something happened with joystick, an update() action could be called here
  }
 
  if((S==1) && (midiClockRunning ==1) ){
  Playit();
  }
}



I'll have to check my code, but if doMenu is true, then its no wonder Playing stops.  ...

deseipel

ok, so it appears that the issue is around a FOR loop in the menus I have to check the joystick.  does anyone know why this stops the SD card from being read?

for( uint8_t b = CheckJoystick(); b != Left; b = CheckJoystick() ) {
//code here
}

I also verified that when I Play the MIDI files from within an interrupt, the issue doesn't occur.  BUT if the MIDI file is large it appears to crash... 

Go Up