Video Signals And Timing: Difference between revisions

From OSDev.wiki
Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content added Content deleted
(Initial dump of Brendan's posts)
 
(Added some background on VGA display signals)
Line 1: Line 1:
'''Work in progress. Is currently a dump of Brendan's worked out formulae'''
'''Work in progress. Needs explanation of the formulae'''

'''Warning: Setting incorrect video settings can damage a monitor'''

== Display Signal ==
There are a large amount of pins in a standard VGA Cable. When your video card sends its video data to the monitor, it uses 5 data channels:
* Analog Red
* Analog Green
* Analog Blue
* Horizontal Sync
* Vertical Sync
The screen is built up scanline by scanline, by sending the appropriate RGB values over the connection. However, only having a stream of colours will not tell you which part of the stream belongs to the top-left-pixel on the screen. To solve this they added two more signals: the horizontal sync which pulses when a horizontal line is done, and the vertical sync, which pulses when all rows have been completed. Thus, each frame corresponds to a single vertical synchronisation pulse. Since each frame has the same amount of pixels, the time between consecutive pulses is a constant. The monitor times the frequency of the pulses, then based on that it knows at what time the color data should be sent to what position on the screen.

The system is however not that simple. The first monitors were CRTs, which used magnetic fields to project electron beams onto a phosphoric layer, making them visible for a short period of time. The magnetic fields of a CRT had some inertia - they couldn't be set from a random location to another random location in the time available for one pixel. Hence the video signal has to have some gaps to cope with the time a monitor needs to alter the magnetic fields and point the electron beam back to the other side of the screen. In the meantime there could be no color signal, or you might have gotten stripes on the screen.

CRTs have improved a lot since then, and are now being superseded by the highly intelligent LCD display. The standard for signaling hasn't changed since.

== Display Composition ==
All frames of a video signal have a specific layout, and video cards have a semi-standard way of thinking about these signals. Basically, you will have to provide the video card with enough information to be able to derive all sizes present in the following diagram. [[VGA Hardware]] explains how you can give these sizes to a VGA compatible. For other hardware, you should check your card's documentation on how these values are stored within them.

[[Image:VGA crtc.gif]]

Both horizontally and vertically, there are 6 states, and hence, 6 sizes. Each size is in pixels. Most of the emitted data is part of the active display, the area of x resolution * y resolution pixels. Each of the cuts are where:
* active display goes into overscan
* where overscan goes into blanking
* where blanking gets the synchronization line changed
* where the sync is restored to its original value
* where the blanking goes back into overscan
* where the overscan goes into active display, where the scanline or frame is completed and the next one is started.

Video cards usually gives you the following registers to program (both horizontally and vertially)
* Resolution (pixel size of active display)
* Total (total number of 'pixels' in a single run)
* Blanking start and end (or start and size) - marks the location of the blanking. The are that is neither blanking nor active display becomes the overscan area.
* Sync start and end (or start and size) - marks the location of the synchronization pulse


== Brendan's Posts ==
== Brendan's Posts ==

Revision as of 23:18, 3 April 2009

Work in progress. Needs explanation of the formulae

Warning: Setting incorrect video settings can damage a monitor

Display Signal

There are a large amount of pins in a standard VGA Cable. When your video card sends its video data to the monitor, it uses 5 data channels:

  • Analog Red
  • Analog Green
  • Analog Blue
  • Horizontal Sync
  • Vertical Sync

The screen is built up scanline by scanline, by sending the appropriate RGB values over the connection. However, only having a stream of colours will not tell you which part of the stream belongs to the top-left-pixel on the screen. To solve this they added two more signals: the horizontal sync which pulses when a horizontal line is done, and the vertical sync, which pulses when all rows have been completed. Thus, each frame corresponds to a single vertical synchronisation pulse. Since each frame has the same amount of pixels, the time between consecutive pulses is a constant. The monitor times the frequency of the pulses, then based on that it knows at what time the color data should be sent to what position on the screen.

The system is however not that simple. The first monitors were CRTs, which used magnetic fields to project electron beams onto a phosphoric layer, making them visible for a short period of time. The magnetic fields of a CRT had some inertia - they couldn't be set from a random location to another random location in the time available for one pixel. Hence the video signal has to have some gaps to cope with the time a monitor needs to alter the magnetic fields and point the electron beam back to the other side of the screen. In the meantime there could be no color signal, or you might have gotten stripes on the screen.

CRTs have improved a lot since then, and are now being superseded by the highly intelligent LCD display. The standard for signaling hasn't changed since.

Display Composition

All frames of a video signal have a specific layout, and video cards have a semi-standard way of thinking about these signals. Basically, you will have to provide the video card with enough information to be able to derive all sizes present in the following diagram. VGA Hardware explains how you can give these sizes to a VGA compatible. For other hardware, you should check your card's documentation on how these values are stored within them.

Both horizontally and vertically, there are 6 states, and hence, 6 sizes. Each size is in pixels. Most of the emitted data is part of the active display, the area of x resolution * y resolution pixels. Each of the cuts are where:

  • active display goes into overscan
  • where overscan goes into blanking
  • where blanking gets the synchronization line changed
  • where the sync is restored to its original value
  • where the blanking goes back into overscan
  • where the overscan goes into active display, where the scanline or frame is completed and the next one is started.

Video cards usually gives you the following registers to program (both horizontally and vertially)

  • Resolution (pixel size of active display)
  • Total (total number of 'pixels' in a single run)
  • Blanking start and end (or start and size) - marks the location of the blanking. The are that is neither blanking nor active display becomes the overscan area.
  • Sync start and end (or start and size) - marks the location of the synchronization pulse

Brendan's Posts

>Any problems if I wikify this? None at all - IMHO this information is required just to use VBE reliably; along with EDID (but you can find version 1.1 of the EDID data structures on Wikipedia) and details for the VBE DDC function (which VESA will let you have for free).

However, I should point out that this information is incomplete - the value of certain constants are missing from my original post. The default values for these constants are: CELL_GRAN_RND = 8, MARGIN_PRECENT = 1.8, MIN_PORCH_RND = 1, MIN_V_SYNC_AND_BACK_PORCH = 550, C_PRIME = 40 and M_PRIME = 600. I'd also mention that for my version of the formulas REFRESH_RATE_REQUIRED, V_FIELD_RATE_REQUIRED, H_FREQ_REQUIRED, PIXEL_FREQ_REQUIRED, V_FIELD_RATE, H_FREQ, PIXEL_FREQ are all in Hz (and not a mixture of Hz, KHz and MHz), which helps to simplify the formulas.

There's also some strange things that can happen with these formulas. For example, if any of the calculations give a negative result then it indicates invalid input (e.g. if the PIXEL_FREQ_REQUIRED input parameter is too low, then you can end up with horizontal blanking that takes "negative N us"). In practice, some of these calculations probably have an allowed range (e.g. things like "horizontal blanking must be >= 20% of the horizontal total") but I've been unable to find anything indicating what the allowed ranges for anything is. :(


This is for my own reference, and in case anyone is wondering what they look like... The GTF formulas.

There's actually 3 separate calculations here - finding all timing parameters from X & Y resolution and desired refresh rate, finding all timing parameters from X & Y resolution and desired horizontal frequency, and finding all timing parameters from X & Y resolution and desired pixel clock frequency.

GTF Formulas For Using Desired Refresh Rate

H_PIXELS_RND = ( ROUND ( H_PIXELS / CELL_GRAN_RND ) ) * CELL_GRAN_RND

IF ( INTERLACE_REQUIRED == "y") {
    V_LINES_RND = ROUND ( V_LINES / 2 )
    V_FIELD_RATE_REQUIRED = REFRESH_RATE_REQUIRED * 2
    INTERLACE = 0.5
  } else {
    V_LINES_RND = ROUND ( V_LINES) )
    V_FIELD_RATE_REQUIRED = REFRESH_RATE_REQUIRED
    INTERLACE = 0
  }

IF ( MARGINS_REQUIRED == "y" ) {
    TOP_MARGIN_LINES = ROUND ( MARGIN_PRECENT / 100 * V_LINES_RND )
    BOTTOM_MARGIN_LINES = ROUND ( MARGIN_PRECENT / 100 * V_LINES_RND )
    LEFT_MARGIN_PIXELS = ( ROUND ( ( H_PIXELS_RND * MARGIN_PRECENT / 100 / CELL_GRAN_RND ) , 0 ) ) * CELL_GRAN_RND
    RIGHT_MARGIN_PIXELS = ( ROUND ( ( H_PIXELS_RND * MARGIN_PRECENT / 100 / CELL_GRAN_RND ) , 0 ) ) * CELL_GRAN_RND
  } else {
    TOP_MARGIN_LINES = 0
    BOTTOM_MARGIN_LINES = 0
    LEFT_MARGIN_PIXELS = 0
    RIGHT_MARGIN_PIXELS = 0
  }

H_PERIOD_ESTIMATE = ( 1 / V_FIELD_RATE_REQUIRED - MIN_V_SYNC_AND_BACK_PORCH / 1000000 ) / ( V_LINES_RND + 2 * TOP_MARGIN_LINES + MIN_PORCH_RND + INTERLACE ) * 1000000

V_SYNC_AND_BACK_PORCH = ROUND ( MIN_V_SYNC_AND_BACK_PORCH / H_PERIOD_ESTIMATE )

V_BACK_PORCH = V_SYNC_AND_BACK_PORCH - V_SYNC_RND

TOTAL_V_LINES = V_LINES_RND + TOP_MARGIN_LINES + BOTTOM_MARGIN_LINES + V_SYNC_AND_BACK_PORCH + INTERLACE + MIN_PORCH_RND

V_FIELD_RATE_ESTIMATE = 1000000 / H_PERIOD_ESTIMATE / TOTAL_V_LINES

H_PERIOD = H_PERIOD_ESTIMATE * V_FIELD_RATE_ESTIMATE / V_FIELD_RATE_REQUIRED

V_FIELD_RATE = 1000000 / H_PERIOD / TOTAL_V_LINES

IF ( INTERLACE_REQUIRED == "y") {
    V_FRAME_RATE = V_FIELD_RATE / 2
  } else {
    V_FRAME_RATE = V_FIELD_RATE
  }

TOTAL_ACTIVE_PIXELS = H_PIXELS_RND + LEFT_MARGIN_PIXELS + RIGHT_MARGIN_PIXELS

IDEAL_DUTY_CYCLE = C_PRIME - M_PRIME * H_PERIOD / 1000

H_BLANK_PIXELS = ( ROUND ( ( TOTAL_ACTIVE_PIXELS * IDEAL_DUTY_CYCLE / ( 100 - IDEAL_DUTY_CYCLE ) / ( 2 * CELL_GRAN_RND ) ) ) ) * 2 * CELL_GRAN_RND

TOTAL_PIXELS = TOTAL_ACTIVE_PIXELS + H_BLANK_PIXELS

PIXEL_FREQ = TOTAL_PIXELS / H_PERIOD * 1000000

H_FREQ = 1 / H_PERIOD


GTF Formulas For Using Horizontal Frequency

H_PIXELS_RND = ( ROUND ( H_PIXELS / CELL_GRAN_RND ) ) * CELL_GRAN_RND

IF ( INTERLACE_REQUIRED == "y") {
    V_LINES_RND = ROUND ( V_LINES / 2 )
    INTERLACE = 0.5
  } else {
    V_LINES_RND = ROUND ( V_LINES) )
    INTERLACE = 0
  }

