Thursday 5 October 2017

Some actual working COP444 code.

In the end after some tinkering I decided on the following for video generation.

Page 0 of RAM, from 0-14 is used for the x coordinate which can be zero (off) or 1-7. Page 1 of RAM from 0-14 is used for the y coordinate which is from 8-15 representing row 0-5 on the LEDs, the left 7 segment and the right 7 segment.

If a Y coordinate in page 1 is 14 or 15 (the 7 segment displays) then the digit is taken from the equivalent row in page 2.

The code is shown below (minus the data tables). The handy thing about the datatables is if my assumptions are wrong about how the wiring works, all I have to do is change the datatables.

I originally thought that the layout had to be sensible (e.g. the 7 LEDs being G2 G1 G0 D3 D2 D1 D0 in order) but with this system it doesn't matter. Though it probably is still that way.

This routine doesn't quite fit in a page with the three tables (column bit, row bit, 7 segment lookup) unfortunately and I can't make it fit, it's about 8 bytes too long.

One perhaps rather optimistic question ; does anyone know if the COP444's IT instruction resets the timeout flag. IT is 'stop processor till timeout' - a COP444 has a 10 bit internal timer but it isn't clear whether this resets the timeout overflow flag or not. SKT definitely does, but of course skips ... because the timer has overflowed. If IT does reset the flag I can reduce the IT/SKT/NOP sequence to just IT.

This synchronises the timing ;  one LED is displayed every timeout, this routine takes the same amount of time (16 timer cycles, a frame rate of about 16Hz) when it is called, irrespective of how many LEDs are displayed (this allows a maximum of 15 or 13 + 2 score digits)

I do wonder if this will be a bit like Microvision Space Invaders. That was on a TMS1100 , a very similar processor with 2k of ROM space. I was a bit panicky about space when I started it and wrote tight but unclear code (the code below has two seperately overlapping loops), but I ended up with half the ROM space unused.

We shall see. I should be able to write tighter code than the original developers if for no other reason than I have much better development tools - I can reassemble in a second, I have a proper single stepping debugger. I don't doubt the original developers were awesome programmers.

I suspect the original devs had a much slower turnaround, which means you program more defensively. A defensive simpler version of this is about half as long again.

It's amazing what you do in retrospect. When I was a kid I had a Sharp MZ80K, which had BASIC loaded from tape. If you crashed it, you reloaded the tape which took 3 or 4 minutes. I hacked the BASIC to add a pile of commands including a complete Z80 assembler that worked like the one in the BBC Micro. Still not quite sure how :)

__Repaint:
    lbi     1,15                            ; point to first one plus 1, also set B upper to one.

RPDoneY:
    ld      1                               ; switch back to zero.

    it                                      ; delay for brightness
    skt
    nop

    cba                                     ; get the pointer.
    aisc    15                              ; effectively subtract 1 and skip on not borrow
    ret                                     ; borrowed, so return.

RPContinue:
    cab                                     ; save new address in B.
    xad     RowTemp                         ; save it in RowTemp

    clra                                    ; A:M now points to the table in the first 16 bytes.
    lqid                                    ; read the 8 bit pattern into Q.
    skmbz   3                               ; if M(B) is in range 0-7 it is 'X', so skip.
    jp      RPDoneY                         ; otherwise we have done Y, so complete.

    ld      1                               ; point to Y
    smb     3                               ; set the mandatory bit 3.

    ld      3                               ; read Y this value is 8-15. Execute if 14,15. Set Bu to 2
    aisc    2                               ; will skip if 14,15
    jp      RPNotSevenSegment 

    clra                                    ; read from seven segment table.
    aisc    15
    lqid

RPNotSevenSegment:
    ldd     HoloDisplay                     ; read the holo display location
    aisc    15                              ; set carry if non zero
    nop

    lbi     RPWork1                         ; point to useable location for CQMA and set to page 1.
    cqma                                    ; copy X 8 bit data to MA

    smb     3                               ; set bit 3 if carry set.
    skc
    rmb     3                               ; otherwise, clear it.

    omg                                     ; output high 3 bits and G3 bit set here.
    cab                                     ; output low 4 bits 
    obd

    ldd     RowTemp                         ; load rowtemp, Bu is still 1
    cab
    jp      RPContinue                      ; and do the Y part

No comments:

Post a Comment