Go Down

Topic: Midi Time Code Reader/Generator with Arduino (Read 3064 times) previous topic - next topic

Grag38

Apr 05, 2011, 05:08 pm Last Edit: Apr 06, 2011, 11:31 am by Grag38 Reason: 1
This is a piece of code for Arduino to decode MidiTimeCode.

It can be usefull for some people that wants to deal with MTC.

Code: [Select]
/*


Midi Time Code Reader.

For information about MTC : http://home.roadrunner.com/~jgglatt/tech/mtc.htm


*/

#include <stdio.h>    // sprintf belongs to this lib

enum { F24 = 0, F25 = 2, F30DF = 4, F30 = 6 }; // Frames type

byte h, m, s, f;      // hour, minutes, secondes, frames time code
byte frameType;       // speed of MTC : 24fps / 25fps / 30 drop frame / 30 fps

byte buf[64];         // Serial Midi Buffer
byte tc[20];          // array to old timecode

void setup()
{
 Serial3.begin(31250);    // I use Arduino Mega TX3/RX3 serial / Modify for other arduino hardware
 Serial.begin(115200);    // To trace and display timeocde
}

void loop()
{
 int bytestoRead;

 bytestoRead = Serial3.available();

 if (bytestoRead>0)
 {
   for (int i=0; i<bytestoRead; i++)
   {
     buf[i]=Serial3.read();

     if (buf[i]!=0xF1)
     {
       int indice;

       indice = (buf[i] & 0xf0)>>4;

       if (indice>7)
         continue;

       tc[indice]= buf[i] & 0x0f;

       if (indice==7)
       {
         char toDisp[30];
         char typeStr[10];
         byte frameType;
         
         frameType = tc[7] & 0x06;

         h = (tc[7] & 0x01)*16 + tc[6];
         m = tc[5]*16+tc[4];
         s = tc[3]*16+tc[2];
         f = tc[1]*16+tc[0];

         if (h>23)  h = 23;
         if (m>59)  m = 59;
         if (s>59)  s = 59;
         if (f>30)  f = 30;

         switch(frameType)
         {
           case F24:
             strcpy(typeStr, "24 fps"); break;
           case F25:
             strcpy(typeStr, "25 fps"); break;
           case F30DF:
             strcpy(typeStr, "30df fps"); break;
           case F30:
             strcpy(typeStr, "30 fps"); break;  
           default:
             strcpy(typeStr, "Error"); break;
         }

         sprintf(toDisp, "TC %02d:%02d:%02d.%02d / %s", h, m, s, f, typeStr);
         Serial.println(toDisp);
       }
     }  

   }
 }
 
 delay(50);  // Save time for other things. Be carefull, every 2 frames as MTC works is around 8/100 of seconde !
 
}



Hope it can help few of you.

Grag

Grag38

#1
Apr 06, 2011, 11:20 am Last Edit: Apr 06, 2011, 06:58 pm by Grag38 Reason: 1
And now, MTC generator.

I used a timing library : http://www.arduino.cc/playground/Code/TimedAction

Easy code to modify, or adapt to other case. Accuracy is'nt good (timing stability along hours, must be implemented in other way with interrupts or else...)

Code: [Select]


#include <PCD8544.h>
#include <stdio.h>

#include <TimedAction.h>

volatile byte h, m, s, f;

//this initializes a TimedAction class that will send MTC quarter frame every 10 milliseconds so 80 milliseconde for
// an 'entire' timecode.

TimedAction timedAction = TimedAction(10,GenMtc);

//pin / state variables
const byte ledPin = 13;
boolean ledState = false;
static PCD8544 lcd;     // 5110 Nokia Lcd
char toDisp[14*6];      // 6 lines of 14 characters.


void setup()
{
 lcd.begin(84,48);
 pinMode(ledPin,OUTPUT);
 digitalWrite(ledPin,ledState);
 Serial3.begin(31250);               // use of TX3/RX3 of Arduino Mega
 h = m = s = f = 0;
}

void loop()
{
 timedAction.check();
}

void GenMtc()
{
 static byte indice=0;
 static byte toSend;

 switch(indice)
 {
 case 0:
   toSend = ( 0x00 + (f & 0xF));        
   break;

 case 1:
   toSend = ( 0x10 + ((f & 0xF0)/16));  
   break;

 case 2:
   toSend = ( 0x20 + (s & 0xF));        
   break;

 case 3:
   toSend = ( 0x30 + ((s & 0xF0)/16));  
   break;

 case 4:
   toSend = ( 0x40 + (m & 0xF));        
   break;

 case 5:
   toSend = ( 0x50 + ((m & 0xF0)/16));  
   break;

 case 6:
   toSend = ( 0x60 + (h & 0xF));        
   break;

 case 7:
   toSend = ( 0x72 + ((h & 0xF0)/16));   // 0x70 = 24 fps // 0x72 = 25 fps // 0x74 = 30df fps // 0x76 = 30 fps
   break;
 }
 
 Serial3.write(0xF1);
 Serial3.write(toSend);
 
 if (++indice>7)
 {
   f+=2;
   if (f>24)    // I'm French, so from standard is 25 frames/second
   {
     s++;
     f-=25;
   }
   if (s>59)
   {
     m++;
     s-=60;
   }
   if (m>59)
   {
     h++;
     m-=60;
   }
   ledState = ledState ? false:true;
   digitalWrite(ledPin,ledState);
   sprintf(toDisp, "%02d:%02d:%02d.%02d", h, m, s, f);
   lcd.setCursor(0,0);
   lcd.print(toDisp);
 
   indice=0;
 }
}

Go Up