User Tools

Site Tools


lcd_controller

LCD controller

The gamepad provides simple framebuffer-based display hardware.

Register map:

Address Desc.
0xF0009400 Horizontal timing control
0xF0009404 Vertical timing control
0xF0009408 ??
0xF000940C ??
0xF0009410 Horizontal start of display
0xF0009414 Vertical start of display
0xF0009418 Horizontal end of display
0xF000941C Vertical end of display
0xF0009420 ?? video-out X offset?
0xF0009424 ?? video-out width?
0xF0009428 ?? video-out Y offset?
0xF000942C ?? video-out height?
0xF0009430 ??
0xF0009434 ??
0xF0009460 Framebuffer X offset
0xF0009464 Framebuffer width
0xF0009468 Framebuffer Y offset
0xF000946C Framebuffer height
0xF0009470 Framebuffer stride
0xF0009474 Framebuffer address
0xF0009478 ??
0xF0009480 Display control
0xF0009484 ??
0xF0009488 ??
0xF0009490 ??
0xF0009494 ??
0xF00094B0 Pixel format
0xF00094B4 ??
0xF00094B8 ??
0xF00094BC ??
0xF00094C0 ??
0xF00094C4 ??
0xF00094C8 VCount - current vertical position
0xF00094D0+(N*4) YUV→RGB matrix (N=0..8)
0xF00094F4 ??
0xF00094F8 Camera sync
0xF00094FC Counter of sorts
0xF0009500 Palette address
0xF0009504 Palette data
0xF0009508 VCount IRQ position 1
0xF000950C VCount IRQ position 2
0xF0009510 VCount IRQ position 3
0xF0009514 VCount IRQ position 4
0xF0009600+(N*4) Color correction LUT entry N (N=0..31)
0xF0009684 Color correction mask
0xF0009700 ??
0xF0009704 ??
0xF0009708 ??

Related IRQs:

IRQ Desc.
0x12 ??
0x15 Display start (VBlank end)
0x16 VBlank
0x1E VCount match

The LCD pixel clock is, by default, 32 MHz. It is sourced from register 0xF0000034.

Framebuffer registers

0xF0009400

Controls horizontal timing.

Bits Desc.
0-11 Total number of horizontal pixels
16-27 ???

The number of horizontal pixels defines how long each line lasts. Should be set to 1047 for 60FPS output.

Bits 16-27 affect video timings in weird, subtle ways.

0xF0009404

Controls vertical timing.

Bits Desc.
0-10 Total number of vertical lines
16-24 ???

The number of vertical lines defines how long each frame lasts. Should be set to 510 for 60FPS output.

Bits 16-24 cause VBlank to last a little longer when set to a value lower than 0x100.

0xF0009410

Horizontal start of display.

Should be set to 96 to match LCD output.

This register is 11 bits wide.

0xF0009414

Vertical start of display.

Should be set to 8 to match LCD output. TODO: this register works weirdly

This register is 13 bits wide.

0xF0009418

Horizontal end of display.

Should be set to 950 to match LCD output. Smaller values result in garbage being displayed after the end of the display area. TODO: some values behave weirdly

This register is 11 bits wide.

0xF000941C

Vertical end of display.

Should be set to 488 to match LCD output. Smaller values result in a longer VBlank interval at the cost of some vertical resolution (the last line to be displayed will be repeated across the rest of the screen).

This register is 9 bits wide.

0xF0009460

X offset, specifies where the framebuffer will start on the screen.

0xF0009464

Framebuffer width in pixels.

0xF0009468

Y offset, specifies where the framebuffer will start on the screen.

0xF000946C

Framebuffer height in pixels.

0xF0009470

Framebuffer stride. It is in bytes, except for pixel formats 2 and 3, where it is in 16-bit units.

0xF0009474

Framebuffer address. This register is 22 bits wide, thus the framebuffer may only be within main RAM.

0xF0009480

Display control register, not yet known how this works.

Bits Desc.
0 ?? breaks display
1 Must be set for display to work. Presumably enables overlay.
2 ?? causes weird effects
3 ??
4 Must be set for display to work. Presumably general display enable.

0xF00094B0

Pixel format register.

Bits Desc.
0-1 Pixel format
2 ??
3 ??
7 Color mode; 0=RGB, 1=YUV
8 ?? collapses overlay to 1px vertical line
9 ??
10 ??
16-23 ?? (set to 0xFF)

The following pixel formats are supported:

Value Desc.
0 8-bit paletted
1 4-bit paletted (LSb first)
2 16-bit ARGB1555
3 16-bit RGB565

For the paletted formats, see the palette registers.

Bit 7 causes color components to be interpreted as YUV, with the following mapping: R=V, G=Y, B=U. It seems the handling is different based on the pixel format? Notably, in YUV mode, pixel formats 0 and 1 seem to entirely ignore the palette and instead somehow directly convert indices to color components.

In YUV mode, the matrix at 0xF00094D0..0xF00094F0 is used to convert the YUV components to RGB.

0xF00094C8

Current vertical position.

0xF00094D0+(N*4)

YUV→RGB matrix.

Register Description Default value
0xF00094D0 Y → G factor 0x0A5 = 74
0xF00094D4 U → G factor 0x04E = -14
0xF00094D8 V → G factor 0x062 = -34
0xF00094DC Y → B factor 0x0A5 = 74
0xF00094E0 U → B factor 0x122 = 136
0xF00094E4 V → B factor 0x000 = 0
0xF00094E8 Y → R factor 0x0A5 = 74
0xF00094EC U → R factor 0x000 = 0
0xF00094F0 V → R factor 0x0B9 = 114

The factors work in a bit of a weird way.

Bits Desc.
0-5 Amount
6   Sign
7-8 Multiplier; 0=1, 1=2, 2/3=4

The sign bit makes the value negative, but it's not two's complement. Instead: 0x3F = 63, 0x7F = -63.

The multiplier allows to increase the final value. For example, values 0x30, 0x98, 0x10C and 0x18C are equivalent.

Note: YUV mode produces darker colors, even with maximum factor values. One can use the color correction registers at 0xF0009600 to compensate for this.

0xF00094F8

Camera sync.

Bits Desc.
0-10 Vertical position
15 ???

This register allows to synchronize camera output to the display. The camera frame IRQ fires 8 scanlines after the specified position.

This register can be disabled by setting it to a value equal to or greater than the display's total vertical span (as set in 0xF0009404). In this case, the camera outputs at its 'natural' framerate without synchronizing to the display, and the camera frame IRQ fires whenever a frame is finished.

0xF00094FC

Counter of sorts. Seems to be based on the count-up timer.

This register is 27 bits wide.

Palette registers

0xF0009500

Palette address. Specifies which palette entry will be accessed by 0xF0009504.

0xF0009504

Palette data.

Reading from this register returns the palette entry pointed by the address register.

Writing to this register will write to the palette entry pointed by the address register, and increment the address register.

The color format is ARGB8888. The MSB of color values seems to actually function as an alpha value, which suggests that the LCD controller may be able to blend the framebuffer with something else, presumably output from the video decoder.

VCount IRQ registers

0xF0009508 to 0xF0009514

These registers allow to trigger IRQ 0x1E based on the current vertical position (VCount).

When VCount matches any of these registers, IRQ 0x1E is triggered. The multiple registers allow to split the frame time in smaller intervals.

These registers are 11 bits wide. They can be 'disabled' by setting them to a value outside of the configured vertical range.

The stock firmware uses IRQ 0x1E to perform input polling and audio sync. The settings it uses divide each frame into 3 equal parts, effectively firing IRQ 0x1E at a 180 Hz interval.

Color correction registers

These registers allow to correct output color levels. They are presumably used to do gamma correction.

Individual RGB components are simply corrected based on a lookup table with 33 entries.

0xF0009600+(N*4)

These registers are the correction LUT.

Presumably, interpolation is used to make up for the limited precision of this LUT, ie. values 0..7 would be mapped to entries 0/1, values 8..15 would be mapped to entries 1/2, and so on.

These registers are 9 bits wide.

0xF0009684

Color correction mask. Enables color correction for individual channels.

Bits Desc.
0 Red
1 Blue
2 Green

0 means to output the corresponding channel as-is, 1 means to correct the corresponding channel using the LUT.

Timing? registers

0xF0009704

Unknown. Affects the way video sync/data is sent to the LCD. Has no effect on video timings.

Display modes

The stock firmware has settings for three different video modes.

Setting Mode 0 Mode 1 Mode 2
Mode 854×480 60Hz 854×480 50Hz 640×480 60Hz
X offset 96 202 96
Width 854 854? 640?
Y offset 8 8 8
Height 480 480? 480?
0xF0009400 0x03B00417 0x01AC04EB 0x03B00417
0xF0009404 0x01B201FE 0x01BD01FD 0x01B201FE
0xF0009408 32 32 32
0xF000940C 8 8 8
0xF0009410 96 202 96
0xF0009414 8 8 8
0xF0009418 950 1056 950
0xF000941C 488 488 488
0xF0009420 96 202 203
0xF0009424 854 854 640
0xF0009428 8 8 8
0xF0009480 0x2 0x2 0xA
0xF0009508 0x8 0x8 0x8
0xF000950C 0xB2 0xB2 0xB2
0xF0009510 0x15C 0x15C 0x15C
0xF0009514 0x7FF 0x7FF 0x7FF
lcd_controller.txt · Last modified: 2025/05/14 21:22 by arisotura

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki