; **************************************************************************** ; The SC/MP I/O Monitor, complete with Tape load/store routines. ; ; Developed from the SCMPKB monitor by D.J.D. ; Tape routines by N.J.T. ; ; Updated to assemble with RCASM assembler with 8060 extensions ; ; **************************************************************************** ; **************************************************************************** ; Required for RCASM 8060{ ; **************************************************************************** Ram: equ 0F00h ; this is where the standard RAM is Disp: equ 0D00h ; this is where the display is ; **************************************************************************** ; Offsets into the data structure , from P2 ; **************************************************************************** dl: equ 0 ; Segment for Digit 1 dh: equ 1 ; Segment for Digit 2 d3: equ 2 ; Segment for Digit 3 d4: equ 3 ; Segment for Digit 4 adll: equ 4 ; Segment for Digit 5 adlh: equ 5 ; Segment for Digit 6 adhl: equ 6 ; Segment for Digit 7 adhh: equ 7 ; Segment for Digit 8 d9: equ 8 ; Segment for Digit 9 cnt: equ 9 ; Counter pushed: equ 10 ; Key pushed char: equ 11 ; Char Read adl: equ 12 ; Memory Address (low) word: equ 13 ; Memory Word adh: equ 14 ; Memory Address (High) ddta: equ 15 ; first flag row: equ 16 ; row counter next: equ 17 ; flag for now data ; **************************************************************************** ; Ram areas used by SCIOS. P3 is saved elsewhere ; **************************************************************************** p1h: equ 0FF9h p1l: equ 0FFAh p2h: equ 0FFBh p2l: equ 0FFCh a: equ 0FFDh e: equ 0FFEh s: equ 0FFFh ; **************************************************************************** ; Start of monitor listing in ROM ; **************************************************************************** org 0000h ; **************************************************************************** Init: halt ; pulse the H flag st @-1(3) ; save A at P3-1, dec it jmp Start ; Go to the monitor start ; **************************************************************************** ; Debug exit : restore environment ; **************************************************************************** GoOut: xpah 3 ; Save A in P3 (A is Go address High) ld adl(2) xpal 3 ld @-1(3) ; fix go address ldr e ; restore registers xae ldr p1l xpal 1 ldr p1h xpah 1 ldr p2l xpal 2 ldr p2h xpah 2 ldr s halt ; reset single step cas ldr a nop ien xppc 3 ; **************************************************************************** ; Debug Entry Point ; **************************************************************************** Start: str a ; Copy all registers to memory lde str e csa str s xpah 1 str p1h xpal 1 str p1l ldi Ram.1 ; Copy P2, make it point to RAM xpah 2 ; at the same time str p2h ldi Ram.0 xpal 2 str p2l ld @1(3) ; Bump P3 for return xpal 3 ; save it in ADL,ADH so on st adl(2) ; exit we are at (end + 1) xpah 3 st adh(2) ldi 0 ; Clear D3 and D4 st d3(2) st d4(2) ldi 1 ; P3H = 1 xpah 3 Abort: jmp Mem ; Go to 'Mem' mode handler ; **************************************************************************** ; Run program from currently displayed address ; **************************************************************************** GoNow: ld adh(2) ; A = High Byte of Address jmp GoOut ; **************************************************************************** ; Tape Interface Routines. ; **************************************************************************** Count: equ 0D5h Len: equ 0D6h ; **************************************************************************** ; Store to Tape. P1^Data,@Count is the bytes ; **************************************************************************** ToTape: ld @1(1) ; E := (P1), increment P1 xae ldi 1 ; A := 1 (the bit pattern) TNext: st Count(3) ; Save in Count (P3) ldi 1 ; set F0 to 1 cas dly 8 ; Delay 8 Cycles ld Count(3) ; A = Count & E ane ; test if bit is set... jz Zero dly 018h ; (bit is 1) Delay $18 cycles ldi 0 ; set F0 to 0 again cas jmp CDone Zero: ldi 0 ; bit is zero (set F0 to 0) cas dly 018h ; Delay $18 Cycles CDone: dly 020h ; Delay $20 more Cycles ld Count(3) ; shift the bit pattern left add Count(3) ; (CYL cleared by CAS !) jnz TNext ; if non zero we haven't finished dld Len(3) ; decrement the length counter jnz ToTape ; if non-zero do the next byte xppc 3 ; return from caller ; **************************************************************************** ; Load from Tape to ^P1. Is broken out via Reset ; **************************************************************************** FrTape: ldi 8 ; Count is a bit count here st Count(3) Loop: csa ; look at the status ani 20h ; wait for the 'start' bit jz Loop dly 01Ch ; wait $1C cycles sio ; shift a bit in dly 01Ch ; wait a few more cycles dld Count(3) ; do this 8 times jnz Loop lde ; get the byte we got st @1(1) ; save it, increment the pointer jmp FrTape ; and get the next one. ; **************************************************************************** ; Offset calculator ; **************************************************************************** Offset: ld @-2(2) ; Subtract 2 from destination address xpal 2 ; put low byte in AC scl cad 0D8h(3) ; subtract low byte of jump inst addr st 1(1) ; put in jump operand xppc 3 ; return nop ; padding ; **************************************************************************** ; Bump MSB of address ; **************************************************************************** DTack: ild adh(2) ; increment and load ADH jmp Data ; **************************************************************************** ; Put Word in Memory ; **************************************************************************** MemDn: ld adh(2) ; P1 = ADH/ADL xpah 1 ld adl(2) xpal 1 ld word(2) ; get and store word st 0(1) jmp DataCK ; **************************************************************************** ; Key Check ; **************************************************************************** MemCK: xri 06 ; Check for 'go' jz GoNow xri 05 ; Check for 'term' jz Data ild adl(2) ; bump address low jnz Data ; no carry-through required jmp DTack ; goto bump MSB code ; **************************************************************************** ; Mem mode ; **************************************************************************** Mem: ldi -1 ; Set "First" flag st next(2) ; and flag for "address now" st ddta(2) MemL: ld adh(2) ; P1 = ADH/L xpah 1 ld adl(2) xpal 1 ld 0(1) ; Get the byte at ADHL st word(2) ; save it away in 'work' ldi DispD.0-1 ; Fix Data Segment... xpal 3 ; P3 now points to DispD routine xppc 3 ; call it jmp MemCK ; command return... ldi Adr.0-1 ; call the 'adr' subroutine xpal 3 xppc 3 jmp MemL ; get next character ; **************************************************************************** ; Data Mode ; **************************************************************************** Data: ldi -1 ; set first flag st ddta(2) ld adh(2) ; P1 = ADHL xpah 1 ld adl(2) xpal 1 DataCK: ld 0(1) ; get word & save it for display st word(2) DataL: ldi DispD.0-1 ; call the display routine xpal 3 xppc 3 jmp MemCK ; go to the memory routine ldi 4 ; shift it in st cnt(2) ild ddta(2) ; if first jnz Dnfst ldi 0 ; zero word if first st word(2) st next(2) ; set flag for address done Dnfst: ccl ; shift left ld word(2) add word(2) st word(2) dld cnt(2) ; do it 8 times jnz Dnfst ld word(2) ; get the word ore ; or with the hex pattern st word(2) jmp MemDn ; store it and try again ; **************************************************************************** ; Display Segment Data definitions ; **************************************************************************** SA: equ 1 ; Segment bit patterns SB: equ 2 SC: equ 4 SD: equ 8 SE: equ 16 SF: equ 32 SG: equ 64 ; **************************************************************************** ; Hex number to seven segment table ; **************************************************************************** CRom: db SA + SB + SC + SD + SE + SF db SB + SC db SA + SB + SD + SE + SG db SA + SB + SC + SD + SG db SB + SC + SF + SG db SA + SC + SD + SF + SG db SA + SC + SD + SE + SF + SG db SA + SB + SC db SA + SB + SC + SD + SE + SF + SG db SA + SB + SC + SF + SG db SA + SB + SC + SE + SF + SG db SC + SD + SE + SF + SG db SA + SD + SE + SF db SB + SC + SD + SE + SG db SA + SD + SE + SF + SG db SA + SE + SF + SG ; **************************************************************************** ; Make 4 digit address. Shift left one then add new low hex ; digit. On entry,digit in E,P2 points to RAM ; **************************************************************************** Adr: ldi 4 ; set number of shifts st cnt(2) ild ddta(2) ; check if first jnz notfst ; if not skip ldi 0 ; zero address st adh(2) st adl(2) notfst: ccl ; shift ADHL left ld adl(2) add adl(2) st adl(2) ld adh(2) add adh(2) st adh(2) dld cnt(2) ; do it 4 times jnz notfst ld adl(2) ; or in the digit ore st adl(2) xppc 3 ; and return ; **************************************************************************** ; Convert Hex Data to Segments. P2 Points to RAM. Drops through ; to hex address conversion ; **************************************************************************** DispD: ldi CRom.1 ; P1 = Segment conversion Table xpah 1 ldi CRom.0 xpal 1 ld word(2) ; get low nibble ani 0Fh xae ld -128(1) ; get CROM + E (low) st dl(2) ld word(2) ; get high nibble sr sr sr sr xae ld -128(1) ; get CROM + E st dh(2) ; update the display ; **************************************************************************** ; Convert Hex Address to segment, P2 points to RAM. Drops through ; to keyboard and display ; **************************************************************************** DispA: scl ldi CRom.1 ; P1 = Segment conversion Table xpah 1 ldi CRom.0 xpal 1 LoopD: ld adl(2) ani 0Fh xae ld -128(1) ; get CROM + E (low) st adll(2) ld adl(2) ; get high nibble sr sr sr sr xae ld -128(1) ; get CROM + E st adlh(2) ; update the display csa ; check if done ani 080h jz Done ccl ; clear carry,done next time ! ldi 0 st d4(2) ; zero digit 4 ld @2(2) ; fix P2 for next time around jmp LoopD Done: ld @-2(2) ; refix P2 on exit ; **************************************************************************** ; Keyboard and Display Input. ; JMP Command in A (GO=6,MEM=7,TERM=3,in E + 16) ; Number return, hex number in E reg ; ABORT key goes to abort ; all registers used ; P2 points to RAM,address MUST be xxx0 ; to re-execute do XPPC3 ; **************************************************************************** Kybd: ldi 0 ; zero char st char(2) ldi Disp.1 ; P1 points to the display xpah 1 Off: ldi -1 ; Set Row/Digit Address st row(2) ldi 10 ; Set Row Count st cnt(2) ldi 0 ; Zero keyboard input st pushed(2) xpal 1 ; Set display address (low) KDLoop: ild row(2) ; next row ? xae ; put it in E ld -128(2) ; get the segment into A st -128(1) ; send it to the display dly 0 ; delay for display,let keys settle ld -128(1) ; get keyboard input xri 0FFh ; invert the input so 1 = pressed jnz Key ; jump if a key pushed (save in Pushed) Back: dld cnt(2) ; check if done jnz KDLoop ; no if jump ld pushed(2) ; check if key pressed jz CkMore ; if no, then go to try again ld char(2) jnz Off ; if yes, wait for release ld pushed(2) ; released ? set char st char(2) jmp Off CkMore: ld char(2) ; check if there was a character jz Off ; no, keep looking ; **************************************************************************** ; Command Key Processing ; **************************************************************************** Command: xae ; copy into E lde ani 020h ; check for command jnz Cmnd ; jump if command ldi 080h ; find number (its a digit 0..F) ane jnz Lt7 ; 0 to 7 ldi 040h ane jnz N89 ; 8, 9 ldi 0fh ; B to F ane adi 7 xae ld -128(0) ; get number KeyRtn: xae ; save in E ld @2(3) ; fix return,add 2 xppc 3 jmp Kybd ; allows us to go round again db 0Ah, 0Bh, 0Ch, 0Dh, 0, 0, 0Eh, 0Fh Lt7: xre ; keep low digit (handler for 0..7) jmp KeyRtn N89: xre ; get low (handler for 8 & 9) adi 8 ; make it 8 or 9 jmp KeyRtn Cmnd: xre xri 4 ; check if abort jz Abrt ; if so,goto abort xppc 3 ; return jmp Kybd ; and allow reentry Key: ore ; make character st pushed(2) ; save it jmp Back Abrt: ldi Abort.1 ; goto abort xpah 3 ldi Abort.0-1 xpal 3 xppc 3 ; **************************************************************************** ; Required for RCASM } ; **************************************************************************** ; ****************************************************************************