Pages: [1]   Go Down
Author Topic: smpte timecode reader  (Read 6119 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 1
Posts: 40
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm working on a project that will have four tc readers and a video display.  I got the reader code working and thought perhaps someone else might find it useful.  Most of the very few examples I was able to find on the web were in asm or basic.  This is my first real project with the Arduino, and as a beginner I'm sure there far better ways to accomplish this then the ones I've chosen.

To all the folks who posted example code for timecode readers, thank-you, I stole bits and pieces from you all.


Code:

#define icpPin 8        // ICP input pin on arduino
#define one_time_max          475 // these values are setup for NTSC video
#define one_time_min          300 // PAL would be around 1000 for 0 and 500 for 1
#define zero_time_max         875 // 80bits times 29.97 frames per sec
#define zero_time_min         700 // equals 833 (divide by 8 clock pulses)
                                  
#define end_data_position      63
#define end_sync_position      77
#define end_smpte_position     80

volatile unsigned int bit_time;
volatile boolean valid_tc_word;
volatile boolean ones_bit_count;
volatile boolean tc_sync;
volatile boolean write_tc_out;
volatile boolean drop_frame_flag;

volatile byte total_bits;
volatile byte current_bit;
volatile byte sync_count;

volatile byte tc[8];
volatile char timeCode[11];

/* ICR interrupt vector */
ISR(TIMER1_CAPT_vect)
{
  //toggleCaptureEdge
  TCCR1B ^= _BV(ICES1);

  bit_time = ICR1;
  
  //resetTimer1
  TCNT1 = 0;

  if ((bit_time < one_time_min) || (bit_time > zero_time_max)) // get rid of anything way outside the norm
  {
    //Serial.println(bit_time, DEC);
    total_bits = 0;
  }
  else
  {
    if (ones_bit_count == true) // only count the second ones pluse
      ones_bit_count = false;
    else
    {    
      if (bit_time > zero_time_min)
      {
        current_bit = 0;
        sync_count = 0;
      }
      else //if (bit_time < one_time_max)
      {
        ones_bit_count = true;
        current_bit = 1;
        sync_count++;
        if (sync_count == 12) // part of the last two bytes of a timecode word
        {
          sync_count = 0;
          tc_sync = true;
          total_bits = end_sync_position;
        }
      }

      if (total_bits <= end_data_position) // timecode runs least to most so we need
      {                                    // to shift things around
        tc[0] = tc[0] >> 1;
  
        for(int n=1;n<8;n++)
        {
          if(tc[n] & 1)
            tc[n-1] |= 0x80;
        
          tc[n] = tc[n] >> 1;
        }
  
        if(current_bit == 1)
          tc[7] |= 0x80;
      }
      total_bits++;
    }

    if (total_bits == end_smpte_position) // we have the 80th bit
    {
      total_bits = 0;
      if (tc_sync)
      {
        tc_sync = false;
        valid_tc_word = true;
      }
    }
    
    if (valid_tc_word)
    {
      valid_tc_word = false;

      timeCode[10] = (tc[0]&0x0F)+0x30;      // frames
      timeCode[9] = (tc[1]&0x03)+0x30;      // 10's of frames
      timeCode[8] =  '.';
      timeCode[7] = (tc[2]&0x0F)+0x30;      // seconds
      timeCode[6] = (tc[3]&0x07)+0x30;      // 10's of seconds
      timeCode[5] =  ':';
      timeCode[4] = (tc[4]&0x0F)+0x30;      // minutes
      timeCode[3] = (tc[5]&0x07)+0x30;      // 10's of minutes
      timeCode[2] = ':';
      timeCode[1] = (tc[6]&0x0F)+0x30;      // hours
      timeCode[0] = (tc[7]&0x03)+0x30;      // 10's of hours
      
      drop_frame_flag = bit_is_set(tc[1], 2);

      write_tc_out = true;
    }
  }
}


void setup()
{
  beginSerial (115200);
  pinMode(icpPin, INPUT);                  // ICP pin (digital pin 8 on arduino) as input

  bit_time = 0;
  valid_tc_word = false;
  ones_bit_count = false;
  tc_sync = false;
  write_tc_out = false;
  drop_frame_flag = false;
  total_bits =  0;
  current_bit =  0;
  sync_count =  0;

  //Serial.println("Finished setup ");
  //delay (1000);

  TCCR1A = B00000000; // clear all
  TCCR1B = B11000010; // ICNC1 noise reduction + ICES1 start on rising edge + CS11 divide by 8
  TCCR1C = B00000000; // clear all
  TIMSK1 = B00100000; // ICIE1 enable the icp

  TCNT1 = 0; // clear timer1
}

void loop()
{
    if (write_tc_out)
    {
      write_tc_out = false;
      if (drop_frame_flag)
        Serial.print("TC-[df] ");
      else
        Serial.print("TC-[nd] ");
      Serial.print((char*)timeCode);
      Serial.print("\r");
    }
}




/me
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 40
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thought I should add this (figured out how to post an image)  Below is a simple timecode generator to Arduino interface.  You could get the parts at Radio Shack.

Douglas


Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hah, that's cool!  I'm actually a member of SMPTE and attend the engineering committee meetings regarding extending SMPTE 12M timecode to 60p (and perhaps beyond).
Logged

Adelaide, South Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino? I like it!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Thought I should add this (figured out how to post an image)  Below is a simple timecode generator to Arduino interface.  You could get the parts at Radio Shack.

Douglas




For a total newb to all this, how does one visualize this timecode? Does the xlr jack plug into some sort of display device? I'm looking to drive a motion controlled device that will step based on timecode.
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6250
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
For a total newb to all this, how does one visualize this timecode? Does the xlr jack plug into some sort of display device? I'm looking to drive a motion controlled device that will step based on timecode.
Hi Dan, the code and circuit in this thread are designed to take industry standard pulses from professional video equipment and make them available to an arduino sketch.

If your application needs to respond to time intervals it would be much easier for you to get the time from a real time clock or use the internal arduino time (there is an arduino software time library here: http://www.arduino.cc/playground/Code/DateTime)

Why not create a new thread in the hardware/interfacing section to describe your application and start a discussion on possible solutions.

« Last Edit: August 02, 2008, 12:28:08 am by mem » Logged

Adelaide, South Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino? I like it!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Quote
For a total newb to all this, how does one visualize this timecode? Does the xlr jack plug into some sort of display device? I'm looking to drive a motion controlled device that will step based on timecode.
Hi Dan, the code and circuit in this thread are designed to take industry standard pulses from professional video equipment and make them available to an arduino sketch.

If your application needs to respond to time intervals it would be much easier for you to get the time from a real time clock or use the internal arduino time (there is an arduino software time library here: http://www.arduino.cc/playground/Code/DateTime)

Why not create a new thread in the hardware/interfacing section to describe your application and start a discussion on possible solutions.

Thanks for the info mem, eventually I will be looking to run this unit from a sync pulse from out of a video or film camera. All just Ideas at the moment though. I will definitely start a thread when I  am ready to sink my teeth into it. Just gathering info at the moment.  smiley-wink
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 40
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's been awhile since I been on here (work gets in the way of fun).  I finished the 4 port timecode reader and a couple of simpler video clocks.  The output video display is handled by a MAX7456 OSD chip.  A rather new video overlay chip running around $18 in single quantity.

With the 4 port reader I had to go to straight 'C' with the Mega168 instead of the Arduino, there was just too much demand for the Arduino OS to keep up with.  In fact with the final build I used all Mega48's because the code fit and I could save my Arduino's for other prototyping.

I also put together a shield with the MAX7456 (built on a nkc protoshield) so I can play with / learn this neat OSD.

If anyone has any interest I will put some drawings and code together and post it.

dfraser
Logged

New Zealand
Offline Offline
God Member
*****
Karma: 0
Posts: 999
Arduino pebbles
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
If anyone has any interest I will put some drawings and code together and post it.
Yes, please. :-)

--Phil.
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 40
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I finished a small project to build a shield for playing with the MAX7456 OSD chip.  This is the video output section I used in my timecode readers.  I will post all of this in a new thread 'Arduino + Max7456 OSD'
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 4
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

here is the schematic again, from dfraser


Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Is this code frame accurate?

I am hoping to build a box with timecode and tally reading to generate an shot log from a live shoot.

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

On Live you get a mixer.... the videomixer has normaly rs232 output for tally's
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For pal: 25 and 24 Fps   smiley-grin


#define one_time_max          588 // these values are setup for NTSC video
#define one_time_min          422 // PAL would be around 1000 for 0 and 500 for 1
#define zero_time_max          1080 // 80bits times 29.97 frames per sec
#define zero_time_min          922 // equals 833 (divide by 8 clock pulses)


For User bit :

        userBit[9] = ((tc[0]&0xF0)>>4)+0x30; // user bits 8
        userBit[8] = ((tc[1]&0xF0)>>4)+0x30; // user bits 7
        userBit[7] = ((tc[2]&0xF0)>>4)+0x30; // user bits 6
        userBit[6] = ((tc[3]&0xF0)>>4)+0x30; // user bits 5
        userBit[5] = '-';
        userBit[4] = ((tc[4]&0xF0)>>4)+0x30; // user bits 4
        userBit[3] = ((tc[5]&0xF0)>>4)+0x30; // user bits 3
        userBit[2] = '-';
        userBit[1] = ((tc[6]&0xF0)>>4)+0x30; // user bits 2  
        userBit[0] = ((tc[7]&0xF0)>>4)+0x30; // user bits 1

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Lucky I stumbled on this, Im actually looking to build my own clapperboard/time code slate (which ever you prefer).

There are iPhone apps that do the same thing but not as well. However there is one app I recently discovered called JumpStart LTC (Longitudinal Time Code) it uses the headphone jack to set the time code on the slate.

Im wondering, 1. would this app and the arduino code here  work the same way? (or is it just for video), 2. how hard would making a slate be? (I have no arduino experience, but no timetable for the slate ie could take forever and i dont care)
Logged

Pages: [1]   Go Up
Jump to: