Pages: [1]   Go Down
Author Topic: Midi Time Code Reader/Generator with Arduino  (Read 2729 times)
0 Members and 1 Guest are viewing this topic.
France
Offline Offline
Sr. Member
****
Karma: 2
Posts: 380
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
/*


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
« Last Edit: April 06, 2011, 04:31:04 am by Grag38 » Logged

France
Offline Offline
Sr. Member
****
Karma: 2
Posts: 380
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

#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;
  }
}
« Last Edit: April 06, 2011, 11:58:31 am by Grag38 » Logged

Pages: [1]   Go Up
Jump to: