]> cloudbase.mooo.com Git - kermit-80.git/blob - cpxac.asm
611f22a774f8d4808dd968c1d76bfa1b39fb4a39
[kermit-80.git] / cpxac.asm
1 IF NOT lasm
2 .printx * CPXAC.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.0
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
24 ;
25 ; Keep module name, edit number, and last revision date in memory.
26 ;
27 family: db 'CPXCP.ASM (1) 3-DEC-2015$' ; First entry for V4.11
28
29 ;
30 ; Assembly time message to let me know I'm building the right version.
31 ;
32
33 .printx * Assembling Kermit-80 for AVR-CP/M *
34
35
36
37 SC16IS740_ADDR equ 90H ;SC16IS740 I2C address. (8bit, A0=VDD, A1=VDD)
38 OUTSIZE equ 64
39
40 ; Virtual I2C Interface
41
42 VI2C_STAT equ 05h
43 VI2C_CTRL equ 05h
44 VI2C_BLEN equ 06h
45 VI2C_ADR equ 07h
46 VI2C_BSIZ equ 66 ;largest message size including address byte (SLA)
47
48 ;----------------------------- ISC16IS740 UART -------------------------------
49 I2C_UART_PORT equ 50H
50
51 I2C_UART_RHR equ I2C_UART_PORT+00H ;R Receive Holding
52 I2C_UART_THR equ I2C_UART_PORT+00H ;W Transmit Holding
53 I2C_UART_IER equ I2C_UART_PORT+01H ;R/W Interrupt Enable
54 I2C_UART_FCR equ I2C_UART_PORT+02H ;W FIFO Control
55 TX_FIFO_RES equ 04H ; TX FIFO reset
56 RX_FIFO_RES equ 02H ; RX FIFO reset
57 FIFO_ENABLE equ 01H ; FIFO enable
58
59 I2C_UART_IIR equ I2C_UART_PORT+02H ;R Interrupt Identification
60 I2C_UART_LCR equ I2C_UART_PORT+03H ;R/W Line Control
61 DLAB equ 80H ; Devisor latch enable
62 WLS0 equ 01H ; Word Length Select Bit 0
63 WLS1 equ 02H ; Word Length Select Bit 1 for 8 bit word
64 STB equ 04H ; Stop bit count - 2 stop bits
65
66 I2C_UART_MCR equ I2C_UART_PORT+04H ;R/W Modem Control
67 RTS equ 02H ;RTS pin, 1 = active (low)
68 DTR equ 01H ;DTR pin (not on '740)
69 I2C_UART_LSR equ I2C_UART_PORT+05H ;R Line Status
70 TXE equ 40H ; THR and TSR empty
71 TXRDY equ 20H ; THR empty
72 RX_FE equ 08H ; Framig error
73 RX_PE equ 04H ; Parity error
74 RX_OE equ 02H ; Overrun error
75 RXRDY equ 01H ; Receved byte available
76 I2C_UART_MSR equ I2C_UART_PORT+06H ;R Modem Status
77 I2C_UART_SPR equ I2C_UART_PORT+07H ;R/W Scratchpad
78 I2C_UART_TCR equ I2C_UART_PORT+06H ;R/W Transmission Control
79 I2C_UART_TLR equ I2C_UART_PORT+07H ;R/W Trigger Level
80 I2C_UART_TXLVL equ I2C_UART_PORT+08H ;R Transmit FIFO Level
81 I2C_UART_RXLVL equ I2C_UART_PORT+09H ;R Receive FIFO Level
82 I2C_UART_EFCR equ I2C_UART_PORT+0FH ;R/W Extra Features
83 I2C_UART_DLL equ I2C_UART_PORT+00H ;R/W divisor latch LSB
84 I2C_UART_DLH equ I2C_UART_PORT+01H ;R/W divisor latch MSB
85 I2C_UART_EFR equ I2C_UART_PORT+02H ;R/W Enhanced Feature
86 I2C_UART_XON1 equ I2C_UART_PORT+04H ;R/W Xon1 word
87 I2C_UART_XON2 equ I2C_UART_PORT+05H ;R/W Xon2 word
88 I2C_UART_XOFF1 equ I2C_UART_PORT+06H ;R/W Xoff1 word
89 I2C_UART_XOFF2 equ I2C_UART_PORT+07H ;R/W Xoff2 word
90
91
92
93 z80 set TRUE ;This one emulates an Z80.
94
95
96 .z80
97
98 sysxin: ; continuation of system initialisation from sysinit
99
100 call speedtest
101 call prspeedmsg
102
103 ld hl,6 ;set default baud rate
104 ld (speed),hl
105 ex de,hl
106 call sysspd
107
108 ld a,RTS+DTR
109 out (I2C_UART_MCR),a
110 ret
111
112 ; ld a,07H ;Enable and clear fifos
113 ; out (I2C_UART_FCR),a ;
114 ; ld a,03H ;8N1
115 ; out (I2C_UART_LCR),a ;
116
117 prspeedmsg:
118 push af
119 ld de,freqmsg
120 call prtstr
121 pop af
122 cp 13+1
123 jr c,$+3
124 xor a
125 ld e,a
126 ld d,0
127 ld hl,fm_tab
128 add hl,de
129 add hl,de
130 ld e,(hl)
131 inc hl
132 ld d,(hl)
133 call prtstr
134 ld de,fdimmsg
135 call prtstr
136 ret
137
138 mkftab macro x
139 irp y,<x>
140 fm&y:
141 db '&y','$'
142 endm
143 fm_tab:
144 irp y,<x>
145 dw fm&y
146 endm
147 endm
148
149
150 freqmsg:
151 db 'UART crystal frequency: ','$'
152 mkftab <?,1.8432,3.6864,5.5296,7.3728,9.216,11.0592,12.9024,14.7456,16.5888,18.432,20.2752,22.1184,23.9616>
153 fdimmsg:
154 db ' MHz.',cr,lf,'$'
155
156
157 ;
158 ; system-dependent KERMIT termination processing
159 ; If we've changed anything, this is our last chance to put it back.
160 ;
161 sysexit:
162 ret
163
164 ;
165 ; system-dependent processing for start of CONNECT command
166 ;
167 syscon:
168 ret
169
170 conmsg: ; Messages printed when entering transparent (CONNECT) mode:
171
172 db '$'
173
174 ;
175 ; syscls - system-dependent close routine
176 ; called when exiting transparent session.
177 ;
178 syscls:
179 ret
180
181 .8080
182
183 ;
184 ; sysinh - help for system-dependent special functions.
185 ; called in response to <escape>?, after listing all the
186 ; system-independent escape sequences.
187 ;
188 sysinh:
189 lxi d, inhlps
190 call prtstr
191 ret
192
193 ; Additional, system-dependent help for transparent mode
194 ; (two-character escape sequences)
195 inhlps:
196 db cr,lf,'B Transmit a BREAK (0.3s)'
197 db cr,lf,'L Transmit a LONG BREAK (1.8s)'
198 db '$' ; string terminator
199
200 .z80
201 ;
202 ; sysint - system dependent special functions
203 ; called when transparent escape character has been typed;
204 ; the second character of the sequence is in A (and in B).
205 ; returns:
206 ; non-skip: sequence has been processed
207 ; skip: seqence was not recognized
208 ;
209 sysint:
210 and 5FH ; convert lower case to upper, for testing...
211 cp 'B' ; send break ?
212 jr z,sendbr ; then jump to send break routine
213 cp 'L' ; long break ?
214 jr z,longbr ; then jump to long break routine
215 jp rskp ; take skip return - command not recognised
216
217 ;
218 ; Break routines
219 ;
220 longbr:
221 ld e,180 ; time for long break is 1800 ms
222 jr setbit
223
224 sendbr:
225 ld e,25 ; time for break is 300 ms
226
227 setbit:
228 in a,(I2C_UART_LCR)
229 set 6,a ; Break contol bit
230 out (I2C_UART_LCR),a
231 ;
232 ; Now, delay for duration of hangup or break
233 ld a,e ; delay count
234 call delay
235 ;
236 ; Time's up. Put transmitter back in normal state and return.
237
238 in a,(I2C_UART_LCR)
239 res 6,a ; Break contol bit
240 out (I2C_UART_LCR),a
241 ret ; done.
242
243 .8080
244 ;
245 ; sysflt - system-dependent filter
246 ; called with character in E.
247 ; if this character should not be printed, return with A = zero.
248 ; preserves bc, de, hl.
249 ; note: <xon>,<xoff>,<del>, and <nul> are always discarded.
250 ;
251 sysflt:
252 mov a,e ; get character for testing
253 ret
254
255 ;
256 ; mdmflt - modem filter
257 ; called with character to be sent to printer in E
258 ; with parity set as appropriate.
259 ; return with accumulator = 0 do do nothing,
260 ; <> 0 to send char in E.
261 mdmflt:
262 mov a,e ; get character to test
263 ret
264
265 ;
266 ; prtflt - printer filter
267 ; called with character to be sent to printer in E
268 ; returns with a = 0 to do nothing
269 ; a <> 0 to print it.
270 ;
271 ; this routine for those printer that automatically insert
272 ; a lf on cr, or cr for lf. Should this be shifted to
273 ; the system indep. stuff, in say 4.06?
274 ;
275 prtflt:
276 mov a,e ; get character to test
277
278 IF FALSE ; strip out lf from printer stream
279 ani 7fh ; make sure it is parity less
280 cpi lf ; is it a line feed?
281 rnz ; no, print it
282 ; xra a ; yes, don't.
283
284 ENDIF
285
286 ret
287
288 ;
289 ; system-dependent processing for BYE command.
290 ;
291 sysbye:
292 ret
293
294 ;
295 ; This is the system-dependent command to change the baud rate.
296 ; DE contains the two-byte value from the baud rate table; both
297 ; bytes of this value are also stored in 'speed'.
298 ;
299 .z80
300 sysspd:
301 ld hl,0
302 ld a,(clk_div)
303 ld b,a
304 sysspd_1:
305 add hl,de
306 djnz sysspd_1
307 ld a,l
308 ld (sysspd_dll),a
309 ld a,h
310 ld (sysspd_dlh),a
311
312 ld hl,sysspd_tab
313 call ioinil
314
315 in a,(I2C_UART_MSR) ;Clear Modem Status Register
316 in a,(I2C_UART_LSR) ;Clear Line Status Register
317 in a,(I2C_UART_RHR) ;Clear Receiver Buffers
318 in a,(I2C_UART_RHR)
319 ret
320
321 sysspd_tab:
322 db (sysspd_tab_end - ($+1))/2
323 db I2C_UART_LCR, DLAB+03H ;Set devisor latch access bit
324 db I2C_UART_DLL
325 sysspd_dll:
326 ds 1 ;1200 bit/s at 1.832 MHz
327 db I2C_UART_DLH
328 sysspd_dlh:
329 ds 1 ;Out to the MSB divisor port
330 db I2C_UART_LCR, 03H ;Disable Divisor Access Latch
331 db I2C_UART_FCR, 07H ;Clear and enable fifos
332 db I2C_UART_MCR, 00H ;Enable loopback
333 db I2C_UART_IER, 0 ;Set no interrupts
334 sysspd_tab_end:
335
336
337
338 ;
339 ; Speed tables
340 ; (Note that speed tables MUST be in alphabetical order for later
341 ; lookup procedures, and must begin with a value showing the total
342 ; number of entries. The speed help tables are just for us poor
343 ; humans.
344 ;
345 ; db string length, string, divisor (2 bytes or 1 word, ab)
346 ; the data byte a is return in A and E, and b in D
347 ; only byte 'a' is the key for the table
348
349 spdtbl: db 15 ; Number of entries
350 db 3,'110$'
351 dw 1047
352 db 6,'115200$'
353 dw 1
354 db 4,'1200$'
355 dw 96
356 db 3,'150$'
357 dw 768
358 db 5,'19200$'
359 dw 6
360 db 4,'2400$'
361 dw 48
362 db 5,'28800$'
363 dw 5
364 db 3,'300$'
365 dw 384
366 db 5,'38400$'
367 dw 3
368 db 3,'450$'
369 dw 288
370 db 4,'4800$'
371 dw 24
372 db 5,'57600$'
373 dw 2
374 db 3,'600$'
375 dw 192
376 db 2,'75$'
377 dw 1536
378 db 4,'9600$'
379 dw 12
380 IF 0
381 sphtbl: db cr,lf,' 75 110 150 300 450 600 1200 2400'
382 db cr,lf,'4800 9600 19200 28800 38400 57600 115200$'
383 ENDIF
384
385 sphtbl: db cr,lf,' 110 300 600 2400 9600 28800 57600'
386 db cr,lf,' 75 150 450 1200 4800 19200 38400 115200$'
387
388
389 speedtest:
390 ld hl,spt_tab
391 call ioinil
392
393 in a,(I2C_UART_MSR) ;Clear Modem Status Register
394 in a,(I2C_UART_LSR) ;Clear Line Status Register
395 in a,(I2C_UART_RHR) ;Clear Receiver Buffers
396 in a,(I2C_UART_RHR)
397
398 ld a,2 ;start write transaction
399 out (VI2C_CTRL),a
400
401 ; get time stamp
402 in a,(41H) ;lsb ms
403 ld e,a
404 in a,(42H) ;msb ms
405 ld d,a
406 in a,(43H) ;lsb seconds
407 ld c,a
408
409 spt_1:
410 in a,(I2C_UART_RXLVL)
411 cp 60
412 jr nz,spt_1
413
414 ; get 2nd time stamp
415 in a,(41H) ;lsb ms
416 ld l,a
417 in a,(42H) ;msb ms
418 ld h,a
419 in a,(43H) ;lsb seconds
420 sub c
421 jr z,spt_3
422 ld bc,1000
423 spt_2:
424 add hl,bc
425 dec a
426 jr nz,spt_2
427 spt_3:
428 sbc hl,de
429 ld d,h
430 ld e,l
431 inc hl
432 srl h
433 rr l
434 ld bc,500
435 add hl,bc
436
437 xor a ;clear carry
438 spt_4:
439 inc a
440 sbc hl,de
441 jr nc,spt_4
442 dec a
443 ld (clk_div),a
444 ret
445
446 spt_tab:
447 db (spt_tab_end - ($+1))/2
448 db I2C_UART_LCR, DLAB+03H ;Set devisor latch access bit
449 db I2C_UART_DLL, low 96 ;1200 bit/s at 1.832 MHz
450 db I2C_UART_DLH, high 96 ;Out to the MSB divisor port
451 db I2C_UART_LCR, 03H ;Disable Divisor Access Latch
452 db I2C_UART_FCR, 07H ;Clear and enable fifos
453 db I2C_UART_MCR, 10H ;Enable loopback
454 db I2C_UART_IER, 0 ;Set no interrupts
455 db VI2C_ADR+0, low outbuf
456 db VI2C_ADR+1, high outbuf
457 db VI2C_BLEN, 60+2
458 spt_tab_end:
459
460 ;----------------------------------------------------------------------
461 ; output bytes to ports
462 ;
463 ; hl: tables of port,value pairs:
464 ; db n ;number of pairs
465 ; db port1,val1, port2,val2,... portn,valn
466 ; ...
467 ; db 0 ; Terminate table
468
469 ioinil:
470 push bc
471 ld b,(hl) ;count
472 inc hl
473 io1_lp:
474 ld c,(hl) ;port address
475 inc hl
476 outi
477 jr nz,io1_lp
478 pop bc
479 ret
480
481 ;
482 ; This is the system-dependent SET PORT command.
483 ; HL contains the argument from the command table.
484 ;
485 sysprt:
486 ret
487
488 prttbl EQU 0 ; SET PORT is not supported
489 prhtbl EQU 0
490
491 ;
492 ; selmdm - select modem port
493 ; selcon - select console port
494 ; selmdm is called before using inpmdm or outmdm;
495 ; selcon is called before using inpcon or outcon.
496 ; For iobyt systems, diddle the I/O byte to select console or comm port;
497 ; For the rest, does nothing.
498 ; preserves bc, de, hl.
499 ;
500 selmdm:
501 ret
502
503 selcon:
504 IF 1
505 jr omflush
506 ELSE
507 ret
508 ENDIF
509
510 ;
511 ; Get character from console, or return zero.
512 ; result is returned in A. destroys bc, de, hl.
513 ;
514 inpcon:
515 ld c,dconio ;Direct console I/O BDOS call.
516 ld e,0FFH ;Input.
517 call BDOS
518
519 ret
520
521 ;
522 ; Output character in E to the console.
523 ; destroys bc, de, hl
524 ;
525 outcon:
526 ld c,dconio ;Console output bdos call.
527 call bdos ;Output the char to the console.
528
529 ret
530
531 ;
532 ; outmdm - output a char from E to the modem.
533 ; the parity bit has been set as necessary.
534 ; returns nonskip; bc, de, hl preserved.
535 ;
536 outmdm:
537 IF 0
538 in a,(I2C_UART_LSR) ;Get the output done flag.
539 and TXRDY ;Is it set?
540 jr z,outmdm ;If not, loop until it is.
541 ld a,e
542 out (I2C_UART_THR),a ;Output it.
543 ENDIF
544 IF 1
545
546 push hl
547 ld hl,(outptr)
548 ld (hl),e ;return buffered char
549 inc hl
550 ld (outptr),hl
551 ld a,(outcnt)
552 inc a
553 ld (outcnt),a
554 cp OUTSIZE
555 jr nc,omflush_1 ;buffer full
556 pop hl
557 ret
558
559 omflush:
560 ld a,(outcnt)
561 or a
562 ret z
563
564 scf
565 push hl
566 omflush_1:
567 push bc
568 ld c,a ;outcnt
569 ld b,a
570 jr c,$+4
571 ld b,1
572 ld hl,outbuf
573 ld a,h
574 out (VI2C_ADR+1),a
575 ld a,l
576 out (VI2C_ADR+0),a
577 omf_0:
578 in a,(I2C_UART_TXLVL)
579 cp b
580 jr c,omf_0
581 cp c
582 jr nc,omf_2
583 ld c,a
584 omf_2:
585 ld a,c
586 add a,2
587 out (VI2C_BLEN),a
588 ld a,2 ;start write transaction
589 out (VI2C_CTRL),a
590
591 ld hl,outbuf+2
592 ld (outptr),hl
593 ld a,(outcnt)
594 sub c
595 ld (outcnt),a
596 jr z,omfex
597
598 push de
599 ld d,h
600 ld e,l
601 ld b,0
602 add hl,bc
603 ld c,a
604 ldir
605 pop de
606 omfex:
607 pop bc
608 pop hl
609 ret
610 ENDIF
611 ;
612 ; get character from modem; return zero if none available.
613 ; for IOBYT systems, the modem port has already been selected.
614 ; destroys bc, de, hl.
615 ;
616 inpmdm:
617 if 0
618 in a,(I2C_UART_LSR) ;Get the port status into A.
619 and RXRDY ;See if the input ready bit is on.
620 ret z ;If not then return.
621
622 in a,(I2C_UART_MCR) ;debug
623 xor RTS
624 out (I2C_UART_MCR),a
625
626 in a,(I2C_UART_RHR);If so, get the char.
627 ret
628 endif
629
630 if 1
631 ld a,(inpcnt)
632 dec a
633 jp m,imdrdi2c ;buffer empty
634 ld (inpcnt),a
635 ld hl,(inpptr)
636 ld a,(hl) ;return buffered char
637 inc hl
638 ld (inpptr),hl
639 ret
640
641 imdrdi2c:
642 in a,(I2C_UART_RXLVL) ;get rx fifo count
643 or a
644 ret z ;fifo is empty, return 0
645
646 ; prepare fifo read
647 inc a ;+ slave address
648 ld (VI2C_BLEN),a
649 ld hl,inbuf
650 ld a,h
651 out (VI2C_ADR+1),a
652 ld a,l
653 out (VI2C_ADR+0),a
654 inc hl
655 ld (hl),0 ;select subaddr 0 (RHR) for next read
656 ld a,3 ;write 1 byte (subaddr.), then read fifo
657 ld (VI2C_CTRL),a
658 in a,(VI2C_CTRL) ;get i2c result
659 xor 01h
660 and 11h ;transfer completed?
661 jr nz,imrdex
662 in a,(VI2C_BLEN) ;get actual transfer count
663
664 sub 2 ;- (slave address + char to return now)
665 jr c,imrdex
666 ld (inpcnt),a ;save new buffer count
667 ld a,(hl)
668 inc hl
669 ld (inpptr),hl
670 ret
671
672 imrdex:
673 xor a
674 ret
675 endif
676
677 .8080
678
679 ;
680 ; flsmdm - flush comm line.
681 ; Modem is selected.
682 ; Currently, just gets characters until none are available.
683 ;
684 flsmdm:
685 call inpmdm ; Try to get a character
686 ora a ; Got one?
687 jnz flsmdm ; If so, try for another
688 ret ; Receiver is drained. Return.
689
690
691 ;
692 ; lptstat - get the printer status. Return a=0 if ok, or 0ffh if not.
693 lptstat:
694 IF iobyte ;[33]
695 call bprtst ; get status
696 ENDIF ;iobyte[33]
697 IF NOT iobyte ;[33]
698 xra a ; assume it is ok.. this may not be necessary
699 ENDIF ;iobyte [33]
700 ret
701 ;
702 ; outlpt - output character in E to printer
703 ; console is selected.
704 ; preserves de.
705 ;
706 outlpt:
707 push d ; save DE in either case
708 call prtflt ; go through printer filter [30]
709 ana a ; if A = 0 do nothing,
710 jz outlp1 ; if a=0 do nothing
711
712 outlp1: pop d ; restore saved register pair
713 ret
714
715 ; delchr - make delete look like a backspace. Unless delete is a printing
716 ; character, we just need to print a backspace. (we'll output clrspc
717 ; afterwards)
718 delchr:
719
720 mvi e,bs ;get a backspace
721 jmp outcon
722
723 ; erase the character at the current cursor position
724 clrspc: mvi e,' '
725 call outcon
726 mvi e,bs ;get a backspace
727 jmp outcon
728
729 ; erase the current line
730 clrlin: lxi d,eralin
731 jmp prtstr
732
733 ; erase the whole screen, and go home. preserves b (but not c)
734 clrtop: lxi d,erascr
735 jmp prtstr
736
737
738 sysver: db 'AVR-CP/M'
739 db '$'
740
741
742 clk_div:
743 db 1 ;default div
744
745 inpptr: dw 0
746 inpcnt: db 0
747 inbuf:
748 db SC16IS740_ADDR
749 ds VI2C_BSIZ-1
750
751
752 outptr: dw outbuf+2
753 outcnt: db 0
754 outbuf:
755 db SC16IS740_ADDR
756 db 0 ;RHR subaddress
757 ds OUTSIZE
758
759
760 IF lasm
761 LINK CPXVDU.ASM ; get terminal defs etc
762 ENDIF ;lasm