]> cloudbase.mooo.com Git - kermit-80.git/blob - cpxbee.asm
Bugfix in outmdm (output buffer flush)
[kermit-80.git] / cpxbee.asm
1 IF NOT lasm
2 .printx * CPXBEE.ASM *
3 ENDIF ;NOT lasm
4 ; KERMIT - (Celtic for "FREE")
5 ;
6 ; This is the CP/M-80 implementation of the Columbia University
7 ; KERMIT file transfer protocol.
8 ;
9 ; Version 4.09
10 ;
11 ; Copyright June 1981,1982,1983,1984,1985
12 ; Columbia University
13 ;
14 ; Originally written by Bill Catchings of the Columbia University Center for
15 ; Computing Activities, 612 W. 115th St., New York, NY 10025.
16 ;
17 ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
18 ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
19 ; others.
20 ;
21 ;
22 ;
23 ; revision history:
24 ;
25 ; edit 1, 1st September 1990
26 ; Original version by Russell Lang <rjl@monu1.cc.monash.edu.au>
27 ; The 'microbee' is designed and manufactured in Australia
28 ; by Microbee Systems Ltd (previously Applied Technology).
29 ; The microprocessor is a Z80 at 3.375MHz.
30 ; The video screen is memory mapped from 0F000h to 0F7FFh,
31 ; with Programmable Characters 80-FF from 0F800h to 0FFFFh.
32 ; The serial and parallel ports are implemented using a Z80 PIO.
33 ; The early model microbees were ROM-Basic computers with up
34 ; to 32k of battery backed RAM. Later models dropped the
35 ; ROM-Basic and added disk drives and CP/M. The disk systems
36 ; include the 56k (64k) APC (5.25" drives), 64k Computer-In-A-Book
37 ; (3.5"), 128k Dynamic (5.25" or 3.5"), 256TC (3.5").
38 ;
39 ; This version of kermit was developed on a 56k APC.
40 ; It has been tested on 56k, 64k, 128k and 256k Microbees.
41 ;
42 ; The serial port is implemented in software NOT hardware.
43 ; A special transmit routine allows simultaneous receiving
44 ; for all speeds except 75/1200, 1200/75, 4800, 9600.
45 ; The receive routine is interrupt driven with a 2 kbyte buffer.
46 ; The 9600 bit/s speed is marginal on receive - if the transmitter
47 ; is slightly fast (more than about 1%), the serial routine will
48 ; not have enough time to put the character in the buffer before
49 ; the next character arrives.
50
51
52 ;
53 ; *** MAIN CODE START ***
54 ;
55 ;
56 ; Keep module name, edit number, and last revision date in memory.
57
58 sysedt: db 'CPXSYS.ASM (35) 01-Dec-86$'
59 family: db 'CPXBEE.ASM (1) 01-Sep-90$'
60
61
62 ; Assembly time message announcing which version we're building
63
64 .printx * Assembling Microbee Kermit-80 *
65
66 z80 EQU TRUE ; They all use Z80s
67
68 defesc EQU ']'-100O ;The default escape character for Microbee
69
70 vtval EQU 0 ; use default emulation which is adm3a superset
71
72 ;
73 sysxin: ;continuation of system initialisation code
74 ; set up baud rate
75 lxi h,t300
76 shld speed
77 xchg
78 call setbaud
79 ; change the interrupt vector so that we intercept rs232 input
80 db 0EDh,57h ;ld a,i ;get old interrupt reg
81 sta oldint
82 mvi a,int ;new value
83 db 0EDh,47h ;ld i,a
84 ret ; return from system-dependent routine
85
86
87 ;
88 ; sysexit - System-dependent termination processing
89 ; if we've changed anything, this is our last
90 ; chance to put it back.
91 ;
92 sysexit:
93 lda oldint ;restore old interrupt reg
94 db 0EDh,47h ;ld i,a
95 ret
96
97 ;
98 ; syscon - System-dependent processing for start
99 ; of CONNECT command.
100 ;
101 syscon:
102 lxi d,conmsg
103 call prtstr
104 ret
105
106 conmsg: ; Messages printed when entering transparent (CONNECT) mode:
107 db cr,lf,'$'
108 ;
109 ; syscls - system-dependent close routine
110 ; called when exiting transparent session.
111 ;
112 syscls:
113 ret
114 ;
115 ; sysinh - help for system-dependent special functions.
116 ; called in response to <escape>?, after listing
117 ; all the system-independent escape sequences.
118 ;
119 sysinh:
120 lxi d,inhlps ; we got options...
121 call prtstr ; print them.
122 ret
123
124
125 ; additional, system-dependent help for transparent mode
126 ; (two-character escape sequences)
127 inhlps:
128 db cr,lf,'B Transmit a BREAK (0.3s)'
129 db cr,lf,'L Transmit a LONG BREAK (1.8s)'
130 db cr,lf,'W Wipe screen clear'
131 db '$'
132
133 ; sysint - system dependent special functions
134 ; called when transparent escape character has been typed;
135 ; the second character of the sequence is in A (and in B).
136 ; returns:-
137 ; non-skip: sequence has been processed
138 ; skip : sequence was not recognized
139 ;
140 sysint: ani 137O ; convert lower case to upper, for testing...
141 cpi 'B' ; send break ?
142 jz sendbr ; then jump to send break routine
143 cpi 'L' ; long break ?
144 jz longbr ; then jump to long break routine
145 cpi 'W' ; clear screen ?
146 jz clrtop ; then jump to clear screen routine
147 jmp rskp ; take skip return - command not recognized.
148
149 ;
150 ; Break routines
151 ;
152 longbr:
153 mvi e,180 ; time for long break is 1800 ms
154 jmp setbit
155
156 sendbr:
157 mvi e,30 ; time for break is 300 ms
158
159 setbit:
160 in portb
161 ani 0dfh ; mask with tx bit
162 out portb
163 ;
164 ; Now, delay for duration of hangup or break
165 mov a,e ; delay count
166 call delay
167 ;
168 ; Time's up. Put transmitter back in normal state and return.
169 in portb
170 ori 20h ; mask with tx bit
171 out portb
172 ret ; done.
173
174 ; sysflt - system-dependent filter
175 ; called with character in E.
176 ; if this character should not be printed, return with A = zero.
177 ; preserves bc, de, hl.
178 ; note: <xon>,<xoff>,<del>, and <nul> are always discarded.
179 ;
180 sysflt:
181 mov a,e ; get character for testing
182 ret
183
184 ;
185 ; sysbye - system-dependent processing for BYE command.
186 ;
187 sysbye:
188 ret
189
190 ;
191 ; This is the system-dependent command to change the baud rate.
192 ; DE contains the two-byte value from the baud rate table; this
193 ; value is also stored in 'speed'.
194 ;
195 sysspd:
196 call setbaud
197 ret
198
199 ;
200 ; Speed tables
201 ; (Note that speed tables MUST be in alphabetical order for later
202 ; lookup procedures, and must begin with a value showing the total
203 ; number of entries. The speed help tables are just for us poor
204 ; humans.
205
206 ; db string length,string,divisor (2 identical bytes or 1 word)
207 ; [Toad Hall]
208
209 spdtbl: db 11 ;11 entries
210 db 03h,'110$'
211 dw t110
212 db 04h,'1200$'
213 dw t1200
214 db 07h,'1200/75$'
215 dw t1275
216 db 03h,'150$'
217 dw t150
218 db 04h,'2400$'
219 dw t2400
220 db 03h,'300$'
221 dw t300
222 db 04h,'4800$'
223 dw t4800
224 db 03h,'600$'
225 dw t600
226 db 02h,'75$'
227 dw t75
228 db 07h,'75/1200$'
229 dw t7512
230 db 04h,'9600$'
231 dw t9600
232
233 sphtbl: db cr,lf,'75 75/1200 110 150 300 600 1200 1200/75'
234 db ' 2400 4800 9600$'
235
236
237 ;
238 ; This is the system-dependent SET PORT command.
239 sysprt:
240 ret
241
242 prttbl equ 0 ; SET PORT is not supported
243 prhtbl equ 0
244
245
246 ;
247 ; selmdm - select modem port
248 ; selcon - select console port
249 ; selmdm is called before using inpmdm or outmdm;
250 ; selcon is called before using inpcon or outcon.
251 ; preserves BC, DE, HL.
252 ;
253 selmdm:
254 selcon:
255 ret
256 ;
257 ; Get character from console, or return zero.
258 ; result is returned in A. destroys bc, de, hl.
259 ;
260 inpcon:
261 mvi c,dconio ;Direct console I/O BDOS call.
262 mvi e,0FFH ;Input.
263 call BDOS
264 ret
265 ;
266 ;
267 ; Output character in E to the console.
268 ; destroys bc, de, hl
269 ;
270 outcon:
271
272 mvi c,dconio ;Console output bdos call.
273 call bdos ;Output the char to the console.
274 ret
275
276
277
278 ;
279 ;
280 ; outmdm - output a char from E to the modem.
281 ; the parity bit has been set as necessary.
282 ; returns nonskip; bc, de, hl preserved.
283 outmdm:
284 ;
285 push psw
286 push b
287 push d
288 push h
289 mov a,e
290 lxi h,outm2 ; return address
291 push h
292 lhld txcall
293 pchl ; send to rs232 port
294 outm2: pop h
295 pop d
296 pop b
297 pop psw
298 ret
299
300
301 ;
302 ; get character from modem; return zero if none available.
303 ; bc, de, hl preserved.
304 inpmdm:
305 call rsin ; get char if available
306 ret ; return with character in A
307
308
309 ;
310 ; flsmdm - flush comm line.
311 ; Modem is selected.
312 ; Currently, just gets characters until none are available.
313 flsmdm: call inpmdm ; Try to get a character
314 ora a ; Got one?
315 jnz flsmdm ; If so, try for another
316 ret ; Receiver is drained. Return.
317
318 ;
319 ; lptstat - get the printer status. Return a=0 if ok, or 0ffh if not.
320 lptstat:
321 lda pflag
322 ret
323
324 ;
325 ; outlpt - output character in E to printer
326 ; console is selected.
327 ; preserves de.
328 outlpt:
329 push d ; save DE in either case
330 ana a ; if A = 0 do nothing,
331 jz outlp1 ; [30] if a=0 do nothing
332 mov a,e
333 call parout
334 outlp1: pop d ; restore saved register pair
335 ret
336
337
338 ;
339 ;
340 ; Screen manipulation routines
341 ; csrpos - move to row B, column C
342 ;
343 ; csrpos for terminals that use a leadin sequence followed
344 ; by (row + 31.) and (column + 31.)
345 ;
346 csrpos: push b ; save coordinates
347 lxi d,curldn ; get cursor leadin sequence
348 call prtstr ; print it
349 pop h ; restore coordinates
350 mov a,h ; get row
351 adi (' '-1) ; space is row one
352 mov e,a
353 push h
354 call outcon ; output row
355 pop h
356 mov a,l ; get column
357 adi (' '-1) ; space is column one
358 mov e,a
359 jmp outcon ; output it and return
360
361 ;
362 ; delchr - make delete look like a backspace. Unless delete is a
363 ; printing character, we just need to print a backspace
364 ; (we'll output clrsp afterwards)
365 delchr:
366 lxi d,delstr
367 jmp prtstr
368
369
370 ; erase the character at the current cursor position
371 clrspc: mvi e,' '
372 call outcon
373 mvi e,bs ;get a backspace
374 jmp outcon
375
376 ; erase the current line
377 clrlin: lxi d,eralin
378 jmp prtstr
379
380 ; erase the whole screen, and go home
381 clrtop: lxi d,erascr
382 jmp prtstr
383
384
385 sysver: db 'Microbee$'
386 outlin: db 1AH,cr,lf,tab,'$' ;(Clear screen, home cursor)
387 erascr: db 1AH,'$' ;Clear screen and go home.
388 eralin: db cr,esc,'T$' ;Clear line.
389 delstr: db bs,'$' ; Adjust for delete
390 curldn: db esc,'=$' ;Cursor lead-in
391 ttab: ;Table start location.
392 ta: db ('K'-100O),'$',0,0 ;Cursor up.
393 tb: db 12O,'$',0,0 ;Cursor down.
394 tc: db ('L'-100O),'$',0,0 ;Cursor right.
395 td: db bs,'$',0,0 ;Cursor left.
396 te: db subt,'$',0,0 ;Clear screen.
397 tf: db '$',0,0,0 ;(can't) Enter graphics mode
398 tg: db '$',0,0,0 ;(can't) Exit graphics mode
399 th: db ('^'-100O),'$',0,0 ;Cursor home.
400 ti: db ('K'-100O),'$',0,0 ;Reverse linefeed.
401 tj: db esc,'Y$',0 ;Clear to end of screen.
402 tk: db esc,'T$',0 ;Clear to end of line.
403
404
405 ;Microbee software serial port routines
406 porta equ 0
407 portb equ 2
408
409
410 ; interrupt vectors
411 ; We change the Z80 Interrupt register to point to these vectors.
412 ; Instead of trying to identify a particular Microbee system,
413 ; we just put vectors here for all systems.
414 ;
415 ; known vectors are:
416 ; 48h : 56k (64k apc) - tested 19-Jun-1990
417 ; 48k : 64k - tested 01-Sep-1990
418 ; 50h : dreamdisk (3rd party disk for Microbee)
419 ; e0h : 128k - tested 19-Jun-1990
420 ; e0h : 256k - tested 01-Sep-1990
421
422 org ($ and 0ff00h) + 100h
423 int equ $/256 ; byte for interrupt register
424
425 dw inta ; printer vector
426 dw intb ; rs232 vector
427 dw inta
428 dw intb
429 dw inta
430 dw intb
431 dw inta
432 dw intb
433 dw inta
434 dw intb
435 dw inta
436 dw intb
437 dw inta
438 dw intb
439 dw inta
440 dw intb
441 dw inta
442 dw intb
443 dw inta
444 dw intb
445 dw inta
446 dw intb
447 dw inta
448 dw intb
449 dw inta
450 dw intb
451 dw inta
452 dw intb
453 dw inta
454 dw intb
455 dw inta
456 dw intb
457 dw inta
458 dw intb
459 dw inta
460 dw intb
461 dw inta
462 dw intb
463 dw inta
464 dw intb
465 dw inta
466 dw intb
467 dw inta
468 dw intb
469 dw inta
470 dw intb
471 dw inta
472 dw intb
473 dw inta
474 dw intb
475 dw inta
476 dw intb
477 dw inta
478 dw intb
479 dw inta
480 dw intb
481 dw inta
482 dw intb
483 dw inta
484 dw intb
485 dw inta
486 dw intb
487 dw inta
488 dw intb
489 dw inta
490 dw intb
491 dw inta
492 dw intb
493 dw inta
494 dw intb
495 dw inta
496 dw intb
497 dw inta
498 dw intb
499 dw inta
500 dw intb
501 dw inta
502 dw intb
503 dw inta
504 dw intb
505 dw inta
506 dw intb
507 dw inta
508 dw intb
509 dw inta
510 dw intb
511 dw inta
512 dw intb
513 dw inta
514 dw intb
515 dw inta
516 dw intb
517 dw inta
518 dw intb
519 dw inta
520 dw intb
521 dw inta
522 dw intb
523 dw inta
524 dw intb
525 dw inta
526 dw intb
527 dw inta
528 dw intb
529 dw inta
530 dw intb
531 dw inta
532 dw intb
533 dw inta
534 dw intb
535 dw inta
536 dw intb
537 dw inta
538 dw intb
539 dw inta
540 dw intb
541 dw inta
542 dw intb
543 dw inta
544 dw intb
545 dw inta
546 dw intb
547 dw inta
548 dw intb
549 dw inta
550 dw intb
551 dw inta
552 dw intb
553
554
555 ; tables for baud rates
556 t75: db 124,13 ; full delay
557 db 55,7 ; semi delay
558 db 168,255 ; txrx delay
559 dw trout ; address of subroutine to transmit char
560 t7512: db 124,13 ; 75R/1200T
561 db 55,7
562 db 194,1 ; txout delay
563 dw txout
564 t110: db 129,9
565 db 55,5
566 db 5,217
567 dw trout
568 t150: db 59,7
569 db 23,4
570 db 2,158
571 dw trout
572 t300: db 26,4
573 db 134,2
574 db 3,75
575 dw trout
576 t600: db 139,2
577 db 191,1
578 db 2,34
579 dw trout
580 t1200: db 195,1
581 db 90,1
582 db 3,13
583 dw trout
584 t1275: db 195,1 ; 1200R/75T
585 db 90,1
586 db 124,13
587 dw txout
588 t2400: db 94,1
589 db 40,1
590 db 2,3
591 dw trout
592 t4800: db 44,1
593 db 15,1
594 db 44,1
595 dw txout
596 t9600: db 19,1
597 db 1,1
598 db 19,1
599 dw txout
600
601
602 ; copy table entries to locations used by serial routines
603 setbaud:
604 lxi h,fulldel
605 mvi b,8
606 setb2: ldax d
607 mov m,a
608 inx h
609 inx d
610 dcr b
611 jnz setb2
612 ret
613
614
615 ;transmit character in E
616 ; destroys all regs
617 txout: mvi b,ntotal ;total number of bits to send
618 di
619 in portb ;c = portb with tx bit zeroed
620 ani 0dfh
621 mov c,a
622 ora a ;carry=0 (start bit)
623 txout2: mov a,c ; 4T
624 jnc txout4 ;10T skip if space
625 ori 20h ; 3T (average) set mark
626 txout4: out portb ;11T
627 lhld txrxdel ;16T
628 txout6: dcr l ;delay
629 jnz txout6
630 dcr h
631 jnz txout6 ; 14*L + 14*H + 3584*(H-1)
632 stc ; 4T carry=1 (stop bit)
633 mov a,e ; 4T shift next bit to carry
634 rar ; 4T
635 mov e,a ; 4T
636 dcr b ; 4T
637 jnz txout2 ;10T
638 ;loop = 74T + (delay loop)
639 ei
640 ret
641
642
643 ;
644 ;transmit character in E
645 ;simultaneous receive char if necessary
646 trout: mov a,e
647 mvi b,ndata
648 lxi h,0
649 tro2: rrc ;shift tx char to hl
650 mov c,a
651 mov a,l
652 ral
653 mov l,a
654 mov a,h
655 ral
656 mov h,a
657 mov a,c ;recover
658 dcr b
659 jnz tro2
660 tro10: mvi b,tqfudge ;adjust char in hl to align with
661 ;tx bit of portb
662 tro12: stc ; pad out
663 mov a,l
664 ral
665 mov l,a
666 mov a,h
667 ral
668 mov h,a
669 dcr b
670 jnz tro12
671 mvi a,0ffh ;flag to say we are not receiving
672 sta trtemp ;save it
673 mvi d,tqbit ;total number of qtr bits to send
674 in portb ;b = portb with tx bit zeroed
675 ani 0dfh
676 mov b,a
677 mvi e,0 ;we are not receiving yet
678 tro14: in portb
679 ori 8h ;test CTS
680 jz tro14 ;loop till Clear To Send
681 out 09h ;Color Wait OFF
682 di
683 call qbit
684 lda trtemp ;are we receiving
685 ora a
686 jnz tro22 ;skip if not
687 in portb ;is last bit a mark?
688 ori 10h
689 jz tro18 ;skip if mark (don't wait for stop)
690 lhld fulldel ;delay to stop bit
691 tro16: dcr l
692 jnz tro16
693 dcr h
694 jnz tro16
695 tro18: lhld wptr ; check buffer
696 xchg
697 lhld rptr
698 dcx d ; decrement queue pointer
699 mov a,d
700 ora e
701 jnz tro20 ; skip if no queue wrap around
702 lxi d,maxque-1 ; wrap around
703 tro20: mov a,l ; sub hl,de
704 sub e
705 mov l,a
706 mov a,h
707 sbb d
708 mov h,a
709 ora l ; check for zero
710 jz tro22 ; skip if buffer full
711 xchg
712 shld wptr ; update queue
713 lxi d,rqueue
714 dad d
715 mov m,c ; put char in queue
716 tro22: ei
717 ret ;ret
718
719
720 ; routine for quarter bit timing
721 ; for transmit and simultaneous receive
722 ; total execution time is 223T + L*14T + H*34T
723 qbit: call txrx ;17T + 162T
724 lda txrxdel ;13T
725 qbit2: dcr a ; 4T
726 jnz qbit2 ;10T
727 lda txrxdel+1 ;13T
728 qbit4: dcr a ; 4T
729 nop ; 4T
730 nop ; 4T
731 nop ; 4T
732 nop ; 4T
733 nop ; 4T
734 jnz qbit4 ;10T
735 mov a,d ; 4T Check if still sending or receiving
736 ora e ; 4T
737 jnz qbit ;10T
738 ret
739
740
741 ;simultaneous transmit/receive
742 ;do next quarter bit
743 ; regs: b = portb with tx bit zeroed
744 ; c = character being received
745 ; d = number of qtr bits remaining to send
746 ; e = number of qtr bits remaining to receive (0 if not receiving)
747 ; hl = character being transmitted
748 ;this subroutine always executes in 162T (or 163T)
749 txrx: mov a,d ; 4T qtr bits remaining to send
750 ora a ; 4T
751 jz txrx12 ;10T skip if no bits remaining (may be receiving)
752 ani 03h ; 7T a complete bit?
753 jnz txrx10 ;10T skip if not
754 dad h ;11T shift tx bit to bit 5 of h
755 mov a,h ; 4T
756 ani 20h ; 7T extract tx bit
757 ora b ; 4T combine with portb
758 out portb ;11T send it
759 txrx2: dcr d ; 4T one less qtr bit to send
760 ;76T total
761 ;now receive part
762 txrx4: mov a,e ; 4T qtr bits remaining to receive
763 ora a ; 4T
764 jz txrx16 ;10T skip if not receiving
765 ani 3h ; 7T a complete bit?
766 jnz txrx14 ;10T skip if not
767 in portb ;11T get input
768 ani 10h ; 7T extract rx bit
769 sui 1 ; 7T bit to carry
770 mov a,c ; 4T bit to c
771 rar ; 4T
772 mov c,a ; 4T
773 txrx6: dcr e ; 4T one less qtr bit to receive
774 txrx8: ret ;10T
775 ;86T total
776
777 ;come here if transmitting, but not a complete bit
778 ;delay to match up execution times
779 txrx10:
780 ora a ; 4T
781 ora a ; 4T
782 ora a ; 4T
783 ora a ; 4T
784 ora a ; 4T
785 ori 00h ; 7T
786 jmp txrx2 ;10T
787
788 ;come here if not sending (but still receiving)
789 ;delay to match up execution times
790 txrx12: ora a ; 4T
791 ora a ; 4T
792 ora a ; 4T
793 ora a ; 4T
794 ora a ; 4T
795 ora a ; 4T
796 ora a ; 4T
797 ora a ; 4T
798 ora a ; 4T
799 ora a ; 4T
800 ora a ; 4T
801 ora a ; 4T
802 jmp txrx4 ;10T
803
804 ;come here if receiving (but not a complete bit)
805 ;delay to match up execution time
806 txrx14: ora a ; 4T
807 ora a ; 4T
808 ora a ; 4T
809 ora a ; 4T
810 ora a ; 4T
811 ori 00h ; 7T
812 jmp txrx6 ;10T
813
814 ;come here if not receiving
815 txrx16: in portb ;11T check if start bit
816 ani 10h ; 7T
817 jz txrx18 ;10T skip if mark
818 mvi e,rqbit ; 7T get quarter bit count for receive
819 xra a ; 4T
820 sta trtemp ;13T store flag to say we are receiving
821 ori a ; 7T delay (should be 6T)
822 ret ;10T
823
824 txrx18: ora a ; 4T
825 ora a ; 4T
826 ora a ; 4T
827 ora a ; 4T
828 ora a ; 4T
829 jmp txrx8 ;10T
830
831
832
833
834 ; RS232 input interrupt routine
835 ; stores received character in queue
836 ; ;semi delay starts here
837 intb: ;20T (approx.) for interrupt
838 push psw ;11T
839 push b ;11T
840 push d ;11T
841 push h ;11T
842 in portb ;11T
843 ani 10h ; 7T test input for start bit
844 jz intb16 ;10T skip if no start bit.
845 out 09h ;11T
846 lhld semidel ;16T half bit delay
847 intb2: dcr l ; 4T
848 jnz intb2 ;10T inner loop 14T*L
849 dcr h ; 4T
850 jnz intb2 ;10T outer loop (14*H + 256*14*(H-1))T
851 mvi e,8 ; 6T number of data bits
852 ;semi delay ends here (125T + delay loop)
853 ;full delay starts here
854 intb4: lhld fulldel ;16T full bit delay
855 intb6: dcr l
856 jnz intb6
857 dcr h
858 jnz intb6 ; 14*L + 14*H + 3584*(H-1)
859 in portb ;11T test input
860 ani 10h ; 7T
861 sui 1 ; 7T input bit to carry
862 mov a,c ; 4T
863 rar ; 4T
864 mov c,a ; 4T and then to C
865 dcr e ; 4T bit count
866 jnz intb4 ;10T loop till all data bits collected
867 ;full delay ends here (67T + delay loop)
868 in portb
869 ani 10h
870 jz intb12 ; skip if mark
871 lhld fulldel ; wait for stop bit
872 intb10: dcr l
873 jnz intb10
874 dcr h
875 jnz intb10
876 intb12: lhld wptr ; check buffer
877 xchg
878 lhld rptr
879 dcx d ; decrement queue pointer
880 mov a,d
881 ora e
882 jnz intb14 ; skip if no queue wrap around
883 lxi d,maxque-1 ; wrap around
884 intb14: mov a,l ; sub hl,de
885 sub e
886 mov l,a
887 mov a,h
888 sbb d
889 mov h,a
890 ora l ; check for zero
891 jz intb16 ; skip if buffer full
892 xchg
893 shld wptr ; update queue
894 lxi d,rqueue
895 dad d
896 mov m,c ; put char in queue
897 intb16: pop h
898 pop d
899 pop b
900 pop psw
901 ei
902 db 0EDh,4Dh ;reti
903
904 ;
905 ; get char from serial port buffer.
906 ; exit: A=char or Z if no char
907 rsin: push d
908 push h
909 lhld rptr
910 xchg
911 lhld wptr
912 mov a,l ;sub hl,de
913 sub e
914 mov l,a
915 mov a,h
916 sbb d
917 mov h,a
918 ora l ;check for zero
919 jnz rsi4 ;get char
920 rsi2: pop h
921 pop d
922 ret
923
924 rsi4: push psw
925 dcx d ; decrement queue pointer
926 mov a,d
927 ora e
928 jnz rsi6 ; skip if no queue wrap around
929 lxi d,maxque-1 ; wrap around
930 rsi6: pop psw
931 xchg
932 shld rptr
933 lxi d,rqueue
934 dad d
935 mov e,m ;get char from queue
936 ori 0ffh ;set NZ
937 mov a,e
938 jmp rsi2
939
940 ; printer routines
941
942 inta: sta ptemp
943 mvi a,0
944 sta pflag
945 lda ptemp
946 ei
947 db 0EDh,4Dh ;reti
948
949 parout: push h
950 lxi h,pflag
951 par2: db 0CBh,46h ;bit 0,(hl)
952 jnz par2
953 mvi m,0ffh
954 out porta
955 pop h
956 ret
957
958 ; data storage
959
960 oldint: db 0 ; storage for old i reg
961 trtemp: db 0
962 ptemp: db 0 ;temp storage used by inta interrupt
963 pflag: db 0 ;0ffh if waiting for printer. 00h if ready
964
965 ;receive queue pointers
966 maxque equ 2048 ; receiver queue size
967 rptr: dw maxque-1
968 wptr: dw maxque-1
969
970 ;transmit
971 ndata equ 8 ; 8 data bits
972 nstrt equ 1 ; 1 start bit
973 nstop equ 1 ; 1 stop bit
974 ntotal equ nstrt+ndata+nstop
975 rqbit equ 4*(nstrt+ndata) ;number of quarter bits to receive
976 tqbit equ 4*(nstrt+ndata+nstop) ;number of quarter bits to transmit
977 tqfudge equ 13-nstrt-ndata
978
979 ;H=0 or L=0 behave as 256
980 ;receive delays.
981 fulldel: dw 0 ; 3584(H-1) + 14H + 14L + 67 cycles
982 semidel: dw 0 ; 3584(H-1) + 14H + 14L + 125 cycles
983 ;1/4 bit transmit and simultaneous tx/rx delay 34H + 14L + 223 cycles
984 ;or full bit delay 3584(H-1) + 14H + 14L + 74 cycles
985 txrxdel: dw 0 ;
986 txcall: dw trout ; address of subroutine to transmit char
987
988 ; receiver queue
989 rqueue: ds maxque
990
991
992 ovlend equ $ ; End of overlay
993
994 IF lasm
995 END
996 ENDIF