Memory/Trace Using Interrupt Mode 2

Pub Details

Date

Pages

Having a Z80 processor in the Timex 2068 gives the user a powerful suite of instructions to use. One of the most useful is IM2. This instruction allows the user to divert interrupts to their own routines to do almost anything imaginable.

In normal operation the processing is interrupted 60 times a second so the CPU can update the screen and read the keyboard. The CPU then returns to the next instruction it was to have executed if an interrupt had not occured. IM2 allows us to assume control and execute some instructions before returning from the interrupt.

The problem with using IM2 in the 2068 is that the Z80 assumes that an interrupting device will place one byte of data on the data bus. It then combines this byte with the I register to form an address. At this address it expects to find a second value, the routine address to which control is to be passed.

In the Spectrum this works very nicely, as the data bus always contains 255 (FFh), due to the way the hardware was designed. A person wanting to use IM2 can always count on the value being placed in the I register will be concatonated with FF to form an address. With the 2068, at the time of an interrupt, the data bus will have any value from 0 to 255. This makes it impossible to predict what will be combined with the I registers.

In the Sept/Oct 1985 Sinc-Linc (from the Toronto Timex-Sinclair Users Club) Bob Mitchell suggested that by setting aside 256 bytes, for a vector table, IM2 could be effectively used. By loading a vector table with the same byte, no matter what value was found on the data bus, it would find the proper routine address.

With this thought in mind, I dug out some old code I had been working on to provide a constant display of how much memory was available and a trace of basic program line numbers. I set up the routine to load a vector table and initialize IM2 upon entry. The routine will start by displaying the amount of free space available. By pressing enter and K, at the same time, the routine will switch to display line numbers as your Basic program runs. A delay has been built in so the line numbers can be read, you will notice a slowing down of your program’s execution. By pressing enter and J, at the same time, the routine will return to displaying free space. To stop the routine completely press enter and L at the same time. To start the routine or restart after pressing enter and L use RANDOMIZE USR 65281.

I have provided a Basic program to load the code. Type it in and save it before running. Once keyed in, and saved, run the program to poke the code into memory. Save the code using SAVE "memtrace" CODE 65021,464. To start the routine use RANDOMIZE USR 65281. Any keying errors may cause your machine to crash so double check the data statements very carefully.

I hope that this routine gives you a good example of how IM2 can be used and spurs you on to develop some good routines to share here.

BASIC Listing — TS2068 Program: MEMTRACE

10 CLEAR 65020
20 FOR C=65021 TO 65023
30 READ X: POKE C,X
40 NEXT C
50 FOR C=65281 TO 65484
60 READ X: POKE C,X
70 NEXT C
80 STOP
90 DATA 195,28,255
100 DATA 197,213,229,245,33,0,254,6,0,54,253,35,16,251,54,253,62,254,237,71
110 DATA 241,225,209,193,237,94,201,255,243,197,213,229,245,1,254,191,237,120,254,28
120 DATA 40,28,254,26,40,10,254,22,32,11,175,50,75,255,24,5,62,1,50,75
130 DATA 255,205,78,255,241,225,209,193,251,201,237,86,24,246,0,191,80,237,91,101
140 DATA 92,33,191,80,34,76,255,58,75,255,254,1,204,187,255,32,5,42,69,92
150 DATA 24,5,42,178,92,237,82,1,240,216,205,139,255,1,24,252,205,139,255,1
160 DATA 156,255,205,139,255,1,246,255,205,139,255,1,255,255,205,139,255,201,175,9
170 DATA 60,56,252,237,66,61,198,48,229,205,165,255,33,76,255,52,42,76,255,205
180 DATA 178,255,225,201,237,75,54,92,38,0,111,41,41,41,9,235,201,6,8,26
190 DATA 119,36,19,16,250,201,6,10,197,1,244,1,33,0,0,17,0,0,237
200 DATA 176,193,16,241,201

Assembly Listing

INTERRUPT MODE 2

CLEAR 65020
RAND USER 65281 TO START

FDFD-FDFF   65021-65023  JUMP ADDRESS
FE00-FF00   65024-65280  VECTORS 'FD'
FF01-FFFF   65281-65635  AVAILABLE

