Signetics 2650 & 2636 programming/Sync to Object completion

Tutorial — Sync to object completion
The PVI has four primary objects that can be reprogrammed to be displayed further down the screen. The screenshot shown here, created by this tutorial's program, solely uses object 1. The primary object is the white rectangle, the first duplicate the yellow triangle, and the second duplicate is the green triangle. The shape, colour, size and position of each occurrence have to be programmed on every frame. Timing of the programming has to be syncronized to VRST, which was covered in another tutorial, and also to the completion of the display of the video of the object.

Detecting completion status
When the PVI outputs the last line of an object it generates an interrupt and sets the appropriate bit in register $1FCA which is named objectstatus in this program.

Handling interrupts will be discussed in a later section, and as there is nothing else for the processor to be doing, this program is going to sit in a loop polling the register waiting for the appropriate bit to be set. That is done by subroutine WaitObj:

:;    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

The program calls this subroutine with r1 = $08 which is used as a mask to test a specific bit in the objectstatus register $1FCA. If the corresponding object complete bit is not set, the result of the andz instruction will be zero, so the program loops back and tries again until the bit is set, the andz operation yields a non-zero result and the subroutine is exited.

Programming the primary object and its duplicates
As soon as VRST goes high the initial state of object 1 is set up. That is done by subroutine Object1A which sets its shape, size, colour (a small white rectangle) and its horizontal and vertical coordinates. It also sets the horizontal coordinate and vertical offset for the first duplicate.

The program then waits for the display of the primary object to complete, at which time subroutine Object1B sets a new shape, size and colour (a yellow triangle). It also sets the vertical offset for the second duplicate.

Finally the program waits for the display of the first duplicate to complete, at which time subroutine Object1C sets a new shape, size, colour (a green triangle) and horizontal coordinate for the second duplicate. It also sets the vertical offset for the third duplicate to a large value to be sure it is off the screen and not displayed.

The program then loops back and waits for the start of the VRST signal. 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 The object complete bits in the objectstatus register are reset by the PVI either when the register is read, or on the trailing edge of VRST. The line of code that waits for VRST to end is there to make sure these bits are clear before we begin processing a new frame. If that line is patched out, you will see that the yellow object is no longer displayed.

What is happening is that we don't test for the second duplicate to complete at the end of the frame, so in the next frame the primary object is mistakenly detected as complete during the VRST period. If a test for object 1 to complete is inserted at the end of the loop you will see that the problem is fixed.

However, waiting for the trailing edge of VRST at the start of the loop is a cleaner solution:
 * In more complex programs there are likely to be multiple duplicates setting status bits at the end of the frame.
 * On the first pass of the loop, we can't be certain of the condition of the status bits.

Creating shapes, WithCarry, and Rotate
Rather than using data tables to define the shape of the three objects in this example, they are created algorithmically.

Creating the rectangle, subroutine Object1A, is a straightforward case of writing $FF to all ten bytes of the shape array.

The triangles are created by writing FF to the bottom row, then 7F, 3F etc.        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 This snippet of code starts off by setting the withcarry bit in the program status word. Now, when a rotate instruction is executed, it includes the carry bit in the loop and operates as a nine-bit rotate. By clearing the carry bit before every rotate, it behaves more like a shift register, shifting the 1s out and a 0 in.

Timing Visualization
Sometimes it is useful to get a visualization of how much time the program is spending simply waiting for completion of an object. This can be achieved quite simply by changing the screen colour while the subroutine WaitObj is executing: 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 In the screenshot here, the normally black screen is turned blue while during WaitObj. In this case we generally have lots of time to spare, but there are animations that make some of the blue lines all but disappear. There is still lots of programming to do, and this shows where in the frame there is time to do it.