It took me a long time to understand how to generate VGA video signals using an AVR…looked at many sites , blogs, but none explained it in simple terms…or perhaps, I was too dumb to understand.
Therefore, if you are as dumb as I’m, then this blog is for you. This is divided into two parts
Step 1 : The basics of Video Signal
We first need to understand how a simple CRT screen works. A beam of light is thrown on a screen, one pixel at a time. The beam travels from left to right. Once the right edge is reached, the beam switches off, the beam pointer goes back to the left edge, switches on again and the next line is drawn.
This process continues till the last line is drawn (or the bottom of the screen is reached) . The figure below explains the process. The solid arrow from left to right is the one that draws one pixel at a time. The dashed, diagonal arrow demonstrates the retrace path.
Once the beam reaches the end (or bottom right corner), it goes back to top-left to start the tracing again (as shown by the bold arrow that goes from bottom-right to top-left)
While the actual process has many more variations, the simple explanation above will suffice. Now let’s turn our mind to some definitions that we need to know:
- Vertical Sync – The signal that is responsible to tell the monitor to move the beam to top-left.
- Horizontal Sync – The signal that is responsible to bring the drawing beam back to the left edge
- Refresh Rate – The number of times the screen drawn in a second or alternatively, the number of times the beam moves from bottom right to top left.
- Resolution – Represented as number of horizontal pixels by number of vertical lines at a given refresh rate. For example 640 x 480 @60 Hz means, there are 640 visible pixels in the horizontal lines, there are 480 visible line and the entire screen is refreshed 60 times per second.
Now, over a period of time, the resolution of the screens have improved and many more technologies have come up (e.g. DVI), however, given the popularity of VGA, its here to stay and nearly all display devices support this standard.
There are many standards that have evolved, but, 640 x 480 @60 Hz still remain very popular and is widely supported. We will also focus on this…simply because, given the slow speed at which the ATTiny2313 runs, this is the closest we can get to. For a complete list of VGA standards visit http://tinyvga.com/vga-timing
Once we have understood the basics of video signal, let’s focus on the specific timings.
Step 2: VGA Signals and Timings (for 640 x 480 @60 Hz)
In this section, we will focus on the 640 x 480 @60Hz specification. There are more specifications, but those could be implemented as extensions of the idea presented here.
In order to build a VGA signal generator, we need the following components:
- A precise “Vertical Sync” signal generator – VSYNC
- A precise “Horizontal Sync” signal generator – HSYNC
- A video signal generator or, RGB signal generator.
Before we can delve into all this, we need to understand the signals well. You also need to know that while the beam travels from extreme left to extreme right, and then from top to bottom, not all lines (in vertical direction) and pixels (in horizontal direction) are visible. This one fundamental mistake beginners in this area make while creating an algorithm (at-least I made that mistake and lost costly time to get it right). The visible area can be conceptualized as something shown below:
The gray shaded box shows the actual visible area. Note that some lines on the top and bottom, and some pixels on left and right, even though drawn, are not visible (important !)
So now let’s understand the signals.
VSYNC – This is a pulse train of 60 Hz. When the signal is low, it tells the monitor that it should put the drawing beam back to top left.
HSYNC – This is a pulse train of about 31.46 KHz. When the pulse is low, it tells the monitor to move the drawing beam back to the left edge.
The VSYNC pulse timings:
P = The negative pulse or the low pulse => 0.06355 milliseconds
Q = Called the back porch => 1.048 milliseconds
R = Visible area = 15.25 milliseconds
S = Called front porch = 0.3177 milliseconds
Let me explain each one of the components.
You surely understand the low pulse. Immediately following the low pulse is something called the backporch. Once a low pulse is received, the beam travels from bottom right to top left. The backporch is the amount of time it takes for the beam to come to the visible area.
R is the time when the pixels drawn on screen fall in the visible are.
S represents the frontporch. This is the time where horizontal lines drawn on the screen fall at the bottom non-visible area.
The HSYNC pulse timings:
The HSYNC pulse timings are shown below:
B = the low pulse => 3.81 microseconds
C = backporch => 1.9 microseconds
D = visible area => 25.4 microseconds
E= frontporch => 0.63 microseconds
From these two diagrams, its logical to conclude that once you generate a VSYNC, you will wait until the “R” phase starts. Then you can start generating the HSYNC pulses. Well, you are wrong! So was I…I hate to say, but what seems logical, does not work!
What works, is that the moment you make the VSYNC pulse low, you also make the HSYNC pulse low. Therefore, VSYNC timings can be expressed as number of HSYNC pulses, or, since one HSYNC pulse translates to one horizontal line, a VSYNC pulse signal component can be expressed as number of horizontal lines.
Remember, B + C + D + E = 3.81 + 1.9 + 25.4 + 0.63 = 31.74 microseconds (Or 31.5 KHz)
Thus, components of VSYNC pulse, expressed as number of HSYNC pulses will be:
P = 0.06355 milliseconds = 2 HSYNC pulses
Q= 1.048 milliseconds = 33 HSYNC pulses
R=15.25 milliseconds = 480 HSYNC pulses
S = 0.3177 milliseconds = 10 HSYNC pulses
The above relationship is extremely important; because it gives you a hint on what should be your algorithm.
Additionally, you also need to understand the speed requirements to paint the picture, because that will drive your selection of the processor.
Given that we have 25.40 microseconds to push 640 horizontal pixels, it comes down to 0.03975 microseconds per pixel. This roughly translates to a speed of 25.15 MHz. This also assumes that we take only one clock cycle to push out a color value…now that’s asking for too much.
Given that we want to build this using readily available and cheap AVR, the one that provides us with maximum speed with those conditions is ATTiny2313. It runs on 20MHz. Fairly close to what we need.
That concludes the first part…The next part is where we begin the algorithm design and implementation.