65021    C31CFF          JP      L1        JUMP TO START OF ROUTINE
65024                    REM               SPACE FOR VECTOR TABLE
65281                    DEFS    65281-ORG
65281    C5              L250   PUSH    BC        SAVE
65282    D5                     PUSH    DE        REGISTERS
65283    E5                     PUSH    HL
65284    F5                     PUSH    AF
65285    2100FE                 LD      HL,65024  LOAD START OF VECTOR TAB
65288    0600                   LD      B,00      SET REG. B FOR LOOP
65290    36FD            L251   LD      (HL),253  LOAD DATA
65292    23                     INC     HL        POINT TO NEXT BYTE
65293    10FB                   DJNZ    L251      CONTINUE LOOP
65295    36FD                   LD      (HL),253  LOAD LAST BYTE
65297    3EFE                   LD      A,254     LOAD VALUE FOR INDEX REG
65299    ED47                   LD      I,A       LOAD INDEX REG FOR 65024
65301    F1                     POP     AF
65303    E1                     POP     HL        RESTORE
65303    D1                     POP     DE        RESTORE
65304    C1                     POP     BC        REGISTERS
65305    ED5E                   IM      2         TURN ON INTERRUPT MODE 2
65307    C9                     RET
65308    FF              L1     RST     56
65309    F3                     DI                DISABLE INTERRUPTS
65310    C5                     PUSH    BC        SAVE
65311    D5                     PUSH    DE
65312    E5                     PUSH    HL        REGISTERS
65313    F5                     PUSH    AF
65314    01FEBF                 LD      BC,49150  CHECK KEYBOARD
65317    ED78                   IN      A,(C)     READ KEY(S) PRESSED
65319    FE1C                   CP      28        ENTER AND 'L'
65321    281C                   JR      Z,L5      YES, TURN OFF ROUTINE
65323    FE1A                   CP      26        ENTER AND 'K'
65325    280A                   JR      Z,L2      YES, TURN ON TRACE
65327    FE16                   CP      22        ENTER AND 'J'
65329    200B                   JR      NZ,L3     NO, CHECK PRIOR SETTING
65331    AF                     XOR     A         YES, TURN TRACE
65332    324BFF                 LD      (L6),A    OFF
65335    1805                   JR      L3        GO SHOW MEMORY LEFT
65337    3E01            L2     LD      A,01      SET SWITCH FOR TRACE
65339    324BFF                 LD      (L6),A
65342    CD4EFF          L3     CALL    L8        GO DO SERVICE REQUIRED
65345    F1              L4     POP     AF
65346    E1                     POP     HL        RESTORE
65347    D1                     POP     DE
65348    C1                     POP     BC        REGISTERS
65349    FB                     EI                ENABLE INTERRUPTS
65350    C9                     RET               RETURN
65351    ED56            L5     IM      1         RESET INTERRUPT MODE 1
65353    18F6                   JR      L4        GO RETURN
65355    00              L6     DEFB    00        ROUTINE SWITCH
65356    BF50            L7     DEFW    20671     SCREEN DISPLAY ADDRESS
65358    ED5B655C        L8     LD      DE,(23653)START OF FREE SPACE
65362    21BF50          L9     LD      HL,20671  RESTORE DISPLAY
65365    224CFF                 LD      (L7),HL   FILE
65368    3A4BFF                 LD      A,(L6)    ADDRESS
65371    FE01                   CP      01        TRACE REQUIRED
65373    CCBBFF                 CALL    Z,L17     YES, CALL TRACE ROUTINE
65376    2005                   JR      NZ,L10    NO, GO TO MEMORY ROUTINE
65378    2A455C                 LD      HL,(23621)CURRENT STATEMENT NUMBER
65381    1805                   JR      L11
65383    2AB25C          L10    LD      HL,(23730)RAMTOP
65386    ED52                   SBC     HL,DE     FIND MEMORY LEFT
65388    01F0D8          L11    LD      BC,55536
65391    CD8BFF                 CALL    L12       CALC. # OF 10,000 BYTES
65394    0118FC                 LD      BC,64536
65397    CD8BFF                 CALL    L12       CALC. # OF 1,000 BYTES
65400    019CFF                 LD      BC,65436
65403    CD8BFF                 CALL    L12       CALC. # OF 100 BYTES
65406    01F6FF                 LD      BC,65526
65409    CD8BFF                 CALL    L12       CALC. # OF 10 BYTES
65412    01FFFF                 LD      BC,65535
65415    CD8BFF                 CALL    L12       CALC. # OF UNIT BYTES
65418    C9                     RET
65419    AF              L12    XOR     A         CLEAR
65420    09              L13    ADD     HL,BC     ADD NEGATIVE VALUE
65421    3C                     INC     A
65422    38FC                   JR      C,L13     CONTINUE TILL NO CARRY
65424    ED42                   SBC     HL,BC     RESTORE TO CORRECT VALUE
65426    3D                     DEC     A         DECREMENT BY ONE
65427    C630                   ADD     A,48      CONVERT DIGIT TO ASCII
65429    E5                     PUSH    HL        SAVE HL REGISTERS
65430    CDA5FF                 CALL    L14       GO FIND DIGIT
65433    214CFF                 LD      HL,L7     INCREMENT SCREEN
65436    34                     INC     (HL)      DISPLAY
65437    2A4CFF                 LD      HL,(L7)   ADDRESS
65440    CDB2FF                 CALL    L15       GO PRINT DIGIT ON SCREEN
65443    E1                     POP     HL        RESTORE HL REGISTERS
65444    C9                     RET               RETURN TO CALLER
65445    ED4B365C        L14    LD      BC,(23606)POINT TO CURR. CHAR. SET
65449    2600                   LD      H,0       ZERO REG. H
65451    6F                     LD      L,A       LOAD VALUE IN REG L
65452    29                     ADD     HL,HL     DOUBLE
65453    29                     ADD     HL,HL     DOUBLE AGAIN
65454    29                     ADD     HL,HL     AND AGAIN
65455    09                     ADD     HL,BC     GET CHAR. ADDRESS
65456    EB                     EX      DE,HL     SAVE IN REGS DE
65457    C9                     RET               RETURN TO CALLER
65458    0608            L15    LD      B,08
65460    1A              L16    LD      A,(DE)    MOVE CHARACTER TO SCREEN
65461    77                     LD      (HL),A
65462    24                     INC     H
65463    13                     INC     DE
65464    10FA                   DJNZ    L16       LOOP UNTIL MOVED
65466    C9                     RET               RETURN TO CALLER
65467    060A            L17    LD      B,10      LOAD DELAY FACTOR
65469    C5              L18    PUSH    BC
65470    01F401                 LD      BC,0500   ROUTINE TO
65473    210000                 LD      HL,0000   DELAY
65476    110000                 LD      DE,0000   FOR
65479    EDB0                   LDIR              TRACE
65481    C1                     POP     BC
65482    10F1                   DJNZ    L18
65484    C9                     RET               RETURN TO CALLER

