AVR Freaks

AVR forum - Storing Data Stream Input

griffw - Jun 29, 2006 - 11:26 PM
Post subject: Storing Data Stream Input
Hi,

I'm currently working on a project that reads SMPTE LTC timecode from a timecode generator, basically i'm running a clock to read the pulse width duration which determines whether the data is a 0 or a 1. I'm using the mega128, and codevision.

I need to store 80bits which i can then pull the values I need from.
Whats the best way to store/read this data, given that it will be built up one bit at a time?

Any help/guidance would be much appreciated.
w0067814 - Jun 30, 2006 - 08:24 AM
Post subject: RE: Storing Data Stream Input
Something like this you mean?

Code:

void getTime(void)
{

    Int8 byteCount  = 0;
    Int8 bitCount   = 0;
    Int8 timeArray[10];


    /* Alter directions of counts and shifts as needed */
    /*  for LSB/MSB first. */
    for( byteCount = 0 ; byteCount < sizeof(timeArray) ; byteCount++ )
    {
        for(bitCount = 0 ; bitCount < 8 ; bitCount++ )
        {
            timeArray[byteCount] |= (getBit() << bitCount);
        }
    }
}


Int8 getBit(void)
{
    Int8 result = 0; /* Can return either 0 or 1 */
   
    /* Your PWM reading code goes here, and sets result to 0 or 1. */
   
    return(result);
}


Tim
griffw - Jun 30, 2006 - 09:36 AM
Post subject:
Yeah thats about right, i'll give it a whirl when the pulse width code is fully functional. Thanks! Smile

Altough reading the pulses is proving to be a bit harder, would be nice if it wasn't bi-phase encoded....hopefully i'll still have some hair left after its done.
jayjay1974 - Jun 30, 2006 - 11:20 AM
Post subject:
At what speed do those pulses arrive?
griffw - Jul 01, 2006 - 11:13 AM
Post subject:
The frequency of the data is 2000khz.
Basically the whole 80 bits are sent in one video frame which is 40ms.
The data is supplied as a audio signal which i'm feeding into the comparator of the mega128 and reading the pulses via input capture on timer1.

At the moment i'm reading pulses between 233us(+/-3) and 116(+/-3)us, i think its a goodsign that the values are roughly half, altough i'm skeptical about the values.

here is the current interrupt code:

interrupt [TIM1_CAPT] timer_capture(void)
{

if(toggle) //trigger when device goes hight
{
time_low = ICR1; //received positive transition __(timelow)__
toggle=0;
time= time_low + (overflow * 0x1000) - time_high; //calculate
overflow =0; //reset overflows
TCCR1B=0b00000010; //set to interrupt on negitive transition.
}
else
{
time_high = ICR1; //received negitive transition
toggle=1; //low, skip this part next interrupt
timeHigh= time_high + (overflow * 0x1000) - time_low; //calculate
overflow =0; //reset overflows
TCCR1B=0b01000010; //set to interrupt on positive trasition
}
}

Thanks

Gareth
jayjay1974 - Jul 01, 2006 - 12:08 PM
Post subject:
To calculate the time from ICR, you need to subtract the previous reading from it, as the timer will continue running, it isn't reset after an ICP event. But you have to check if the previous value is lower then the newer value or not and compensate for the rollover.

You might be able to setup the timer rate in such way that you don't need the overflow interrupt for normal time calculations, except as a timeout if no pulses arrive.

I wouldn't do multiplies in an ISR.

This is ICP code I use to measure frequency (in this particular example vehicle speed sensor readings) on a tiny2313:

Code:


.
.
.
static unsigned long prev_icp,icp,interval;
static unsigned char *icp_p=(unsigned char *)&icp;
static unsigned int *icp_high=(unsigned int *)(&icp)+1;
static unsigned int next_oca;
static unsigned char update_flag,timer,vss_timeout;
.
.
.

#pragma interrupt_handler timer1_capt_isr:4
void timer1_capt_isr(void)
{
 icp_p[0]=ICR1L; // Read low byte first (important)
 icp_p[1]=ICR1H;

 if (prev_icp>icp) interval=0xFFFFFFFF-prev_icp+icp;
  else interval=icp-prev_icp;
   
 prev_icp=icp;

 //

 vss_timeout=8;
}

//
// Compare interrupt. Increment a timer and update compare register
//
#pragma interrupt_handler timer1_compa_isr:5
void timer1_compa_isr(void)
{
 next_oca+=0x4800;

 OCR1AH=next_oca>>8;
 OCR1AL=next_oca;

 timer+=1;
}

//
// Overflow interrupt. Increment the MSB of ICP. Decrement a timeout timer in case no VSS pulses
// are present
//
#pragma interrupt_handler timer1_ovf_isr:6
void timer1_ovf_isr(void)
{
 *icp_high+=1;
 
 if (vss_timeout) vss_timeout-=1;
}


I also use the same timer to create a timebase for the software by utilizing the output compare function, and incrementing the compare value on each interrupt. So with one timer, I can measure frequency and have a timebase too.

You will have to change it of course to measure pulsewidths, but maybe it helps.

Atmel also has an application note on how to measure pulse widths using the input capture unit.
All times are GMT + 1 Hour
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits