Beatstep MIDI communication with teensy 4.0

Status
Not open for further replies.

Granulka

Member
Hi
Im working on sampler and i come across bug that when to much pads(to many midi messages) are sent from beatstep teensy freezes and crashes.

This is the code that im using witch is still WIP teense is clocked at 600Mhz.

Could this be to slow response of optocoupler or is this software problem? I'm using schematic of midi connection from PJRC midi library page.

Code:
//LIBS
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <MIDI.h>
#include <LiquidCrystal_I2C.h>
#include <Encoder.h>

//CLASSES
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27, 16 column and 2 rows
Encoder myEnc(4, 5);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);


// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;    
AudioPlaySdWav           playSdWav4;    
AudioPlaySdWav           playSdWav3;     
AudioPlaySdWav           playSdWav2;     
AudioPlaySdWav           playSdWav9;     
AudioPlaySdWav           playSdWav8;    
AudioPlaySdWav           playSdWav15;
AudioPlaySdWav           playSdWav6;     
AudioPlaySdWav           playSdWav5;     
AudioPlaySdWav           playSdWav7;    
AudioPlaySdWav           playSdWav14;   
AudioPlaySdWav           playSdWav16;    
AudioPlaySdWav           playSdWav11;    
AudioPlaySdWav           playSdWav12;    
AudioPlaySdWav           playSdWav13;    
AudioPlaySdWav           playSdWav10;    

AudioMixer4              mixer7; 
AudioMixer4              mixer3; 
AudioMixer4              mixer4; 
AudioMixer4              mixer6; 
AudioMixer4              mixer8;   
AudioMixer4              mixer2; 
AudioMixer4              mixer9; 
AudioMixer4              mixer1;         
AudioMixer4              mixer5; 
AudioMixer4              mixer10; 

AudioOutputI2S           i2s1;           

AudioConnection          patchCord1(playSdWav1, 0, mixer4, 0);
AudioConnection          patchCord2(playSdWav1, 1, mixer6, 0);
AudioConnection          patchCord3(playSdWav4, 0, mixer4, 3);
AudioConnection          patchCord4(playSdWav4, 1, mixer6, 3);
AudioConnection          patchCord5(playSdWav3, 0, mixer4, 2);
AudioConnection          patchCord6(playSdWav3, 1, mixer6, 2);
AudioConnection          patchCord7(playSdWav2, 0, mixer4, 1);
AudioConnection          patchCord8(playSdWav2, 1, mixer6, 1);
AudioConnection          patchCord9(playSdWav9, 0, mixer2, 0);
AudioConnection          patchCord10(playSdWav9, 1, mixer8, 0);
AudioConnection          patchCord11(playSdWav8, 0, mixer3, 3);
AudioConnection          patchCord12(playSdWav8, 1, mixer7, 3);
AudioConnection          patchCord13(playSdWav15, 0, mixer1, 2);
AudioConnection          patchCord14(playSdWav15, 1, mixer9, 2);
AudioConnection          patchCord15(playSdWav6, 0, mixer3, 1);
AudioConnection          patchCord16(playSdWav6, 1, mixer7, 1);
AudioConnection          patchCord17(playSdWav5, 0, mixer3, 0);
AudioConnection          patchCord18(playSdWav5, 1, mixer7, 0);
AudioConnection          patchCord19(playSdWav7, 0, mixer3, 2);
AudioConnection          patchCord20(playSdWav7, 1, mixer7, 2);
AudioConnection          patchCord21(playSdWav14, 0, mixer1, 1);
AudioConnection          patchCord22(playSdWav14, 1, mixer9, 1);
AudioConnection          patchCord23(playSdWav16, 0, mixer1, 3);
AudioConnection          patchCord24(playSdWav16, 1, mixer9, 3);
AudioConnection          patchCord25(playSdWav11, 0, mixer2, 2);
AudioConnection          patchCord26(playSdWav11, 1, mixer8, 2);
AudioConnection          patchCord27(playSdWav12, 0, mixer2, 3);
AudioConnection          patchCord28(playSdWav12, 1, mixer8, 3);
AudioConnection          patchCord29(playSdWav13, 0, mixer1, 0);
AudioConnection          patchCord30(playSdWav13, 1, mixer9, 0);
AudioConnection          patchCord31(playSdWav10, 0, mixer2, 1);
AudioConnection          patchCord32(playSdWav10, 1, mixer8, 1);
AudioConnection          patchCord33(mixer7, 0, mixer10, 1);
AudioConnection          patchCord34(mixer3, 0, mixer5, 1);
AudioConnection          patchCord35(mixer4, 0, mixer5, 0);
AudioConnection          patchCord36(mixer6, 0, mixer10, 0);
AudioConnection          patchCord37(mixer8, 0, mixer10, 2);
AudioConnection          patchCord38(mixer2, 0, mixer5, 2);
AudioConnection          patchCord39(mixer9, 0, mixer10, 3);
AudioConnection          patchCord40(mixer1, 0, mixer5, 3);
AudioConnection          patchCord41(mixer5, 0, i2s1, 0);
AudioConnection          patchCord42(mixer10, 0, i2s1, 1);

