Signetics 2650 & 2636 编程/对象完成同步
PVI 有四个主对象,可以重新编程以在屏幕上显示。此处显示的屏幕截图,由 本教程的程序 创建,仅使用对象 1。主对象是白色矩形,第一个副本是黄色三角形,第二个副本是绿色三角形。每个事件的形状、颜色、大小和位置必须在每一帧上编程。编程的时机必须 与 VRST 同步,这在另一个教程中已经介绍过,还必须与对象视频显示的完成同步。
当 PVI 输出对象的最后一行时,它会生成一个中断并设置寄存器 $1FCA 中的相应位,在本程序中称为 objectstatus。
字节 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1FCA |
|
|
处理中断将在后面的章节中讨论,由于处理器没有其他工作要做,因此该程序将在一个循环中轮询该寄存器,等待相应位被设置。这由子程序 WaitObj 完成
:;================================================================= :;subroutine - wait for object to finish :; enter with r1=mask for bit to be tested: :; obj1=$08, obj2=$04, obj3=$02, obj4=$01 :WaitObj: 00B7 0C1FCA : loda,r0 objectstatus 00BA 41 : andz r1 00BB 187A : bctr,eq waitobj 00BD 17 : retc,un
程序以 r1 = $08 调用该子程序,该值用作掩码来测试 objectstatus 寄存器 $1FCA 中的特定位。如果相应的对象完成位没有被设置,则 andz 指令的结果将为零,因此程序将循环回并再次尝试,直到该位被设置,andz 操作产生非零结果并且子程序退出。
一旦 VRST 变为高电平,就会设置对象 1 的初始状态。这由子程序 Object1A 完成,该子程序设置其形状、大小、颜色(一个小白色矩形)及其水平和垂直坐标。它还设置第一个副本的水平坐标和垂直偏移量。
然后,程序等待主对象显示完成,此时子程序 Object1B 会设置新的形状、大小和颜色(黄色三角形)。它还设置第二个副本的垂直偏移量。
最后,程序等待第一个副本显示完成,此时子程序 Object1C 会设置新的形状、大小、颜色(绿色三角形)和第二个副本的水平坐标。它还将第三个副本的垂直偏移量设置为一个较大的值,以确保它不在屏幕上并且没有显示。
然后,程序循环回并等待 VRST 信号的开始。
bsta,un Vsync0 ; make sure VRST hasn't started endless: bsta,un Vsync1 ; wait for VRST to start bsta,un Object1A ; set initial state of object 1 bsta,un Vsync0 ; wait for VRST to end (SEE BELOW) lodi,r1 $08 bsta,un WaitObj ; wait for primary object 1 to complete bsta,un Object1B ; set first duplicate of object 1 lodi,r1 $08 bsta,un WaitObj ; wait for first duplicate to complete bsta,un Object1C ; set second duplicate of object 1: bctr,un endless
objectstatus 寄存器中的 对象完成 位由 PVI 重置,无论是在读取寄存器时还是在 VRST 的下降沿时。等待 VRST 结束 的代码行是为了确保在开始处理新帧之前这些位被清除。如果将该行修补掉,您将看到黄色对象不再显示。
发生的情况是,我们没有测试第二個副本是否在帧结束时完成,因此在下一帧中,主对象会在 VRST 期间被错误地检测为完成。如果在循环结束时插入对对象 1 完成的测试,您将看到问题已解决。
但是,在循环开始时等待 VRST 的下降沿是一个更简洁的解决方案
- 在更复杂的程序中,很可能会有多个副本在帧结束时设置状态位。
- 在循环的第一次传递中,我们不能确定状态位的条件。
在本例中,没有使用数据表来定义三个对象的形状,而是以算法方式创建它们。
创建矩形,子程序 Object1A,是将 $FF 写入形状数组的全部十个字节的简单情况。
三角形是通过将 FF 写入底行,然后是 7F、3F 等来创建的。
lodi,r3 10 lodi,r0 $FF ppsl withcarry ; include carry in rotate instructions loop1B: stra,r0 shape1,r3- ; triangle shape cpsl carrybit rrr,r0 ; shift right with 0 from the carry bit brnr,r3 loop1B
这段代码片段首先设置程序状态字中的 withcarry 位。现在,当执行旋转指令时,它将进位位包含在循环中并作为九位旋转操作。通过在每次旋转之前清除进位位,它的行为更像一个移位寄存器,将 1 移出并移入 0。
有时,可视化程序花费多少时间仅仅等待对象的完成非常有用。这可以通过在子程序 WaitObj 执行时更改屏幕颜色来轻松实现
WaitObj: lodi,r0 $19 ; blue stra,r0 backgnd wo2 loda,r0 ocomplete andz r1 bctr,eq wo2 lodi,r0 $00 ; black stra,r0 backgnd retc,un
在本文的屏幕截图中,通常为黑色的屏幕在 WaitObj 期间变为蓝色。在本例中,我们通常有大量时间可以浪费,但也有一些动画使一些蓝色线条几乎消失。仍然有很多编程要做,这展示了在帧的哪些地方有时间进行编程。