Authors
Publication
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 \n65021 C31CFF JP L1 JUMP TO START OF ROUTINE\n65024 REM SPACE FOR VECTOR TABLE\n65281 DEFS 65281-ORG\n65281 C5 L250 PUSH BC SAVE\n65282 D5 PUSH DE REGISTERS\n65283 E5 PUSH HL\n65284 F5 PUSH AF\n65285 2100FE LD HL,65024 LOAD START OF VECTOR TAB\n65288 0600 LD B,00 SET REG. B FOR LOOP\n65290 36FD L251 LD (HL),253 LOAD DATA\n65292 23 INC HL POINT TO NEXT BYTE\n65293 10FB DJNZ L251 CONTINUE LOOP\n65295 36FD LD (HL),253 LOAD LAST BYTE\n65297 3EFE LD A,254 LOAD VALUE FOR INDEX REG\n65299 ED47 LD I,A LOAD INDEX REG FOR 65024\n65301 F1 POP AF\n65303 E1 POP HL RESTORE\n65303 D1 POP DE RESTORE\n65304 C1 POP BC REGISTERS\n65305 ED5E IM 2 TURN ON INTERRUPT MODE 2\n65307 C9 RET\n65308 FF L1 RST 56\n65309 F3 DI DISABLE INTERRUPTS\n65310 C5 PUSH BC SAVE\n65311 D5 PUSH DE\n65312 E5 PUSH HL REGISTERS\n65313 F5 PUSH AF\n65314 01FEBF LD BC,49150 CHECK KEYBOARD\n65317 ED78 IN A,(C) READ KEY(S) PRESSED\n65319 FE1C CP 28 ENTER AND 'L'\n65321 281C JR Z,L5 YES, TURN OFF ROUTINE\n65323 FE1A CP 26 ENTER AND 'K'\n65325 280A JR Z,L2 YES, TURN ON TRACE\n65327 FE16 CP 22 ENTER AND 'J'\n65329 200B JR NZ,L3 NO, CHECK PRIOR SETTING\n65331 AF XOR A YES, TURN TRACE\n65332 324BFF LD (L6),A OFF\n65335 1805 JR L3 GO SHOW MEMORY LEFT\n65337 3E01 L2 LD A,01 SET SWITCH FOR TRACE\n65339 324BFF LD (L6),A\n65342 CD4EFF L3 CALL L8 GO DO SERVICE REQUIRED\n65345 F1 L4 POP AF\n65346 E1 POP HL RESTORE\n65347 D1 POP DE\n65348 C1 POP BC REGISTERS\n65349 FB EI ENABLE INTERRUPTS\n65350 C9 RET RETURN\n65351 ED56 L5 IM 1 RESET INTERRUPT MODE 1\n65353 18F6 JR L4 GO RETURN\n65355 00 L6 DEFB 00 ROUTINE SWITCH\n65356 BF50 L7 DEFW 20671 SCREEN DISPLAY ADDRESS\n65358 ED5B655C L8 LD DE,(23653)START OF FREE SPACE\n65362 21BF50 L9 LD HL,20671 RESTORE DISPLAY\n65365 224CFF LD (L7),HL FILE\n65368 3A4BFF LD A,(L6) ADDRESS\n65371 FE01 CP 01 TRACE REQUIRED\n65373 CCBBFF CALL Z,L17 YES, CALL TRACE ROUTINE\n65376 2005 JR NZ,L10 NO, GO TO MEMORY ROUTINE\n65378 2A455C LD HL,(23621)CURRENT STATEMENT NUMBER\n65381 1805 JR L11\n65383 2AB25C L10 LD HL,(23730)RAMTOP\n65386 ED52 SBC HL,DE FIND MEMORY LEFT\n65388 01F0D8 L11 LD BC,55536\n65391 CD8BFF CALL L12 CALC. # OF 10,000 BYTES\n65394 0118FC LD BC,64536\n65397 CD8BFF CALL L12 CALC. # OF 1,000 BYTES\n65400 019CFF LD BC,65436\n65403 CD8BFF CALL L12 CALC. # OF 100 BYTES\n65406 01F6FF LD BC,65526\n65409 CD8BFF CALL L12 CALC. # OF 10 BYTES\n65412 01FFFF LD BC,65535\n65415 CD8BFF CALL L12 CALC. # OF UNIT BYTES\n65418 C9 RET\n65419 AF L12 XOR A CLEAR\n65420 09 L13 ADD HL,BC ADD NEGATIVE VALUE\n65421 3C INC A\n65422 38FC JR C,L13 CONTINUE TILL NO CARRY\n65424 ED42 SBC HL,BC RESTORE TO CORRECT VALUE\n65426 3D DEC A DECREMENT BY ONE\n65427 C630 ADD A,48 CONVERT DIGIT TO ASCII\n65429 E5 PUSH HL SAVE HL REGISTERS\n65430 CDA5FF CALL L14 GO FIND DIGIT\n65433 214CFF LD HL,L7 INCREMENT SCREEN\n65436 34 INC (HL) DISPLAY\n65437 2A4CFF LD HL,(L7) ADDRESS\n65440 CDB2FF CALL L15 GO PRINT DIGIT ON SCREEN\n65443 E1 POP HL RESTORE HL REGISTERS\n65444 C9 RET RETURN TO CALLER\n65445 ED4B365C L14 LD BC,(23606)POINT TO CURR. CHAR. SET\n65449 2600 LD H,0 ZERO REG. H\n65451 6F LD L,A LOAD VALUE IN REG L\n65452 29 ADD HL,HL DOUBLE\n65453 29 ADD HL,HL DOUBLE AGAIN\n65454 29 ADD HL,HL AND AGAIN\n65455 09 ADD HL,BC GET CHAR. ADDRESS\n65456 EB EX DE,HL SAVE IN REGS DE\n65457 C9 RET RETURN TO CALLER\n65458 0608 L15 LD B,08\n65460 1A L16 LD A,(DE) MOVE CHARACTER TO SCREEN\n65461 77 LD (HL),A\n65462 24 INC H\n65463 13 INC DE\n65464 10FA DJNZ L16 LOOP UNTIL MOVED\n65466 C9 RET RETURN TO CALLER\n65467 060A L17 LD B,10 LOAD DELAY FACTOR\n65469 C5 L18 PUSH BC\n65470 01F401 LD BC,0500 ROUTINE TO\n65473 210000 LD HL,0000 DELAY\n65476 110000 LD DE,0000 FOR\n65479 EDB0 LDIR TRACE\n65481 C1 POP BC\n65482 10F1 DJNZ L18\n65484 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
- The article gives the entry point as
RANDOMIZE USER 65281in the text andRAND USER 65025in the Example Routine header.USERis not a Sinclair BASIC keyword; the statement isRANDOMIZE USR. - The assembly listing prints the address 65303 twice, against both
POP HLandPOP DE.POP AFat 65301 occupies one byte, soPOP HLis at 65302; corrected here. The object bytes are unaffected and are confirmed by the DATA statements in the BASIC loader.
Products
Media
Image Gallery
Source Code
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.