AudioControlSGTL5000     sgtl5000_1;
// GUItool: end automatically generated code

//PINS
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   13
#define e1r 14
#define e1g 15
#define e1sw 3

//VARS
char filechar[13] = "BANK02/00.WAV";
char *MENU [] = {"Channel","Mode","Bank","Save & Exit"};
int globalsettings[]={10,1,2,0};//channel,mode,bank,smth
float slotvol[]={0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,};
byte slot[16]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
long oldPosition = 999;
long newPosition = 666;
byte i=0;
bool e1press=false;

//**************************************************************************************
void setup() 
{
  pinMode(e1r,OUTPUT);
  pinMode(e1g,OUTPUT);
  pinMode(e1sw,INPUT_PULLUP);

  
  lcd.init(); // initialize the lcd
  lcd.backlight();

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Press and hold");
  lcd.setCursor(0, 1);
  lcd.print("for settings");
  //delay(500);
  
  
    
  Serial.begin(57600);
  MIDI.begin(MIDI_CHANNEL_OMNI);
 
  AudioMemory(32);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);

  if (!(SD.begin(SDCARD_CS_PIN))) 
  {
    while (1) 
    {
      lcd.clear();
      lcd.print("SD FAIL");
      delay(500);
      lcd.clear();
      delay(500);     
    }
  }
  if (digitalRead(e1sw)==LOW)  
   { 
   settings();
   }
  
}
//**************************************************************************************
void settings()
{
  while(true)
  {
  newPosition = myEnc.read()/2;
  if (newPosition != oldPosition) 
  {
    oldPosition = newPosition;
    i = oldPosition;
    
    if(i>=5)
    {
      i=0;
      myEnc.write(0);
    }
    if(i==0||i==1)
    {
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print(MENU[0]);
      lcd.setCursor(14, 0);
      lcd.print(globalsettings[0]);
    
      lcd.setCursor(1, 1);
      lcd.print(MENU[1]);        
    
      switch(globalsettings[1])
      {
        case 0:
          lcd.setCursor(13, 1);
          lcd.print("USB");
        break;
      
        case 1:
          lcd.setCursor(12, 0);
          lcd.print("MIDI");
        break;
      }
    }
    
    else if(i==2||i==3)
    {
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print(MENU[2]);

      lcd.setCursor(1, 1);
      lcd.print(MENU[3]);
    }
        
    lcd.setCursor(0, i%2 );
    lcd.write(0x7E);//arrow char
    }
    if (digitalRead(e1sw)==LOW)
    {
          
    }
}
}
//**************************************************************************************
void loop()
{
  if(MIDI.read())
 {
  byte type = MIDI.getType();//type
  if(type==0x90)
 {

   switch(globalsettings[1])
   {
   case 0:  
     usbmidi();
   break;

   case 1:

      dinmidi(); 
   break;
   }
 }
 }
 else
 {
  newPosition = myEnc.read()/2;
  
  if (newPosition != oldPosition) 
  {
    oldPosition = newPosition;
    i = oldPosition;
    if(i>=16)
    {
      i=0;
      myEnc.write(0);
    }
    if(i<0)
    {
      i=15;
      myEnc.write(i*2);
    }
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Slot ");
    lcd.write(0x7E);
    lcd.print(i);
    lcd.print(" ");
    lcd.print("Spl ");
    lcd.print(slot[i]);    
   }
   
   if (digitalRead(e1sw)==LOW&&e1press==false)  
   { 
      e1press=true;
      digitalWrite(e1r , HIGH);
      lcd.setCursor(0, 5);
      lcd.print(" ");
      slotMenuSelect(i);
      lcd.setCursor(1, 0);
      lcd.print("                ");
      myEnc.write(i*2);   
      delay(200);   
   }
   else
   {   
       e1press=false;
       //digitalWrite(e1r , LOW);
       //digitalWrite(e1g , LOW);
   }

 }
}
//**************************************************************************************
void slotMenuSelect(byte slot_number)
{
  byte n;
  lcd.setCursor(0, 1);
  lcd.write(0x7E);
  lcd.print("Sample  ");  
  myEnc.write(0);
  
  while(digitalRead(e1sw)==LOW&&e1press==true)
  {
    
    delay(200);
    //wait for depress
  }  
  e1press=false;
  while(true)
  { 

    
    newPosition = myEnc.read()/2;
    if (newPosition != oldPosition) 
    {
      oldPosition = newPosition;
      n = oldPosition;
      if(n>=6)
      {
        n=0;
        myEnc.write(0);
      }
      if(n<0)
      {
        n=5;
        myEnc.write(5*2);
      }
      
      switch(n)
      {
      case 0:
        lcd.setCursor(0, 1);
        lcd.write(0x7E);
        lcd.print("Sample  ");
      break;
      
      case 1:
        lcd.setCursor(0, 1);
        lcd.write(0x7E);
        lcd.print("Vol     ");
      break; 
      
      case 2:
        lcd.setCursor(0, 1);
        lcd.write(0x7E);
        lcd.print("Start  ");
      break; 
      
      case 3:
        lcd.setCursor(0, 1);
        lcd.write(0x7E);
        lcd.print("End     ");
      break;
      
      case 4:
        lcd.setCursor(0, 1);
        lcd.write(0x7E);
        lcd.print("Rev     ");
      break;

      case 5:
        lcd.setCursor(0, 1);
        lcd.write(0x7E);//arrow
        lcd.print("Back    ");
      break;
      }
    }
    
    if (digitalRead(e1sw)==LOW&&e1press==false)  
    { 
      e1press=true;
           
      switch(n)
      {
      case 0:
        slotSampleSelect(slot_number);
        
        lcd.setCursor(0, 1);
        lcd.write(0x7E);
        lcd.print("Sample         ");
        
        delay(200);
      break;
      
      case 1:
        //slotSampleSelect();
        lcd.setCursor(0, 1);
        lcd.write(0x7E);
        lcd.print("WIP_Back      ");        
      break; 
      
      case 2:
        //slotSampleSelect();
        lcd.setCursor(0, 1);
        lcd.write(0x7E);
        lcd.print("WIP_Back      ");
        break; 
      
      case 3:
        //slotSampleSelect();
        lcd.setCursor(0, 1);
        lcd.write(0x7E);
        lcd.print("WIP_Back      ");
      break;
      
      case 4:
        //slotSampleSelect();
        lcd.setCursor(0, 1);
        lcd.write(0x7E);
        lcd.print("WIP_Back      ");
        break;

      case 5:        
        return 0;
      break;
      }
    }
    if (digitalRead(e1sw)==HIGH)
    {
      e1press=false;
    }
  }
}
//**************************************************************************************
void slotSampleSelect(const byte slot_number)
{
  byte n=0;
  myEnc.write(0);
  lcd.setCursor(0, 1);
  lcd.print("Sample ");
  lcd.write(0x7E);
  lcd.setCursor(8, 1);
  lcd.print(slot[slot_number]);

  while(digitalRead(e1sw)==LOW&&e1press==true)
  {
    
    //wait for depress
    delay(200);
  }
    e1press=false;
  while (true)
  {
   if(myEnc.read()<0)
   {
    myEnc.write(99*2);
   }
   
  newPosition = myEnc.read()/2;  
  
  if (newPosition != oldPosition) 
  {
    
    oldPosition = newPosition;
    n = oldPosition;
 Serial.print(n);
    if(n>99)
    {
      n=0;
      myEnc.write(0);
    }
        
    lcd.setCursor(8, 1);
    lcd.print(n);
    lcd.print(" ");

    playPlayer(n,slot_number);
    
    
  }
  if(digitalRead(e1sw)==LOW&&e1press==false)
    {
      slot[slot_number]=n;      
      lcd.setCursor(12,0);
      lcd.print(n);
      lcd.print(" ");
      return 0;
    }
  }  
}
//**************************************************************************************
void usbmidi()
{  
  /*
    Serial.println(usbMIDI.getChannel());    
    Serial.println(usbMIDI.getType(),HEX);       
    Serial.print(usbMIDI.getData1(),HEX);
    Serial.print(" HEX| ");
    Serial.print(usbMIDI.getData1(),DEC);
    Serial.print(" DEC| ");
    Serial.println();    
    Serial.print(usbMIDI.getData2(),HEX);
    Serial.print(" HEX| ");
    Serial.print(usbMIDI.getData2(),DEC);
    Serial.print(" DEC| ");
    Serial.println();
    */
    
    byte type = usbMIDI.getType();
    byte data1 = usbMIDI.getData1();
    byte data2 = usbMIDI.getData2();
    
        

    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x24)
    {
      playPlayer(slot[0],0);      
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x25)
    {
       playPlayer(slot[1],1);    
     }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x26)
    {
      //playFile(slot[2],2);
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x27)
    {
      //playFile(slot[3],3);
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x28)
    {
      //playFile(slot[4],4);
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x29)
    {
      //playFile(slot[5],5);
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x2A)
    {
      //playFile(slot[6],6);
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x2B)
    {
      //playFile(slot[7],7);
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x2C)
    {
      //playFile(slot[8],8);
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x2D)
    {
      //playFile(slot[9],9);
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x2E)
    {
      //playFile(slot[10],10);
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x2F)
    {
      //playFile(slot[11],11);
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x30)
    {
      //playFile(slot[12],12);
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x31)
    {
      //playFile(slot[13],13);
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x32)
    {
      //playFile(slot[14],14);
    }
    if(usbMIDI.getType()==0x90&&usbMIDI.getData1()==0x33)
    {
     // playFile(slot[15],15);
    }
}        

//**************************************************************************************
void playPlayer(const byte sample_num, const byte player_num)
{
  byte x = (sample_num/10)%10;
  byte y = (sample_num)%10;
  filechar[7]='0'+x;
  filechar[8]='0'+y;
  //Serial.println(filechar);
  switch(player_num)
   {
    case 0:
    //playWav1.stop();
    playSdWav1.play(filechar);
    //Serial.println(filechar);
    break;

    case 1:
    //playWav2.stop();
    playSdWav2.play(filechar);
    break;

    case 2:
    //playWav3.stop();
    playSdWav3.play(filechar);
    break;
    
    case 3:
    //playWav4.stop();
    playSdWav4.play(filechar);
    break;
    
    case 4:
    //playWav5.stop();
    playSdWav5.play(filechar);
    break;
    
    case 5:
    //playWav6.stop();
    playSdWav6.play(filechar);
    break;
    
    case 6:
    //playWav7.stop();
    playSdWav7.play(filechar);
    break;
    
    case 7:
    //playWav8.stop();
    playSdWav8.play(filechar);
    break;
    
    case 8:
    //playWav9.stop();
    playSdWav9.play(filechar);
    break;
    
    case 9:
    //playWav10.stop();
    playSdWav10.play(filechar);
    break;
    
    case 10:
    //playWav11.stop();
    playSdWav11.play(filechar);
    break;
    
    case 11:
    //playWav12.stop();
    playSdWav12.play(filechar);
    break;
    
    case 12:
    //playWav13.stop();
    playSdWav13.play(filechar);
    break;
    
    case 13:
    //playWav14.stop();
    playSdWav14.play(filechar);
    break;
    
    case 14:
    //playWav15.stop();
    playSdWav15.play(filechar);
    break;
    
    case 15:
    //playWav16.stop();
    playSdWav16.play(filechar);
    break;
   }
}
//**************************************************************************************
void dinmidi()
{  
  /*
    Serial.println(MIDI.getChannel());    
    Serial.println(MIDI.getType(),HEX);       
    Serial.print(MIDI.getData1(),HEX);
    Serial.print(" HEX| ");
    Serial.print(MIDI.getData1(),DEC);
    Serial.print(" DEC| ");
    Serial.println();    
    Serial.print(MIDI.getData2(),HEX);
    Serial.print(" HEX| ");
    Serial.print(MIDI.getData2(),DEC);
    Serial.print(" DEC| ");
    Serial.println();
    */
    
    
    
    
    
    
   // if(type==0x90)
    //{ 
      byte data1 = MIDI.getData1();//note
      byte data2 = MIDI.getData2();//velo
      
      switch(data1)
      {
      case 0x24:
        playPlayer(slot[0],0);
       break;

      case 0x25:
        playPlayer(slot[1],1);
      break;

      case 0x26:
        playPlayer(slot[2],2);
      break;

       case 0x27:
        playPlayer(slot[3],3);
      break;

      case 0x28:
        playPlayer(slot[4],4);
      break;

      case 0x29:
        playPlayer(slot[5],5);
      break;

      case 0x2A:
        playPlayer(slot[6],6);
      break;

      case 0x2B:
        playPlayer(slot[7],7);
      break;

      case 0x2C:
        playPlayer(slot[8],8);
      break;

      case 0x2D:
        playPlayer(slot[9],9);
      break;

      case 0x2E:
        playPlayer(slot[10],10);
      break;

      case 0x2F:
        playPlayer(slot[11],11);
      break;

      case 0x30:
        playPlayer(slot[12],12);
      break;

      case 0x31:
       playPlayer(slot[13],13);
      break;

      case 0x32:
        playPlayer(slot[14],14);
      break;

      case 0x33:
        playPlayer(slot[15],15);
      break;
      }    
   // }
    
}
 
