Generating composite video signals

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I've been reading tutorials about how composite video signals works. For exmaple rickard's tut, http://www.rickard.gunee.com/projects/video/pic/howto.php.
And I've been trying to generate something by myself. I got a white screen (I am not really sure what I am doing though). The white screen works fine though.
However, when I try to "paint" an specific line on the TV with other color, black for example, I get a flickering image, and it is not what I want.

I have a variable incrementing by one every 64us (that's one line, after the 4us sync signal, the next line should be painted and so on....). When that variable reaches 525, it will be reset to 0 (since the TV has 525 lines). It is not working for me though. here is my code:

int count = 1;

//(4us pulse) Sync with tv (like the enter key)
void sync()
{
        PORTB &= ~(1<<PB3); //SYNC : 0V (low)
        PORTB &= ~(1= 525) count = 1;  //Resets to 0
  }
  return 0;
}

What am I doing wrong? does someone knows?

Last Edited: Sun. Jan 31, 2010 - 06:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

By the way, I am using an atmega328 running at 14.7456 MHz

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Video requires very precise timing. You will not be able to do it with straight C, you will need at least some assembly. Certainly using _delay_us you will not get even close to good enough timing.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But I have seen the signals on the oscilloscope, and I was surprised when I saw that the timing of the signals were very close (maybe exact) as I had in my code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Then you got very lucky. You will be needing clock cycle accuracy to get a stable signal.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There seems to be several problems that I can see with the code, not least the following two major points:

1. There's no VSync (unless I missed it). That'll produce a rolling image. This can be as simple (IIRC) as 3 scanlines of SYNC (e.g. 192us of SYNC) - this would be needed twice in the 525 line frame (it's an interlaced format).
2. You don't have an 8us 'black' after the 4us HSync pulse - that's needed for the TV to work out what's 'black'.

You might try the following (very) bare-bones approach:

Write 3 different routines:
blank() = 4us sync + 60us black
vsync() = 64us sync
display() = 4us sync + 8us black + 52us

Then they could be repeatedly called in the following order...
3 x blank()
3 x vsync()
16 x blank()
240 x display()

This might give you a stable display.

I wrote up a load of notes on monochrome Composite Video about this when developing my TellyMate project - they might help.

Nigel Batten
www.batsocks.co.uk

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the reply. I will make sure to add the VSync and let you know my progress. Just some few questions...

The Vsync should be a 64us signal? Blanking is the horizontal sync right? It has to be 64us too?
Shouldn't be the whole signal for each line a 64us signal with the VSync, blanking, and display? :)

Thank you!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here are a few links to some working video projects which might give you some ideas.

http://www.batsocks.co.uk/products/Other/TellyMate.htm

http://www.serasidis.gr/circuits/AVR_VGA/avr_vga.htm

http://sbc.rictor.org/io/vid3.html

My favorite one is the TellyMate. It is a complete setup that can be controlled by a serial port.
But all of these examples are based on a 16Mhz clock.

--- bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
But all of these examples are based on a 16Mhz clock.

This shouldn't make a difference, just adjust the timing to the frequency that you have. It is more important to be consistent between scan lines then it is to have the frequencies exactly to spec.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The Vsync should be a 64us signal? Blanking is the horizontal sync right? It has to be 64us too?

You seem to be confusing HSync, VSync and Blanking.
HSync allows the TV to recognise the left-hand side of the display.
VSync allows the TV to recognise the top of the display.
Blanking is just an area that isn't drawn on the screen.

The diagram below should help [but be aware - it's for PAL]. The Yellow sections are the HSync. The Broad and Narrow sync pulses make up the VSync.
[note: VSync is a little easier for NTSC - 6 narrow pulses (= 3 scanlines), 6 broad pulses (= 3 scanlines), 6 narrow pulses (= 3 scanlines)]

Most TVs will be happy with much simpler vsync pulses than are shown in the diagram. I believe you can get away with no pulses in the 'narrow sync pulse' area and a sync on all the time in a 'broad sync pulse' area.

Nigel Batten
www.batsocks.co.uk

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here you got a nice project: http://instruct1.cit.cornell.edu...

You must modify it for your needs (read remove a lot of code), but what is most important - routines for VSYNC and HSYNC can be used "as is".

Probably you already know that, but just for sure - it's easy to generate black&white images but if you need colorful pictures it's a bit more complicated.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Years ago I've done some video generation on the AVR.(ATmega32 using only the timers.) And this was the result.

Nothing more than generating a scanline (64 usec / PAL).

8)

RES

Last Edited: Fri. Aug 19, 2016 - 06:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all again!

I got this code now: (is this the right way to generate NTSC vertical sync?).

int count = 0;

int main() {
DDRB |= (1<<PB3);
DDRB |= (1<<PB2);

void sync ()
{
    PORTB &= ~(1<<PB3);
    PORTB &= ~(1<<PB2);
    _delay_us(4);
    count++;
}

void Vsync ()
{
    PORTB &= ~(1<<PB3);
    PORTB &= ~(1<<PB2);
    _delay_us(192); //6 long syncs of 30us followed by a 2us sync

}


  while(1) {

//Will draw a gray bar at line 150...

if( count != 150 )
{
           PORTB &= ~(1<<PB2);
        _delay_us(8);
        PORTB |= (1<<PB2);
        _delay_us(52);
           sync();

}
if( count == 150 )
{
    PORTB &= ~(1<<PB3);
    _delay_us(8);
    PORTB |= (1<<PB3);
    _delay_us(52);
    sync();
}



      if( count == 262 ) Vsync(); //Even VSync
      if( count == 525){ count = 1;     Vsync(); } //Odd VSync
  }

  return 0;
}

I could draw a gray bar at the middle, but the screen is kinda flickering still. The gray bar looks like "blinking". and there is a very flickering black part at the border of the screen.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

_delay_us() is based on the CPU clock.
It is not an "exact" number of microseconds.
In your case each CPU tick is ~67.82ns
so the actual delay you get will be some multiple of that.

The delays that you have asked for are not a multiple of your CPU clock and therefore cannot be achieved.

Compounding to the problem of getting precise delays, is that the resolution of the delay routines in is 3 clock cycles.
Which means that the delay you get is +/- 3 cpu clocks of what you ask for.

The calculation it uses suffers from rounding errors that can cause delays that are not what you asked for even if that exact delay is possible with your CPU clock rate.

While you may never be able to get the exact delay values you need,
if you switch to this alternate delay package you will at least get the delay
you ask for if it is possible with your CPU clock rate.

https://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=665&item_type=project

--- bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting fact.... thanks for the info!