视频配置
11.1 概述
Zeal Video Board 提供了一些寄存器,用于获取当前状态或配置视频输出。这些寄存器包括设置当前视频模式、滚动、扫描束位置甚至当前中断状态。
该配置区域在 I/O 总线上的基地址为 0x90,它永远不会被映射出去,因此随时可用。
11.2 虚拟扫描束
渲染
Zeal Video Board 实现了 VGA 协议以生成视频信号。该信号可以想象为一条虚拟扫描束,从屏幕左上角扫描到右下角。渲染分辨率固定为 640×480 像素,与当前模式无关,像素时钟频率为 25 MHz。
尽管可见区域为 640×480,但虚拟扫描束实际上会遍历更大的区域。每条水平线包含一个额外的 160 像素宽的不可见区域,称为水平消隐(或 H-blank)。
同样,在渲染完 480 条可见线之后,扫描束会继续通过 42 条额外的不可见线,称为垂直消隐(或 V-blank)。
因此,虚拟扫描束的坐标范围在水平方向为 0 到 799,垂直方向为 0 到 524,包括可见区域和消隐区域。
VGA 完整渲染区域
根据这些信息,可以计算出扫描束在这些消隐间隔中停留的时间。
水平消隐期由 160 个像素组成,在 25 MHz 的像素时钟下(即每个像素需要 40 ns),其持续时间为:
\( t = 160 \text{ px} \times 40\,\text{ns} = 6400\,\text{ns} = 6.4\,\mu\text{s} \)
垂直消隐期由 42 条线组成,每条线包含 800 个像素(640 可见 + 160 消隐)。因此:
\( t = 42 \text{ lines} \times 800 \text{ px} \times 40\,\text{ns} = 1344000\text{ns} = 1.344\,\text{ms} \)
理论上,标准 640×480 VGA 分辨率需要以 25.125MHz 的像素时钟生成 525 条线,但 Zeal Video Board 的主时钟为 50MHz,因此使用 25MHz 的像素时钟。为补偿这一差异,仅生成 524 条线。
320×240 模式
320×240 模式是纯虚拟的,其行为类似于一个 2 倍放大到左上象限的 640×480 显示。换句话说,320×240 空间中的每个像素在屏幕上渲染为一个 2×2 的像素块。
VGA 信号保持不变,仍然输出 640×480 的图像。扫描束位置值不受影响,仅修改渲染逻辑以在水平和垂直方向上对每个像素进行加倍。
获取位置
虚拟扫描束位置由两个 16 位值表示,一个用于垂直位置,一个用于水平位置。因此,提供了四个寄存器来读取这些值:V_CURSOR_LOW 和 V_CURSOR_HIGH 用于垂直位置,H_CURSOR_LOW 和 H_CURSOR_HIGH 用于水平位置。有关地址,请参阅寄存器汇总部分。
与 ZVB 上的其他 16 位值一样,必须先读取低字节才能锁存高字节寄存器中的高位字节。
另一种快速检查当前是否处于 H-blank 或 V-blank 间隔的方法是读取 VIDEO_STATUS 寄存器,该寄存器专门提供了两个位用于此目的。借助该寄存器,与 ZVB 连接的 CPU 无需读取 16 位值并手动进行比较。
11.3 屏幕滚动
如瓦片地图章节所述,ZVB 具有两个瓦片地图层:
layer0 和 layer1。每层在内存中存储 80×40 个瓦片。在固定的 16×16 像素瓦片大小下,每层的虚拟屏幕分辨率为 1280×640 像素。
然而,如上所述,实际视频输出分辨率固定为 640×480 像素。这意味着在任何给定时间,只有部分瓦片地图在屏幕上可见。
这就是滚动的作用。滚动允许您在 X 和 Y 方向上移动瓦片地图的可见部分,从而有效控制在 640×480 视口内显示的内容。在其他模式下,滚动也可能定义渲染开始的起始位置。滚动使用模运算,因此超出瓦片地图范围的值会自动回绕,产生连续滚动效果。
Layer0 和 layer1 可以独立滚动,精度为像素级。例如,可以通过让 layer0(背景)比 layer1(前景)滚动更快来实现深度或视差效果:
8 位 640×480 模式下的滚动示例
同样,320×240 模式是纯虚拟的,因此原理相同,唯一的区别是屏幕视图更小。滚动值不受影响,X 和 Y 的范围仍然分别为 $[0,1279]$ 和 $[0,799]$。
在图形模式下,提供了八个寄存器用于获取或设置当前 X 和 Y 方向的滚动值:
同样,读取最低字节时寄存器会被锁存,写入最高字节时写入的值才会生效。
在文本模式下,上述寄存器将被忽略且不会影响输出,因为滚动由文本控制器的 SCROLL_X 和 SCROLL_Y 寄存器负责。
Layer1 的滚动值在 4 位图形模式下将被忽略,因为该层用于 layer0 的瓦片属性。这些滚动寄存器仅在瓦片图形模式下影响视频输出。在其他任何视频模式下,硬件将忽略它们。
11.4 禁用屏幕输出
在某些情况下,禁用屏幕输出以防止视觉伪影非常有用,例如在加载新字形集或更新瓦片地图时。这些操作可能会暂时损坏屏幕图像,尤其是当它们耗时超过一帧时。
为此,VIDEO_STATUS 寄存器包含一个可读写的 ENABLE 位。当该位被清除时,屏幕输出被禁用,当前帧及后续帧将渲染黑色像素。当该位再次被设置时,正常视频输出将使用视频存储器的当前内容恢复。
为避免可见的闪烁,建议尽可能在垂直消隐期(V-blank)期间禁用屏幕输出。
11.5 寄存器总览
11.6 寄存器
V_CURSOR_LOW (0x00)
垂直光标最低字节(先读取此寄存器以锁存完整的11位值)
Reset
V_CURSOR_LSB
垂直光标位置的低8位。读取此寄存器将高位锁存到内部影子寄存器中,以实现原子性的垂直光标读取。 (RO)
V_CURSOR_HIGH (0x01)
垂直光标最高字节(在V_CURSOR_LOW之后读取以获取完整的11位值)
Reset
V_CURSOR[10:8]
锁存的垂直光标位置的高3位。必须在读取`V_CURSOR_LOW`之后进行。 (RO)
H_CURSOR_LOW (0x02)
水平光标最低字节(先读取此寄存器以锁存完整的11位值)
Reset
H_CURSOR_LSB
水平光标位置的低8位。读取此寄存器将高位锁存到内部影子寄存器中,以实现原子性的水平光标读取。 (RO)
H_CURSOR_HIGH (0x03)
水平光标最高字节(在H_CURSOR_LOW之后读取以获取完整的11位值)
Reset
H_CURSOR[10:8]
锁存的水平光标位置的高3位。必须在读取`H_CURSOR_LOW`之后进行。 (RO)
VIDEO_MODE (0x0C)
选择当前视频模式
Reset
MODE
选择预定义的视频模式,请查看上表了解所有可用选项 (RW)
VIDEO_STATUS (0x0D)
当前视频系统状态
Reset
ENABLE
置位以启用视频输出。写入1将渲染黑屏。 (RW)
VBLANK
垂直消隐状态(激活时为1) (RO)
HBLANK
水平消隐状态(激活时为1) (RO)
VIDEO_INT_STATUS (0x0E)
中断状态位
Reset
VBLANK_INT
表示有挂起的垂直消隐中断 (RO)
VIDEO_INT_CLEAR (0x0F)
清除视频中断标志
Reset
CLR_VBLANK
写入1以清除垂直消隐中断 (WO)