Hello to all,
first of all, this post will be long, but I will try to expose the VGA RGB video generation on the PSoC62S4 Pioneer kit, that I am working on. I hope this will be helpful to understand some problems involved in this phase of the project. Of course, feel free to correct me.
So let's start.
As I said before, I decided to choose the RGB video generation method because it's easier than the composite video because the signals of the colors are driven separately from the synchronization signal. One of the most popular RGB video systems has been the VGA for years. It's very simple to generate this video signal because two signals drive the video frame geometry generation (synchronization), and even a single signal for all Red, green and Blue components can be used to generate a basic monochrome b/w video.
Currently, for my project, I have reserved 2 signals for the synchronization (P9_0, P9_1) and 8 signals for RGB colors (P10_0 .. P10_7, divided into 3 for Red, 3 for Green, and 2 for Blue). But I will explain it later in the post.
Let's see how we could generate a video. As an example, just for fun, I took a video frame from the game OutRun:
As known, a video image is made of pixels. These are drawn one after another in a contiguous horizontal line until the width of the image is reached. At that point, a new line starts, like a normal text after a period.
In order to instruct a video monitor what to do with pixels, we have the synchronization signals that tell the monitor when a horizontal line stops (HSync), and when the entire image finishes (VSync).
So, color pixels are sent through RGB signals while the HSync signal is at the HIGH logic level. When the horizontal pixels are over, the RGB signals are off (black), and after a little time (front porch) the HSync signal goes LOW and HIGH to tell the monitor to restart drawing from the left border and go down to the next line (like a carriage return). In order to give time for the electronics to prepare for the next line, another short time passes (back porch).
When the image is completed a similar thing happens with the VSync signal, after some black lines (front porch) the VSync goes from HIGH to LOW and then back to HIGH. That tells the monitor to restart drawing from the top.
This is a very simple mechanism. Considering I want to generate a VGA Signal 640 x 480 @ 60 Hz Industry standard timing, I have to respect specific timings to drive the Sync signals and the color pixels:
VGA Signal 640 x 480 @ 60 Hz Industry standard
General timing
Screen refresh rate | 60 Hz |
Vertical refresh | 31.46875 kHz |
Pixel freq. | 25.175 MHz |
What rules the stream of pixels and the horizontal sync is the pixel clock, that in this case is 25.175 MHz. that means that each color pixel is sent through the RGB lines every (1 second / 25175000 = 0.000000039722 seconds) 39.722 ns.
In order to simplify the electronics, all the timings are counted in pixel clocks, but of course, we also know the duration of each phase of the signal.
Horizontal timing (line)
Polarity of horizontal sync pulse is negative (HIGH-LOW-HIGH).
Scanline part | Pixels | Time [µs] |
Visible area | 640 | 25.422045680238 |
Front porch | 16 | 0.63555114200596 |
Sync pulse | 96 | 3.8133068520357 |
Back porch | 48 | 1.9066534260179 |
Whole line | 800 | 31.777557100298 |
Vertical timing (frame)
Polarity of vertical sync pulse is negative (HIGH-LOW-HIGH).
Frame part | Lines | Time [ms] |
Visible area | 480 | 15.253227408143 |
Front porch | 10 | 0.31777557100298 |
Sync pulse | 2 | 0.063555114200596 |
Back porch | 33 | 1.0486593843098 |
Whole frame | 525 | 16.683217477656 |
Now, how I can implement this mechanism?
I know that the most important signals here are the H/VSync, so in order to make the monitor hook a perfect VGA frame, I need to send a negative pulse 96 pixels long every 800 pixels (3.813 us every 31.777 us). That's easy, I can do this through a PWM assigned to a pin of the PSoC62S4. For this purpose, I decided to use P9_0. All I need is to set a PWM with a period of 31.777 us and a Counter Compare 0 at 3.813 us. This signal must run continuously.
Now we need to count lines and drive the VSync at specific line numbers. After the lines of the visible area (480) and the lines of the front porch (10), I have 2 lines where the VSync is LOW. Then it goes back to HIGH. I decided to use P9_1 as VSync. Basically every HSync pulse I could increment an index, and when it reaches 490 I can set P9_1 LOW, and at line 492 I can set P9_1 back HIGH:
The first solution that I can use is to set an IRQ triggered by the HSync pulse, so an ISR is called and the index is incremented. In the same routine, I check the index number and set the VSync LOW when 490 <= index < 492. This should work nicely.
A pseudo-language ISR could be:
scanline_index = scanline_index + 1
if (scanline_index = 525) then scanline_index = 0
if (scanline_index = 490) then VSync = LOW
if (scanline_index = 492) then VSync = HIGH
I will do the math in the next part.