IF ( MARGINS_REQUIRED == "y" ) {
    TOP_MARGIN_LINES = ROUND ( MARGIN_PRECENT / 100 * V_LINES_RND )
    BOTTOM_MARGIN_LINES = ROUND ( MARGIN_PRECENT / 100 * V_LINES_RND )
    LEFT_MARGIN_PIXELS = ( ROUND ( ( H_PIXELS_RND * MARGIN_PRECENT / 100 / CELL_GRAN_RND ) , 0 ) ) * CELL_GRAN_RND
    RIGHT_MARGIN_PIXELS = ( ROUND ( ( H_PIXELS_RND * MARGIN_PRECENT / 100 / CELL_GRAN_RND ) , 0 ) ) * CELL_GRAN_RND
  } else {
    TOP_MARGIN_LINES = 0
    BOTTOM_MARGIN_LINES = 0
    LEFT_MARGIN_PIXELS = 0
    RIGHT_MARGIN_PIXELS = 0
  }

H_FREQ = H_FREQ_REQUIRED

V_SYNC_AND_BACK_PORCH = ROUND ( MIN_V_SYNC_AND_BACK_PORCH * H_FREQ / 1000000 )

V_BACK_PORCH = V_SYNC_AND_BACK_PORCH - V_SYNC_RND