The optocoupler in the midi specification should handle the midi data from a beatstep fine. Interestingly, i have a similar project connecting a beatstep and an arduino due which is slower performance wise, but also works fine when i input a lot of pad data. So you can likely rule out midi in problems, provided that your circuit is adhering to the midi standard, and your midi library is tried and tested.

I'd guess that your problem lies elsewhere. I'm assuming that you checked the memory card data handling?

Also, another thing. On my beatstep unit, i've noticed that the encoders are a bit erratic in relative mode, causing rather big value skips occasionally. Does your code handle that?
 
Organise and optimise your code, and never use delay (except possibly in setup code).

That will make it much easier to work with.

For example, lot's of places arrays could be used to avoid the huge switch statements, and you could reduce your usbmidi code down to:

Code:
if (usbMIDI.getType()==0x90)
{
    int index = usbMIDI.getData1() - 0x24;
    if (index >= 0 && index < 16)
      playPlayer(slot[index],index);      
}

Then with easier to manage and read code you can think more clearly about what you are asking it to do when, and what might block things up - perhaps a slow write to the lcd much more often than is necessary?
 
Last edited:
Writing to lcd only occurs right after user input and there is no .clear() or write functions during playback, also delays are temporary just to achieve stable effects while pressing on the encoder.
Could this be a problem with SD card then im not using any trusted or new one just some random card that i found in my pile of electronics.
 
For now im only testing it with pads and sequencer.
My process is that i put track full of notes on 1st pad then add same thing on 2nd and so on.
Near 6th-7th pad teensy crashes and stops responding and continues to play bugged audio, you know something like tryrtryttryttryt xD (i know really technical representation)
Also i did not test memory card data handling and would love for you to point me how to do it and what results i should have to have stable operation.
 
Status
Not open for further replies.
Back
Top