PDA

View Full Version : SMPTE Timecode reader



docwisdom
- 16th August 2007, 18:26
Hey all.

We are working in a production studio and all of our cameras are locked together by timecode. I would like a little timecode display in the control room so the logger is able to write down the timecode at varioius times.

Basically I just need to read the 80 bit digital signal and display it on an LCD display.

Its been a while since I coded anything so my picbasic is rusty. Maybe someone can check out these docs and get me on the right path.
I have the code to work the display, I just need a refresher on detecting start & stop bits, reading and splitting strings to appropriate variables.

thanks
-brian

http://www.philrees.co.uk/articles/timecode.htm#mod
http://www.philrees.co.uk/articles/timecode.htm#bcd


ps. right now using a 16F737 because I have one laying around.

docwisdom
- 18th August 2007, 00:52
ah, c'mon. i know someone wants to dive into this.

mr e, mel, you know you want to.

docwisdom
- 9th October 2007, 00:37
nothin yet. Darn.

docwisdom
- 28th January 2008, 22:59
??
anyone

BrianT
- 29th January 2008, 03:46
Untried but should get you started.

'************************************************* ***************
'* Name : BiPhase 01.BAS *
'* Author : Brian Taylor *
'* Notice : Copyright (c) 2008 Brian Taylor *
'* : All Rights Reserved *
'* Date : 29/01/2008 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************

' an untried attempt at decoding the 2400 bps data stream used in the
' SMPTE LTC timecode system
'
'Defines go here

' Hardware definitions
LineIn var portB.0 'or whatever moves you


' Software definitions
A var byte
B var byte
C var byte
Msg var byte[8] ' up to 64 bits of timecode data
Valu var bit ' data bit from the biPhase data stream
Width var byte ' the number of 20 uSec chunks in the bit period
' 2400 bps is approx 416 uSecs per bit
' a ZERO should return a count of approx 20
' a ONE should yield a count of approx 10
Pattern var word ' this must match the SYNC pattern to start

'************************* Initialise block *************************
FlashLEDs: ' show em we are alive, etc
PickNose: ' etc
ScratchBum: ' etc

goto start 'jump subroutines at startup

'************************* Subroutines ****************************
FindBit:
' This extracts the 0 or 1 data bits from the incoming data stream
width = 0
FindEdge:
a = linein
pauseus 20
width = width + 1
if width > 14 then foundzero ' can't be a ONE - must be a ZERO.
' important that we exit early so we have approx 100 uSecs for
' other tasks before the next data transition. Allow for jitter
' and don't make the width comparison too tight
if linein = a then findedge
' sample a second time - repeat if no change
FoundOne:
'at this point we have a transition under 15 counts so must be a ONE.
valu = 1
goto findbitdone
FoundZero:
valu = 0
FindBitDone:
return

'***************************** MAIN ******************************
START:

FindSync:
' The values of the sync bits are fixed as 0011 1111 1111 1101
' Make a sliding window comparator by sliding the bits in the Pattern word
' up one place and adding the latest bit to the end and comparing this
' with the Sync word. NOTE the MSB/LSB might need swapping end for end.
gosub findbit
pattern = pattern << 1 + valu ' slide up one place and add latest bit
if pattern = %0011111111111101 then foundsync
goto findsync 'get one more bit & check again - keep doing it until a match
FoundSync:

GetData:
for b = 0 to 5 ' get 6 message bytes - bytes 6 & 7 are sync - so skip
for a = 0 to 7 ' get 8 bits in each message byte
gosub findbit
c.0[a] = valu ' fill the 8 bits in the byte
' MAY need a tweak to get MSB/LSB sense correct
next a
msg[b] = c
next b
' at this point you should have 6 bytes of message that needs
' to be broken down into the various data blocks per the
' SMPTE LTC specification

DoWhatever:
' unpack the nibbles you are interested in.

goto start


HTH
Brian

docwisdom
- 30th January 2008, 03:17
Thanks brian
ill give it a stab and come back with a report ( and questions most likely)

-brian

docwisdom
- 3rd May 2008, 02:39
Brian,
Thanks for the great help thus far. Here is where I am at the moment.
Camera timecode out is wired to portc.2 and shield is connected to the circuits ground.
So far, I get the 'TC reader' greeting on the LCD but no readout of Timecode.
I threw in some LCDOUT lines for diagnostics. It gets to Found 0 and repeats there. So Found 1 doesn't seem to be occurring. Unless my pauses are causing problems.

One thing that stand out in the code that I dont understand. The LineIn = A then a couple lines down A = LineIn, seems like it would create an infinite loop.

'************************************************* ***************
'* Name : Timecode.BAS *
'* Author : Brian Critchlow & Brian Taylor *
'* Notice : Copyright (c) 2007 Brian Critchlow & Brian Taylor *
'* : All Rights Reserved *
'* Date : 10/11/2007 *
'* Version : 1.0 *
'* Notes : PIC 16F737 *
'* : *
'************************************************* ***************
TRISB = %00000000 'portb output
TRISC = %11111111 'portc input
ADCON1 = %11111111 'all ports digital

define OSC 4 '4mhz oscillator

DEFINE LCD_DREG PORTB ' Set LCD Data port
DEFINE LCD_DBIT 0 ' Set starting Data bit (0)

DEFINE LCD_RSREG PORTB ' Set LCD Register Select port
DEFINE LCD_RSBIT 4 ' Set LCD Register Select bit

DEFINE LCD_EREG PORTB ' Set LCD Enable port
DEFINE LCD_EBIT 6 ' Set LCD Enable bit

DEFINE LCD_BITS 4 ' Set LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 2 ' Set number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Set command delay time in us
DEFINE LCD_DATAUS 50 ' Set data delay time in us
pause 1000 '1 second delay

'-------------------Begin timecode section---------------------------
' an untried attempt at decoding the 2400 bps data stream used in the
' SMPTE LTC timecode system
'
'Defines go here

' Hardware definitions
LineIn var portC.2 'or whatever moves you

' Software definitions
A var byte
B var byte
C var byte
Msg var byte[8] ' up to 64 bits of timecode data
Valu var bit ' data bit from the biPhase data stream
Width var byte ' the number of 20 uSec chunks in the bit period
' 2400 bps is approx 416 uSecs per bit
' a ZERO should return a count of approx 20
' a ONE should yield a count of approx 10
Pattern var word ' this must match the SYNC pattern to start

'************************* Initialise block *************************
FlashLEDs: ' show em we are alive, etc
LCDOUT $FE, 1, "TC ", $FE, $C0, "Reader" 'tag line
pause 1000 '1 second delay

goto start 'jump subroutines at startup

'************************* Subroutines ****************************
FindBit:
' This extracts the 0 or 1 data bits from the incoming data stream
width = 0
FindEdge:
a = linein
pauseus 20
width = width + 1
if width > 14 then foundzero ' can't be a ONE - must be a ZERO.
' important that we exit early so we have approx 100 uSecs for
' other tasks before the next data transition. Allow for jitter
' and don't make the width comparison too tight
if linein = a then findedge
' sample a second time - repeat if no change
FoundOne:
LCDOUT $FE, 1, "Found ", $FE, $C0, "1" 'tag line
pause 500 '1 second delay
'at this point we have a transition under 15 counts so must be a ONE.
valu = 1
goto findbitdone
FoundZero:
LCDOUT $FE, 1, "Found ", $FE, $C0, "0" 'tag line
pause 500 '1 second delay
valu = 0
FindBitDone:
return

'***************************** MAIN ******************************
START:
FindSync:
' The values of the sync bits are fixed as 0011 1111 1111 1101
' Make a sliding window comparator by sliding the bits in the Pattern word
' up one place and adding the latest bit to the end and comparing this
' with the Sync word. NOTE the MSB/LSB might need swapping end for end.
gosub findbit
pattern = pattern << 1 + valu ' slide up one place and add latest bit
if pattern = %0011111111111101 then foundsync
goto findsync 'get one more bit & check again - keep doing it until a match
FoundSync:
LCDOUT $FE, 1, "Found ", $FE, $C0, "Sync" 'tag line
pause 500 '1 second delay
GetData:
for b = 0 to 5 ' get 6 message bytes - bytes 6 & 7 are sync - so skip
for a = 0 to 7 ' get 8 bits in each message byte
gosub findbit
c.0[a] = valu ' fill the 8 bits in the byte
' MAY need a tweak to get MSB/LSB sense correct
next a
msg[b] = c
next b
' at this point you should have 6 bytes of message that needs
' to be broken down into the various data blocks per the
' SMPTE LTC specification

DoWhatever:
' unpack the nibbles you are interested in.
LCDOUT $FE, 1, Msg[0], $FE, $C0, Msg[1]

goto start

docwisdom
- 19th May 2008, 23:28
still stuck in the same spot.
anyone have any insight?

mister_e
- 19th May 2008, 23:41
First, you can't have an accurate PAUSEUS 20 with 4MHz using PAUSEUS. See PBP manual.

OR you could still use a Timer/Counter... or use few asm GOTO $+1 or NOP.

BrianT
- 20th May 2008, 02:14
Hi Brian,
I have not given your post its due consideration but a couple of things jump to mind.

a/ Don't use LCDOUT in a time critical loop. The fastest indicator is to set a LED ON when the target event occurs and off at another part of the code.
HIGH LED takes more time and code space than LED = 1 so make sure the relevant TRIS statement makes the LED pin an output then set LED = 1 instead of LCDOUT.

b/ The statements....
Findedge:
A = linein
..dothings..
if linein = A then Findedge

make a looping structure that keeps going until linein changes state. It does not care whether LineIn is high or low, it just looks for a change. The assumption is that linein changes and stays changed for longer than a loop time in order to be found. Adding extras like LCDOUT can trip you up badly with fast toggling inputs. There is a problem with this approach if the state of linein changes during the ever so small time it takes to execute the 'if linein = A then findedge' line. If that happens you will miss finding sync but this will only be once every thousand or so blocks. It can be fixed.

c/ I agree with mister-e and you really should be running a 20 MHz part at 20 MHz for anything that interacts with real world data communications.

d/ The FindBit routine must run flat out. 20 MHz will be better than 4 MHz although it does look like 4 MH4 would be barely fast enough. You cannot have any LCDOUT or pauses in it or the routine will only find the first bit and the rest of the mesage will fall on the floor during the pause 500 line.

You CANNOT have a pause 500 after finding sync or finding a one or zero. You must immediately gather in the full 48 or 64 bit data field and decode it. Any pauses where you show them will cause the code to immediately miss the following data bits.

e/ I suggest the FindSync: routine should look something like.....

FoundSync:
LED = 1 'Shows we have met the SYNC conditions
GetData:
for b = 0 to 5 ' get 6 message bytes - bytes 6 & 7 are sync - so skip
for a = 0 to 7 ' get 8 bits in each message byte
gosub findbit
c.0[a] = valu ' fill the 8 bits in the byte
' MAY need a tweak to get MSB/LSB sense correct
next a
msg[b] = c
LED = 0 ' turn the LED off after one character time - about 4 mSecs
next b

-or- shift the LED = 0 command to after the 'next b' and have the LED on for 6 character times which may be easier to see.

HTH
Brian