Example Routine

A relocatable skeleton of the same technique, for building your own IM2 routine. START marks where the service routine goes.

INTERRUPT MODE 2

CLEAR 64763   GIVES 484 BYTES  FOR ROUTINES
RAND USER 65025 TO START

FCFC - FCFE   64764 - 64766   JUMP ADDRESS
FD00 - FE00   64768 - 65024   VECTORS SET TO 'FC'
FE01 - FE1B   65025 - 65051   STARTUP CODE
FE1C - FFFF   65052 - 65535   AVAILABLE

         DEFS   64764-ORG
         JP     65052          JUMP TO START OF ROUTINE
         REM
         REM                   SPACE FOR VECTOR TABLE
         REM
         DEFS   65025-ORG
INIT     PUSH   BC             SAVE
         PUSH   DE               REGISTERS
         PUSH   HL
         PUSH   AF
         LD     HL,64768       LOAD START OF VECTOR TABLE
         LD     B,00           SET REG. B FOR LOOP
LOOP     LD     (HL),252       LOAD DATA
         INC    HL             POINT TO NEXT BYTE
         DJNZ   LOOP           CONTINUE LOOP
         LD     (HL),252       LOAD LAST BYTE
         LD     A,253          LOAD VALUE FOR INDEX REG.
         LD     I,A            LOAD INDEX REG. FOR 64768
         POP    AF
         POP    HL             RESTORE
         POP    DE               REGISTERS
         POP    BC
         IM     2              TURN ON INTERRUPT MODE 2
         RET
         DEFS   65052-ORG
START    REM

Notes

  1. The article gives the entry point as RANDOMIZE USER 65281 in the text and RAND USER 65025 in the Example Routine header. USER is not a Sinclair BASIC keyword; the statement is RANDOMIZE USR.
  2. The assembly listing prints the address 65303 twice, against both POP HL and POP DE. POP AF at 65301 occupies one byte, so POP HL is at 65302; corrected here. The object bytes are unaffected and are confirmed by the DATA statements in the BASIC loader.

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.