TOTAL_V_LINES = V_LINES_RND + TOP_MARGIN_LINES + BOTTOM_MARGIN_LINES + INTERLACE + V_SYNC_AND_BACK_PORCH + MIN_PORCH_RND

V_FIELD_RATE = H_FREQ / TOTAL_V_LINES

IF ( INTERLACE_REQUIRED == "y") {
    V_FRAME_RATE = V_FIELD_RATE / 2
  } else {
    V_FRAME_RATE = V_FIELD_RATE
  }

TOTAL_ACTIVE_PIXELS = H_PIXELS_RND + RIGHT_MARGIN_PIXELS + LEFT_MARGIN_PIXELS

IDEAL_DUTY_CYCLE = C_PRIME - ( M_PRIME / H_FREQ )

H_BLANK_PIXELS = ( ROUND ( TOTAL_ACTIVE_PIXELS * IDEAL_DUTY_CYCLE / ( 100 - IDEAL_DUTY_CYCLE ) / ( 2 * CELL_GRAN_RND ) ) ) * 2 * CELL_GRAN_RND

TOTAL_PIXELS = TOTAL_ACTIVE_PIXELS + H_BLANK_PIXELS

H_PERIOD = 1 / H_FREQ

PIXEL_FREQ = TOTAL_PIXELS * H_FREQ

