Go Down

Topic: Midi Time Code Reader/Generator with Arduino (Read 3439 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
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy