diff --git a/build/misc.tcl b/build/misc.tcl index 1e8a6553..0d506865 100644 --- a/build/misc.tcl +++ b/build/misc.tcl @@ -1308,6 +1308,17 @@ expect ":KILL" respond "*" ":midas klh; ts 80tran_80tran\r" expect ":KILL" +respond "*" ":cwd klh\r" +respond "*" ":midas dfoo\r" +expect ":KILL" +respond "*" ":klh;80tran klh; dmlp 8080_dfoo bin\r" +expect ":kill" + +respond "*" ":midas nfoo\r" +expect ":KILL" +respond "*" ":klh;80tran klh; newlp 8080_nfoo bin\r" +expect ":kill" + # The old CLIB has a UFA instruction which doesn't work on a KS10. # Patch out the call to FIXIFY. respond "*" ":job cc\r" diff --git a/src/klh/dfoo.1 b/src/klh/dfoo.1 new file mode 100644 index 00000000..b5151709 --- /dev/null +++ b/src/klh/dfoo.1 @@ -0,0 +1,4 @@ +title nfoo +.insrt klh;8080df > +.insrt dmlp > +end diff --git a/src/klh/dmlp.11 b/src/klh/dmlp.11 new file mode 100644 index 00000000..85c55c59 --- /dev/null +++ b/src/klh/dmlp.11 @@ -0,0 +1,782 @@ +blnksw==1 ; set to assemble blinking cursor! +ibufsw==1 ; set to assemble input buffering routines. +;--------------------------------------------------; +; ; +; INTRODUCTION ; +; ; +;--------------------------------------------------; +; + ; TTY simulator and Downwire loader + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; Programmable Peripheral Interface #0 + ; + ; Use: Keyboard, Mouse, and Keyset buttons + ; + ; Mode: 273 (BB) + ; Port A used in Mode 1 for keyboard input + ; Port B used in Mode 0 for button sampling + ; Port C lower interrupt vector + ; Port C bit 6 and 7 unused + ; + ; Addresses: 367 (F7) control + ; 364 (F4) keyboard data - parity in MSB + ; 365 (F5) keyset (0-4), mouse (5-7) + ; 366 (F6) test keyboard ready bit 5 + ; + ; Programmable Peripheral Interface #1 + ; + ; Use: A/D Converter + ; + ; Mode: 232 (9A) + ; Port A used in Mode 0 for count LSB + ; Port B used in Mode 0 for count MSB + ; Port C lower Mode 0 output for cntl + ; Port C upper Mode input for status + ; + ; Addresses: 357 (EF) control + ; 354 (EC) bit 0-7 count + ; 355 (ED) bit 8-11 count + ; bit 12-15 are zero + ; 356 (EE) bit 0 strobe low to zero count + ; bit 1 strobe high to start x + ; bit 2 strobe high to start y + ; bit 3 not used + ; bit 4 (input) high during conversion + ; bit 5-7 (input) not used + ; + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; Programmable Peripheral Interface #2 + ; + ; Use: Video Display Controller + ; + ; Mode: 202 (82) + ; Port A used in Mode 0 for refresh base X 256 + ; Port B used in Mode 0 for status input + ; bit 0 vertical blanking + ; 1 horizontal blanking + ; 2 free + ; 3 free + ; 4 free + ; 5 free + ; 6 free + ; 7 "9th" refresh bit read + ; Port C various mode output + ; bit 0 memory access 0-CPU or 1-DPU + ; 1 free + ; 2 free + ; 3 free + ; 4 free + ; 5 free + ; 6 free + ; 7 "9th" refresh bit write + ; + ; Addresses: 177 (7F) control + ; 174 (7C) refresh base X 256 + ; 175 (7D) status input + ; 176 (7E) mode control output + ; + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; Programmable Communication Interface #0 + ; + ; Use: Display Interface (DI) + ; + ; Mode: 316 (CE) (2 stop bits,no parity, 8 bit, X16 factor) + ; + ; Command: 47 (27) (transmitter and receiver enable) + ; + ; Addresses: 373 (FB) control + ; 372 (FA) data (input or output) + ; + ; Programmable Communication Interface #1 + ; + ; Use: External Processor (EP) + ; + ; Mode: 316 (CE) (2 stop bits,no parity, 8 bit, X16 factor) + ; + ; Command: 47 (27) (transmitter and receiver enable) + ; + ; Addresses: 337 (DF) control + ; 336 (DE) data (input or output) + ; + ; Programmable Communication Interface #2 + ; + ; Use: Copy Printer (CP) + ; + ; Mode: 316 (CE)(2 stop bits,no parity, 8 bit, X16 factor) + ; + ; Command: 47 (27) (transmitter and receiver enable) + ; + ; Addresses: 277 (BF) control + ; 276 (BE) data (input or output) + ; + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; Device names + ; + keysmd= 273 ;keyboard and button mode + keys= 367 ;ppi-0 address + kbd= 364 ;keyboard address + kbdmsk= 177 ;clear parity + kbdflg= 040 ;keyboard ready bit + kbdsts= 366 ;keyboard status address + bttns= 365 ;mouse and keyset switches + msmsk= 340 ;mouse button mask + kstmsk= 37 ;keyset mask + ; + admd= 232 ;A/D converter mode + ad= 357 ;control address + adflg= 020 ;a/d busy bit + adsts= 356 ;a/d status address + strbx1= 3 ;bit set 1 + strbx2= 2 ;bit clear 1 + strby1= 5 ;bit set 2 + strby2= 4 ;bitr clear 2 + adclr1= 0 ;bit clear 0 + adclr2= 1 ;bit set 1 + admsb= 355 ;count msb's + adlsb= 354 ;count lsb's + ; + uartmd= 316 ;UART mode setting + uartcd= 47 ;UART command word + dicntl= 373 ;display control + dir= 372 ;di receiver + dix= 372 ;di transmitter + epcntl= 337 ;external processor contro + epr= 336 ;ep receiver + epx= 336 ;ep transmitter + cpcntl= 277 ;copy printer control + cpr= 276 ;cp receiver + cpx= 276 ;cp transmitter + rxrdy= 2 ;receiver ready bit + txrdy= 1 ;transmitter ready bit + parity= 177 ;clear parity bit + ; + vdmd= 202 ;Video Display mode + vd= 177 ;control address + vdbase= 174 ;refresh base address X 256 + vdstat= 175 ;status port + vdmode= 176 ;mode control port + vdscpu= 0 ;set CPU mode + vdsdpu= 1 ;set DPU mode + vds9= 17 ;set "9th" bit + vdc9= 16 ;clear "9th" bit + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; + ; Monitor constants + ; + mstak= 11752 ;top of stack + ; +; ptr= 11753 ;video diplay address +; ln= 11752 ;current display line + vdbsad==140000 ; base location of refresh memory + nchar= 80. ;characters per line + nline= 64. ;number of lines per screen + ; + moncll= ^_ ;US recalls monitor + monloc= 10 ;RST 1 address monitor start + ; + lpesc= 33 ;line processor escape char + ; + mar= 11776 ;memory address pointer + epbs= 11774 ;secondary state switch + +;--------------------------------------------------; +; ; +; SYSTEM INITIALIZATION ; +; ; +;--------------------------------------------------; +; + loc 10000 + .space 2 + jmp monci ;monitor input + jmp init ;monitor initalization and tty + .space 2 + init: mvi a,uartmd ;set uart modes + out dicntl + out epcntl + out cpcntl + mvi a,uartcd ;set command word + out dicntl + out epcntl + out cpcntl + .space 2 + mvi a,keysmd ;set keyboard mode (ppi) + out keys + .space 2 + mvi a,admd ;set a/d converter (ppi1) + out ad + .space 2 + mvi a,vdmd ;set video display controller + out vd + .space 2 + lxi h,mstak ;set stack pointer + sphl + +;--------------------------------------------------; +; ; +; TTY MODE ; +; ; +;--------------------------------------------------; +; + ttymd: lxi d,eps10 ;ep idle state + mvi a,300 ;set refresh base + out vdbase + kbdtst: in kbdsts ;keyboard full? + ani kbdflg + jz eptst ;no go on + kbdfc: in kbd ;attempt to clear flag + in kbdsts ;done? + ani kbdflg ;flag bit + jnz kbdfc ;keep trying + kbdin: in kbd ;get keyboard data + ani kbdmsk ;clear parity +; jz vdclr ;NULL key to clear screen +; cpi moncll ;US means back to monitor + ; NULL now means go to monitor... + jz monloc ;go there + mov c,a ;mov result to c + call epout ;send to ep + in kbd ;clear keyboard flag + ; +eptst: call episto + push d + call epiget + pop d + ani parity +; in epcntl ;ep full? +; ani rxrdy + jnz epin ;if something, jump. + call cblchk ; if nothing, check blinking. + jmp kbdtst + +epin: +; in epr +; ani parity +; jz kbdtst ;ignore nulls + cpi lpesc ;does a command begin? + jz eps12 + mov h,d ;dispatch + mov l,e + pchl ;reg pair d,e main state + ; + eps10: mov c,a ;transmit char + call vdout + eps14: lxi d,eps10 ;reset state switch + jmp kbdtst ;next + eps12: lxi d,eps20 ;set up to check next + jmp kbdtst + ; + eps20: cpi 100 ;case test on acc + jz eps21 + cpi 101 + jz eps22 + cpi 102 + jz eps14 + cpi 103 + jz eps24 + jmp eps10 + ; + eps21: lxi h,eps50 ;memory address reg + eps23: shld epbs ;after byte comes + ;epbs point to next routine + eps25: lxi d,eps30 ;lsb state + jmp kbdtst + eps22: lxi h,eps60 ;memory load turn on + jmp eps23 + eps24: jmp eps14 ;starting address ignored now + ; + eps30: ani 17 ;lsb to b + mov b,a + lxi d,eps40 ;set msb state + jmp kbdtst + eps40: ani 17 ;msb V b to a + rlc ;rotate to msb + rlc + rlc + rlc + ora b + lhld epbs ;post byte state + pchl ;jump there + ; + eps50: lxi h,mar ;memory address lsb + mov m,a ;store it + lxi h,eps51 ;next byte to msb + shld epbs + jmp eps25 + eps51: lxi h,mar+1 ;msb + mov m,a ;this build the top 8 bits + mvi c,53 ;tell user addr set + call vdout + jmp eps14 ;reset + ; + eps60: lhld mar ;pick memory address + mov m,a ;store the current byte + inx h ;next + shld mar ;and restore pointer + jmp eps25 ;stay in byte build up state + .space 2 + epout: in epcntl ;busy? + ani txrdy + jz epout ;wait + mov a,c ;char n c + out epx ;gone + ret + .space 2 + diout: in dicntl ;busy? + ani txrdy + jz diout + mov a,c ;char in c + out dix ;di transmitter + ret + .page +;--------------------------------------------------; +; ; +; MONITOR MODE KEYBOARD INPUT ; +; ; +;--------------------------------------------------; +; + monci: in kbdsts ;keyboard full? + ani kbdflg + jz mci1 ;no check di input + mci4: in kbd ;attempt to clear flag + in kbdsts ;done? + ani kbdflg ;flag bit + jnz mci4 ;keep trying + in kbd ;get char + jmp mci2 + mci1: in dicntl ;any di keyboard? + ani rxrdy + jz monci ;none keep trying + in dir ;get char + mci2: ani parity ;clear parity + cpi "a" ;force upper case + rm ;return less than small a + cpi "{" + rp ;greater than small z + sui 40 ;case change + mci3: ret + .page +;--------------------------------------------------; +; ; +; VIDEO DISPLAY OUTPUT ; +; ; +;--------------------------------------------------; +; + ; c -> video display + ; + vdout: +ifn blnksw, call cblset ; remove cursor char before performing operation. + lhld ptr ; Load HL with current dsp ptr for use by rtns. + mov a,c ; Test - anything special? + cpi 12 ;LF + jz dmlf ; go hack LF + sta lfflag ; reset LFFLAG non-Z to indicate LF operative. + cpi 15 ;CR? + jz dmcr ;uh-oh. go do. + sta nlflag ; reset auto-newline flag, CR operative. + cpi 002 ; ^B = HOME ? + jz dmhome + cpi 034 ; ^\ Forward Cursor? + jz dmfwd + cpi 010 ; ^H Back Cursor? + jz dmbkwd + cpi 032 ; ^Z Up Row Cursor? + jz dmup + cpi 037 ; Erase?(may be Clear-to-End-of-Screen for some models) + jz dmeos + cpi 036 ; Master Clear - defintely clear screen & home. + jz dmhclr + cpi 027 ; Erase to EOL + jz dmeol + cpi 014 ; ^L Start Absolute Positioning Address. + jz dmapos ; (takes two more chars as args) +; cpi 007 ; ^G Bell. What to do? Oh well. +; jz dmbell + ; more, but later. + + + cpi 40 ; hack to avoid bad font for blank. + jnz vdo2 ; skip smash of C if not blank. + mvi c,0 ; Ah, a blank! zero C to write + + ; "normal" char, stuff into display memory. +vdo2: mov a,c + sta bugch ; save char for debugging + mvi a,vdscpu ;get control of memory + out vd + mov m,c ;char -> refresh store + mvi a,vdsdpu ;give control back to dpu + out vd + shld bugptr ; save ptr for debugging +bmrk1: jmp dmfwd ; use standard rtn to move cursor & return. + inx h ;next loc (do this if above nop'd out. + shld ptr ;save + ret + ; + +dmcr: + sub a ; clear A + sta lfflag ; and disable LF if next char. + sta hcpos ; and clear horiz pos. + lda vcpos ;get line count + lxi h,vdbsad ; add vcpos*80. to this. + call mul80 + jmp dmlf50 ; Now hack LF, will set PTR. + + ; MUL80 - given value in A, multiplies by 80 and adds to HL. +mul80: sta bsav1 ; save for debug + mov c,a ;ln * 80 + 0C000H -> hl + rlc + rlc + rlc + rlc + mov e,a + ani 17 + mov d,a + mov a,e + ani 17_4 + mov e,a ;de have 16*ln + ; + mov a,c + rrc + rrc + mov c,a + ani 17 + mov b,a + mov a,c + ani 300 + mov c,a ;bc have 64*ln + ; + dad b ; add to current HL + dad d + shld bsav2 ; debug + ret ; return with value in HL + + +lfflag: 0 ; newline flag. zero means suppress LF, CR +vdlf: +dmlf: + lda lfflag ; Was newline done last pass? + cpi 0 + jnz dmlf50 ; jump if OK. + mvi a,^J ; Not OK this time, but reset flag. + sta lfflag + ret + +dmlf50: lda vcpos ; get current vert position + cpi 63. ; on bottom line now? + jnc dmlf60 ; Jump if A >= 63. and hence on bottom + inr a ; no, OK to move down. + sta vcpos ; store new V psition + lxi d,80. ; and add 80. to disp ptr + dad d ; like so. + shld ptr + ret + + ; Overflow, going off bottom! Either wrap or scroll. +dmlf60: xra a ; for now, wrap. + sta vcpos ; set to zero. + lhld hcpos ; get H position in HL, + lxi d,vdbsad ; and disp ptr base in DE + dad d ; and add to get new position. + shld ptr + ret + + + ; Clear to EOL from current position. +dmeol: lda vcpos ; Get current line # + inr a ; add one + lxi h,vdbsad + call mul80 ; multiply by 80. and add into HL + xchg ; put HL into DE + lhld ptr ; get back current dsp ptr + mov a,e ; get lo byte for subtract + sub l ; subtract lo byte + mov e,a ; move back. wins since can't be larger than 80. + + ; E now holds count of # chars to zero. +dmeol4: mvi a,vdscpu ; Grab access + out vd + sub a ; Clear ACC +dmeol5: mov m,a ; Deposit at least one blank + inx h ; increment dsp ptr + dcr e ; and bump count down... + jnz dmeol5 ; loop til line flushed. + mvi a,vdsdpu ; Now release access + out vd + ret ; return. PTR stays same, HL clobbered. + + ; Move Cursor Forward. If at end of line, do CRLF (yes, can scroll) +dmfwd: lda hcpos ; get horiz position + cpi 79. ; in last possible char position on line? + jnc dmcr ; jump if A >= 79. (carry only set if data greater) + inx h ; no, can safely increment horiz position. + inr a + sta hcpos ; store incremented hpos + shld ptr ; and ptr + ret + + ; Move Cursor Backward. If reach first char of line, don't move. +dmbkwd: lda hcpos ; Get horiz position + dcr a ; decrement + rm ; return if became negative; change nothing. + sta hcpos ; else store back decremented hpos + dcx h ; and decrement disp ptr also. + shld ptr + ret + + ; Move Cursor Upward. If already at top, don't move. +dmup: lda vcpos ; get vertical pos. + dcr a ; decrement... + rm ; return if negative, change nothing. + sta vcpos ; else store it, + lxi d,-80. ; and now subtract 80. from HL. + dad d ; like so. + shld ptr ; store back disp ptr. + ret + + ; Home Up. Move cursor to 0,0. +dmhome: sub a ; clear A, + sta hcpos ; and thus both H and V. + sta vcpos + lxi h,vdbsad ; Base of refresh memory. + shld ptr ; store initial ptr. + ret + + + + + + +;--------------------------------------------------; +; ; +; VIDEO DISPLAY OUTPUT ; +; ; +;--------------------------------------------------; +; + ; clear video display screen + ; +vdclr: push d ; called out of main loop which needs state saved. + call dmhclr + pop d + jmp kbdtst +dmeos: +dmhclr: call dmhome ; set up in home position + mvi d,64. + mvi a,vdscpu ;get control of CPU + out vd + sub a +vdcl1: mvi e,80. +vdcl2: mov m,a ; clear char pos + inx h ;next + dcr e + jnz vdcl2 + call episto ; after each line, check input. + xra a ; and re-zap acc. + dcr d + jnz vdcl1 + mvi a,vdsdpu ;return control to dpu + out vd + ret + + + ; DM2500 absolute cursor positioning. Must set up + ; special states to gobble next two input chars! +dmapos: pop h ; get return addr off stack, + shld dmapsv ; and save specially so don't depend on stack. + lxi d,dmaps2 ; jump to dmaps2 on next input. + jmp kbdtst +dmaps2: xri 140 ; First char is X position - complement bits 140. + sta hcpos ; and store. + lxi d,dmaps3 ; don't change PTR now, wait for Y position. + jmp kbdtst +dmaps3: xri 140 ; Second char is Y position - same mung. + sta vcpos ; and store. + call cblset ; reset cursor before moving... + lda vcpos ; get back line #. + lxi h,vdbsad ; now set up for + call mul80 ; finding V*80. + vdbsad. + xchg ; move HL to DE. + lhld hcpos ; get H pos into L, 0 into H + dad d ; add in to get final disp ptr. + shld ptr ; and store it. + lhld dmapsv ; now get back original return addr + pchl ; and pretend we're returning. + +dmapsv: 0 ? 0 ; 1 word + +vars:: +hcpos: 0 ; Horiz Cursor Position. Only one byte, but + .HI. 0 ; have zero byte following so double loads win. +vcpos: 0 ; Vertical Cursor Position. Like HCPOS. + .HI. 0 +ptr: 0 ? 0 + +bugch: 0 ; char written by VDO2 +bugptr: 0 ? 0 ; into this refresh location. +bsav1: 0 ? 0 ; arg in A to MUL80 +bsav2: 0 ? 0 ; rsult in HL of MUL80 + + +; optional cursor blinking stuff! +ifn blnksw,[ + + ; check whether time to blink cursor. +cblchk: lxi h,cbltic + dcr m + rnz + + +; lhld cbltic ; load tick counter into HL +; lxi b,1 ; st BC to 1 +; dad b ; add 1 into HL tick counter +; jc cblck2 ; jump if carried out! +; shld cbltic ; nope, move back new tick count +; ret ; that's all folks +cblck2: lxi h,cblcnt ; load addr to count word + dcr m ; decrement cnt + rnz ; return if not zero yet. + + ; Aha, ready to blink! + lhld ptr ; get cursor loc + lda cblch ; and saved blinkchar in acc + mov b,a ; now in b + mvi a,vdscpu ; seize access + out vd + mov c,m ; get char currently on screen + mov m,b ; replace with blinkchar + mvi a,vdsdpu ; release access + out vd + mov a,c + sta cblch ; save replaced char as new blinkchar! + ; drop thru to reset blink cnt + ; start a blink countdown +cblst: mvi a,377 + sta cbltic +; lxi h,0 ; clear the +; shld cbltic ; tick counter, and + lda blnktm ; put some random tuning number in + sta cblcnt ; main count. + ret + + ; Call this when about to move cursor, to ensure right + ; char gets left on screen! +cblset: lda blnkch ; get blink char + mov b,a + lda cblch ; get cha saved + cmp b ; compare. +; lda cblch ; get char saved +; cpi blnkch ; compare with blink ch + jz cblst ; if same, no worry - to reset count! + lhld ptr ; els must replace blink char... + mov b,a + mvi a,vdscpu ; grab access + out vd + mov m,b ; store the char. + mvi a,vdsdpu + out vd + lda blnkch ; now reset blinkchar to + sta cblch ; proper value! + jmp cblst +cbltic: 0 ; one word + 0 +cblcnt: 0 ; for overall count +blnkch: "_ ; defines cursor character. +blnktm: 12. ; defines time rate for blinking. +cblch: 0 ; holds swapped cursor char. +] ; end of IFN BLNKSW +nlflag: 0 + +ifn ibufsw,[ +; Input buffering routines. + + +tiwp: ibufln ? .hi. 0 ; write ptr index into buffer. points to last loc writ. +tirp: ibufln+1 ? .hi. 0 ; read ptr index into buffer, points to last loc read +tirm: ibufln ; # chars of room in buffer. +ibufln==60. ; buffer up 60 chars... .0625 sec @ 9.6 kbd +ibuff: block ibufln+1 + +; EPISTO - tests for EP input, and stores in buffer if any. +; Clobbers A + +episto: in epcntl + ani rxrdy + rz ; return if nothing to read. + in epr + + push d + push h + lxi d,ibuff ; get addr of buffer + lhld tiwp ; get write ptr index + xchg ; index in DE, buffer base in HL + dad d ; final addr + mov m,a ; store right away. + lda tirm ; now get count of chars left + dcr a ; decrement, and + jm epist7 ; flush it if zero - no more room. + sta tirm ; else store back. + mov a,e ; Now get low byte of index + dcr a ; bump down + jnz epist5 ; skip if needn't wrap. + mvi a,ibufln ; else must wrap index. +epist5: sta tiwp ; store back write index. +epist7: pop h + pop d + ret ; Return. + + + +; EPIGET - Reads one char from EP input buffer, returns in A. +; A will be 0 if nothing was there, or if char was null, hence is OK +; to test that way. + +epiget: lda tirm ; See how many chars left in buffer + cpi ibufln ; If this many, + jz epigt7 ; then none to read, try direct I/O. + inr a ; Ah, something, bump count up. + sta tirm ; and store back. + lxi d,ibuff ; get buffer base + lhld tirp ; and read-pointer index + dcr l ; decrement, + jnz epigt5 ; and skip if needn't wrap + mvi l,ibufln ; else wrap it, +epigt5: shld tirp ; store index back, + dad d ; get final address, + mov a,m ; and finally get character! + ret +epigt7: in epcntl + ani rxrdy + rz + in epr + ret +] ; ifn ibufsw diff --git a/src/klh/lp.3 b/src/klh/lp.3 new file mode 100644 index 00000000..5dc3c52b --- /dev/null +++ b/src/klh/lp.3 @@ -0,0 +1,477 @@ + +;--------------------------------------------------; +; ; +; INTRODUCTION ; +; ; +;--------------------------------------------------; +; + ; TTY simulator and Downwire loader + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; Programmable Peripheral Interface #0 + ; + ; Use: Keyboard, Mouse, and Keyset buttons + ; + ; Mode: 273 (BB) + ; Port A used in Mode 1 for keyboard input + ; Port B used in Mode 0 for button sampling + ; Port C lower interrupt vector + ; Port C bit 6 and 7 unused + ; + ; Addresses: 367 (F7) control + ; 364 (F4) keyboard data - parity in MSB + ; 365 (F5) keyset (0-4), mouse (5-7) + ; 366 (F6) test keyboard ready bit 5 + ; + ; Programmable Peripheral Interface #1 + ; + ; Use: A/D Converter + ; + ; Mode: 232 (9A) + ; Port A used in Mode 0 for count LSB + ; Port B used in Mode 0 for count MSB + ; Port C lower Mode 0 output for cntl + ; Port C upper Mode input for status + ; + ; Addresses: 357 (EF) control + ; 354 (EC) bit 0-7 count + ; 355 (ED) bit 8-11 count + ; bit 12-15 are zero + ; 356 (EE) bit 0 strobe low to zero count + ; bit 1 strobe high to start x + ; bit 2 strobe high to start y + ; bit 3 not used + ; bit 4 (input) high during conversion + ; bit 5-7 (input) not used + ; + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; Programmable Peripheral Interface #2 + ; + ; Use: Video Display Controller + ; + ; Mode: 202 (82) + ; Port A used in Mode 0 for refresh base X 256 + ; Port B used in Mode 0 for status input + ; bit 0 vertical blanking + ; 1 horizontal blanking + ; 2 free + ; 3 free + ; 4 free + ; 5 free + ; 6 free + ; 7 "9th" refresh bit read + ; Port C various mode output + ; bit 0 memory access 0-CPU or 1-DPU + ; 1 free + ; 2 free + ; 3 free + ; 4 free + ; 5 free + ; 6 free + ; 7 "9th" refresh bit write + ; + ; Addresses: 177 (7F) control + ; 174 (7C) refresh base X 256 + ; 175 (7D) status input + ; 176 (7E) mode control output + ; + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; Programmable Communication Interface #0 + ; + ; Use: Display Interface (DI) + ; + ; Mode: 316 (CE) (2 stop bits,no parity, 8 bit, X16 factor) + ; + ; Command: 47 (27) (transmitter and receiver enable) + ; + ; Addresses: 373 (FB) control + ; 372 (FA) data (input or output) + ; + ; Programmable Communication Interface #1 + ; + ; Use: External Processor (EP) + ; + ; Mode: 316 (CE) (2 stop bits,no parity, 8 bit, X16 factor) + ; + ; Command: 47 (27) (transmitter and receiver enable) + ; + ; Addresses: 337 (DF) control + ; 336 (DE) data (input or output) + ; + ; Programmable Communication Interface #2 + ; + ; Use: Copy Printer (CP) + ; + ; Mode: 316 (CE)(2 stop bits,no parity, 8 bit, X16 factor) + ; + ; Command: 47 (27) (transmitter and receiver enable) + ; + ; Addresses: 277 (BF) control + ; 276 (BE) data (input or output) + ; + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; Device names + ; + keysmd= 273 ;keyboard and button mode + keys= 367 ;ppi-0 address + kbd= 364 ;keyboard address + kbdmsk= 177 ;clear parity + kbdflg= 040 ;keyboard ready bit + kbdsts= 366 ;keyboard status address + bttns= 365 ;mouse and keyset switches + msmsk= 340 ;mouse button mask + kstmsk= 37 ;keyset mask + ; + admd= 232 ;A/D converter mode + ad= 357 ;control address + adflg= 020 ;a/d busy bit + adsts= 356 ;a/d status address + strbx1= 3 ;bit set 1 + strbx2= 2 ;bit clear 1 + strby1= 5 ;bit set 2 + strby2= 4 ;bitr clear 2 + adclr1= 0 ;bit clear 0 + adclr2= 1 ;bit set 1 + admsb= 355 ;count msb's + adlsb= 354 ;count lsb's + ; + uartmd= 316 ;UART mode setting + uartcd= 47 ;UART command word + dicntl= 373 ;display control + dir= 372 ;di receiver + dix= 372 ;di transmitter + epcntl= 337 ;external processor contro + epr= 336 ;ep receiver + epx= 336 ;ep transmitter + cpcntl= 277 ;copy printer control + cpr= 276 ;cp receiver + cpx= 276 ;cp transmitter + rxrdy= 2 ;receiver ready bit + txrdy= 1 ;transmitter ready bit + parity= 177 ;clear parity bit + ; + vdmd= 202 ;Video Display mode + vd= 177 ;control address + vdbase= 174 ;refresh base address X 256 + vdstat= 175 ;status port + vdmode= 176 ;mode control port + vdscpu= 0 ;set CPU mode + vdsdpu= 1 ;set DPU mode + vds9= 17 ;set "9th" bit + vdc9= 16 ;clear "9th" bit + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; + ; Monitor constants + ; + mstak= 11752 ;top of stack + ; + ptr= 11753 ;video diplay address + ln= 11752 ;current display line + nchar= 80. ;characters per line + nline= 64. ;number of lines per screen + ; + moncll= ^_ ;US recalls monitor + monloc= 10 ;RST 1 address monitor start + ; + lpesc= 33 ;line processor escape char + ; + mar= 11776 ;memory address pointer + epbs= 11774 ;secondary state switch + +;--------------------------------------------------; +; ; +; SYSTEM INITIALIZATION ; +; ; +;--------------------------------------------------; +; + loc 10000 + .space 2 + jmp monci ;monitor input + jmp init ;monitor initalization and tty + .space 2 + init: mvi a,uartmd ;set uart modes + out dicntl + out epcntl + out cpcntl + mvi a,uartcd ;set command word + out dicntl + out epcntl + out cpcntl + .space 2 + mvi a,keysmd ;set keyboard mode (ppi) + out keys + .space 2 + mvi a,admd ;set a/d converter (ppi1) + out ad + .space 2 + mvi a,vdmd ;set video display controller + out vd + .space 2 + lxi h,mstak ;set stack pointer + sphl + +;--------------------------------------------------; +; ; +; TTY MODE ; +; ; +;--------------------------------------------------; +; + ttymd: lxi d,eps10 ;ep idle state + mvi a,300 ;set refresh base + out vdbase + kbdtst: in kbdsts ;keyboard full? + ani kbdflg + jz eptst ;no go on + kbdfc: in kbd ;attempt to clear flag + in kbdsts ;done? + ani kbdflg ;flag bit + jnz kbdfc ;keep trying + kbdin: in kbd ;get keyboard data + ani kbdmsk ;clear parity + jz vdclr ;NULL key to clear screen + cpi moncll ;US means back to monitor + jz monloc ;go there + mov c,a ;mov result to c + call epout ;send to ep + in kbd ;clear keyboard flag + ; + eptst: in epcntl ;ep full? + ani rxrdy + jz kbdtst ;nothing repeat loop + epin: in epr + ani parity + jz kbdtst ;ignore nulls + cpi lpesc ;does a command begin? + jz eps12 + mov h,d ;dispatch + mov l,e + pchl ;reg pair d,e main state + ; + eps10: mov c,a ;transmit char + call vdout + eps14: lxi d,eps10 ;reset state switch + jmp kbdtst ;next + eps12: lxi d,eps20 ;set up to check next + jmp kbdtst + ; + eps20: cpi 100 ;case test on acc + jz eps21 + cpi 101 + jz eps22 + cpi 102 + jz eps14 + cpi 103 + jz eps24 + jmp eps10 + ; + eps21: lxi h,eps50 ;memory address reg + eps23: shld epbs ;after byte comes + ;epbs point to next routine + eps25: lxi d,eps30 ;lsb state + jmp kbdtst + eps22: lxi h,eps60 ;memory load turn on + jmp eps23 + eps24: jmp eps14 ;starting address ignored now + ; + eps30: ani 17 ;lsb to b + mov b,a + lxi d,eps40 ;set msb state + jmp kbdtst + eps40: ani 17 ;msb V b to a + rlc ;rotate to msb + rlc + rlc + rlc + ora b + lhld epbs ;post byte state + pchl ;jump there + ; + eps50: lxi h,mar ;memory address lsb + mov m,a ;store it + lxi h,eps51 ;next byte to msb + shld epbs + jmp eps25 + eps51: lxi h,mar+1 ;msb + mov m,a ;this build the top 8 bits + mvi c,53 ;tell user addr set + call vdout + jmp eps14 ;reset + ; + eps60: lhld mar ;pick memory address + mov m,a ;store the current byte + inx h ;next + shld mar ;and restore pointer + jmp eps25 ;stay in byte build up state + .space 2 + epout: in epcntl ;busy? + ani txrdy + jz epout ;wait + mov a,c ;char n c + out epx ;gone + ret + .space 2 + diout: in dicntl ;busy? + ani txrdy + jz diout + mov a,c ;char in c + out dix ;di transmitter + ret + .page +;--------------------------------------------------; +; ; +; MONITOR MODE KEYBOARD INPUT ; +; ; +;--------------------------------------------------; +; + monci: in kbdsts ;keyboard full? + ani kbdflg + jz mci1 ;no check di input + mci4: in kbd ;attempt to clear flag + in kbdsts ;done? + ani kbdflg ;flag bit + jnz mci4 ;keep trying + in kbd ;get char + jmp mci2 + mci1: in dicntl ;any di keyboard? + ani rxrdy + jz monci ;none keep trying + in dir ;get char + mci2: ani parity ;clear parity + cpi "a" ;force upper case + rm ;return less than small a + cpi "{" + rp ;greater than small z + sui 40 ;case change + mci3: ret + .page +;--------------------------------------------------; +; ; +; VIDEO DISPLAY OUTPUT ; +; ; +;--------------------------------------------------; +; + ; c -> video display + ; + vdout: mov a,c ;anything special? + cpi 15 ;CR + jz vdcr + cpi 12 ;LF + jz vdlf + cpi 40 ; hack to avoid bad font for blank. + jnz vdo2 ; skip smash of C if not blank. + mvi c,0 ; Ah, a blank! zero C to write + ; + vdo2: lhld ptr ;pointer to next char + mvi a,vdscpu ;get control of memory + out vd + mov m,c ;char -> refresh store + mvi a,vdsdpu ;give control back to dpu + out vd + inx h ;next loc + shld ptr ;save + ret + ; + vdcr: lda ln ;get line count + inr a ;next line + ani 77 ;constrain to 64 lines + sta ln ;restore + ; + mov c,a ;ln * 80 + 0C000H -> hl + rlc + rlc + rlc + rlc + mov e,a + ani 17 + mov d,a + mov a,e + ani 17_4 + mov e,a ;de have 16*ln + ; + mov a,c + rrc + rrc + mov c,a + ani 17 + mov b,a + mov a,c + ani 300 + mov c,a ;bc have 64*ln + ; + lxi h,140000 ;base of refresh + dad b + dad d + shld ptr ;pointer + ; + mvi a,vdscpu ;get control of memory + out vd + mvi a,0 ;clear this line + mvi b,nchar + vdcr1: mov m,a + inx h + dcr b + jnz vdcr1 + mvi a,vdsdpu ;give control back to dpu + out vd + ret + ; + vdlf: ret ;for now + .page +;--------------------------------------------------; +; ; +; VIDEO DISPLAY OUTPUT ; +; ; +;--------------------------------------------------; +; + ; clear video display screen + ; + vdclr: mvi b,nline ;number of lines + lxi h,140000 ;base address + mvi a,vdscpu ;get control of CPU + out vd + mvi a,0 + vdcl1: mvi c,nchar ;number of chars + vdcl2: mov m,a + inx h ;next + dcr c + jnz vdcl2 + ; + dcr b + jnz vdcl1 + ; + xra a ;clear a + sta ln ;reset line count + lxi h,140000 ;base address + shld ptr + mvi a,vdsdpu ;return control to dpu + out vd + jmp kbdtst diff --git a/src/klh/newlp.33 b/src/klh/newlp.33 new file mode 100644 index 00000000..d14e0a3d --- /dev/null +++ b/src/klh/newlp.33 @@ -0,0 +1,759 @@ +blnksw==1 ; set to assemble blinking cursor! +ibufsw==0 ; set to assemble input buffering routines. +;--------------------------------------------------; +; ; +; INTRODUCTION ; +; ; +;--------------------------------------------------; +; + ; TTY simulator and Downwire loader + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; Programmable Peripheral Interface #0 + ; + ; Use: Keyboard, Mouse, and Keyset buttons + ; + ; Mode: 273 (BB) + ; Port A used in Mode 1 for keyboard input + ; Port B used in Mode 0 for button sampling + ; Port C lower interrupt vector + ; Port C bit 6 and 7 unused + ; + ; Addresses: 367 (F7) control + ; 364 (F4) keyboard data - parity in MSB + ; 365 (F5) keyset (0-4), mouse (5-7) + ; 366 (F6) test keyboard ready bit 5 + ; + ; Programmable Peripheral Interface #1 + ; + ; Use: A/D Converter + ; + ; Mode: 232 (9A) + ; Port A used in Mode 0 for count LSB + ; Port B used in Mode 0 for count MSB + ; Port C lower Mode 0 output for cntl + ; Port C upper Mode input for status + ; + ; Addresses: 357 (EF) control + ; 354 (EC) bit 0-7 count + ; 355 (ED) bit 8-11 count + ; bit 12-15 are zero + ; 356 (EE) bit 0 strobe low to zero count + ; bit 1 strobe high to start x + ; bit 2 strobe high to start y + ; bit 3 not used + ; bit 4 (input) high during conversion + ; bit 5-7 (input) not used + ; + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; Programmable Peripheral Interface #2 + ; + ; Use: Video Display Controller + ; + ; Mode: 202 (82) + ; Port A used in Mode 0 for refresh base X 256 + ; Port B used in Mode 0 for status input + ; bit 0 vertical blanking + ; 1 horizontal blanking + ; 2 free + ; 3 free + ; 4 free + ; 5 free + ; 6 free + ; 7 "9th" refresh bit read + ; Port C various mode output + ; bit 0 memory access 0-CPU or 1-DPU + ; 1 free + ; 2 free + ; 3 free + ; 4 free + ; 5 free + ; 6 free + ; 7 "9th" refresh bit write + ; + ; Addresses: 177 (7F) control + ; 174 (7C) refresh base X 256 + ; 175 (7D) status input + ; 176 (7E) mode control output + ; + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; Programmable Communication Interface #0 + ; + ; Use: Display Interface (DI) + ; + ; Mode: 316 (CE) (2 stop bits,no parity, 8 bit, X16 factor) + ; + ; Command: 47 (27) (transmitter and receiver enable) + ; + ; Addresses: 373 (FB) control + ; 372 (FA) data (input or output) + ; + ; Programmable Communication Interface #1 + ; + ; Use: External Processor (EP) + ; + ; Mode: 316 (CE) (2 stop bits,no parity, 8 bit, X16 factor) + ; + ; Command: 47 (27) (transmitter and receiver enable) + ; + ; Addresses: 337 (DF) control + ; 336 (DE) data (input or output) + ; + ; Programmable Communication Interface #2 + ; + ; Use: Copy Printer (CP) + ; + ; Mode: 316 (CE)(2 stop bits,no parity, 8 bit, X16 factor) + ; + ; Command: 47 (27) (transmitter and receiver enable) + ; + ; Addresses: 277 (BF) control + ; 276 (BE) data (input or output) + ; + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; Device names + ; + keysmd= 273 ;keyboard and button mode + keys= 367 ;ppi-0 address + kbd= 364 ;keyboard address + kbdmsk= 177 ;clear parity + kbdflg= 040 ;keyboard ready bit + kbdsts= 366 ;keyboard status address + bttns= 365 ;mouse and keyset switches + msmsk= 340 ;mouse button mask + kstmsk= 37 ;keyset mask + ; + admd= 232 ;A/D converter mode + ad= 357 ;control address + adflg= 020 ;a/d busy bit + adsts= 356 ;a/d status address + strbx1= 3 ;bit set 1 + strbx2= 2 ;bit clear 1 + strby1= 5 ;bit set 2 + strby2= 4 ;bitr clear 2 + adclr1= 0 ;bit clear 0 + adclr2= 1 ;bit set 1 + admsb= 355 ;count msb's + adlsb= 354 ;count lsb's + ; + uartmd= 316 ;UART mode setting + uartcd= 47 ;UART command word + dicntl= 373 ;display control + dir= 372 ;di receiver + dix= 372 ;di transmitter + epcntl= 337 ;external processor contro + epr= 336 ;ep receiver + epx= 336 ;ep transmitter + cpcntl= 277 ;copy printer control + cpr= 276 ;cp receiver + cpx= 276 ;cp transmitter + rxrdy= 2 ;receiver ready bit + txrdy= 1 ;transmitter ready bit + parity= 177 ;clear parity bit + ; + vdmd= 202 ;Video Display mode + vd= 177 ;control address + vdbase= 174 ;refresh base address X 256 + vdstat= 175 ;status port + vdmode= 176 ;mode control port + vdscpu= 0 ;set CPU mode + vdsdpu= 1 ;set DPU mode + vds9= 17 ;set "9th" bit + vdc9= 16 ;clear "9th" bit + +;--------------------------------------------------; +; ; +; INPUT/OUTPUT EQUIPMENT ; +; ; +;--------------------------------------------------; +; + ; + ; Monitor constants + ; + mstak= 11752 ;top of stack + ; +; ptr= 11753 ;video diplay address +; ln= 11752 ;current display line + vdbsad==140000 ; base location of refresh memory + nchar= 80. ;characters per line + nline= 64. ;number of lines per screen + ; + moncll= ^_ ;US recalls monitor + monloc= 10 ;RST 1 address monitor start + ; + lpesc= 33 ;line processor escape char + ; + mar= 11776 ;memory address pointer + epbs= 11774 ;secondary state switch + +;--------------------------------------------------; +; ; +; SYSTEM INITIALIZATION ; +; ; +;--------------------------------------------------; +; + loc 10000 + .space 2 + jmp monci ;monitor input + jmp init ;monitor initalization and tty + .space 2 + init: mvi a,uartmd ;set uart modes + out dicntl + out epcntl + out cpcntl + mvi a,uartcd ;set command word + out dicntl + out epcntl + out cpcntl + .space 2 + mvi a,keysmd ;set keyboard mode (ppi) + out keys + .space 2 + mvi a,admd ;set a/d converter (ppi1) + out ad + .space 2 + mvi a,vdmd ;set video display controller + out vd + .space 2 + lxi h,mstak ;set stack pointer + sphl + +;--------------------------------------------------; +; ; +; TTY MODE ; +; ; +;--------------------------------------------------; +; + ttymd: lxi d,eps10 ;ep idle state + mvi a,300 ;set refresh base + out vdbase + kbdtst: in kbdsts ;keyboard full? + ani kbdflg + jz eptst ;no go on + kbdfc: in kbd ;attempt to clear flag + in kbdsts ;done? + ani kbdflg ;flag bit + jnz kbdfc ;keep trying + kbdin: in kbd ;get keyboard data + ani kbdmsk ;clear parity +nulclr: jz vdclr ;NULL key to clear screen + cpi moncll ;US means back to monitor + jz monloc ;go there + mov c,a ;mov result to c + call epout ;send to ep + in kbd ;clear keyboard flag + ; + eptst: in epcntl ;ep full? + ani rxrdy +ifn blnksw,[ jnz epin ;if something, jump. + call cblchk ; if nothing, check blinking. + jmp kbdtst +] +ife blnksw, jz kbdtst + epin: in epr + ani parity + jz kbdtst ;ignore nulls + cpi lpesc ;does a command begin? + jz eps12 + mov h,d ;dispatch + mov l,e + pchl ;reg pair d,e main state + ; + eps10: mov c,a ;transmit char + call vdout + eps14: lxi d,eps10 ;reset state switch + jmp kbdtst ;next + eps12: lxi d,eps20 ;set up to check next + jmp kbdtst + ; + eps20: cpi 100 ;case test on acc + jz eps21 + cpi 101 + jz eps22 + cpi 102 + jz eps14 + cpi 103 + jz eps24 + jmp eps10 + ; + eps21: lxi h,eps50 ;memory address reg + eps23: shld epbs ;after byte comes + ;epbs point to next routine + eps25: lxi d,eps30 ;lsb state + jmp kbdtst + eps22: lxi h,eps60 ;memory load turn on + jmp eps23 + eps24: jmp eps14 ;starting address ignored now + ; + eps30: ani 17 ;lsb to b + mov b,a + lxi d,eps40 ;set msb state + jmp kbdtst + eps40: ani 17 ;msb V b to a + rlc ;rotate to msb + rlc + rlc + rlc + ora b + lhld epbs ;post byte state + pchl ;jump there + ; + eps50: lxi h,mar ;memory address lsb + mov m,a ;store it + lxi h,eps51 ;next byte to msb + shld epbs + jmp eps25 + eps51: lxi h,mar+1 ;msb + mov m,a ;this build the top 8 bits + mvi c,53 ;tell user addr set + call vdout + jmp eps14 ;reset + ; + eps60: lhld mar ;pick memory address + mov m,a ;store the current byte + inx h ;next + shld mar ;and restore pointer + jmp eps25 ;stay in byte build up state + .space 2 + epout: in epcntl ;busy? + ani txrdy + jz epout ;wait + mov a,c ;char n c + out epx ;gone + ret + .space 2 + diout: in dicntl ;busy? + ani txrdy + jz diout + mov a,c ;char in c + out dix ;di transmitter + ret + .page +;--------------------------------------------------; +; ; +; MONITOR MODE KEYBOARD INPUT ; +; ; +;--------------------------------------------------; +; + monci: in kbdsts ;keyboard full? + ani kbdflg + jz mci1 ;no check di input + mci4: in kbd ;attempt to clear flag + in kbdsts ;done? + ani kbdflg ;flag bit + jnz mci4 ;keep trying + in kbd ;get char + jmp mci2 + mci1: in dicntl ;any di keyboard? + ani rxrdy + jz monci ;none keep trying + in dir ;get char + mci2: ani parity ;clear parity + cpi "a" ;force upper case + rm ;return less than small a + cpi "{" + rp ;greater than small z + sui 40 ;case change + mci3: ret + .page +;--------------------------------------------------; +; ; +; VIDEO DISPLAY OUTPUT ; +; ; +;--------------------------------------------------; +; + ; c -> video display + ; + vdout: +ifn blnksw, call cblset ; remove cursor char before performing operation. + lhld ptr ; Load HL with current dsp ptr for use by rtns. + mov a,c ; Test - anything special? + cpi 12 ;LF + jz dmlf ; go hack LF + sta lfflag ; reset LFFLAG non-Z to indicate LF operative. + cpi 15 ;CR? + jz dmcr ;uh-oh. go do. + sta nlflag ; reset auto-newline flag, CR operative. + cpi 002 ; ^B = HOME ? + jz dmhome + cpi 034 ; ^\ Forward Cursor? + jz dmfwd + cpi 010 ; ^H Back Cursor? + jz dmbkwd + cpi 032 ; ^Z Up Row Cursor? + jz dmup + cpi 037 ; Erase?(may be Clear-to-End-of-Screen for some models) + jz dmeos + cpi 036 ; Master Clear - defintely clear screen & home. + jz dmhclr + cpi 027 ; Erase to EOL + jz dmeol + cpi 014 ; ^L Start Absolute Positioning Address. + jz dmapos ; (takes two more chars as args) +; cpi 007 ; ^G Bell. What to do? Oh well. +; jz dmbell + ; more, but later. + + + cpi 40 ; hack to avoid bad font for blank. + jnz vdo2 ; skip smash of C if not blank. + mvi c,0 ; Ah, a blank! zero C to write + + ; "normal" char, stuff into display memory. +vdo2: mov a,c + sta bugch ; save char for debugging + mvi a,vdscpu ;get control of memory + out vd + mov m,c ;char -> refresh store + mvi a,vdsdpu ;give control back to dpu + out vd + shld bugptr ; save ptr for debugging +bmrk1: jmp dmfwd ; use standard rtn to move cursor & return. + inx h ;next loc (do this if above nop'd out. + shld ptr ;save + ret + ; + +dmcr: + sub a ; clear A + sta lfflag ; and disable LF if next char. + sta hcpos ; and clear horiz pos. + lda vcpos ;get line count + lxi h,vdbsad ; add vcpos*80. to this. + call mul80 + jmp dmlf50 ; Now hack LF, will set PTR. + + ; MUL80 - given value in A, multiplies by 80 and adds to HL. +mul80: sta bsav1 ; save for debug + mov c,a ;ln * 80 + 0C000H -> hl + rlc + rlc + rlc + rlc + mov e,a + ani 17 + mov d,a + mov a,e + ani 17_4 + mov e,a ;de have 16*ln + ; + mov a,c + rrc + rrc + mov c,a + ani 17 + mov b,a + mov a,c + ani 300 + mov c,a ;bc have 64*ln + ; + dad b ; add to current HL + dad d + shld bsav2 ; debug + ret ; return with value in HL + + +lfflag: 0 ; newline flag. zero means suppress LF, CR +vdlf: +dmlf: + lda lfflag ; Was newline done last pass? + cpi 0 + jnz dmlf50 ; jump if OK. + mvi a,^J ; Not OK this time, but reset flag. + sta lfflag + ret + +dmlf50: lda vcpos ; get current vert position + cpi 63. ; on bottom line now? + jnc dmlf60 ; Jump if A >= 63. and hence on bottom + inr a ; no, OK to move down. + sta vcpos ; store new V psition + lxi d,80. ; and add 80. to disp ptr + dad d ; like so. + shld ptr + ret + + ; Overflow, going off bottom! Either wrap or scroll. +dmlf60: xra a ; for now, wrap. + sta vcpos ; set to zero. + lhld hcpos ; get H position in HL, + lxi d,vdbsad ; and disp ptr base in DE + dad d ; and add to get new position. + shld ptr + ret + + + ; Clear to EOL from current position. +dmeol: lda vcpos ; Get current line # + inr a ; add one + lxi h,vdbsad + call mul80 ; multiply by 80. and add into HL + xchg ; put HL into DE + lhld ptr ; get back current dsp ptr + mov a,e ; get lo byte for subtract + sub l ; subtract lo byte + mov e,a ; move back. wins since can't be larger than 80. + + ; E now holds count of # chars to zero. +dmeol4: mvi a,vdscpu ; Grab access + out vd + sub a ; Clear ACC +dmeol5: mov m,a ; Deposit at least one blank + inx h ; increment dsp ptr + dcr e ; and bump count down... + jnz dmeol5 ; loop til line flushed. + mvi a,vdsdpu ; Now release access + out vd + ret ; return. PTR stays same, HL clobbered. + + ; Move Cursor Forward. If at end of line, do CRLF (yes, can scroll) +dmfwd: lda hcpos ; get horiz position + cpi 79. ; in last possible char position on line? + jnc dmcr ; jump if A >= 79. (carry only set if data greater) + inx h ; no, can safely increment horiz position. + inr a + sta hcpos ; store incremented hpos + shld ptr ; and ptr + ret + + ; Move Cursor Backward. If reach first char of line, don't move. +dmbkwd: lda hcpos ; Get horiz position + dcr a ; decrement + rm ; return if became negative; change nothing. + sta hcpos ; else store back decremented hpos + dcx h ; and decrement disp ptr also. + shld ptr + ret + + ; Move Cursor Upward. If already at top, don't move. +dmup: lda vcpos ; get vertical pos. + dcr a ; decrement... + rm ; return if negative, change nothing. + sta vcpos ; else store it, + lxi d,-80. ; and now subtract 80. from HL. + dad d ; like so. + shld ptr ; store back disp ptr. + ret + + ; Home Up. Move cursor to 0,0. +dmhome: sub a ; clear A, + sta hcpos ; and thus both H and V. + sta vcpos + lxi h,vdbsad ; Base of refresh memory. + shld ptr ; store initial ptr. + ret + + + + + + +;--------------------------------------------------; +; ; +; VIDEO DISPLAY OUTPUT ; +; ; +;--------------------------------------------------; +; + ; clear video display screen + ; +vdclr: push d ; called out of main loop which needs state saved. + call dmhclr + pop d + jmp kbdtst +dmeos: +dmhclr: call dmhome ; set up in home position + mvi d,64. + mvi a,vdscpu ;get control of CPU + out vd + sub a +vdcl1: mvi e,80. +vdcl2: mov m,a ; clear char pos + inx h ;next + dcr e + jnz vdcl2 + dcr d + jnz vdcl1 + mvi a,vdsdpu ;return control to dpu + out vd + ret + + + ; DM2500 absolute cursor positioning. Must set up + ; special states to gobble next two input chars! +dmapos: pop h ; get return addr off stack, + shld dmapsv ; and save specially so don't depend on stack. + lxi d,dmaps2 ; jump to dmaps2 on next input. + jmp kbdtst +dmaps2: xri 140 ; First char is X position - complement bits 140. + sta hcpos ; and store. + lxi d,dmaps3 ; don't change PTR now, wait for Y position. + jmp kbdtst +dmaps3: xri 140 ; Second char is Y position - same mung. + sta vcpos ; and store. + call cblset ; reset cursor before moving... + lda vcpos ; get back line #. + lxi h,vdbsad ; now set up for + call mul80 ; finding V*80. + vdbsad. + xchg ; move HL to DE. + lhld hcpos ; get H pos into L, 0 into H + dad d ; add in to get final disp ptr. + shld ptr ; and store it. + lhld dmapsv ; now get back original return addr + pchl ; and pretend we're returning. + +dmapsv: 0 ? 0 ; 1 word + +vars:: +hcpos: 0 ; Horiz Cursor Position. Only one byte, but + .HI. 0 ; have zero byte following so double loads win. +vcpos: 0 ; Vertical Cursor Position. Like HCPOS. + .HI. 0 +ptr: 0 ? 0 + +bugch: 0 ; char written by VDO2 +bugptr: 0 ? 0 ; into this refresh location. +bsav1: 0 ? 0 ; arg in A to MUL80 +bsav2: 0 ? 0 ; rsult in HL of MUL80 + + +; optional cursor blinking stuff! +ifn blnksw,[ + + ; check whether time to blink cursor. +cblchk: lxi h,cbltic + dcr m + rnz + + +; lhld cbltic ; load tick counter into HL +; lxi b,1 ; st BC to 1 +; dad b ; add 1 into HL tick counter +; jc cblck2 ; jump if carried out! +; shld cbltic ; nope, move back new tick count +; ret ; that's all folks +cblck2: lxi h,cblcnt ; load addr to count word + dcr m ; decrement cnt + rnz ; return if not zero yet. + + ; Aha, ready to blink! + lhld ptr ; get cursor loc + lda cblch ; and saved blinkchar in acc + mov b,a ; now in b + mvi a,vdscpu ; seize access + out vd + mov c,m ; get char currently on screen + mov m,b ; replace with blinkchar + mvi a,vdsdpu ; release access + out vd + mov a,c + sta cblch ; save replaced char as new blinkchar! + ; drop thru to reset blink cnt + ; start a blink countdown +cblst: mvi a,377 + sta cbltic +; lxi h,0 ; clear the +; shld cbltic ; tick counter, and + lda blnktm ; put some random tuning number in + sta cblcnt ; main count. + ret + + ; Call this when about to move cursor, to ensure right + ; char gets left on screen! +cblset: lda blnkch ; get blink char + mov b,a + lda cblch ; get cha saved + cmp b ; compare. +; lda cblch ; get char saved +; cpi blnkch ; compare with blink ch + jz cblst ; if same, no worry - to reset count! + lhld ptr ; els must replace blink char... + mov b,a + mvi a,vdscpu ; grab access + out vd + mov m,b ; store the char. + mvi a,vdsdpu + out vd + lda blnkch ; now reset blinkchar to + sta cblch ; proper value! + jmp cblst +cbltic: 0 ; one word + 0 +cblcnt: 0 ; for overall count +blnkch: "_ ; defines cursor character. +blnktm: 25 ; defines time rate for blinking. +cblch: 0 ; holds swapped cursor char. +] ; end of IFN BLNKSW +nlflag: 0 + +ifn ibufsw,[ +; Input buffering routines. + +tiip: 0 ? 0 ; points to loc where last char stored. If incrementing + ; it would = tiop, nothing is done. +tiop: 0 ? 0 ; points to loc to read from. if = tiip, nothing there. +tiip: ibufln-1 ? 0 ; points to loc to write into, if room. +tiop: ibufln-1 ? 0 ; points to loc to read from, if anything. +ticc: 0 ; # chars to read in buffer. +ibufln==30. ; buffer up 30 chars... .03125 sec @ 9.6 kbd +ibuff: block ibufln +; EPISTO - tests for EP input, and stores in buffer if any. +; Clobbers A + +episto: in epcntl + ani rxrdy + rz ; return if nothing to read. + in epr + ani parity ; remove parity bit. + mov b,a ; save char + lda ticc ; get count + cpi ibufln ; compare with max + rz ; flush it if no more room. + inr a ; else increment + sta ticc ; and store back. + lxi d,ibuff ; get ptr into buffer + lhld tiip ; and idx for it + dad d ; form ptr + mov m,b ; store the char + dcr + + + + + + + + + + + + + + + + +; EPIGET - Reads one char from EP input buffer, returns in A. +; Sets foo flag if got a char, clears otherwise. +]; ifn ibufsw diff --git a/src/klh/nfoo.1 b/src/klh/nfoo.1 new file mode 100644 index 00000000..06de27a5 --- /dev/null +++ b/src/klh/nfoo.1 @@ -0,0 +1,4 @@ +title nfoo +.insrt klh;8080df > +.insrt newlp > +end