]> cloudbase.mooo.com Git - kermit-80.git/blobdiff - cpxbee.asm
Convert line endings to CP/M format (cr/lf).
[kermit-80.git] / cpxbee.asm
index 7333c2a96a5eeec6a036f7145bafcadb76bfe821..883bce2b6a929de03d5b748f18b096af74c11cb0 100644 (file)
-IF NOT lasm
-.printx * CPXBEE.ASM *
-ENDIF  ;NOT lasm
-;       KERMIT - (Celtic for "FREE")
-;
-;       This is the CP/M-80 implementation of the Columbia University
-;       KERMIT file transfer protocol.
-;
-;       Version 4.09
-;
-;       Copyright June 1981,1982,1983,1984,1985
-;       Columbia University
-;
-; Originally written by Bill Catchings of the Columbia University Center for
-; Computing Activities, 612 W. 115th St., New York, NY 10025.
-;
-; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
-; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
-; others.
-;
-;
-;
-; revision history:
-;
-; edit 1,  1st September 1990 
-;      Original version by Russell Lang <rjl@monu1.cc.monash.edu.au>
-;       The 'microbee' is designed and manufactured in Australia
-;       by Microbee Systems Ltd (previously Applied Technology).
-;      The microprocessor is a Z80 at 3.375MHz.
-;      The video screen is memory mapped from 0F000h to 0F7FFh, 
-;      with Programmable Characters 80-FF from 0F800h to 0FFFFh.  
-;      The serial and parallel ports are implemented using a Z80 PIO.
-;      The early model microbees were ROM-Basic computers with up
-;      to 32k of battery backed RAM.  Later models dropped the
-;      ROM-Basic and added disk drives and CP/M.  The disk systems
-;      include the 56k (64k) APC (5.25" drives), 64k Computer-In-A-Book 
-;      (3.5"), 128k Dynamic (5.25" or 3.5"), 256TC (3.5").
-;      
-;      This version of kermit was developed on a 56k APC.
-;      It has been tested on 56k, 64k, 128k and 256k Microbees.
-;
-;      The serial port is implemented in software NOT hardware.
-;      A special transmit routine allows simultaneous receiving
-;      for all speeds except 75/1200, 1200/75, 4800, 9600.
-;      The receive routine is interrupt driven with a 2 kbyte buffer.
-;      The 9600 bit/s speed is marginal on receive - if the transmitter
-;      is slightly fast (more than about 1%), the serial routine will 
-;      not have enough time to put the character in the buffer before 
-;      the next character arrives.
-
-
-;
-;              *** MAIN CODE START ***
-;
-;
-; Keep module name, edit number, and last revision date in memory.
-
-sysedt: db      'CPXSYS.ASM (35) 01-Dec-86$'
-family: db     'CPXBEE.ASM (1)  01-Sep-90$'
-
-
-; Assembly time message announcing which version we're building
-
-.printx * Assembling Microbee Kermit-80 *
-
-z80    EQU     TRUE    ; They all use Z80s
-
-defesc  EQU     ']'-100O        ;The default escape character for Microbee
-
-vtval  EQU     0       ; use default emulation which is adm3a superset
-
-;
-sysxin:                ;continuation of system initialisation code
-       ; set up baud rate
-       lxi     h,t300
-       shld    speed
-       xchg
-       call    setbaud
-       ; change the interrupt vector so that we intercept rs232 input
-       db      0EDh,57h        ;ld     a,i     ;get old interrupt reg
-       sta     oldint
-       mvi     a,int           ;new value
-       db      0EDh,47h        ;ld     i,a
-        ret                     ; return from system-dependent routine
-
-
-;
-; sysexit - System-dependent termination processing
-;          if we've changed anything, this is our last
-;          chance to put it back.
-;
-sysexit:
-       lda     oldint          ;restore old interrupt reg
-       db      0EDh,47h        ;ld     i,a
-        ret
-
-;
-; syscon - System-dependent processing for start
-;         of CONNECT command.
-;
-syscon:
-       lxi     d,conmsg
-       call    prtstr
-        ret
-
-conmsg:         ; Messages printed when entering transparent (CONNECT) mode:
-       db      cr,lf,'$'
-;
-; syscls - system-dependent close routine
-;          called when exiting transparent session.
-;
-syscls:
-        ret
-;
-; sysinh - help for system-dependent special functions.
-;          called in response to <escape>?, after listing
-;          all the system-independent escape sequences.
-;
-sysinh:
-        lxi     d,inhlps        ; we got options...
-        call    prtstr          ; print them.
-        ret
-
-
-; additional, system-dependent help for transparent mode
-; (two-character escape sequences)
-inhlps:
-        db      cr,lf,'B  Transmit a BREAK (0.3s)'
-       db      cr,lf,'L  Transmit a LONG BREAK (1.8s)'
-       db      cr,lf,'W  Wipe screen clear'
-       db      '$'
-
-; sysint - system dependent special functions
-;          called when transparent escape character has been typed;
-;          the second character of the sequence is in A (and in B).
-;          returns:-
-;                non-skip: sequence has been processed
-;                skip    : sequence was not recognized
-;
-sysint: ani     137O            ; convert lower case to upper, for testing...
-        cpi     'B'             ; send break ?
-        jz      sendbr          ; then jump to send break routine
-       cpi     'L'             ; long break ?
-       jz      longbr          ; then jump to long break routine
-       cpi     'W'             ; clear screen ?
-       jz      clrtop          ; then jump to clear screen routine
-        jmp     rskp            ; take skip return - command not recognized.
-
-;
-; Break routines
-;
-longbr:
-       mvi     e,180           ; time for long break is 1800 ms
-       jmp     setbit
-
-sendbr:
-       mvi     e,30            ; time for break is 300 ms
-
-setbit:        
-       in      portb
-       ani     0dfh            ; mask with tx bit
-       out     portb
-;
-;       Now, delay for duration of hangup or break
-        mov     a,e            ; delay count
-        call    delay
-;
-;       Time's up. Put transmitter back in normal state and return.
-       in      portb
-       ori     20h             ; mask with tx bit
-       out     portb
-        ret                     ; done.
-
-; sysflt - system-dependent filter
-;          called with character in E.
-;          if this character should not be printed, return with A = zero.
-;          preserves bc, de, hl.
-;          note: <xon>,<xoff>,<del>, and <nul> are always discarded.
-;
-sysflt:
-        mov     a,e             ; get character for testing
-       ret
-
-;
-; sysbye - system-dependent processing for BYE command.
-;
-sysbye:
-        ret
-
-;
-; This is the system-dependent command to change the baud rate.
-; DE contains the two-byte value from the baud rate table; this
-; value is also stored in 'speed'.
-;
-sysspd:
-       call    setbaud
-       ret
-
-;
-;       Speed tables
-; (Note that speed tables MUST be in alphabetical order for later
-; lookup procedures, and must begin with a value showing the total
-; number of entries.  The speed help tables are just for us poor
-; humans.
-
-;       db      string length,string,divisor (2 identical bytes or 1 word)
-; [Toad Hall]
-
-spdtbl:        db      11                      ;11 entries
-       db      03h,'110$'
-       dw      t110
-       db      04h,'1200$'
-       dw      t1200
-       db      07h,'1200/75$'
-       dw      t1275
-       db      03h,'150$'
-       dw      t150
-       db      04h,'2400$'
-       dw      t2400
-       db      03h,'300$'
-       dw      t300
-       db      04h,'4800$'
-       dw      t4800
-       db      03h,'600$'
-       dw      t600
-       db      02h,'75$'
-       dw      t75
-       db      07h,'75/1200$'
-       dw      t7512
-       db      04h,'9600$'
-       dw      t9600
-
-sphtbl:        db      cr,lf,'75  75/1200  110  150  300  600  1200  1200/75'
-       db      ' 2400 4800 9600$'
-
-
-;
-;      This is the system-dependent SET PORT command.
-sysprt:
-       ret
-
-prttbl equ     0               ; SET PORT is not supported
-prhtbl equ     0
-
-
-;
-; selmdm - select modem port
-; selcon - select console port
-; selmdm is called before using inpmdm or outmdm;
-; selcon is called before using inpcon or outcon.
-; preserves BC, DE, HL.
-;
-selmdm:
-selcon:
-        ret
-;
-; Get character from console, or return zero.
-; result is returned in A.  destroys bc, de, hl.
-;
-inpcon:
-        mvi     c,dconio        ;Direct console I/O BDOS call.
-        mvi     e,0FFH          ;Input.
-        call    BDOS
-        ret
-;
-;
-;       Output character in E to the console.
-;       destroys bc, de, hl
-;
-outcon:
-
-        mvi     c,dconio        ;Console output bdos call.
-        call    bdos            ;Output the char to the console.
-        ret
-
-
-
-;
-;
-;       outmdm - output a char from E to the modem.
-;               the parity bit has been set as necessary.
-;       returns nonskip; bc, de, hl preserved.
-outmdm:
-;
-       push    psw
-       push    b
-       push    d
-       push    h
-       mov     a,e
-       lxi     h,outm2 ; return address
-       push    h
-       lhld    txcall
-       pchl            ; send to rs232 port
-outm2: pop     h
-       pop     d
-       pop     b
-       pop     psw
-       ret
-
-
-;
-;       get character from modem; return zero if none available.
-;       bc, de, hl preserved.
-inpmdm:
-       call    rsin    ; get char if available
-       ret                     ; return with character in A
-
-
-;
-;       flsmdm - flush comm line.
-;       Modem is selected.
-;       Currently, just gets characters until none are available.
-flsmdm: call    inpmdm          ; Try to get a character
-        ora     a               ; Got one?
-        jnz     flsmdm          ; If so, try for another
-        ret                     ; Receiver is drained.  Return.
-
-;
-;       lptstat - get the printer status. Return a=0 if ok, or 0ffh if not.
-lptstat:
-       lda     pflag
-        ret
-
-;
-;       outlpt - output character in E to printer
-;       console is selected.
-;       preserves de.
-outlpt:
-        push    d               ; save DE in either case
-        ana     a               ; if A = 0 do nothing,
-        jz      outlp1          ; [30] if a=0 do nothing
-       mov     a,e
-       call    parout
-outlp1: pop     d               ; restore saved register pair
-        ret
-
-
-;
-;
-;       Screen manipulation routines
-;       csrpos - move to row B, column C
-;
-;       csrpos for terminals that use a leadin sequence followed
-;        by (row + 31.) and (column + 31.)
-;
-csrpos: push    b               ; save coordinates
-        lxi     d,curldn        ; get cursor leadin sequence
-        call    prtstr          ; print it
-        pop     h               ; restore coordinates
-        mov     a,h             ; get row
-        adi     (' '-1)         ; space is row one
-        mov     e,a
-        push    h
-        call    outcon          ; output row
-        pop     h
-        mov     a,l             ; get column
-        adi     (' '-1)         ; space is column one
-        mov     e,a
-        jmp     outcon          ; output it and return
-
-;
-; delchr - make delete look like a backspace.  Unless delete is a
-;          printing character, we just need to print a backspace
-;          (we'll output clrsp afterwards)
-delchr:
-        lxi     d,delstr
-        jmp     prtstr
-
-
-; erase the character at the current cursor position
-clrspc: mvi     e,' '
-        call    outcon
-        mvi     e,bs            ;get a backspace
-        jmp     outcon
-
-; erase the current line
-clrlin: lxi     d,eralin
-        jmp     prtstr
-
-; erase the whole screen, and go home
-clrtop: lxi     d,erascr
-        jmp     prtstr
-
-
-sysver:        db      'Microbee$'
-outlin:        db      1AH,cr,lf,tab,'$'       ;(Clear screen, home cursor)
-erascr:        db      1AH,'$'                 ;Clear screen and go home.
-eralin:        db      cr,esc,'T$'             ;Clear line.
-delstr:        db      bs,'$'                  ; Adjust for delete
-curldn:        db      esc,'=$'                ;Cursor lead-in
-ttab:                                  ;Table start location.
-ta:    db      ('K'-100O),'$',0,0      ;Cursor up.
-tb:    db      12O,'$',0,0             ;Cursor down.
-tc:    db      ('L'-100O),'$',0,0      ;Cursor right.
-td:    db      bs,'$',0,0              ;Cursor left.
-te:    db      subt,'$',0,0            ;Clear screen.
-tf:    db      '$',0,0,0               ;(can't) Enter graphics mode
-tg:    db      '$',0,0,0               ;(can't) Exit graphics mode
-th:    db      ('^'-100O),'$',0,0      ;Cursor home.
-ti:    db      ('K'-100O),'$',0,0      ;Reverse linefeed.
-tj:    db      esc,'Y$',0              ;Clear to end of screen.
-tk:    db      esc,'T$',0              ;Clear to end of line.
-
-
-;Microbee software serial port routines
-porta  equ     0
-portb  equ     2
-
-
-; interrupt vectors
-; We change the Z80 Interrupt register to point to these vectors.
-; Instead of trying to identify a particular Microbee system, 
-; we just put vectors here for all systems.
-;
-; known vectors are:
-;  48h : 56k (64k apc) - tested 19-Jun-1990
-;  48k : 64k           - tested 01-Sep-1990
-;  50h : dreamdisk (3rd party disk for Microbee)
-;  e0h : 128k          - tested 19-Jun-1990
-;  e0h : 256k          - tested 01-Sep-1990
-
-       org     ($ and 0ff00h) + 100h
-int    equ     $/256   ; byte for interrupt register
-
-       dw      inta    ; printer vector
-       dw      intb    ; rs232 vector
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       dw      inta
-       dw      intb
-       
-
-; tables for baud rates
-t75:   db      124,13  ; full delay
-       db      55,7    ; semi delay
-       db      168,255 ; txrx delay
-       dw      trout   ; address of subroutine to transmit char
-t7512: db      124,13  ; 75R/1200T
-       db      55,7
-       db      194,1   ; txout delay
-       dw      txout
-t110:  db      129,9
-       db      55,5
-       db      5,217   
-       dw      trout
-t150:  db      59,7
-       db      23,4
-       db      2,158
-       dw      trout
-t300:  db      26,4
-       db      134,2
-       db      3,75
-       dw      trout
-t600:  db      139,2
-       db      191,1
-       db      2,34
-       dw      trout
-t1200: db      195,1
-       db      90,1
-       db      3,13
-       dw      trout
-t1275: db      195,1   ; 1200R/75T
-       db      90,1
-       db      124,13
-       dw      txout
-t2400: db      94,1
-       db      40,1
-       db      2,3
-       dw      trout
-t4800: db      44,1
-       db      15,1
-       db      44,1
-       dw      txout
-t9600: db      19,1
-       db      1,1
-       db      19,1
-       dw      txout
-
-
-; copy table entries to locations used by serial routines
-setbaud:
-       lxi     h,fulldel
-       mvi     b,8
-setb2: ldax    d
-       mov     m,a
-       inx     h
-       inx     d
-       dcr     b
-       jnz     setb2
-       ret
-
-
-;transmit character in E
-; destroys all regs
-txout: mvi     b,ntotal        ;total number of bits to send
-       di
-       in      portb           ;c = portb with tx bit zeroed
-       ani     0dfh
-       mov     c,a
-       ora     a               ;carry=0 (start bit)
-txout2:        mov     a,c             ; 4T
-       jnc     txout4          ;10T skip if space
-       ori     20h             ; 3T (average)   set mark
-txout4:        out     portb           ;11T
-       lhld    txrxdel         ;16T
-txout6:        dcr     l               ;delay
-       jnz     txout6
-       dcr     h
-       jnz     txout6          ;  14*L + 14*H + 3584*(H-1)
-       stc                     ; 4T carry=1 (stop bit)
-       mov     a,e             ; 4T shift next bit to carry
-       rar                     ; 4T
-       mov     e,a             ; 4T
-       dcr     b               ; 4T
-       jnz     txout2          ;10T
-                               ;loop = 74T + (delay loop)
-       ei
-       ret
-
-       
-;
-;transmit character in E
-;simultaneous receive char if necessary
-trout: mov     a,e
-       mvi     b,ndata
-       lxi     h,0
-tro2:  rrc             ;shift tx char to hl
-       mov     c,a
-       mov     a,l
-       ral
-       mov     l,a
-       mov     a,h
-       ral
-       mov     h,a
-       mov     a,c     ;recover
-       dcr     b
-       jnz     tro2
-tro10: mvi     b,tqfudge ;adjust char in hl to align with
-                         ;tx bit of portb
-tro12: stc             ; pad out
-       mov     a,l
-       ral
-       mov     l,a
-       mov     a,h
-       ral
-       mov     h,a
-       dcr     b
-       jnz     tro12
-       mvi     a,0ffh  ;flag to say we are not receiving
-       sta     trtemp  ;save it
-       mvi     d,tqbit ;total number of qtr bits to send
-       in      portb   ;b = portb with tx bit zeroed
-       ani     0dfh
-       mov     b,a
-       mvi     e,0     ;we are not receiving yet
-tro14: in      portb
-       ori     8h      ;test CTS
-       jz      tro14   ;loop till Clear To Send
-       out     09h     ;Color Wait OFF
-       di
-       call    qbit
-       lda     trtemp  ;are we receiving
-       ora     a
-       jnz     tro22   ;skip if not
-       in      portb   ;is last bit a mark?
-       ori     10h
-       jz      tro18   ;skip if mark (don't wait for stop)
-       lhld    fulldel ;delay to stop bit
-tro16: dcr     l
-       jnz     tro16
-       dcr     h
-       jnz     tro16
-tro18: lhld    wptr            ; check buffer
-       xchg
-       lhld    rptr
-       dcx     d               ; decrement queue pointer
-       mov     a,d
-       ora     e
-       jnz     tro20           ; skip if no queue wrap around
-       lxi     d,maxque-1      ; wrap around
-tro20: mov     a,l             ; sub hl,de
-       sub     e
-       mov     l,a
-       mov     a,h
-       sbb     d
-       mov     h,a
-       ora     l               ; check for zero
-       jz      tro22           ; skip if buffer full
-       xchg
-       shld    wptr            ; update queue
-       lxi     d,rqueue
-       dad     d
-       mov     m,c             ; put char in queue
-tro22: ei
-       ret                     ;ret
-
-
-; routine for quarter bit timing
-; for transmit and simultaneous receive
-; total execution time is 223T + L*14T + H*34T
-qbit:  call    txrx    ;17T + 162T
-       lda     txrxdel ;13T
-qbit2: dcr     a       ; 4T
-       jnz     qbit2   ;10T
-       lda   txrxdel+1 ;13T
-qbit4: dcr     a       ; 4T
-       nop             ; 4T
-       nop             ; 4T
-       nop             ; 4T
-       nop             ; 4T
-       nop             ; 4T
-       jnz     qbit4   ;10T
-       mov     a,d     ; 4T Check if still sending or receiving
-       ora     e       ; 4T
-       jnz     qbit    ;10T
-       ret
-
-
-;simultaneous transmit/receive
-;do next quarter bit
-; regs: b = portb with tx bit zeroed
-;      c = character being received
-;      d = number of qtr bits remaining to send
-;      e = number of qtr bits remaining to receive (0 if not receiving)
-;      hl = character being transmitted
-;this subroutine always executes in 162T (or 163T)
-txrx:  mov     a,d     ; 4T qtr bits remaining to send
-       ora     a       ; 4T
-       jz      txrx12  ;10T skip if no bits remaining (may be receiving)
-       ani     03h     ; 7T a complete bit?
-       jnz     txrx10  ;10T skip if not
-       dad     h       ;11T shift tx bit to bit 5 of h
-       mov     a,h     ; 4T
-       ani     20h     ; 7T extract tx bit
-       ora     b       ; 4T combine with portb
-       out     portb   ;11T send it
-txrx2: dcr     d       ; 4T one less qtr bit to send
-                       ;76T total
-;now receive part
-txrx4: mov     a,e     ; 4T qtr bits remaining to receive
-       ora     a       ; 4T
-       jz      txrx16  ;10T skip if not receiving
-       ani     3h      ; 7T a complete bit?
-       jnz     txrx14  ;10T skip if not
-       in      portb   ;11T get input
-       ani     10h     ; 7T extract rx bit
-       sui     1       ; 7T bit to carry
-       mov     a,c     ; 4T bit to c
-       rar             ; 4T
-       mov     c,a     ; 4T
-txrx6: dcr     e       ; 4T one less qtr bit to receive
-txrx8: ret             ;10T
-                       ;86T total
-
-;come here if transmitting, but not a complete bit
-;delay to match up execution times
-txrx10:
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ori     00h     ; 7T
-       jmp     txrx2   ;10T
-
-;come here if not sending (but still receiving)
-;delay to match up execution times
-txrx12:        ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       jmp     txrx4   ;10T
-
-;come here if receiving (but not a complete bit)
-;delay to match up execution time
-txrx14:        ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ori     00h     ; 7T
-       jmp     txrx6   ;10T
-
-;come here if not receiving
-txrx16:        in      portb   ;11T check if start bit
-       ani     10h     ; 7T
-       jz      txrx18  ;10T skip if mark
-       mvi     e,rqbit ; 7T get quarter bit count for receive
-       xra     a       ; 4T
-       sta     trtemp  ;13T store flag to say we are receiving
-       ori     a       ; 7T delay (should be 6T)
-       ret             ;10T
-       
-txrx18:        ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       ora     a       ; 4T
-       jmp     txrx8   ;10T
-
-
-
-
-; RS232 input interrupt routine
-; stores received character in queue
-;                              ;semi delay starts here
-intb:                          ;20T (approx.) for interrupt
-       push    psw             ;11T
-       push    b               ;11T
-       push    d               ;11T
-       push    h               ;11T
-       in      portb           ;11T
-       ani     10h             ; 7T test input for start bit
-       jz      intb16          ;10T skip if no start bit.
-       out     09h             ;11T
-       lhld    semidel         ;16T half bit delay
-intb2: dcr     l               ; 4T
-       jnz     intb2           ;10T  inner loop 14T*L
-       dcr     h               ; 4T
-       jnz     intb2           ;10T  outer loop (14*H + 256*14*(H-1))T
-       mvi     e,8             ; 6T number of data bits
-                               ;semi delay ends here (125T + delay loop)
-                               ;full delay starts here
-intb4: lhld    fulldel         ;16T  full bit delay
-intb6: dcr     l
-       jnz     intb6
-       dcr     h
-       jnz     intb6           ;  14*L + 14*H + 3584*(H-1)
-       in      portb           ;11T test input
-       ani     10h             ; 7T
-       sui     1               ; 7T input bit to carry
-       mov     a,c             ; 4T
-       rar                     ; 4T
-       mov     c,a             ; 4T and then to C
-       dcr     e               ; 4T bit count
-       jnz     intb4           ;10T  loop till all data bits collected
-                               ;full delay ends here (67T + delay loop)
-       in      portb
-       ani     10h
-       jz      intb12          ; skip if mark
-       lhld    fulldel         ; wait for stop bit
-intb10:        dcr     l
-       jnz     intb10
-       dcr     h
-       jnz     intb10
-intb12:        lhld    wptr            ; check buffer
-       xchg
-       lhld    rptr
-       dcx     d               ; decrement queue pointer
-       mov     a,d
-       ora     e
-       jnz     intb14          ; skip if no queue wrap around
-       lxi     d,maxque-1      ; wrap around
-intb14:        mov     a,l             ; sub hl,de
-       sub     e
-       mov     l,a
-       mov     a,h
-       sbb     d
-       mov     h,a
-       ora     l               ; check for zero
-       jz      intb16          ; skip if buffer full
-       xchg
-       shld    wptr            ; update queue
-       lxi     d,rqueue
-       dad     d
-       mov     m,c             ; put char in queue
-intb16:        pop     h
-       pop     d
-       pop     b
-       pop     psw
-       ei
-       db      0EDh,4Dh        ;reti
-
-;
-; get char from serial port buffer.
-; exit:  A=char  or  Z if no char
-rsin:  push    d
-       push    h
-       lhld    rptr
-       xchg
-       lhld    wptr
-       mov     a,l             ;sub hl,de
-       sub     e
-       mov     l,a
-       mov     a,h
-       sbb     d
-       mov     h,a
-       ora     l               ;check for zero
-       jnz     rsi4            ;get char
-rsi2:  pop     h
-       pop     d
-       ret
-
-rsi4:  push    psw
-       dcx     d               ; decrement queue pointer
-       mov     a,d
-       ora     e
-       jnz     rsi6            ; skip if no queue wrap around
-       lxi     d,maxque-1      ; wrap around
-rsi6:  pop     psw
-       xchg
-       shld    rptr
-       lxi     d,rqueue
-       dad     d
-       mov     e,m     ;get char from queue
-       ori     0ffh    ;set NZ
-       mov     a,e
-       jmp     rsi2
-
-; printer routines
-
-inta:  sta     ptemp
-       mvi     a,0
-       sta     pflag
-       lda     ptemp
-       ei
-       db      0EDh,4Dh        ;reti
-
-parout:        push    h
-       lxi     h,pflag
-par2:  db      0CBh,46h        ;bit    0,(hl)
-       jnz     par2
-       mvi     m,0ffh
-       out     porta
-       pop     h
-       ret
-
-; data storage
-
-oldint:                db      0       ; storage for old i reg
-trtemp:                db      0
-ptemp:         db      0       ;temp storage used by inta interrupt
-pflag:         db      0       ;0ffh if waiting for printer. 00h if ready
-
-;receive queue pointers
-maxque         equ     2048    ; receiver queue size
-rptr:          dw      maxque-1
-wptr:          dw      maxque-1
-
-;transmit
-ndata  equ     8       ; 8 data bits
-nstrt  equ     1       ; 1 start bit
-nstop  equ     1       ; 1 stop bit
-ntotal equ     nstrt+ndata+nstop
-rqbit  equ     4*(nstrt+ndata)         ;number of quarter bits to receive
-tqbit  equ     4*(nstrt+ndata+nstop)   ;number of quarter bits to transmit
-tqfudge        equ     13-nstrt-ndata
-
-;H=0 or L=0 behave as 256
-;receive delays.
-fulldel:       dw      0       ; 3584(H-1) + 14H + 14L + 67 cycles
-semidel:       dw      0       ; 3584(H-1) + 14H + 14L + 125 cycles
-;1/4 bit transmit and simultaneous tx/rx delay  34H + 14L + 223 cycles
-;or full bit delay  3584(H-1) + 14H + 14L + 74 cycles
-txrxdel:       dw      0       ;
-txcall:                dw      trout   ; address of subroutine to transmit char
-
-; receiver queue
-rqueue:                ds      maxque
-
-
-ovlend equ     $       ; End of overlay
-
-IF lasm
-       END
-ENDIF
+IF NOT lasm\r
+.printx * CPXBEE.ASM *\r
+ENDIF  ;NOT lasm\r
+;       KERMIT - (Celtic for "FREE")\r
+;\r
+;       This is the CP/M-80 implementation of the Columbia University\r
+;       KERMIT file transfer protocol.\r
+;\r
+;       Version 4.09\r
+;\r
+;       Copyright June 1981,1982,1983,1984,1985\r
+;       Columbia University\r
+;\r
+; Originally written by Bill Catchings of the Columbia University Center for\r
+; Computing Activities, 612 W. 115th St., New York, NY 10025.\r
+;\r
+; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,\r
+; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many\r
+; others.\r
+;\r
+;\r
+;\r
+; revision history:\r
+;\r
+; edit 1,  1st September 1990 \r
+;      Original version by Russell Lang <rjl@monu1.cc.monash.edu.au>\r
+;       The 'microbee' is designed and manufactured in Australia\r
+;       by Microbee Systems Ltd (previously Applied Technology).\r
+;      The microprocessor is a Z80 at 3.375MHz.\r
+;      The video screen is memory mapped from 0F000h to 0F7FFh, \r
+;      with Programmable Characters 80-FF from 0F800h to 0FFFFh.  \r
+;      The serial and parallel ports are implemented using a Z80 PIO.\r
+;      The early model microbees were ROM-Basic computers with up\r
+;      to 32k of battery backed RAM.  Later models dropped the\r
+;      ROM-Basic and added disk drives and CP/M.  The disk systems\r
+;      include the 56k (64k) APC (5.25" drives), 64k Computer-In-A-Book \r
+;      (3.5"), 128k Dynamic (5.25" or 3.5"), 256TC (3.5").\r
+;      \r
+;      This version of kermit was developed on a 56k APC.\r
+;      It has been tested on 56k, 64k, 128k and 256k Microbees.\r
+;\r
+;      The serial port is implemented in software NOT hardware.\r
+;      A special transmit routine allows simultaneous receiving\r
+;      for all speeds except 75/1200, 1200/75, 4800, 9600.\r
+;      The receive routine is interrupt driven with a 2 kbyte buffer.\r
+;      The 9600 bit/s speed is marginal on receive - if the transmitter\r
+;      is slightly fast (more than about 1%), the serial routine will \r
+;      not have enough time to put the character in the buffer before \r
+;      the next character arrives.\r
+\r
+\r
+;\r
+;              *** MAIN CODE START ***\r
+;\r
+;\r
+; Keep module name, edit number, and last revision date in memory.\r
+\r
+sysedt: db      'CPXSYS.ASM (35) 01-Dec-86$'\r
+family: db     'CPXBEE.ASM (1)  01-Sep-90$'\r
+\r
+\r
+; Assembly time message announcing which version we're building\r
+\r
+.printx * Assembling Microbee Kermit-80 *\r
+\r
+z80    EQU     TRUE    ; They all use Z80s\r
+\r
+defesc  EQU     ']'-100O        ;The default escape character for Microbee\r
+\r
+vtval  EQU     0       ; use default emulation which is adm3a superset\r
+\r
+;\r
+sysxin:                ;continuation of system initialisation code\r
+       ; set up baud rate\r
+       lxi     h,t300\r
+       shld    speed\r
+       xchg\r
+       call    setbaud\r
+       ; change the interrupt vector so that we intercept rs232 input\r
+       db      0EDh,57h        ;ld     a,i     ;get old interrupt reg\r
+       sta     oldint\r
+       mvi     a,int           ;new value\r
+       db      0EDh,47h        ;ld     i,a\r
+        ret                     ; return from system-dependent routine\r
+\r
+\r
+;\r
+; sysexit - System-dependent termination processing\r
+;          if we've changed anything, this is our last\r
+;          chance to put it back.\r
+;\r
+sysexit:\r
+       lda     oldint          ;restore old interrupt reg\r
+       db      0EDh,47h        ;ld     i,a\r
+        ret\r
+\r
+;\r
+; syscon - System-dependent processing for start\r
+;         of CONNECT command.\r
+;\r
+syscon:\r
+       lxi     d,conmsg\r
+       call    prtstr\r
+        ret\r
+\r
+conmsg:         ; Messages printed when entering transparent (CONNECT) mode:\r
+       db      cr,lf,'$'\r
+;\r
+; syscls - system-dependent close routine\r
+;          called when exiting transparent session.\r
+;\r
+syscls:\r
+        ret\r
+;\r
+; sysinh - help for system-dependent special functions.\r
+;          called in response to <escape>?, after listing\r
+;          all the system-independent escape sequences.\r
+;\r
+sysinh:\r
+        lxi     d,inhlps        ; we got options...\r
+        call    prtstr          ; print them.\r
+        ret\r
+\r
+\r
+; additional, system-dependent help for transparent mode\r
+; (two-character escape sequences)\r
+inhlps:\r
+        db      cr,lf,'B  Transmit a BREAK (0.3s)'\r
+       db      cr,lf,'L  Transmit a LONG BREAK (1.8s)'\r
+       db      cr,lf,'W  Wipe screen clear'\r
+       db      '$'\r
+\r
+; sysint - system dependent special functions\r
+;          called when transparent escape character has been typed;\r
+;          the second character of the sequence is in A (and in B).\r
+;          returns:-\r
+;                non-skip: sequence has been processed\r
+;                skip    : sequence was not recognized\r
+;\r
+sysint: ani     137O            ; convert lower case to upper, for testing...\r
+        cpi     'B'             ; send break ?\r
+        jz      sendbr          ; then jump to send break routine\r
+       cpi     'L'             ; long break ?\r
+       jz      longbr          ; then jump to long break routine\r
+       cpi     'W'             ; clear screen ?\r
+       jz      clrtop          ; then jump to clear screen routine\r
+        jmp     rskp            ; take skip return - command not recognized.\r
+\r
+;\r
+; Break routines\r
+;\r
+longbr:\r
+       mvi     e,180           ; time for long break is 1800 ms\r
+       jmp     setbit\r
+\r
+sendbr:\r
+       mvi     e,30            ; time for break is 300 ms\r
+\r
+setbit:        \r
+       in      portb\r
+       ani     0dfh            ; mask with tx bit\r
+       out     portb\r
+;\r
+;       Now, delay for duration of hangup or break\r
+        mov     a,e            ; delay count\r
+        call    delay\r
+;\r
+;       Time's up. Put transmitter back in normal state and return.\r
+       in      portb\r
+       ori     20h             ; mask with tx bit\r
+       out     portb\r
+        ret                     ; done.\r
+\r
+; sysflt - system-dependent filter\r
+;          called with character in E.\r
+;          if this character should not be printed, return with A = zero.\r
+;          preserves bc, de, hl.\r
+;          note: <xon>,<xoff>,<del>, and <nul> are always discarded.\r
+;\r
+sysflt:\r
+        mov     a,e             ; get character for testing\r
+       ret\r
+\r
+;\r
+; sysbye - system-dependent processing for BYE command.\r
+;\r
+sysbye:\r
+        ret\r
+\r
+;\r
+; This is the system-dependent command to change the baud rate.\r
+; DE contains the two-byte value from the baud rate table; this\r
+; value is also stored in 'speed'.\r
+;\r
+sysspd:\r
+       call    setbaud\r
+       ret\r
+\r
+;\r
+;       Speed tables\r
+; (Note that speed tables MUST be in alphabetical order for later\r
+; lookup procedures, and must begin with a value showing the total\r
+; number of entries.  The speed help tables are just for us poor\r
+; humans.\r
+\r
+;       db      string length,string,divisor (2 identical bytes or 1 word)\r
+; [Toad Hall]\r
+\r
+spdtbl:        db      11                      ;11 entries\r
+       db      03h,'110$'\r
+       dw      t110\r
+       db      04h,'1200$'\r
+       dw      t1200\r
+       db      07h,'1200/75$'\r
+       dw      t1275\r
+       db      03h,'150$'\r
+       dw      t150\r
+       db      04h,'2400$'\r
+       dw      t2400\r
+       db      03h,'300$'\r
+       dw      t300\r
+       db      04h,'4800$'\r
+       dw      t4800\r
+       db      03h,'600$'\r
+       dw      t600\r
+       db      02h,'75$'\r
+       dw      t75\r
+       db      07h,'75/1200$'\r
+       dw      t7512\r
+       db      04h,'9600$'\r
+       dw      t9600\r
+\r
+sphtbl:        db      cr,lf,'75  75/1200  110  150  300  600  1200  1200/75'\r
+       db      ' 2400 4800 9600$'\r
+\r
+\r
+;\r
+;      This is the system-dependent SET PORT command.\r
+sysprt:\r
+       ret\r
+\r
+prttbl equ     0               ; SET PORT is not supported\r
+prhtbl equ     0\r
+\r
+\r
+;\r
+; selmdm - select modem port\r
+; selcon - select console port\r
+; selmdm is called before using inpmdm or outmdm;\r
+; selcon is called before using inpcon or outcon.\r
+; preserves BC, DE, HL.\r
+;\r
+selmdm:\r
+selcon:\r
+        ret\r
+;\r
+; Get character from console, or return zero.\r
+; result is returned in A.  destroys bc, de, hl.\r
+;\r
+inpcon:\r
+        mvi     c,dconio        ;Direct console I/O BDOS call.\r
+        mvi     e,0FFH          ;Input.\r
+        call    BDOS\r
+        ret\r
+;\r
+;\r
+;       Output character in E to the console.\r
+;       destroys bc, de, hl\r
+;\r
+outcon:\r
+\r
+        mvi     c,dconio        ;Console output bdos call.\r
+        call    bdos            ;Output the char to the console.\r
+        ret\r
+\r
+\r
+\r
+;\r
+;\r
+;       outmdm - output a char from E to the modem.\r
+;               the parity bit has been set as necessary.\r
+;       returns nonskip; bc, de, hl preserved.\r
+outmdm:\r
+;\r
+       push    psw\r
+       push    b\r
+       push    d\r
+       push    h\r
+       mov     a,e\r
+       lxi     h,outm2 ; return address\r
+       push    h\r
+       lhld    txcall\r
+       pchl            ; send to rs232 port\r
+outm2: pop     h\r
+       pop     d\r
+       pop     b\r
+       pop     psw\r
+       ret\r
+\r
+\r
+;\r
+;       get character from modem; return zero if none available.\r
+;       bc, de, hl preserved.\r
+inpmdm:\r
+       call    rsin    ; get char if available\r
+       ret                     ; return with character in A\r
+\r
+\r
+;\r
+;       flsmdm - flush comm line.\r
+;       Modem is selected.\r
+;       Currently, just gets characters until none are available.\r
+flsmdm: call    inpmdm          ; Try to get a character\r
+        ora     a               ; Got one?\r
+        jnz     flsmdm          ; If so, try for another\r
+        ret                     ; Receiver is drained.  Return.\r
+\r
+;\r
+;       lptstat - get the printer status. Return a=0 if ok, or 0ffh if not.\r
+lptstat:\r
+       lda     pflag\r
+        ret\r
+\r
+;\r
+;       outlpt - output character in E to printer\r
+;       console is selected.\r
+;       preserves de.\r
+outlpt:\r
+        push    d               ; save DE in either case\r
+        ana     a               ; if A = 0 do nothing,\r
+        jz      outlp1          ; [30] if a=0 do nothing\r
+       mov     a,e\r
+       call    parout\r
+outlp1: pop     d               ; restore saved register pair\r
+        ret\r
+\r
+\r
+;\r
+;\r
+;       Screen manipulation routines\r
+;       csrpos - move to row B, column C\r
+;\r
+;       csrpos for terminals that use a leadin sequence followed\r
+;        by (row + 31.) and (column + 31.)\r
+;\r
+csrpos: push    b               ; save coordinates\r
+        lxi     d,curldn        ; get cursor leadin sequence\r
+        call    prtstr          ; print it\r
+        pop     h               ; restore coordinates\r
+        mov     a,h             ; get row\r
+        adi     (' '-1)         ; space is row one\r
+        mov     e,a\r
+        push    h\r
+        call    outcon          ; output row\r
+        pop     h\r
+        mov     a,l             ; get column\r
+        adi     (' '-1)         ; space is column one\r
+        mov     e,a\r
+        jmp     outcon          ; output it and return\r
+\r
+;\r
+; delchr - make delete look like a backspace.  Unless delete is a\r
+;          printing character, we just need to print a backspace\r
+;          (we'll output clrsp afterwards)\r
+delchr:\r
+        lxi     d,delstr\r
+        jmp     prtstr\r
+\r
+\r
+; erase the character at the current cursor position\r
+clrspc: mvi     e,' '\r
+        call    outcon\r
+        mvi     e,bs            ;get a backspace\r
+        jmp     outcon\r
+\r
+; erase the current line\r
+clrlin: lxi     d,eralin\r
+        jmp     prtstr\r
+\r
+; erase the whole screen, and go home\r
+clrtop: lxi     d,erascr\r
+        jmp     prtstr\r
+\r
+\r
+sysver:        db      'Microbee$'\r
+outlin:        db      1AH,cr,lf,tab,'$'       ;(Clear screen, home cursor)\r
+erascr:        db      1AH,'$'                 ;Clear screen and go home.\r
+eralin:        db      cr,esc,'T$'             ;Clear line.\r
+delstr:        db      bs,'$'                  ; Adjust for delete\r
+curldn:        db      esc,'=$'                ;Cursor lead-in\r
+ttab:                                  ;Table start location.\r
+ta:    db      ('K'-100O),'$',0,0      ;Cursor up.\r
+tb:    db      12O,'$',0,0             ;Cursor down.\r
+tc:    db      ('L'-100O),'$',0,0      ;Cursor right.\r
+td:    db      bs,'$',0,0              ;Cursor left.\r
+te:    db      subt,'$',0,0            ;Clear screen.\r
+tf:    db      '$',0,0,0               ;(can't) Enter graphics mode\r
+tg:    db      '$',0,0,0               ;(can't) Exit graphics mode\r
+th:    db      ('^'-100O),'$',0,0      ;Cursor home.\r
+ti:    db      ('K'-100O),'$',0,0      ;Reverse linefeed.\r
+tj:    db      esc,'Y$',0              ;Clear to end of screen.\r
+tk:    db      esc,'T$',0              ;Clear to end of line.\r
+\r
+\r
+;Microbee software serial port routines\r
+porta  equ     0\r
+portb  equ     2\r
+\r
+\r
+; interrupt vectors\r
+; We change the Z80 Interrupt register to point to these vectors.\r
+; Instead of trying to identify a particular Microbee system, \r
+; we just put vectors here for all systems.\r
+;\r
+; known vectors are:\r
+;  48h : 56k (64k apc) - tested 19-Jun-1990\r
+;  48k : 64k           - tested 01-Sep-1990\r
+;  50h : dreamdisk (3rd party disk for Microbee)\r
+;  e0h : 128k          - tested 19-Jun-1990\r
+;  e0h : 256k          - tested 01-Sep-1990\r
+\r
+       org     ($ and 0ff00h) + 100h\r
+int    equ     $/256   ; byte for interrupt register\r
+\r
+       dw      inta    ; printer vector\r
+       dw      intb    ; rs232 vector\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       dw      inta\r
+       dw      intb\r
+       \r
+\r
+; tables for baud rates\r
+t75:   db      124,13  ; full delay\r
+       db      55,7    ; semi delay\r
+       db      168,255 ; txrx delay\r
+       dw      trout   ; address of subroutine to transmit char\r
+t7512: db      124,13  ; 75R/1200T\r
+       db      55,7\r
+       db      194,1   ; txout delay\r
+       dw      txout\r
+t110:  db      129,9\r
+       db      55,5\r
+       db      5,217   \r
+       dw      trout\r
+t150:  db      59,7\r
+       db      23,4\r
+       db      2,158\r
+       dw      trout\r
+t300:  db      26,4\r
+       db      134,2\r
+       db      3,75\r
+       dw      trout\r
+t600:  db      139,2\r
+       db      191,1\r
+       db      2,34\r
+       dw      trout\r
+t1200: db      195,1\r
+       db      90,1\r
+       db      3,13\r
+       dw      trout\r
+t1275: db      195,1   ; 1200R/75T\r
+       db      90,1\r
+       db      124,13\r
+       dw      txout\r
+t2400: db      94,1\r
+       db      40,1\r
+       db      2,3\r
+       dw      trout\r
+t4800: db      44,1\r
+       db      15,1\r
+       db      44,1\r
+       dw      txout\r
+t9600: db      19,1\r
+       db      1,1\r
+       db      19,1\r
+       dw      txout\r
+\r
+\r
+; copy table entries to locations used by serial routines\r
+setbaud:\r
+       lxi     h,fulldel\r
+       mvi     b,8\r
+setb2: ldax    d\r
+       mov     m,a\r
+       inx     h\r
+       inx     d\r
+       dcr     b\r
+       jnz     setb2\r
+       ret\r
+\r
+\r
+;transmit character in E\r
+; destroys all regs\r
+txout: mvi     b,ntotal        ;total number of bits to send\r
+       di\r
+       in      portb           ;c = portb with tx bit zeroed\r
+       ani     0dfh\r
+       mov     c,a\r
+       ora     a               ;carry=0 (start bit)\r
+txout2:        mov     a,c             ; 4T\r
+       jnc     txout4          ;10T skip if space\r
+       ori     20h             ; 3T (average)   set mark\r
+txout4:        out     portb           ;11T\r
+       lhld    txrxdel         ;16T\r
+txout6:        dcr     l               ;delay\r
+       jnz     txout6\r
+       dcr     h\r
+       jnz     txout6          ;  14*L + 14*H + 3584*(H-1)\r
+       stc                     ; 4T carry=1 (stop bit)\r
+       mov     a,e             ; 4T shift next bit to carry\r
+       rar                     ; 4T\r
+       mov     e,a             ; 4T\r
+       dcr     b               ; 4T\r
+       jnz     txout2          ;10T\r
+                               ;loop = 74T + (delay loop)\r
+       ei\r
+       ret\r
+\r
+       \r
+;\r
+;transmit character in E\r
+;simultaneous receive char if necessary\r
+trout: mov     a,e\r
+       mvi     b,ndata\r
+       lxi     h,0\r
+tro2:  rrc             ;shift tx char to hl\r
+       mov     c,a\r
+       mov     a,l\r
+       ral\r
+       mov     l,a\r
+       mov     a,h\r
+       ral\r
+       mov     h,a\r
+       mov     a,c     ;recover\r
+       dcr     b\r
+       jnz     tro2\r
+tro10: mvi     b,tqfudge ;adjust char in hl to align with\r
+                         ;tx bit of portb\r
+tro12: stc             ; pad out\r
+       mov     a,l\r
+       ral\r
+       mov     l,a\r
+       mov     a,h\r
+       ral\r
+       mov     h,a\r
+       dcr     b\r
+       jnz     tro12\r
+       mvi     a,0ffh  ;flag to say we are not receiving\r
+       sta     trtemp  ;save it\r
+       mvi     d,tqbit ;total number of qtr bits to send\r
+       in      portb   ;b = portb with tx bit zeroed\r
+       ani     0dfh\r
+       mov     b,a\r
+       mvi     e,0     ;we are not receiving yet\r
+tro14: in      portb\r
+       ori     8h      ;test CTS\r
+       jz      tro14   ;loop till Clear To Send\r
+       out     09h     ;Color Wait OFF\r
+       di\r
+       call    qbit\r
+       lda     trtemp  ;are we receiving\r
+       ora     a\r
+       jnz     tro22   ;skip if not\r
+       in      portb   ;is last bit a mark?\r
+       ori     10h\r
+       jz      tro18   ;skip if mark (don't wait for stop)\r
+       lhld    fulldel ;delay to stop bit\r
+tro16: dcr     l\r
+       jnz     tro16\r
+       dcr     h\r
+       jnz     tro16\r
+tro18: lhld    wptr            ; check buffer\r
+       xchg\r
+       lhld    rptr\r
+       dcx     d               ; decrement queue pointer\r
+       mov     a,d\r
+       ora     e\r
+       jnz     tro20           ; skip if no queue wrap around\r
+       lxi     d,maxque-1      ; wrap around\r
+tro20: mov     a,l             ; sub hl,de\r
+       sub     e\r
+       mov     l,a\r
+       mov     a,h\r
+       sbb     d\r
+       mov     h,a\r
+       ora     l               ; check for zero\r
+       jz      tro22           ; skip if buffer full\r
+       xchg\r
+       shld    wptr            ; update queue\r
+       lxi     d,rqueue\r
+       dad     d\r
+       mov     m,c             ; put char in queue\r
+tro22: ei\r
+       ret                     ;ret\r
+\r
+\r
+; routine for quarter bit timing\r
+; for transmit and simultaneous receive\r
+; total execution time is 223T + L*14T + H*34T\r
+qbit:  call    txrx    ;17T + 162T\r
+       lda     txrxdel ;13T\r
+qbit2: dcr     a       ; 4T\r
+       jnz     qbit2   ;10T\r
+       lda   txrxdel+1 ;13T\r
+qbit4: dcr     a       ; 4T\r
+       nop             ; 4T\r
+       nop             ; 4T\r
+       nop             ; 4T\r
+       nop             ; 4T\r
+       nop             ; 4T\r
+       jnz     qbit4   ;10T\r
+       mov     a,d     ; 4T Check if still sending or receiving\r
+       ora     e       ; 4T\r
+       jnz     qbit    ;10T\r
+       ret\r
+\r
+\r
+;simultaneous transmit/receive\r
+;do next quarter bit\r
+; regs: b = portb with tx bit zeroed\r
+;      c = character being received\r
+;      d = number of qtr bits remaining to send\r
+;      e = number of qtr bits remaining to receive (0 if not receiving)\r
+;      hl = character being transmitted\r
+;this subroutine always executes in 162T (or 163T)\r
+txrx:  mov     a,d     ; 4T qtr bits remaining to send\r
+       ora     a       ; 4T\r
+       jz      txrx12  ;10T skip if no bits remaining (may be receiving)\r
+       ani     03h     ; 7T a complete bit?\r
+       jnz     txrx10  ;10T skip if not\r
+       dad     h       ;11T shift tx bit to bit 5 of h\r
+       mov     a,h     ; 4T\r
+       ani     20h     ; 7T extract tx bit\r
+       ora     b       ; 4T combine with portb\r
+       out     portb   ;11T send it\r
+txrx2: dcr     d       ; 4T one less qtr bit to send\r
+                       ;76T total\r
+;now receive part\r
+txrx4: mov     a,e     ; 4T qtr bits remaining to receive\r
+       ora     a       ; 4T\r
+       jz      txrx16  ;10T skip if not receiving\r
+       ani     3h      ; 7T a complete bit?\r
+       jnz     txrx14  ;10T skip if not\r
+       in      portb   ;11T get input\r
+       ani     10h     ; 7T extract rx bit\r
+       sui     1       ; 7T bit to carry\r
+       mov     a,c     ; 4T bit to c\r
+       rar             ; 4T\r
+       mov     c,a     ; 4T\r
+txrx6: dcr     e       ; 4T one less qtr bit to receive\r
+txrx8: ret             ;10T\r
+                       ;86T total\r
+\r
+;come here if transmitting, but not a complete bit\r
+;delay to match up execution times\r
+txrx10:\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ori     00h     ; 7T\r
+       jmp     txrx2   ;10T\r
+\r
+;come here if not sending (but still receiving)\r
+;delay to match up execution times\r
+txrx12:        ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       jmp     txrx4   ;10T\r
+\r
+;come here if receiving (but not a complete bit)\r
+;delay to match up execution time\r
+txrx14:        ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ori     00h     ; 7T\r
+       jmp     txrx6   ;10T\r
+\r
+;come here if not receiving\r
+txrx16:        in      portb   ;11T check if start bit\r
+       ani     10h     ; 7T\r
+       jz      txrx18  ;10T skip if mark\r
+       mvi     e,rqbit ; 7T get quarter bit count for receive\r
+       xra     a       ; 4T\r
+       sta     trtemp  ;13T store flag to say we are receiving\r
+       ori     a       ; 7T delay (should be 6T)\r
+       ret             ;10T\r
+       \r
+txrx18:        ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       ora     a       ; 4T\r
+       jmp     txrx8   ;10T\r
+\r
+\r
+\r
+\r
+; RS232 input interrupt routine\r
+; stores received character in queue\r
+;                              ;semi delay starts here\r
+intb:                          ;20T (approx.) for interrupt\r
+       push    psw             ;11T\r
+       push    b               ;11T\r
+       push    d               ;11T\r
+       push    h               ;11T\r
+       in      portb           ;11T\r
+       ani     10h             ; 7T test input for start bit\r
+       jz      intb16          ;10T skip if no start bit.\r
+       out     09h             ;11T\r
+       lhld    semidel         ;16T half bit delay\r
+intb2: dcr     l               ; 4T\r
+       jnz     intb2           ;10T  inner loop 14T*L\r
+       dcr     h               ; 4T\r
+       jnz     intb2           ;10T  outer loop (14*H + 256*14*(H-1))T\r
+       mvi     e,8             ; 6T number of data bits\r
+                               ;semi delay ends here (125T + delay loop)\r
+                               ;full delay starts here\r
+intb4: lhld    fulldel         ;16T  full bit delay\r
+intb6: dcr     l\r
+       jnz     intb6\r
+       dcr     h\r
+       jnz     intb6           ;  14*L + 14*H + 3584*(H-1)\r
+       in      portb           ;11T test input\r
+       ani     10h             ; 7T\r
+       sui     1               ; 7T input bit to carry\r
+       mov     a,c             ; 4T\r
+       rar                     ; 4T\r
+       mov     c,a             ; 4T and then to C\r
+       dcr     e               ; 4T bit count\r
+       jnz     intb4           ;10T  loop till all data bits collected\r
+                               ;full delay ends here (67T + delay loop)\r
+       in      portb\r
+       ani     10h\r
+       jz      intb12          ; skip if mark\r
+       lhld    fulldel         ; wait for stop bit\r
+intb10:        dcr     l\r
+       jnz     intb10\r
+       dcr     h\r
+       jnz     intb10\r
+intb12:        lhld    wptr            ; check buffer\r
+       xchg\r
+       lhld    rptr\r
+       dcx     d               ; decrement queue pointer\r
+       mov     a,d\r
+       ora     e\r
+       jnz     intb14          ; skip if no queue wrap around\r
+       lxi     d,maxque-1      ; wrap around\r
+intb14:        mov     a,l             ; sub hl,de\r
+       sub     e\r
+       mov     l,a\r
+       mov     a,h\r
+       sbb     d\r
+       mov     h,a\r
+       ora     l               ; check for zero\r
+       jz      intb16          ; skip if buffer full\r
+       xchg\r
+       shld    wptr            ; update queue\r
+       lxi     d,rqueue\r
+       dad     d\r
+       mov     m,c             ; put char in queue\r
+intb16:        pop     h\r
+       pop     d\r
+       pop     b\r
+       pop     psw\r
+       ei\r
+       db      0EDh,4Dh        ;reti\r
+\r
+;\r
+; get char from serial port buffer.\r
+; exit:  A=char  or  Z if no char\r
+rsin:  push    d\r
+       push    h\r
+       lhld    rptr\r
+       xchg\r
+       lhld    wptr\r
+       mov     a,l             ;sub hl,de\r
+       sub     e\r
+       mov     l,a\r
+       mov     a,h\r
+       sbb     d\r
+       mov     h,a\r
+       ora     l               ;check for zero\r
+       jnz     rsi4            ;get char\r
+rsi2:  pop     h\r
+       pop     d\r
+       ret\r
+\r
+rsi4:  push    psw\r
+       dcx     d               ; decrement queue pointer\r
+       mov     a,d\r
+       ora     e\r
+       jnz     rsi6            ; skip if no queue wrap around\r
+       lxi     d,maxque-1      ; wrap around\r
+rsi6:  pop     psw\r
+       xchg\r
+       shld    rptr\r
+       lxi     d,rqueue\r
+       dad     d\r
+       mov     e,m     ;get char from queue\r
+       ori     0ffh    ;set NZ\r
+       mov     a,e\r
+       jmp     rsi2\r
+\r
+; printer routines\r
+\r
+inta:  sta     ptemp\r
+       mvi     a,0\r
+       sta     pflag\r
+       lda     ptemp\r
+       ei\r
+       db      0EDh,4Dh        ;reti\r
+\r
+parout:        push    h\r
+       lxi     h,pflag\r
+par2:  db      0CBh,46h        ;bit    0,(hl)\r
+       jnz     par2\r
+       mvi     m,0ffh\r
+       out     porta\r
+       pop     h\r
+       ret\r
+\r
+; data storage\r
+\r
+oldint:                db      0       ; storage for old i reg\r
+trtemp:                db      0\r
+ptemp:         db      0       ;temp storage used by inta interrupt\r
+pflag:         db      0       ;0ffh if waiting for printer. 00h if ready\r
+\r
+;receive queue pointers\r
+maxque         equ     2048    ; receiver queue size\r
+rptr:          dw      maxque-1\r
+wptr:          dw      maxque-1\r
+\r
+;transmit\r
+ndata  equ     8       ; 8 data bits\r
+nstrt  equ     1       ; 1 start bit\r
+nstop  equ     1       ; 1 stop bit\r
+ntotal equ     nstrt+ndata+nstop\r
+rqbit  equ     4*(nstrt+ndata)         ;number of quarter bits to receive\r
+tqbit  equ     4*(nstrt+ndata+nstop)   ;number of quarter bits to transmit\r
+tqfudge        equ     13-nstrt-ndata\r
+\r
+;H=0 or L=0 behave as 256\r
+;receive delays.\r
+fulldel:       dw      0       ; 3584(H-1) + 14H + 14L + 67 cycles\r
+semidel:       dw      0       ; 3584(H-1) + 14H + 14L + 125 cycles\r
+;1/4 bit transmit and simultaneous tx/rx delay  34H + 14L + 223 cycles\r
+;or full bit delay  3584(H-1) + 14H + 14L + 74 cycles\r
+txrxdel:       dw      0       ;\r
+txcall:                dw      trout   ; address of subroutine to transmit char\r
+\r
+; receiver queue\r
+rqueue:                ds      maxque\r
+\r
+\r
+ovlend equ     $       ; End of overlay\r
+\r
+IF lasm\r
+       END\r
+ENDIF\r