GTF Formulas For Using Pixel Clock Frequency

H_PIXELS_RND = ( ROUND ( H_PIXELS / CELL_GRAN_RND ) ) * CELL_GRAN_RND

IF ( INTERLACE_REQUIRED == "y") {
    V_LINES_RND = ROUND ( V_LINES / 2 )
    INTERLACE = 0.5
  } else {
    V_LINES_RND = ROUND ( V_LINES) )
    INTERLACE = 0
  }

PIXEL_FREQ = PIXEL_FREQ_REQUIRED

IF ( MARGINS_REQUIRED == "y" ) {
    TOP_MARGIN_LINES = ROUND ( MARGIN_PRECENT / 100 * V_LINES_RND )
    BOTTOM_MARGIN_LINES = ROUND ( MARGIN_PRECENT / 100 * V_LINES_RND )
    LEFT_MARGIN_PIXELS = ( ROUND ( ( H_PIXELS_RND * MARGIN_PRECENT / 100 / CELL_GRAN_RND ) , 0 ) ) * CELL_GRAN_RND
    RIGHT_MARGIN_PIXELS = ( ROUND ( ( H_PIXELS_RND * MARGIN_PRECENT / 100 / CELL_GRAN_RND ) , 0 ) ) * CELL_GRAN_RND
  } else {
    TOP_MARGIN_LINES = 0
    BOTTOM_MARGIN_LINES = 0
    LEFT_MARGIN_PIXELS = 0
    RIGHT_MARGIN_PIXELS = 0
  }

TOTAL_ACTIVE_PIXELS = H_PIXELS_RND + RIGHT_MARGIN_PIXELS + LEFT_MARGIN_PIXELS

IDEAL_H_PERIOD = ( ( C_PRIME - 100 ) + ( SQRT ( ( ( 100 - C_PRIME ) ^ 2 ) + ( 0.4 * M_PRIME * ( TOTAL_ACTIVE_PIXELS + RIGHT_MARGIN_PIXELS + LEFT_MARGIN_PIXELS ) / PIXEL_FREQ / 1000000 ) ) ) ) / 2 / M_PRIME * 1000

IDEAL_DUTY_CYCLE = C_PRIME - ( M_PRIME * IDEAL_H_PERIOD / 1000 )

H_BLANK_PIXELS = ( ROUND ( TOTAL_ACTIVE_PIXELS * IDEAL_DUTY_CYCLE / ( 100 - IDEAL_DUTY_CYCLE ) / ( 2 * CELL_GRAN_RND ) ) ) * 2 * CELL_GRAN_RND

TOTAL_PIXELS = TOTAL_ACTIVE_PIXELS + H_BLANK_PIXELS

H_FREQ = PIXEL_FREQ / TOTAL_PIXELS

H_PERIOD = 1 / H_FREQ

V_SYNC_AND_BACK_PORCH = ROUND ( MIN_V_SYNC_AND_BACK_PORCH * H_FREQ / 1000000 )

V_BACK_PORCH = V_SYNC_AND_BACK_PORCH - V_SYNC_RND

TOTAL_V_LINES = V_LINES_RND + TOP_MARGIN_LINES + BOTTOM_MARGIN_LINES + INTERLACE + V_SYNC_AND_BACK_PORCH + MIN_PORCH_RND

V_FIELD_RATE = H_FREQ / TOTAL_V_LINES

IF ( INTERLACE_REQUIRED == "y") {
    V_FRAME_RATE = V_FIELD_RATE / 2
  } else {
    V_FRAME_RATE = V_FIELD_RATE
  }

Note: The "round()" function here rounds to the nearest integer (it doesn't round down or round up).

Cheers,

Brendan