1 0000: ; **************************************************************************** 2 0000: ; The SC/MP I/O Monitor, complete with Tape load/store routines. 3 0000: ; 4 0000: ; Developed from the SCMPKB monitor by D.J.D. 5 0000: ; Tape routines by N.J.T. 6 0000: ; 7 0000: ; Updated to assemble with RCASM assembler with 8060 extensions 8 0000: ; 9 0000: ; **************************************************************************** 10 0000: 11 0000: ; **************************************************************************** 12 0000: ; Required for RCASM 8060{ 14 0000: 15 0000: ; **************************************************************************** 16 0000: 17 0000: Ram: equ 0F00h ; this is where the standard RAM is 18 0000: Disp: equ 0D00h ; this is where the display is 19 0000: 20 0000: ; **************************************************************************** 21 0000: ; Offsets into the data structure , from P2 22 0000: ; **************************************************************************** 23 0000: 24 0000: dl: equ 0 ; Segment for Digit 1 25 0000: dh: equ 1 ; Segment for Digit 2 26 0000: d3: equ 2 ; Segment for Digit 3 27 0000: d4: equ 3 ; Segment for Digit 4 28 0000: adll: equ 4 ; Segment for Digit 5 29 0000: adlh: equ 5 ; Segment for Digit 6 30 0000: adhl: equ 6 ; Segment for Digit 7 31 0000: adhh: equ 7 ; Segment for Digit 8 32 0000: d9: equ 8 ; Segment for Digit 9 33 0000: cnt: equ 9 ; Counter 34 0000: pushed: equ 10 ; Key pushed 35 0000: char: equ 11 ; Char Read 36 0000: adl: equ 12 ; Memory Address (low) 37 0000: word: equ 13 ; Memory Word 38 0000: adh: equ 14 ; Memory Address (High) 39 0000: ddta: equ 15 ; first flag 40 0000: row: equ 16 ; row counter 41 0000: next: equ 17 ; flag for now data 42 0000: 43 0000: ; **************************************************************************** 44 0000: ; Ram areas used by SCIOS. P3 is saved elsewhere 45 0000: ; **************************************************************************** 46 0000: 47 0000: p1h: equ 0FF9h 48 0000: p1l: equ 0FFAh 49 0000: p2h: equ 0FFBh 50 0000: p2l: equ 0FFCh 51 0000: a: equ 0FFDh 52 0000: e: equ 0FFEh 53 0000: s: equ 0FFFh 54 0000: 55 0000: ; **************************************************************************** 56 0000: ; Start of monitor listing in ROM 57 0000: ; **************************************************************************** 58 0000: org 0000h 59 0000: ; **************************************************************************** 60 0000: 61 0000: Init: 62 0000: 00 halt ; pulse the H flag 63 0001: CF FF st @-1(3) ; save A at P3-1, dec it 64 0003: 90 1E jmp Start ; Go to the monitor start 65 0005: 66 0005: ; **************************************************************************** 67 0005: ; Debug exit : restore environment 68 0005: ; **************************************************************************** 69 0005: 70 0005: GoOut: 71 0005: 37 xpah 3 ; Save A in P3 (A is Go address High) 72 0006: C2 0C ld adl(2) 73 0008: 33 xpal 3 74 0009: C7 FF ld @-1(3) ; fix go address 75 000B: C0 F2 ldr e ; restore registers 76 000D: 01 xae 77 000E: C0 EB ldr p1l 78 0010: 31 xpal 1 79 0011: C0 E7 ldr p1h 80 0013: 35 xpah 1 81 0014: C0 E7 ldr p2l 82 0016: 32 xpal 2 83 0017: C0 E3 ldr p2h 84 0019: 36 xpah 2 85 001A: C0 E4 ldr s 86 001C: 00 halt ; reset single step 87 001D: 07 cas 88 001E: C0 DE ldr a 89 0020: 08 nop 90 0021: 05 ien 91 0022: 3F xppc 3 92 0023: 93 0023: ; **************************************************************************** 94 0023: ; Debug Entry Point 95 0023: ; **************************************************************************** 96 0023: 97 0023: Start: 98 0023: C8 D9 str a ; Copy all registers to memory 99 0025: 40 lde 100 0026: C8 D7 str e 101 0028: 06 csa 102 0029: C8 D5 str s 103 002B: 35 xpah 1 104 002C: C8 CC str p1h 105 002E: 31 xpal 1 106 002F: C8 CA str p1l 107 0031: C4 0F ldi Ram.1 ; Copy P2, make it point to RAM 108 0033: 36 xpah 2 ; at the same time 109 0034: C8 C6 str p2h 110 0036: C4 00 ldi Ram.0 111 0038: 32 xpal 2 112 0039: C8 C2 str p2l 113 003B: C7 01 ld @1(3) ; Bump P3 for return 114 003D: 33 xpal 3 ; save it in ADL,ADH so on 115 003E: CA 0C st adl(2) ; exit we are at (end + 1) 116 0040: 37 xpah 3 117 0041: CA 0E st adh(2) 118 0043: C4 00 ldi 0 ; Clear D3 and D4 119 0045: CA 02 st d3(2) 120 0047: CA 03 st d4(2) 121 0049: C4 01 ldi 1 ; P3H = 1 122 004B: 37 xpah 3 123 004C: Abort: 124 004C: 90 6D jmp Mem ; Go to 'Mem' mode handler 125 004E: 126 004E: ; **************************************************************************** 127 004E: ; Run program from currently displayed address 128 004E: ; **************************************************************************** 129 004E: 130 004E: GoNow: 131 004E: C2 0E ld adh(2) ; A = High Byte of Address 132 0050: 90 B3 jmp GoOut 133 0052: 134 0052: ; **************************************************************************** 135 0052: ; Tape Interface Routines. 136 0052: ; **************************************************************************** 137 0052: 138 0052: Count: equ 0D5h 139 0052: Len: equ 0D6h 140 0052: 141 0052: ; **************************************************************************** 142 0052: ; Store to Tape. P1^Data,@Count is the bytes 143 0052: ; **************************************************************************** 144 0052: ToTape: 145 0052: C5 01 ld @1(1) ; E := (P1), increment P1 146 0054: 01 xae 147 0055: C4 01 ldi 1 ; A := 1 (the bit pattern) 148 0057: TNext: 149 0057: CB D5 st Count(3) ; Save in Count (P3) 150 0059: C4 01 ldi 1 ; set F0 to 1 151 005B: 07 cas 152 005C: 8F 08 dly 8 ; Delay 8 Cycles 153 005E: C3 D5 ld Count(3) ; A = Count & E 154 0060: 50 ane ; test if bit is set... 155 0061: 98 07 jz Zero 156 0063: 8F 18 dly 018h ; (bit is 1) Delay $18 cycles 157 0065: C4 00 ldi 0 ; set F0 to 0 again 158 0067: 07 cas 159 0068: 90 05 jmp CDone 160 006A: Zero: 161 006A: C4 00 ldi 0 ; bit is zero (set F0 to 0) 162 006C: 07 cas 163 006D: 8F 18 dly 018h ; Delay $18 Cycles 164 006F: CDone: 165 006F: 8F 20 dly 020h ; Delay $20 more Cycles 166 0071: C3 D5 ld Count(3) ; shift the bit pattern left 167 0073: F3 D5 add Count(3) ; (CYL cleared by CAS !) 168 0075: 9C E0 jnz TNext ; if non zero we haven't finished 169 0077: BB D6 dld Len(3) ; decrement the length counter 170 0079: 9C D7 jnz ToTape ; if non-zero do the next byte 171 007B: 3F xppc 3 ; return from caller 172 007C: 173 007C: ; **************************************************************************** 174 007C: ; Load from Tape to ^P1. Is broken out via Reset 175 007C: ; **************************************************************************** 176 007C: 177 007C: FrTape: 178 007C: C4 08 ldi 8 ; Count is a bit count here 179 007E: CB D5 st Count(3) 180 0080: Loop: 181 0080: 06 csa ; look at the status 182 0081: D4 20 ani 20h ; wait for the 'start' bit 183 0083: 98 FB jz Loop 184 0085: 8F 1C dly 01Ch ; wait $1C cycles 185 0087: 19 sio ; shift a bit in 186 0088: 8F 1C dly 01Ch ; wait a few more cycles 187 008A: BB D5 dld Count(3) ; do this 8 times 188 008C: 9C F2 jnz Loop 189 008E: 40 lde ; get the byte we got 190 008F: CD 01 st @1(1) ; save it, increment the pointer 191 0091: 90 E9 jmp FrTape ; and get the next one. 192 0093: 193 0093: ; **************************************************************************** 194 0093: ; Offset calculator 195 0093: ; **************************************************************************** 196 0093: 197 0093: Offset: 198 0093: C6 FE ld @-2(2) ; Subtract 2 from destination address 199 0095: 32 xpal 2 ; put low byte in AC 200 0096: 03 scl 201 0097: FB D8 cad 0D8h(3) ; subtract low byte of jump inst addr 202 0099: C9 01 st 1(1) ; put in jump operand 203 009B: 3F xppc 3 ; return 204 009C: 08 nop ; padding 205 009D: 206 009D: ; **************************************************************************** 207 009D: ; Bump MSB of address 208 009D: ; **************************************************************************** 209 009D: 210 009D: DTack: 211 009D: AA 0E ild adh(2) ; increment and load ADH 212 009F: 90 36 jmp Data 213 00A1: 214 00A1: ; **************************************************************************** 215 00A1: ; Put Word in Memory 216 00A1: ; **************************************************************************** 217 00A1: 218 00A1: MemDn: 219 00A1: C2 0E ld adh(2) ; P1 = ADH/ADL 220 00A3: 35 xpah 1 221 00A4: C2 0C ld adl(2) 222 00A6: 31 xpal 1 223 00A7: C2 0D ld word(2) ; get and store word 224 00A9: C9 00 st 0(1) 225 00AB: 90 34 jmp DataCK 226 00AD: 227 00AD: ; **************************************************************************** 228 00AD: ; Key Check 229 00AD: ; **************************************************************************** 230 00AD: 231 00AD: MemCK: 232 00AD: E4 06 xri 06 ; Check for 'go' 233 00AF: 98 9D jz GoNow 234 00B1: E4 05 xri 05 ; Check for 'term' 235 00B3: 98 22 jz Data 236 00B5: AA 0C ild adl(2) ; bump address low 237 00B7: 9C 1E jnz Data ; no carry-through required 238 00B9: 90 E2 jmp DTack ; goto bump MSB code 239 00BB: 240 00BB: ; **************************************************************************** 241 00BB: ; Mem mode 242 00BB: ; **************************************************************************** 243 00BB: 244 00BB: Mem: 245 00BB: C4 FF ldi -1 ; Set "First" flag 246 00BD: CA 11 st next(2) ; and flag for "address now" 247 00BF: CA 0F st ddta(2) 248 00C1: MemL: 249 00C1: C2 0E ld adh(2) ; P1 = ADH/L 250 00C3: 35 xpah 1 251 00C4: C2 0C ld adl(2) 252 00C6: 31 xpal 1 253 00C7: C1 00 ld 0(1) ; Get the byte at ADHL 254 00C9: CA 0D st word(2) ; save it away in 'work' 255 00CB: C4 3F ldi DispD.0-1 ; Fix Data Segment... 256 00CD: 33 xpal 3 ; P3 now points to DispD routine 257 00CE: 3F xppc 3 ; call it 258 00CF: 90 DC jmp MemCK ; command return... 259 00D1: C4 1A ldi Adr.0-1 ; call the 'adr' subroutine 260 00D3: 33 xpal 3 261 00D4: 3F xppc 3 262 00D5: 90 EA jmp MemL ; get next character 263 00D7: 264 00D7: ; **************************************************************************** 265 00D7: ; Data Mode 266 00D7: ; **************************************************************************** 267 00D7: 268 00D7: Data: 269 00D7: C4 FF ldi -1 ; set first flag 270 00D9: CA 0F st ddta(2) 271 00DB: C2 0E ld adh(2) ; P1 = ADHL 272 00DD: 35 xpah 1 273 00DE: C2 0C ld adl(2) 274 00E0: 31 xpal 1 275 00E1: DataCK: 276 00E1: C1 00 ld 0(1) ; get word & save it for display 277 00E3: CA 0D st word(2) 278 00E5: DataL: 279 00E5: C4 3F ldi DispD.0-1 ; call the display routine 280 00E7: 33 xpal 3 281 00E8: 3F xppc 3 282 00E9: 90 C2 jmp MemCK ; go to the memory routine 283 00EB: C4 04 ldi 4 ; shift it in 284 00ED: CA 09 st cnt(2) 285 00EF: AA 0F ild ddta(2) ; if first 286 00F1: 9C 06 jnz Dnfst 287 00F3: C4 00 ldi 0 ; zero word if first 288 00F5: CA 0D st word(2) 289 00F7: CA 11 st next(2) ; set flag for address done 290 00F9: Dnfst: 291 00F9: 02 ccl ; shift left 292 00FA: C2 0D ld word(2) 293 00FC: F2 0D add word(2) 294 00FE: CA 0D st word(2) 295 0100: BA 09 dld cnt(2) ; do it 8 times 296 0102: 9C F5 jnz Dnfst 297 0104: C2 0D ld word(2) ; get the word 298 0106: 58 ore ; or with the hex pattern 299 0107: CA 0D st word(2) 300 0109: 90 96 jmp MemDn ; store it and try again 301 010B: 302 010B: ; **************************************************************************** 303 010B: ; Display Segment Data definitions 304 010B: ; **************************************************************************** 305 010B: 306 010B: SA: equ 1 ; Segment bit patterns 307 010B: SB: equ 2 308 010B: SC: equ 4 309 010B: SD: equ 8 310 010B: SE: equ 16 311 010B: SF: equ 32 312 010B: SG: equ 64 313 010B: 314 010B: ; **************************************************************************** 315 010B: ; Hex number to seven segment table 316 010B: ; **************************************************************************** 317 010B: CRom: 318 010B: 3F db SA + SB + SC + SD + SE + SF 319 010C: 06 db SB + SC 320 010D: 5B db SA + SB + SD + SE + SG 321 010E: 4F db SA + SB + SC + SD + SG 322 010F: 66 db SB + SC + SF + SG 323 0110: 6D db SA + SC + SD + SF + SG 324 0111: 7D db SA + SC + SD + SE + SF + SG 325 0112: 07 db SA + SB + SC 326 0113: 7F db SA + SB + SC + SD + SE + SF + SG 327 0114: 67 db SA + SB + SC + SF + SG 328 0115: 77 db SA + SB + SC + SE + SF + SG 329 0116: 7C db SC + SD + SE + SF + SG 330 0117: 39 db SA + SD + SE + SF 331 0118: 5E db SB + SC + SD + SE + SG 332 0119: 79 db SA + SD + SE + SF + SG 333 011A: 71 db SA + SE + SF + SG 334 011B: 335 011B: ; **************************************************************************** 336 011B: ; Make 4 digit address. Shift left one then add new low hex 337 011B: ; digit. On entry,digit in E,P2 points to RAM 338 011B: ; **************************************************************************** 339 011B: 340 011B: Adr: 341 011B: C4 04 ldi 4 ; set number of shifts 342 011D: CA 09 st cnt(2) 343 011F: AA 0F ild ddta(2) ; check if first 344 0121: 9C 06 jnz notfst ; if not skip 345 0123: C4 00 ldi 0 ; zero address 346 0125: CA 0E st adh(2) 347 0127: CA 0C st adl(2) 348 0129: notfst: 349 0129: 02 ccl ; shift ADHL left 350 012A: C2 0C ld adl(2) 351 012C: F2 0C add adl(2) 352 012E: CA 0C st adl(2) 353 0130: C2 0E ld adh(2) 354 0132: F2 0E add adh(2) 355 0134: CA 0E st adh(2) 356 0136: BA 09 dld cnt(2) ; do it 4 times 357 0138: 9C EF jnz notfst 358 013A: C2 0C ld adl(2) ; or in the digit 359 013C: 58 ore 360 013D: CA 0C st adl(2) 361 013F: 3F xppc 3 ; and return 362 0140: 363 0140: ; **************************************************************************** 364 0140: ; Convert Hex Data to Segments. P2 Points to RAM. Drops through 365 0140: ; to hex address conversion 366 0140: ; **************************************************************************** 367 0140: 368 0140: DispD: 369 0140: C4 01 ldi CRom.1 ; P1 = Segment conversion Table 370 0142: 35 xpah 1 371 0143: C4 0B ldi CRom.0 372 0145: 31 xpal 1 373 0146: C2 0D ld word(2) ; get low nibble 374 0148: D4 0F ani 0Fh 375 014A: 01 xae 376 014B: C1 80 ld -128(1) ; get CROM + E (low) 377 014D: CA 00 st dl(2) 378 014F: C2 0D ld word(2) ; get high nibble 379 0151: 1C sr 380 0152: 1C sr 381 0153: 1C sr 382 0154: 1C sr 383 0155: 01 xae 384 0156: C1 80 ld -128(1) ; get CROM + E 385 0158: CA 01 st dh(2) ; update the display 386 015A: 387 015A: ; **************************************************************************** 388 015A: ; Convert Hex Address to segment, P2 points to RAM. Drops through 389 015A: ; to keyboard and display 390 015A: ; **************************************************************************** 391 015A: 392 015A: DispA: 393 015A: 03 scl 394 015B: C4 01 ldi CRom.1 ; P1 = Segment conversion Table 395 015D: 35 xpah 1 396 015E: C4 0B ldi CRom.0 397 0160: 31 xpal 1 398 0161: LoopD: 399 0161: C2 0C ld adl(2) 400 0163: D4 0F ani 0Fh 401 0165: 01 xae 402 0166: C1 80 ld -128(1) ; get CROM + E (low) 403 0168: CA 04 st adll(2) 404 016A: C2 0C ld adl(2) ; get high nibble 405 016C: 1C sr 406 016D: 1C sr 407 016E: 1C sr 408 016F: 1C sr 409 0170: 01 xae 410 0171: C1 80 ld -128(1) ; get CROM + E 411 0173: CA 05 st adlh(2) ; update the display 412 0175: 06 csa ; check if done 413 0176: D4 80 ani 080h 414 0178: 98 09 jz Done 415 017A: 02 ccl ; clear carry,done next time ! 416 017B: C4 00 ldi 0 417 017D: CA 03 st d4(2) ; zero digit 4 418 017F: C6 02 ld @2(2) ; fix P2 for next time around 419 0181: 90 DE jmp LoopD 420 0183: Done: 421 0183: C6 FE ld @-2(2) ; refix P2 on exit 422 0185: 423 0185: ; **************************************************************************** 424 0185: ; Keyboard and Display Input. 425 0185: ; JMP Command in A (GO=6,MEM=7,TERM=3,in E + 16) 426 0185: ; Number return, hex number in E reg ; ABORT key goes to abort 427 0185: ; all registers used ; P2 points to RAM,address MUST be xxx0 428 0185: ; to re-execute do XPPC3 429 0185: ; **************************************************************************** 430 0185: 431 0185: Kybd: 432 0185: C4 00 ldi 0 ; zero char 433 0187: CA 0B st char(2) 434 0189: C4 0D ldi Disp.1 ; P1 points to the display 435 018B: 35 xpah 1 436 018C: Off: 437 018C: C4 FF ldi -1 ; Set Row/Digit Address 438 018E: CA 10 st row(2) 439 0190: C4 0A ldi 10 ; Set Row Count 440 0192: CA 09 st cnt(2) 441 0194: C4 00 ldi 0 ; Zero keyboard input 442 0196: CA 0A st pushed(2) 443 0198: 31 xpal 1 ; Set display address (low) 444 0199: KDLoop: 445 0199: AA 10 ild row(2) ; next row ? 446 019B: 01 xae ; put it in E 447 019C: C2 80 ld -128(2) ; get the segment into A 448 019E: C9 80 st -128(1) ; send it to the display 449 01A0: 8F 00 dly 0 ; delay for display,let keys settle 450 01A2: C1 80 ld -128(1) ; get keyboard input 451 01A4: E4 FF xri 0FFh ; invert the input so 1 = pressed 452 01A6: 9C 4C jnz Key ; jump if a key pushed (save in Pushed) 453 01A8: Back: 454 01A8: BA 09 dld cnt(2) ; check if done 455 01AA: 9C ED jnz KDLoop ; no if jump 456 01AC: C2 0A ld pushed(2) ; check if key pressed 457 01AE: 98 0A jz CkMore ; if no, then go to try again 458 01B0: C2 0B ld char(2) 459 01B2: 9C D8 jnz Off ; if yes, wait for release 460 01B4: C2 0A ld pushed(2) ; released ? set char 461 01B6: CA 0B st char(2) 462 01B8: 90 D2 jmp Off 463 01BA: CkMore: 464 01BA: C2 0B ld char(2) ; check if there was a character 465 01BC: 98 CE jz Off ; no, keep looking 466 01BE: 467 01BE: ; **************************************************************************** 468 01BE: ; Command Key Processing 469 01BE: ; **************************************************************************** 470 01BE: 471 01BE: Command: 472 01BE: 01 xae ; copy into E 473 01BF: 40 lde 474 01C0: D4 20 ani 020h ; check for command 475 01C2: 9C 28 jnz Cmnd ; jump if command 476 01C4: C4 80 ldi 080h ; find number (its a digit 0..F) 477 01C6: 50 ane 478 01C7: 9C 1B jnz Lt7 ; 0 to 7 479 01C9: C4 40 ldi 040h 480 01CB: 50 ane 481 01CC: 9C 19 jnz N89 ; 8, 9 482 01CE: C4 0F ldi 0fh ; B to F 483 01D0: 50 ane 484 01D1: F4 07 adi 7 485 01D3: 01 xae 486 01D4: C0 80 ld -128(0) ; get number 487 01D6: KeyRtn: 488 01D6: 01 xae ; save in E 489 01D7: C7 02 ld @2(3) ; fix return,add 2 490 01D9: 3F xppc 3 491 01DA: 90 A9 jmp Kybd ; allows us to go round again 492 01DC: 493 01DC: 0A 0B 0C 0D 00 00 0E 0F db 0Ah, 0Bh, 0Ch, 0Dh, 0, 0, 0Eh, 0Fh 494 01E4: Lt7: 495 01E4: 60 xre ; keep low digit (handler for 0..7) 496 01E5: 90 EF jmp KeyRtn 497 01E7: N89: 498 01E7: 60 xre ; get low (handler for 8 & 9) 499 01E8: F4 08 adi 8 ; make it 8 or 9 500 01EA: 90 EA jmp KeyRtn 501 01EC: Cmnd: 502 01EC: 60 xre 503 01ED: E4 04 xri 4 ; check if abort 504 01EF: 98 08 jz Abrt ; if so,goto abort 505 01F1: 3F xppc 3 ; return 506 01F2: 90 91 jmp Kybd ; and allow reentry 507 01F4: Key: 508 01F4: 58 ore ; make character 509 01F5: CA 0A st pushed(2) ; save it 510 01F7: 90 AF jmp Back 511 01F9: Abrt: 512 01F9: C4 00 ldi Abort.1 ; goto abort 513 01FB: 37 xpah 3 514 01FC: C4 4B ldi Abort.0-1 515 01FE: 33 xpal 3 516 01FF: 3F xppc 3 517 0200: 518 0200: ; **************************************************************************** 519 0200: ; Required for RCASM } 521 0200: ; **************************************************************************** 522 0200: ; **************************************************************************** 523 0200: