Signetics 2650 & 2636 programming/Sync to Object completion

Tutorial — Sync to object completion

edit
 

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

edit

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.

Byte 7 6 5 4 3 2 1 0
1FCA
Object/grid collision
1 2 3 4
Object display complete
1 2 3 4

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:

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

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

edit

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

edit

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

edit
 
Changing the screen colour to observe time spent waiting for object completion

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.